我正在编写一个实用程序(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.c
rxvt源代码树中,在被调用的函数中实现hideConsole()
.基本上,它打开它的控制台(带a CreateFile("CONOUT$" ...)
),并检查光标位置是否为(0,0)(GetConsoleScreenBufferInfo()
在控制台句柄上使用).
如果是,那么它会推断它已作为独立应用程序启动,而不是从控制台父应用程序启动,因此它知道操作系统已为该进程创建了专用的Win32控制台.它继续隐藏这个控制台窗口,但它必须先找到它.它用于SetConsoleTitle
根据应用程序名称和当前线程ID将控制台窗口的标题设置为唯一值.然后它FindWindow
用于查找此窗口的句柄(Sleep
如果需要,可以定期更新几秒以更改标题,因为控制台窗口实际上完全由Windows中的不同进程控制).当它最终找到窗口句柄时,它隐藏它ShowWindowAsync
,传入SW_HIDE
.
使用此方法,您可以编写一个应用程序:
如果从控制台父级启动,它可以继续使用此控制台
如果作为应用程序启动,它可以选择是否隐藏控制台
唯一的缺点是在应用程序启动时非常简短的控制台窗口闪存.
对于需要在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.c
rxvt源代码树中,在被调用的函数中实现hideConsole()
.基本上,它打开它的控制台(带a CreateFile("CONOUT$" ...)
),并检查光标位置是否为(0,0)(GetConsoleScreenBufferInfo()
在控制台句柄上使用).
如果是,那么它会推断它已作为独立应用程序启动,而不是从控制台父应用程序启动,因此它知道操作系统已为该进程创建了专用的Win32控制台.它继续隐藏这个控制台窗口,但它必须先找到它.它用于SetConsoleTitle
根据应用程序名称和当前线程ID将控制台窗口的标题设置为唯一值.然后它FindWindow
用于查找此窗口的句柄(Sleep
如果需要,可以定期更新几秒以更改标题,因为控制台窗口实际上完全由Windows中的不同进程控制).当它最终找到窗口句柄时,它隐藏它ShowWindowAsync
,传入SW_HIDE
.
使用此方法,您可以编写一个应用程序:
如果从控制台父级启动,它可以继续使用此控制台
如果作为应用程序启动,它可以选择是否隐藏控制台
唯一的缺点是在应用程序启动时非常简短的控制台窗口闪存.