3

I have a little console application which outputs a single line. When I run the program from within a console instance I am able to see the result because the command pormpt reappers after completion of the program. But when I start the program from the "Run"-window ([Win]+[R]) the console window instantly disappears (because I have not built in a break and i don't want to build in a break unless it isn't launched by the commandline).

So how can I determine if the program was started from a command line or directly?

LostPhysx
  • 3,573
  • 8
  • 43
  • 73
  • 4
    You can just put `Console.ReadLine();` at the end of your program so you can read the output regardless of how it was run. It will pause the program until you hit Enter one more time. – Bill the Lizard Mar 28 '16 at 22:25
  • 4
    which is unnecessary and annoying, when you launch it from the commandline – LostPhysx Mar 28 '16 at 22:33
  • Try looking at [this SO Question](http://stackoverflow.com/questions/17508093/determine-if-program-is-run-from-cmd-or-from-explorer) – Icemanind Mar 28 '16 at 23:02

2 Answers2

4

I don't think there a built-in way to find this out. However I think you could look up the parent process and use that as fairly good heuristic. A quick test shows that the parent process is "explorer" when started from Run (Win+R) or double clicking. It would probably be cmd or powershell any other time except when debugging in VS, then devenv will be the parent process. Obviously, if there are scenarios where other tools will start an instance of the process you may want to give a command line parameter to force a particular behavior.

You code would look something like this:

// Note: Adapted from Hans Passant's answer linked above.
private static string GetParentProcessName() 
{
    var myId = Process.GetCurrentProcess().Id;
    var query = string.Format("SELECT ParentProcessId FROM Win32_Process WHERE ProcessId = {0}", myId);
    var search = new ManagementObjectSearcher("root\\CIMV2", query);
    var queryObj = search.Get().OfType<ManagementBaseObject>().FirstOrDefault();
    if (queryObj == null)
    {
        return null;
    }
    var parentId = (uint)queryObj["ParentProcessId"];
    var parent = Process.GetProcessById((int)parentId);
    return parent.ProcessName;
}

static void Main() 
{
    /*
       Program code here.
    */
    if (string.Equals(GetParentProcessName(), "explorer", StringComparison.InvariantCultureIgnoreCase)) 
    {
        Console.ReadLine();
    }
}
Community
  • 1
  • 1
Mike Zboray
  • 39,828
  • 3
  • 90
  • 122
  • This is just what I was looking for, but I'm using !...,"cmd",... to match anything except cmd. Thanks alot – LostPhysx Mar 29 '16 at 00:18
2

I don't think there is any way to programmatically determine how the console application was started.

If you want the application to behave differently in these different situations then I would suggest using arguments e.g.

MyApp.exe /keepopen

code:

static int Main(string[] args)
{
    // Test if argument was supplied:
    if (args.Any(a => a == "/keepopen"))
    {
        System.Console.ReadLine();
    }
}

If you want the console to stay open when running from Visual Studio I believe you can use Ctrl-F5 to start without debugging.

Glen Thomas
  • 10,190
  • 5
  • 33
  • 65