tags:

views:

835

answers:

11

There is any command line or .NET method that runs a process in the background hiding any window it tries to open?

Already tried:

 var process = new Process()
 {
      StartInfo = new ProcessStartInfo()
      {
          CreateNoWindow = true,
          WindowStyle = ProcessWindowStyle.Hidden,
          FileName = TheRealExecutableFileNameHere
      }
 }
 process.Start();

With no success so far

+1  A: 

It depends on whether you want to start the application minimized, but allow it to interact with the user if required, or if you want to prohibit all access with the user regardless of what happens.

If the latter, you could run the process under a different desktop context to the current user.

Different Desktop contexts are used, for example, by the Login dialog and by Vista UAC - anything that happens in one desktop context is independent of others.

Might be a sledgehammer approach to your problem though.

Bevan
I want to prohibit all access with the user regardless of what happens.
Jader Dias
I couldn't find an article about "desktop context in .net", can you help me find it?
Jader Dias
I was't able to find the exact page that I wanted, but did find a page that talks about some of the standard desktops that are normally present. Start here (http://msdn.microsoft.com/en-us/library/aa375994(VS.85).aspx) and look around, you should find what you need.
Bevan
I tried to run the process as another user, but it didn't solve the problem
Jader Dias
A: 

I assume you want a process that is not visible to users while running.

You can try the following to see whether this is what you want.

  1. Create a simple console app that keeps running (and launch it to test).
  2. Right click on Project --> Properties --> Application tab --> Output type --> Change it from "Console Application" to Windows Application.
  3. Launch the same app one more time (to see whether this is what you want).
  4. Close the app via Windows Task Manager :)

It seems that the process appears in Task Manager, yet, is not visible in the task bar. Alt+TAB cannot bring this process up.

I just hope that you are not making any malicious app, though :)

Chansik Im
Thanks, but it will not work for me, since the application is not a console application. Matlab is not malicious.
Jader Dias
+3  A: 

I reviewed my code and it looks nearly identical to yours:

ProcessStartInfo psi = new ProcessStartInfo(fileName, arguments)
{
   CreateNoWindow = true,
   WindowStyle = ProcessWindowStyle.Hidden,
   UseShellExecute = false,
   RedirectStandardOutput = true                                               
};

Process process = Process.Start(psi);

The only notable difference (other than formatting and which PSI constructor we chose) is my use of UseShellExecute and RedirectStandardOutput as I needed to read the result of the ran process.

I have found the code above consistently runs a hidden process on XP and Vista. I have also found, however, and you may be experiencing the same, that a hidden process may kick off another process which by default isn't hidden. In other words, if you start hidden Process A and Process A, in turn, kicks off Process B, you have no control as to how Process B will be displayed. Windows which you have no control over may be displayed.

I hope this helps a little. Good luck.

Ben Griswold
Damn! Good try, but matlab is very persistent... It didn't work
Jader Dias
Sorry. That's the best I've got. I'm looking forward to seeing the resolution.
Ben Griswold
+7  A: 

Check out the Matlab Engine.

There's even an interesting article on CodeProject, if this approach fits your needs.

kek444
+1 Besides not answering the title question, it is the best solution for my problem. I should give up doing the wrong way.
Jader Dias
Other than this, I've seen people use WinAPI FindWindow and SendMessage with CS_MINIMIZE or something like that, in case you really want to try it out.
kek444
A way to run a process in the background is ... to use a matlab engine. ... I must be missing something.
modosansreves
@modosansreves: Check the entire thread and comments, it boils down to matlab actually in this case.
kek444
@jader dias: unless i'm missing something, shouldn't you be "accepting" this answer, since you find it the best answer so far?
Liao
+3  A: 

There is no I do not know a pure .Net way to achieve this.

Then I thought about kernel Job Objects, but found no similar option in UI restrictions.

So, the next (yet unverified) idea is to create than process suspended, create a windows hook then, which will monitor CallWndProc and filter out WM_SHOW messages. (Then, surely, resume the process, wait in a separate thread till it terminates, remove the hook)

modosansreves
+2  A: 

You may want to try the BackgroundWorker Class in the .Net Framework if you haven't already. It's for executing long running processes on a separate thread to prevent them from impeding the UI. Give it a look.

CertifiedCrazy
+1: I wanted to say the same thing
Timotei Dolean
+3  A: 

Have you tried using the Microsoft DOS start command with the /B switch?

Microsoft DOS start command

For example,

START /B cmd.exe
Mark Good
A: 

I think what you might want to try is to create a new Windows Station. Check out this article that explains a bit about them on msdn.

http://msdn.microsoft.com/en-us/library/ms681928(VS.85).aspx

Matt
A: 

I noticed that if CreateNoWindow = false does absolutely nothing when the Filename is pointing to a Windows executable, if you have access to the source code of the winform app then you might be able to provide a command line argument which controls the default visibility of the form, and do something like this in the Winform App startup code:

static void Main(string[] args)
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        Form1 form1 = new Form1();

        form1.Load += new EventHandler((s,o) =>
            {
              //check if the form should be shown based on command line arg
                if (args.Contains("dontShowWindow"))
                {
                    //hide it
                    form1.ShowInTaskbar = false;
                    form1.Visible = form1.ShowInTaskbar = false;
                }
            }
        );
        Application.Run(form1);
    }

In you calling code, you can now specify "dontShowWindow" as a process Argument:

 ProcessStartInfo info = new ProcessStartInfo
        {
            CreateNoWindow = false, 
            WindowStyle = ProcessWindowStyle.Hidden,
            UseShellExecute = false, 
            FileName = @"C:\temp\testWinForm.exe",
            Arguments = "dontShowWindow"
        };
        Process.Start(info);

Hope this helps

Abhijeet Patel
answered your comment in the question comments
Jader Dias
A: 

One very simply way to achieve this is to create a Service Account and run the executable under the context of the Service Account user via the Windows Task Scheduler.

You could use this CodeProject to setup the scheduled task:

http://www.codeproject.com/KB/cs/tsnewlib.aspx

You could create the service account programatically in the Domain or local machine very easily with C#.

http://www.codeproject.com/KB/system/OSUserMangement.aspx http://support.microsoft.com/kb/306273

Processes running as scheduled tasks in the context of another user do not appear interactively unless that user is logged in; hence the use of a service account.

Nissan Fan
+1  A: 

I realize this has been answered but you could force a window to hide with unmanaged calls to FindWindow and ShowWindow.

[DllImport("user32.dll")]
public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);

[DllImport("user32.dll")]
static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);

psi = new ProcessStartInfo(); // etc..
some_process = Process.Start(psi);
System.Threading.Thread.Sleep(50); // need give the window a chance to be created
IntPtr hWnd = FindWindow(null, "name of the window");
if (hWnd != IntPtr.Zero) ShowWindow(hWnd, 0); // 0 = SW_HIDE

Rather kludgy.

Mark
+1. I think that's a really simple and effective solution, but I don't need to Sleep(50) since some_process.WaitToEnd() will do.
Jader Dias