Process.WaitForExit在不同的机器上不一致

Rot*_*tem 15 .net c# process

此代码在大量计算机上按预期运行.但是在一台特定的机器上,呼叫WaitForExit()似乎被忽略了,实际上标志着该过程已经退出.

static void Main(string[] args)
{
    Process proc = Process.Start("notepad.exe");
    Console.WriteLine(proc.HasExited); //Always False
    proc.WaitForExit(); //Blocks on all but one machines
    Console.WriteLine(proc.HasExited); //**See comment below
    Console.ReadLine();
}
Run Code Online (Sandbox Code Playgroud)

请注意,与SO上的类似问题不同,被调用的过程是notepad.exe(出于测试原因),因此故障不太可能 - 即它不会产生第二个子过程并关闭.即便如此,也无法解释为什么它适用于所有其他机器.

在问题机器上,即使记事本仍然在屏幕和任务管理器中仍然清楚地打开第二次Console.WriteLine(proc.HasExited))返回调用true.

该机器运行的是Windows 7和.NET 4.0.

我的问题是; 该特定机器上的条件可能导致这种情况?我应该检查什么?

编辑 - 到目前为止我尝试过的事情/更新/可能相关的信息:

  • 重新安装.NET.
  • 关闭任务管理器中我不知道的任何进程.
  • Windows尚未在此计算机上激活.
  • 根据评论中的建议,我尝试使用"现有"进程ID,GetProcessesByName但这只是在问题机器上返回一个空数组.因此,很难说问题就是这样WaitForExit,因为GetProcessesByName即使在调用之前调用也没有返回进程WaitForExit.
  • 在问题机器上,生成的记事本进程的ParentID是代码手动启动的记事本进程的ID,换句话说,记事本正在生成子进程并终止自身.

Chr*_*ain 7

问题是默认情况下Process.StartInfo.UseShellExecute设置为true.将此变量设置为true,而不是自己启动该过程,您要求shell为您启动它.这可能非常有用 - 它允许您执行诸如"执行"HTML文件之类的操作(shell将使用适当的默认应用程序).

当你想要在执行它之后跟踪应用程序时(如你所发现的那样)它不太好,因为启动应用程序有时会混淆它应该跟踪哪个实例.

这里发生的原因可能超出了我的回答能力 - 我知道当UseShellExecute == true时,框架使用ShellExecuteEx Windows API,当它使用UseShellExecute == false时,它使用CreateProcessWithLogonW,但是为什么一个引导跟踪进程和另一个我不知道,因为他们似乎都返回进程ID.

编辑:经过一番挖掘:

这个问题向我指出了SEE_MASK_NOCLOSEPROCESS标志,它确实在使用ShellExecute时确实设置了.掩码值的文档说明:

在某些情况下,例如通过DDE对话满足执行时,将不返回句柄.调用应用程序负责在不再需要时关闭句柄.

所以它确实表明返回进程句柄是不可靠的.我仍然没有深入了解你可能在这里遇到的特殊边缘情况.

  • 我没有最微弱的想法.我是C#语言及其编译器的设计和实现方面的专家.我几乎不知道Windows如何管理进程. (2认同)