We Are All Monica
We Are All Monica

Reputation: 13334

Detect whether an application is displaying its own console window or running in another one

I'd like to detect whether my application is displaying its own console window or running in another console (for example, as part of a batch file). The two ways I know of that this could happen are when the application is launched from Explorer or when it is executed from Visual Studio.

The reason I want to do this is so that I can make the application pause after running if it has displayed its own window, otherwise it is probably part of a batch script and it should exit cleanly.

Is this possible?

Upvotes: 3

Views: 143

Answers (2)

driis
driis

Reputation: 164291

To expand on Adrianos comment, yes, it is possible by checking the parent process. You will need to do some heuristics based on the parent, and I think there might be cases where it is inaccurate. This code looks at the parent process:

    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;
}

Based on my testing, the parent process is:

  • devenv.exe when running in Debug from VS
  • cmd when running without debugging
  • cmd when running from command prompt
  • powershell if invoked from PowerShell
  • Explorer if double-clicked in Windows explorer

As you can imagine, there will be other ways another process could have invoked your program, other than those I have mentioned, and you will need to take care of that in your code.

Upvotes: 2

Louis Ingenthron
Louis Ingenthron

Reputation: 1368

Normally, the correct way to do this is to allow a flag to be taken in as a parameter that informs the program it should operate in "Quiet Mode". That way the batch file would call it with that parameter (e.g. "myprogram.exe /Q") and it would run and exit without pause. If it was just double-clicked, that parameter would not be there and it would run normally.

Upvotes: 3

Related Questions