CreateProcess 创建进程失败原因调查

使用 CreateProcess 函数创建进程(调用外部程序)算是很常用的操作了,最近在工作中却遇到一个少见的怪现象,经常使用的一段代码(调用外部程序并等待其结束,主要就使用了 CreateProcess 函数),在少数某些机器上会失败(目前只在某一个 Win8.1 和某一个 Win10 机器遭遇失败)。

经调查分析,发现正是 CreateProcess 调用失败,GetLastError 返回 0x05 错误(ERROR_ACCESS_DENIED),凭经验知道这是权限不足的问题,但具体是什么原因?一时无解。继续排查,发现原先有另一处调用外部程序的代码是不存在该问题的,仔细对比两处代码,发现调用 CreateProcess 时的第6个参数(dwCreationFlags)不一样!问题代码中使用了 CREATE_BREAKAWAY_FROM_JOB 值(和 Job Object 有关),马上去掉该值再测试,问题果然没有了!

抱着「知其然,还要知其所以然。」的一惯态度,继续寻找导致该问题的原因,历程如下:

1. 先是深入解读了 MSDN 相关部分,了解到使用 CREATE_BREAKAWAY_FROM_JOB 参数是需要前提条件的:需要其关联的 Job 对象具有 JOB_OBJECT_LIMIT_BREAKAWAY_OK 属性,否则就会失败,但 MSDN 中并未明确指出失败码为 0x05。

2. 网上求解过程中,意外地在 Chrome Issues 列表中发现同样的问题:「WinAPI  CreateProcessAsUserW() with CREATE_BREAKAWAY_FROM_JOB flag which fails with 0x5 (access denied) error.」。

3. 翻书《Windows核心编程》也找到了对 CREATE_BREAKAWAY_FROM_JOB 的相关说明(如下图):
CreateProcess 创建进程失败原因调查_第1张图片

总结一下:
我使用的这段代码是从以前的工程里拷贝来的,至于为什么带上了 CREATE_BREAKAWAY_FROM_JOB 参数,属于历史问题就不得而知了,这个参数的目的是让子进程脱离父进程的 Job,如果本没有这个需求的话,可以不用考虑直接去掉,如果确实需要该特性的话,那就得按官方的要求来,要确保其 Job 对象具有 JOB_OBJECT_LIMIT_BREAKAWAY_OK 属性(具体怎么实现不属于本文的范畴了)。个别机器上可能由于系统环境的某些特殊原因,造成相关 Job 对象不具有 JOB_OBJECT_LIMIT_BREAKAWAY_OK 属性,因此导致了该问题的出现,图证如下:

CreateProcess 创建进程失败原因调查_第2张图片
vs
CreateProcess 创建进程失败原因调查_第3张图片

所以,以后遇到 CreateProcess 失败,错误码为 0x05 时,去检查一下参数里是否有 CREATE_BREAKAWAY_FROM_JOB 吧!


参考:
https://msdn.microsoft.com/en-us/library/windows/desktop/ms682425(v=vs.85).aspx
https://msdn.microsoft.com/en-us/library/windows/desktop/ms684863(v=vs.85).aspx
https://msdn.microsoft.com/en-us/library/windows/desktop/ms684161(v=vs.85).aspx
https://msdn.microsoft.com/en-us/library/windows/desktop/ms681382(v=vs.85).aspx
https://msdn.microsoft.com/en-us/library/windows/desktop/ms684147(v=vs.85).aspx
https://code.google.com/p/chromium/issues/detail?id=79091#c45
《Windows核心编程》


你可能感兴趣的:(进程,CreateProcess,API)