当前位置:  开发笔记 > 编程语言 > 正文

如何获取父进程标准输出?

如何解决《如何获取父进程标准输出?》经验,为你挑选了1个好方法。

我正在编写一个实用程序(http://reg2run.sf.net),如果没有参数的执行作为Windows应用程序(显示OpenFileDialog等),否则 - 作为控制台应用程序.

因此,在第一种情况下,我不想显示控制台窗口,这就是为什么项目是Windows应用程序.但在第二个 - 我需要展示它,它是用它创建的

if (ptrNew == IntPtr.Zero)
{
    ptrNew = GetStdHandle(-11);
}
if (!AllocConsole())
{
    throw new ExternalCallException("AllocConsole");
}
ptrNew = CreateFile("CONOUT$", 0x40000000, 2, IntPtr.Zero, 3, 0, IntPtr.Zero);
if (!SetStdHandle(-11, ptrNew))
{
    throw new ExternalCallException("SetStdHandle");
}
StreamWriter newOut = new StreamWriter(Console.OpenStandardOutput());
newOut.AutoFlush = true;
Console.SetOut(newOut);
Console.SetError(newOut);

我想要的是 - 获取父进程标准输出并使用它,如果它存在(如果通过cmd.exe或远程管理器执行).我该怎么做?

我试过了

static Process GetParentProc()
{
int pidParent = 0;
int pidCurrent = Process.GetCurrentProcess().Id;

IntPtr hSnapshot = CreateToolhelp32Snapshot(2, 0);
if (hSnapshot == IntPtr.Zero)
{
    return null;
}

PROCESSENTRY32 oProcInfo = new PROCESSENTRY32();
oProcInfo.dwSize = (uint)Marshal.SizeOf(typeof(PROCESSENTRY32));

if (!Process32First(hSnapshot, ref oProcInfo))
{
    return null;
}
do
{
    if (pidCurrent == oProcInfo.th32ProcessID)
    {
        pidParent = (int)oProcInfo.th32ParentProcessID;
    }
}
while (pidParent == 0 && Process32Next(hSnapshot, ref oProcInfo));

if (pidParent > 0)
{
    return Process.GetProcessById(pidParent);
}
else
{
    return null;
}

StreamWriter newOut = GetParentProc().StandardInput;

但得到了InvalidOperationException:StandardIn尚未重定向.因为

GetParentProc().StartInfo.RedirectStandardOutput = false

Barry Kelly.. 6

对于需要在Windows上根据上下文选择是否充当控制台或GUI应用程序的应用程序,有几种方法:

    有两个单独的应用程序,并有一个有条件地启动另一个.

    上述策略的一个变体,有两个应用程序,一个叫做'app.com'(即只是用COM扩展名重命名控制台EXE),另一个名为'app.exe',这样命令行调用就能找到app.com第一.由于古老的DOS兼容性,.COM可执行文件在.EXE之前找到.(这在Windows中是可配置的;请参阅PATHEXT环境变量.)

    rxvt/Cygwin技术,这是我在其他任何地方都没有记录的技术.

让我详细介绍一下有关Cygwin上rxvt的工作原理.Rxvt是一个终端仿真器,通常在X Window系统上运行.由于Win32控制台的局限性,Cygwin将其打包为功能更全面的控制台,支持大量历史记录,动态调整大小,每个实例可配置字体和颜色主题,非应用程序冻结鼠标选择为了在Windows上本机运行,Cygwin附带的rxvt包含一个用于Win32的小型X11包装器库.Windows上的Rxvt实际上是一个控制台应用程序,出于与现有本机Win32可执行文件的兼容性原因,但大多数时候你从未看过控制台; 你只看到rxvt终端模拟器窗口本身.

它的工作方式具体在rxvt/W11/wrap/wrap.crxvt源代码树中,在被调用的函数中实现hideConsole().基本上,它打开它的控制台(带a CreateFile("CONOUT$" ...)),并检查光标位置是否为(0,0)(GetConsoleScreenBufferInfo()在控制台句柄上使用).

如果是,那么它会推断它已作为独立应用程序启动,而不是从控制台父应用程序启动,因此它知道操作系统已为该进程创建了专用的Win32控制台.它继续隐藏这个控制台窗口,但它必须先找到它.它用于SetConsoleTitle根据应用程序名称和当前线程ID将控制台窗口的标题设置为唯一值.然后它FindWindow用于查找此窗口的句柄(Sleep如果需要,可以定期更新几秒以更改标题,因为控制台窗口实际上完全由Windows中的不同进程控制).当它最终找到窗口句柄时,它隐藏它ShowWindowAsync,传入SW_HIDE.

使用此方法,您可以编写一个应用程序:

如果从控制台父级启动,它可以继续使用此控制台

如果作为应用程序启动,它可以选择是否隐藏控制台

唯一的缺点是在应用程序启动时非常简短的控制台窗口闪存.



1> Barry Kelly..:

对于需要在Windows上根据上下文选择是否充当控制台或GUI应用程序的应用程序,有几种方法:

    有两个单独的应用程序,并有一个有条件地启动另一个.

    上述策略的一个变体,有两个应用程序,一个叫做'app.com'(即只是用COM扩展名重命名控制台EXE),另一个名为'app.exe',这样命令行调用就能找到app.com第一.由于古老的DOS兼容性,.COM可执行文件在.EXE之前找到.(这在Windows中是可配置的;请参阅PATHEXT环境变量.)

    rxvt/Cygwin技术,这是我在其他任何地方都没有记录的技术.

让我详细介绍一下有关Cygwin上rxvt的工作原理.Rxvt是一个终端仿真器,通常在X Window系统上运行.由于Win32控制台的局限性,Cygwin将其打包为功能更全面的控制台,支持大量历史记录,动态调整大小,每个实例可配置字体和颜色主题,非应用程序冻结鼠标选择为了在Windows上本机运行,Cygwin附带的rxvt包含一个用于Win32的小型X11包装器库.Windows上的Rxvt实际上是一个控制台应用程序,出于与现有本机Win32可执行文件的兼容性原因,但大多数时候你从未看过控制台; 你只看到rxvt终端模拟器窗口本身.

它的工作方式具体在rxvt/W11/wrap/wrap.crxvt源代码树中,在被调用的函数中实现hideConsole().基本上,它打开它的控制台(带a CreateFile("CONOUT$" ...)),并检查光标位置是否为(0,0)(GetConsoleScreenBufferInfo()在控制台句柄上使用).

如果是,那么它会推断它已作为独立应用程序启动,而不是从控制台父应用程序启动,因此它知道操作系统已为该进程创建了专用的Win32控制台.它继续隐藏这个控制台窗口,但它必须先找到它.它用于SetConsoleTitle根据应用程序名称和当前线程ID将控制台窗口的标题设置为唯一值.然后它FindWindow用于查找此窗口的句柄(Sleep如果需要,可以定期更新几秒以更改标题,因为控制台窗口实际上完全由Windows中的不同进程控制).当它最终找到窗口句柄时,它隐藏它ShowWindowAsync,传入SW_HIDE.

使用此方法,您可以编写一个应用程序:

如果从控制台父级启动,它可以继续使用此控制台

如果作为应用程序启动,它可以选择是否隐藏控制台

唯一的缺点是在应用程序启动时非常简短的控制台窗口闪存.

推荐阅读
李桂平2402851397
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有