Cannot run a command process from a Windows Service

G

Guest

Hi,

This problem has been frustrating me for days and I hope you experts can
help me out. I am trying to run a command, which I would normally run from
the command line, from within my C# application. The command runs
successfully from a Windows Form but fails if the application is recasted as
a Windows service. The application is essentially a File Watcher that should
run the process when a file is dropped into a specific directory.

Here is the code:

private void FileMonitor_Changed(object sender,
System.IO.FileSystemEventArgs e)
{
string ChangeType = e.ChangeType.ToString();
string renamed = e.FullPath;
System.Diagnostics.Process process1;
process1= new System.Diagnostics.Process();
process1.EnableRaisingEvents = false;
string strCmdLine;
strCmdLine = "/K Dumper.exe \"" + renamed + "\"";
Thread.Sleep(4000);
IDictionary environmentVariables = Environment.GetEnvironmentVariables();
process1.StartInfo.EnvironmentVariables.Clear();
foreach (DictionaryEntry de in environmentVariables)
{
// EventLog.WriteEntry("Directory Monitor", " KeyValue: " + de.Key +
de.Value);
process1.StartInfo.EnvironmentVariables.Add((string)de.Key,
(string)de.Value);
}
process1.StartInfo.WorkingDirectory = "C:\\Temp";
process1.StartInfo.FileName = "CMD.exe";
process1.StartInfo.Arguments = strCmdLine;
process1.StartInfo.UseShellExecute = false;
process1.StartInfo.RedirectStandardOutput = true;
process1.StartInfo.RedirectStandardError = true;
process1.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
process1.StartInfo.CreateNoWindow = true;
process1.Start();
StreamReader myStreamReader = process1.StandardOutput;
StreamReader myStreamError = process1.StandardError;
string myID = myStreamReader.ReadLine();
string stdError = myStreamError.ReadLine();
process1.Close();
EventLog.WriteEntry("Directory Monitor", "myID: " + myID);
EventLog.WriteEntry("Directory Monitor", "stdError: " + stdError);
}

The event log reports the following error:

stdError: 'Dumper.exe' is not recognized as an internal or external command

Configuring the service so that it can interact with the desktop doesn't
help.

Any ideas why my application can't find the command? Perhaps I have not set
up the environment variables correctly?

Many thanks in advance and happy holidays!
 
M

mphanke

Hi,

have you tried to call the dumper.exe with the full path? I believe
there are no ENV-Vars set for services... This might solve your problem.

Martin
 
W

Willy Denoyette [MVP]

Primo said:
Hi,

This problem has been frustrating me for days and I hope you experts can
help me out. I am trying to run a command, which I would normally run from
the command line, from within my C# application. The command runs
successfully from a Windows Form but fails if the application is recasted
as
a Windows service. The application is essentially a File Watcher that
should
run the process when a file is dropped into a specific directory.

Here is the code:

private void FileMonitor_Changed(object sender,
System.IO.FileSystemEventArgs e)
{
string ChangeType = e.ChangeType.ToString();
string renamed = e.FullPath;
System.Diagnostics.Process process1;
process1= new System.Diagnostics.Process();
process1.EnableRaisingEvents = false;
string strCmdLine;
strCmdLine = "/K Dumper.exe \"" + renamed + "\"";
Thread.Sleep(4000);
IDictionary environmentVariables =
Environment.GetEnvironmentVariables();
process1.StartInfo.EnvironmentVariables.Clear();
foreach (DictionaryEntry de in environmentVariables)
{
// EventLog.WriteEntry("Directory Monitor", " KeyValue: " + de.Key +
de.Value);
process1.StartInfo.EnvironmentVariables.Add((string)de.Key,
(string)de.Value);
}
process1.StartInfo.WorkingDirectory = "C:\\Temp";
process1.StartInfo.FileName = "CMD.exe";
process1.StartInfo.Arguments = strCmdLine;
process1.StartInfo.UseShellExecute = false;
process1.StartInfo.RedirectStandardOutput = true;
process1.StartInfo.RedirectStandardError = true;
process1.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
process1.StartInfo.CreateNoWindow = true;
process1.Start();
StreamReader myStreamReader = process1.StandardOutput;
StreamReader myStreamError = process1.StandardError;
string myID = myStreamReader.ReadLine();
string stdError = myStreamError.ReadLine();
process1.Close();
EventLog.WriteEntry("Directory Monitor", "myID: " + myID);
EventLog.WriteEntry("Directory Monitor", "stdError: " + stdError);
}

The event log reports the following error:

stdError: 'Dumper.exe' is not recognized as an internal or external
command

Configuring the service so that it can interact with the desktop doesn't
help.

Any ideas why my application can't find the command? Perhaps I have not
set
up the environment variables correctly?

Many thanks in advance and happy holidays!

Windows services are designed to run as self contained background processes,
that is:
- they preferably run in a security context of a restricted service account
("localservice", "network service" or "local system")
Solution: run as a non service account.
- they are meant to run in an unattended non-interactive mode (don't assume
the presence of an interactive logon session),That means that certain
windows resources such as OLE embedded objects, and the clipboard are
unavailable.
Solution: Run with "Interact with desktop" privilege enabled.
- they have no access to the logon user profile nor do they have access to
HKCU (if any), That means that printers, mapped drives, or any other
networked resources may not be available.
Solution: explicitly load the user profile using the Win32 "LoadUserProfile"
API. Note that you need to create a logon session (call LogonUser) for the
user before you can load the user's profile.
- they have their own environment block associated with the process.
[This is exactly your problem; dumper.exe is not in the "path" environment.
So maybe you can move forward by specifying the full path.]
Solution: call Win32 "CreateEnvironmentBlock" API. Note that you need to
create a logon session (LogonUser) for the user and load the user's profile
(LoadUserProfile)before you can retrieve the user's environment.
- they are not meant to execute external processes that need to break-out of
this secured context.
Solution: Run in an interactive desktop/winstation, create a new logon
session, load user profile and environment before creating the child process
using Win32 "CreateProcessAs" API . (But ask yourself why you run this as a
service!).

Above is a non-restricted list of possible issues and "solutions", however,
I would not recommended these as they all result in a security breach,
therefore I suggest you to find an alternative for a windows service.

Willy.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top