我有.net Windows服务作为本地系统运行。我有另一个.net进程需要等待服务终止。该进程不知道服务名称,因此无法查询服务控制管理器。它确实知道服务进程Id。我可以修改Windows服务和其他进程的源。
当我这样做时:
process = Process.GetProcessById(processId);
process.WaitForExit();
来自另一个过程,我得到了:
System.ComponentModel.Win32Exception: Access is denied
Stack trace:
at System.Diagnostics.Process.GetProcessHandle(Int32 access, Boolean throwIfExited)
at System.Diagnostics.Process.WaitForExit(Int32 milliseconds)
GetProcessHandle调用OpenProcess。显然,目标进程应该允许SYNCHRONIZE bit以上工作,理论上可以通过SetSecurityInfo从Windows服务设置。然而,似乎没有一种简单的方法可以在.NET中执行此操作,而不是调用几个pinvoke来提升,启用权限并最终更改安全性。
我是否忽略了从用户进程等待另一个(系统)进程的简单方法?
答案 0 :(得分:0)
尝试使用相同的用户帐户启动服务和程序,或使用内置管理员帐户运行程序(Windows Vista及之后)。
如果仍然抛出异常,请尝试设置计算机的DEP(数据执行保护)设置。
<强>更新强> 也许你可以使用这个愚蠢的代码..获取服务名称很麻烦,因为它可能与Process.Name不同。
static ServiceController GetServiceControllerByPId(int processId)
{
string serviceName = "";
string qry = "SELECT NAME FROM WIN32_SERVICE WHERE PROCESSID = " + processId.ToString();
System.Management.ManagementObjectSearcher searcher = new System.Management.ManagementObjectSearcher(qry);
System.Management.ManagementObjectCollection mngntObjs = searcher.Get();
foreach (System.Management.ManagementObject mngntObj in mngntObjs)
{
serviceName = (string)mngntObj["NAME"];
}
if (serviceName == "")
{
return null;
}
return System.ServiceProcess.ServiceController.GetServices().FirstOrDefault(x => x.ServiceName == serviceName);
}
调用此函数,并监视ServiceController.Status
答案 1 :(得分:0)
如果您知道服务进程ID,为什么不能获取服务名称并从流程检查服务状态如下?
Process process = Process.GetProcessById(1);
ServiceController windowsService = ServiceController.GetServices().FirstOrDefault(x => x.ServiceName == process.ProcessName);
//Wait until the windows service stops running
while (windowsService.Status == ServiceControllerStatus.Running)
{
Thread.Sleep(1000);
}