【问题标题】:Detect whether an application is displaying its own console window or running in another one检测应用程序是显示自己的控制台窗口还是在另一个控制台窗口中运行
【发布时间】:2014-04-09 16:06:23
【问题描述】:

我想检测我的应用程序是显示自己的控制台窗口还是在另一个控制台中运行(例如,作为批处理文件的一部分)。我知道这可能发生的两种方式是从资源管理器启动应用程序或从 Visual Studio 执行应用程序。

我想这样做的原因是,如果应用程序显示了自己的窗口,我可以让应用程序在运行后暂停,否则它可能是批处理脚本的一部分,它应该干净地退出。

这可能吗?

【问题讨论】:

  • 检查父进程。当从批处理文件(或控制台窗口)执行时,它将 cmd.exe 作为父级,但从 shell 运行时不会。顺便说一句,当来自 VS IMO VS 负责保持该窗口打开时,应用程序本身并不知道这一点。
  • VS 不会让父窗口保持打开状态(根据我对 2005 和 2008 版本的经验)。
  • VS 只会在不调试 (Ctrl+F5) 时保持父窗口打开。当您调试 (F5) 时,它会在没有您自己的处理代码后立即关闭。

标签: c# console-application


【解决方案1】:

通常,执行此操作的正确方法是允许将标志作为参数接收,通知程序应该在“安静模式”下运行。这样,批处理文件将使用该参数(例如“myprogram.exe /Q”)调用它,并且它将运行并退出而不会暂停。如果只是双击,则该参数不存在,正常运行。

【讨论】:

  • 这可行,但我希望程序在大多数情况下默认“做正确的事”。无论如何,我最终可能会添加一个像 --pause={yes,no,error} 这样的选项。
【解决方案2】:

要扩展 Adrianos 评论,是的,可以通过检查父进程来实现。您将需要根据父母进行一些启发式方法,我认为可能存在不准确的情况。此代码查看父进程:

    static void Main(string[] args)
    {
        Process p = Process.GetCurrentProcess();
        ParentProcessUtilities pInfo = new ParentProcessUtilities();
        int l;
        int error = NtQueryInformationProcess(p.Handle, 0, ref pInfo, Marshal.SizeOf(typeof(ParentProcessUtilities)), out l);
        if (error == 0)
        {
            var parent = Process.GetProcessById(pInfo.InheritedFromUniqueProcessId.ToInt32());
            Console.WriteLine("My parent is: {0}", parent.ProcessName);
        }
        else
        {
            Console.WriteLine("Error occured: {0:X}", error);
        }
        Console.ReadKey();
    }


    [DllImport("ntdll.dll")]
    private static extern int NtQueryInformationProcess(IntPtr processHandle, int processInformationClass, ref ParentProcessUtilities processInformation, int processInformationLength, out int returnLength);

}

[StructLayout(LayoutKind.Sequential)]
public struct ParentProcessUtilities
{
    // These members must match PROCESS_BASIC_INFORMATION
    internal IntPtr Reserved1;
    internal IntPtr PebBaseAddress;
    internal IntPtr Reserved2_0;
    internal IntPtr Reserved2_1;
    internal IntPtr UniqueProcessId;
    internal IntPtr InheritedFromUniqueProcessId;
}

根据我的测试,父进程是:

  • 在 VS 调试中运行时的 devenv.exe
  • 无调试运行时的cmd
  • 从命令提示符运行时的 cmd
  • powershell(如果从 PowerShell 调用)
  • 在 Windows 资源管理器中双击时的资源管理器

您可以想象,除了我提到的那些之外,另一个进程可能会以其他方式调用您的程序,您需要在代码中处理这些问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-04-04
    • 1970-01-01
    • 1970-01-01
    • 2010-10-22
    • 2019-01-18
    • 1970-01-01
    • 2017-09-09
    • 2011-04-20
    相关资源
    最近更新 更多