我们正在运行一个 Windows 服务,它负责监视一组进程。该服务基本上只负责 (a) 检查定义的作业是否正在运行,以及 (b) 如果未运行则启 Action 业。
服务是通过以下命令创建的 (sc: https://technet.microsoft.com/en-us/library/bb490995.aspx ):
sc create "My Service" binPath= C:\heyoo\myservice.exe type= own start= auto error= normal
sc start "SCF Service"
该服务负责创建的作业之一是“Camera.exe”。 Camera.exe 从连接的摄像头 (FireWire 1394) 检索视频源,并对它们进行一些处理。
一周前,该服务从使用 ShellExecute 重写为使用 CreateProcess,因此它能够更好地监控定义的作业(因为它获取进程的 HANDLE)。
ShellExecute 调用(旧方法):
bool Execute()
{
int result = (int)ShellExecute(NULL, "open", "C:\\bin\\Camera.exe", NULL, NULL, SW_SHOWDEFAULT);
return result > 32;
}
CreateProcess 调用(新方法):
// Called with Execute("C:\\bin\\Camera.exe", "");
bool Execute(std::string prog, std::string args)
{
std::string cmd = std::string(prog) + " " + args;
char *path = new char[cmd.length()+1];
strcpy(path, cmd.c_str());
STARTUPINFO si = {0};
si.cb = sizeof(STARTUPINFO);
PROCESS_INFORMATION pi;
ZeroMemory(&pi, sizeof(pi));
DWORD creationFlags = REALTIME_PRIORITY_CLASS;
BOOL result = CreateProcess(NULL, path, NULL, NULL, FALSE, creationFlags, NULL, NULL, &si, &pi);
delete[] path;
if (result) {
SetProcInfo(pi);
}
return result;
}
使用新的 CreateProcess 方法,我们注意到 (A) 网络在一定时间间隔后系统性失败,并且 (B) 从摄像机检索的图像包含无效时间戳(正确的时间戳对我们至关重要)。
A 经常断开整个网络连接,需要重新启动才能恢复在线。 B 导致图像处理失败,因为我们高度依赖有效的时间戳。
当 Service.exe 作为服务运行时,问题(A 和 B)仅出现。从命令行运行 Service.exe 或 Camera.exe 时,没有出现任何问题。
今天我从服务中删除了 CreateProcess 调用(返回到 ShellExecute),问题又消失了。我在调用 API 时做错了什么?
最佳答案
DWORD creationFlags = REALTIME_PRIORITY_CLASS;
这是最明显的区别。当您调用 ShellExecute
时,进程将以正常优先级创建。 documentation对于实时优先级说:
Process that has the highest possible priority. The threads of a real-time priority class process preempt the threads of all other processes, including operating system processes performing important tasks. For example, a real-time process that executes for more than a very brief interval can cause disk caches not to flush or cause the mouse to be unresponsive.
你真的不想这样做!
传递 0
作为创建标志。 documentation说:
If none of the priority class flags is specified, the priority class defaults to NORMAL_PRIORITY_CLASS unless the priority class of the creating process is IDLE_PRIORITY_CLASS or BELOW_NORMAL_PRIORITY_CLASS. In this case, the child process receives the default priority class of the calling process.
就其值(value)而言,您可以使用 ShellExecuteEx
而不是 ShellExecute
来获取进程句柄。事实上,你应该总是更喜欢 ShellExecuteEx
而不是 ShellExecute
因为后者不能正确报告错误。尽管如此,您还是在创建一个新进程,因此 CreateProcess
是完成该任务的正确函数。
关于windows - 依赖进程创建的执行异常(ShellExecute vs CreateProcess),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32863252/