依赖进程创建的执行异常(ShellExecute vs CreateProcess)
Execution abnormalities depending on process creation (ShellExecute vs CreateProcess)
我们正在 运行ning 一个 Windows 服务,该服务负责监视一组进程。该服务基本上只负责 (a) 检查定义的作业是否 运行ning,以及 (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,因此它能够更好地监控定义的作业 (因为它获取进程的句柄)。
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) .当从命令行 运行ning Service.exe 或 Camera.exe 时,会出现 none 的问题。
今天我从服务 (回到 ShellExecute) 中删除了 CreateProcess 调用,问题又消失了。 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.
就其价值而言,您可以使用 ShellExecuteEx
而不是 ShellExecute
来获取进程句柄。事实上,你应该总是更喜欢 ShellExecuteEx
而不是 ShellExecute
因为后者不能正确报告错误。即便如此,您还是在创建一个新流程,因此 CreateProcess
是该任务的正确函数。
我们正在 运行ning 一个 Windows 服务,该服务负责监视一组进程。该服务基本上只负责 (a) 检查定义的作业是否 运行ning,以及 (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,因此它能够更好地监控定义的作业 (因为它获取进程的句柄)。
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) .当从命令行 运行ning Service.exe 或 Camera.exe 时,会出现 none 的问题。
今天我从服务 (回到 ShellExecute) 中删除了 CreateProcess 调用,问题又消失了。 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.
就其价值而言,您可以使用 ShellExecuteEx
而不是 ShellExecute
来获取进程句柄。事实上,你应该总是更喜欢 ShellExecuteEx
而不是 ShellExecute
因为后者不能正确报告错误。即便如此,您还是在创建一个新流程,因此 CreateProcess
是该任务的正确函数。