我们正在运行一个Windows服务,负责监视一组进程。 该服务基本上只负责(a)检查定义的作业是否正在运行,以及(b)如果不是,则开始作业。
该服务是通过以下命令创build的(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"
服务负责创build的作业之一是“Camera.exe”。 Camera.exe从连接的摄像机(FireWire 1394)中检索video源,并对其进行一些处理。
一个星期前,使用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)networking在一定的时间间隔后系统地失败,(B)从相机取回的图像包含无效的时间戳(正确的时间戳对我们至关重要)。
A频繁地断开整个networking连接,并且需要重新启动才能恢复在线。 B导致image processing失败,因为我们高度依赖于有效的时间戳。
只有在Service.exe 作为服务运行时才会出现问题(A和B)。 从命令行运行Service.exe或Camera.exe时,不会发生任何问题。
今天我从服务中删除了CreateProcess调用(返回到ShellExecute) ,问题又一次消失了。 我在做什么错误的API调用?
DWORD creationFlags = REALTIME_PRIORITY_CLASS;
这是最明显的区别。 当你调用ShellExecute
,进程将被创建为普通的优先级。 实时优先权文件说:
具有最高优先级的进程。 实时优先级进程的线程抢占所有其他进程的线程,包括执行重要任务的操作系统进程。 例如,执行超过非常短时间间隔的实时进程可能会导致磁盘缓存不能刷新或导致鼠标无法响应。
你真的不想这样做!
传递0
作为创建标志。 该文件说:
如果没有指定任何优先级标志,则优先级缺省为NORMAL_PRIORITY_CLASS,除非创建进程的优先级为IDLE_PRIORITY_CLASS或BELOW_NORMAL_PRIORITY_CLASS。 在这种情况下,子进程接收调用进程的默认优先级。
对于它的价值,你可以通过使用ShellExecuteEx
而不是ShellExecute
获得一个进程句柄。 事实上,你应该总是喜欢ShellExecuteEx
ShellExecute
因为后者不能正确报告错误。 即使如此,您正在创建一个新的进程,所以CreateProcess
是该任务的正确功能。