barlop
barlop

Reputation: 13790

C# I can't get CreateNoWindow to work - not even the msdn.com example

I have looked here

https://msdn.microsoft.com/en-us/library/system.diagnostics.processstartinfo.createnowindow(v=vs.110).aspx

And I understand that

A) Not every program respects a CreateNoWindow request and

B) It requires UseShellExecute=False (default is true).

C) It is meant to indicate whether a window is created. (it won't ever hide the parent window). It's speaking of whether a window is created for the child process. (msdn says 'new window')

D) CreateNoWindow defaults to false.

I am running this from cmd, though clicking play in visual studio illustrates the same behaviour.

I set CreateNoWindow to false so i'd have thought it'd create a new window for the child process.

But it does not.

task manager shows the second instance of cmd.exe but there's still the one window as you can see. Below is the paste from one window. It has loaded the child cmd.exe in the parent window (the one cmd window)

Whether I set CreateNoWindow to true, or to false, it seems to make no difference.

So i'm clearly not getting the example at that msdn link to work.

C:\crp>type aaa.csc
using System.Diagnostics;

class blah{
   public static void Main(string[] args) {
          Process p = new Process();
          ProcessStartInfo psi = new ProcessStartInfo();
          psi.UseShellExecute=false; 
          psi.FileName="cmd.exe";
          psi.CreateNoWindow=false;
          p.StartInfo=psi;
          p.Start();
   }
}
C:\crp>csc aaa.csc
Microsoft (R) Visual C# Compiler version 4.0.30319.34209
for Microsoft (R) .NET Framework 4.5
Copyright (C) Microsoft Corporation. All rights reserved.


C:\crp>aaa.exe

C:\crp>Microsoft Windows [Version 6.1.7601]
Copyright (c) 2009 Microsoft Corporation.  All rights reserved.

C:\crp>

UPDATE

It seems it does work. If you open a cmd prompt and run the exe, then in one case it starts cmd.exe within the parent. In the other case it starts a cmd.exe without any window. The behaviour within visual studio seems odd though, see my comment to ephraim's answer. In this question while within visual studio, i'd only tried it with the project set to being a console application, and there a cmd prompt window will always at least flick up. Behaviour is much simpler for a non console application e.g. a winforms application.

Upvotes: 3

Views: 4865

Answers (4)

Demilitarized Zone
Demilitarized Zone

Reputation: 319

I have finally found the answer by correctly understanding CreateNoWindow. CreateNoWindow is about creating a parent window which will cover the target application main window.

CreateNoWindow = false;

=> This will cause Process to create a parent window to hold the target app window, not about creating app window

WindowStyle = ProcessWindowStyle.Hidden;

=> This will hide the parent window created by Process, not the app window style

        using (Process process = new Process())
        {
            process.StartInfo.FileName = @"notepad";
            process.StartInfo.CreateNoWindow = false;
            process.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
            process.Start();
        }

Upvotes: 4

barlop
barlop

Reputation: 13790

It makes most sense to first try from a cmd.exe

then from there understand the behaviour when running from visual studio

The word new in CreateNoNewWindow, is a bit misleading. It's more like it creates no window and even uses no window.

If you have CreateNoNewWindow=false (the default), then it will run that child cmd in the parent window. (that may seem strange but if you compare it to what happens when CreateNoNewWindow=true then it's not so strange). When you run the program you'll see it says the cmd banner with Copyright e.t.c. that's from the child cmd running in the parent window.

If you have CreateNoNewWindow=true and you run your program then it will output nothing. Task manager will still show the second cmd.exe that is because it is running the child cmd.exe but not in any cmd window at all.

Now for the behaviour within visual studio.

With Visual studio console applications when you click play, visual studio will pop up its cmd window which disappears once the program has completed, but any spawned processes would live on.

With visual studio, If you have CreateNoNewWindow set to true (i.e. use no window at all), then it will pop up its cmd window, spawn the second cmd in no window, so it's invisible, then the parent cmd window will close and the spawned child cmd.exe will continue to show in task manager but will have no window. So task manager will show one cmd.exe, and you'll see no window.

As a test before testing the paragraph below, you can create a cmd window, sdfsdfds so you have something in command history accessible with up arrow so you can see whether you're in the parenet command or not. Then start a child process. type cmd<ENTER>. Now kill the parent. The child is still there.

With visual studio, if you have CreateNoNewWindow set to false(i.e. use the parent window), (this, as we have seen, is possible even after a parent process has been killed, if the child was created and using that window, before the parent was killed) then click play, then visual studio will flick up its cmd window as it does, and it will spawn a child cmd.exe process and task manager only shows one cmd.exe process but in a window, and the play button shows as active again, so the program must have completed execution, and the parent process was completed. So visual studio closed the parent cmd.exe but the child is still there still using the parent's window as it was prior to the parent cmd.exe being completed.

That's for when a visual studio project is set to console application, where a console will always at least flick up.

But for a project that isn't created as a console application e.g. for a winforms application, the console can be set to hide, and no console would flick up or need to be run at all even for the main program.

Note here- UseShellExecute and CreateNoWindow are being set to their non default values. UseShellExecute is by default true, and we set it to false because when UseShellExecute is true then CreateNoWindow ignores the value of itself(CreateNoWindow), and a new window is created(even if CreateNoWindow is set to true). CreateNoWindow is by default false, and we set it to true. If you are going to use CreateNoWindow, then the only non superfluous and working use case would be UseShellExecute=false and CreateNoWindow=true. (If UseShellExecute=true(default) then you should use process window style hidden.. ) Also bear in mind these things work for cmd.exe but fail for some other things like calc.exe

ProcessStartInfo psi = new ProcessStartInfo();
psi.FileName = "cmd.exe";
psi.UseShellExecute = false;
psi.CreateNoWindow = true;
Process.Start(psi);

Upvotes: 0

Steve Wellens
Steve Wellens

Reputation: 20640

I set UseShellExecute=True; ....and it seems to work.

Odd, without that line, you have to type exit twice, once to 'close' the child cmd.exe (which doesn't really close the window) and once to close the parent cmd.exe.

Upvotes: 0

jegtugado
jegtugado

Reputation: 5141

Try this out using Visual Studio and define the pull file path for the cmd.exe

public static void Main(string[] args) {
    try 
    {
      ProcessStartInfo psi = new ProcessStartInfo();
      psi.FileName = "C:\\Windows\\System32\\cmd.exe"; // full path
      psi.CreateNoWindow = true; 
      psi.UseShellExecute = false;
      Process childProcess = Process.Start(psi); // child process
      // This code assumes the process you are starting will terminate itself. 
      // Given that is is started without a window so you cannot terminate it 
      // on the desktop, it must terminate itself or you can do it programmatically
      // from this application using the Kill method.
    }
    catch(Exception ex)
    {
        Console.WriteLine(e.Message);
    }
}

Upvotes: 0

Related Questions