编辑:我已经创建了一个问题的工作概念验证。见here
我需要以非交互方式运行一个进程,作为使用C#的Windows服务中的另一个用户。我的代码如下所示:
var process = new Process
{
EnableRaisingEvents = true,
StartInfo =
{
FileName = /* process name */,
Arguments = /* arguments */,
Domain = /* domain */,
UserName = /* username */,
Password = /* password */,
CreateNoWindow = true,
RedirectStandardError = true,
RedirectStandardInput = true,
RedirectStandardOutput = true,
UseShellExecute = false
}
};
var error = new StringBuilder();
var errorWaitHandle = new ManualResetEventSlim();
process.ErrorDataReceived += (s, e) =>
{
if (e.Data != null)
{
error.AppendLine(e.Data);
}
else
{
errorWaitHandle.Set();
}
};
var output = new StringBuilder();
var outputWaitHandle = new ManualResetEventSlim();
process.OutputDataReceived += (s, e) =>
{
if (e.Data == /* detect that it's time to write to the input */)
{
process.StandardInput.Write(/* write to the input something that will give an output and exit the process */);
process.StandardInput.Close();
}
else if (e.Data != null)
{
output.AppendLine(e.Data);
}
else
{
outputWaitHandle.Set();
}
};
process.Exited += (s, e) =>
{
try
{
errorWaitHandle.Wait();
outputWaitHandle.Wait();
if (error.Length == 0)
{
// Do something with 'output.ToString()'.
}
else
{
// Do something with 'error.ToString()'.
}
}
finally
{
process.Dispose();
}
};
process.Start();
process.BeginErrorReadLine();
process.BeginOutputReadLine();
当我从控制台应用程序运行它时,它运行没有任何问题。但是,当我从Windows服务运行它时:
如果Windows服务正在以LOCAL_SYSTEM
运行Process.Start()
方法抛出异常。如果Windows服务作为另一个帐户运行:
ErrorDataReceived
事件会立即收到空数据。OutputDataReceived
事件会立即收到空数据。如果我删除这些行:
FileName = /* process name */,
Arguments = /* arguments */,
Domain = /* domain */,
在具有LOCAL_SYSTEM
个其他帐户的Windows服务上,代码运行时没有任何问题。
经过大量的挖掘后,我学会了以下内容:
Process.Start()
时,将使用CreateProcess
进程创建标志调用Win32 CREATE_NO_WINDOW
方法。由于没有创建窗口,因此该过程可以在Windows服务下运行。Process.Start()
时,将调用Win32 CreateProcessWithLogonW
方法。由于此方法不支持CREATE_NO_WINDOW
进程创建标志,因此始终会创建一个窗口,因此该进程无法在Windows服务下运行。理论上,有一个Win32 CreateProcessAsUser
方法支持Win32 CreateProcess
方法功能,并添加了以另一个用户身份运行它。
CreateProcessAsUser
方法是否真正解决了这个问题?System.Diagnostics.Process
类提供的功能相同(例如标准输入,输出,错误重定向等)。