Process.Start does not work when called from windows service - c#

On Windows 8 I am running a windows service. This service is supposed to start a program by
Process.Start(exePath);
But the process exits immediately - even first line in the Main procedure is not executed. Before, when running the same process in same service on Windows 7, everything worked fine.
How can I make it work again? How to properly start a process from a windows service?

Found the solution. Process has to be started like this:
ProcessStartInfo info = new ProcessStartInfo(exePath);
info.CreateNoWindow = true;
info.UseShellExecute = false;
Process.Start(info);
For some reason there are problems with priviledges when creating a shell window in the background of the SYSTEM.

Use WaitForExit method on your Process instance will instruct to wait until the time elapsed or the process has exited.
See this MSDN link for more.

Related

Is a process started from a web form stopped when IIS shuts down the application?

I have an old web form application that spawns a process when an ImageButton is pressed:
System.Diagnostics.Process someProcess = new System.Diagnostics.Process();
someProcess.StartInfo.WorkingDirectory = "path goes here";
someProcess.StartInfo.UseShellExecute = true;
someProcess.StartInfo.FileName = "SomeProcess.exe";
someProcess.StartInfo.Arguments = "arguments goes there";
someProcess.Start();
The process has a variable duration but it is somewhat long running.
Is it possible that IIS shuts down the application before the process is completed?
The kill command will be given, it depends on the process and its settings on whether or not the kill command will actually be executed prior to work being finished.
In other words; this is something you should and can easily test yourself.

Process.Start without creating a child process (port handle inheritance)?

I have a WCF service in a self hosted application using TCP bindings. If I start an external process "commandLineApp" from the application, that continues even after my application has closed, I run into problems next time the WCF service is started by my application.
WCF says that the address/port is already in use. If I close the external application (that isn't using WCF or any sockets at all) before restarting my application, the WCF service starts just fine.
It looks like that the socket handles from my application is somehow inherited by the new process "commandLineApp", and not released until that process has exited.
How do I prevent the other process from inheriting the handles (or becoming a child process?) from my main application? Currently I'm using Process.Start to launch the other process, using UseShellExecute set to False because I need to set both EnvironmentVarables and RedirectStandardOutput/Error.
I think the child process setup is prevented if I set UseShellExecute = true, but then I don't get all features I need.
Are there any way around this problem? See example code below.
ProcessStartInfo psi = new ProcessStartInfo();
psi.FileName = "commandLineApp.exe";
psi.Arguments = "/someParameter";
psi.EnvironmentVariables.Add("...", "...");
psi.RedirectStandardOutput = true;
psi.RedirectStandardError = true;
psi.UseShellExecute = false;
Process process = new Process();
process.StartInfo = psi;
process.Start();
// Monitor if process with PID = process.Id is running
// ...
Edit - Additional information:
Doing "netstat -noa" indicates that the port is used with state LISTEN by the previous PID of the main application, but there is no process with that PID anymore. As soon as I close "commandLineApp", the port isn't listed by the netstat command anymore.
WCF services are closed like this before the main application exit:
try
{
serviceHost.Close(TimeSpan.FromSeconds(4));
}
catch (Exception)
{
serviceHost.Abort();
}
I was wrong in the above comment: SO_REUSEADDR would only apply if the handle had been closed, but it seems like socket handles truly are inherited by child processes and there is no easy way to prevent this. This seems like a very stupid design decision, particularly since some places noted that the handle can't be used in the child if any LSPs are installed.
If you had more control over the call to WSASocket, you might be able to pass the WSA_FLAG_NO_HANDLE_INHERIT flag, but this is going to be hard to accomplish inside WCF. Here's a couple other options:
Option #1: Call CreateProcess yourself and pass FALSE for bInheritHandles.
Option #2: Create a helper process before you set up WCF (or any other sockets). Communicate with it via named pipes. Start the child process from this helper instead of from the main process.

Invoke console app from windows service

I have a simple windows service which i need to use to invoke a console application.The console app generates pdf to print by opening the adobe reader window.Running the console app works fine to print pdf.But invoking it from service not successful.It doesnt even show up the console window where i log events.
Process pdfprocess = new Process();
pdfprocess.StartInfo.FileName = #"C:\Documents and Settings\xyz\Desktop\dgdfg\PdfReportGeneration\bin\Debug\PdfReportGeneration.exe";
pdfprocess.StartInfo.UseShellExecute = false;
pdfprocess.StartInfo.RedirectStandardOutput = true;
pdfprocess.Start();
But invoking other application like
pdfprocess.StartInfo.FileName = #"C:\Program Files\Adobe\Reader 11.0\Reader\AcroRd32.exe";
works fine.
What will be the reason?
There is probably some permissions issue there (PdfReportGeneration.exe inaccessible under service account or maybe something that it uses...)
I would advise to capture Process Monitor log to see where exactly it fails.
Windows services run in a different window station and cannot interact with the desktop, unless you're using an older version of Windows and tick a checkbox in the service properties in the service manager.

How to call buggy .dll in new process?

I have a c# windows service application that is crashing without throwing an exception when processing certain files using a third-party .dll. What I decided to do was create a new console application which replicates a small portion of the windows service code, particularly the part the causes the service to crash. What I want to do is call the new .exe program from the windows service, and if it crashes, I throw an exception myself.
So, I need to call this .exe program (not in the background as I can't allow the windows service to continue until I know the file to be processed is safe), and then determine if it exited successfully or not. How do I go about doing this? The examples I've seen run the .exe in a background process which is not what I want.
Thanks.
Look at this SO answer how to run console application from windows service. Just add WaitForExit, like this :
ProcessStartInfo info = new ProcessStartInfo(#"c:\myprogram.exe");
info.UseShellExecute = false;
info.RedirectStandardError = true;
info.RedirectStandardInput = true;
info.RedirectStandardOutput = true;
info.CreateNoWindow = true;
info.ErrorDialog = false;
info.WindowStyle = ProcessWindowStyle.Hidden;
Process process = Process.Start(info);
process.WaitForExit();
In console application you can set exit code if you exit with Environment.Exit(statusCode) or return int value from main function of console applicaiton. Or you can write to output and then in your service examine exit code (process.ExitCode) or output stream so you can determine is process was exited successfully.

Process.Start() not spawning new process under the same user

I was always under the impression that when you're running a process as (domain\user) mydomain\myuser, when using Process.Start() it would start this new process using the same credentials - mydomain\myuser.
The issue I'm having is that my Process.Start() call seems to be creating a process under the SYSTEM account which is causing me permission issues in the started process (which must run under an admin account due to the work it does). If it changes things - I'm spawning this process (a custom built exe) from within a windows installer.
Any suggestions? I've read about windows group policies (possibly) having an impact on this, but if I'm honest, it's lost on me.
EDIT: a little snippet:
Where exename and commandLine are parameters for this method body:
ProcessStartInfo procInfo = new ProcessStartInfo(exeName, commandLine);
procInfo.WorkingDirectory = workingDirectory;
procInfo.UseShellExecute = false;
procInfo.CreateNoWindow = true;
Process process = Process.Start(procInfo);
Process.WaitForExit();
return process.ExitCode;
Either set procInfo.UseShellExecute to true, or execute cmd as a process with your exe as a parameter to the cmd command. When UseShellExecute is set to false, here are a lot of interesting side effects: UseShellExecute
Your impression is true. Process.Start() will always start the new process under current user's credentials - unless you provide alternative credentials in the ProcessStartInfo or use one of the overloads that take credentials.
There must be another problem - share a snippet of your code.
UPDATE
OK! You did not mention anything about installer. All MSI installers will be running under system since they will be run by "Windows Installer" which you can check and they run under SYSTEM.

Categories