检测应用程序是显示自己的控制台窗口还是在另一个窗口中运行

时间:2014-04-09 16:06:24

标签: c# console-application

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

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

这可能吗?

2 个答案:

答案 0 :(得分:3)

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

答案 1 :(得分: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资源管理器中双击的资源管理器

你可以想象,除了我提到的那些之外,还有其他方法可以调用你的程序,你将需要在你的代码中处理它。