我们正在运行一个Windows服务,它负责监视一组进程 . 该服务基本上只负责(a)检查定义的作业是否正在运行,以及(b)如果不是,则启动作业 .
该服务通过以下命令创建(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导致图像处理失败,因为我们高度依赖于有效时间戳 .
问题(A和B)仅在Service.exe作为服务运行时出现 . 从命令行运行Service.exe或Camera.exe时,不会出现任何问题 .
今天我从服务中删除了CreateProcess调用(回到ShellExecute),问题再次消失 . API调用我做错了什么?
1 回答
这是最明显的区别 . 当您调用
ShellExecute
时,将以正常优先级创建进程 . documentation实时优先级说:你真的不想这样做!
将
0
作为创建标志传递 . documentation说:对于它的 Value ,您可以使用
ShellExecuteEx
而不是ShellExecute
来获取进程句柄 . 事实上,你应该总是更喜欢ShellExecuteEx
到ShellExecute
,因为后者无法正确报告错误 . 即便如此,您正在创建一个新流程,因此CreateProcess
是该任务的正确功能 .