2012-01-17 28 views
16

此代码按预期在大量机器上运行。然而,在一台特定的机器上,对WaitForExit()的呼叫似乎被忽略,事实上标志着该过程已退出。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(); 
} 

注意,不像SO一similar question,该过程被称为是notepad.exe(用于测试的原因),所以这是不可能的症结在于它 - 即它不产卵第二子过程和关闭。即便如此,这也无法解释为什么它可以在所有其他机器上运行。

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

机器运行Windows 7和.NET 4.0。

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

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

  • 重新安装.NET。
  • 关闭我在任务管理器中不知道的任何进程。
  • Windows尚未在此机器上激活。
  • 按照意见中的建议,我尝试使用GetProcessesByName获得'现有'进程标识,但是这只是在问题机器上返回空数组。因此,很难说问题与WaitForExit一样,因为在调用WaitForExit之前,不会通过调用GetProcessesByName来返回该过程。
  • 在问题机,将得到的记事本过程的PARENTID是记事本过程的ID代码手动启动,或换句话说,记事本是产卵子进程和终止本身。
+1

是否有可能之前打开过另一个记事本?所以你创建一个,杀死一个,但仍然看到旧的记事本? 'proc.WaitForExit()'可能会立即返回,如果进程无法创建或由于某些原因被直接终止,例如缺少创建新进程的原始代码的特权。 – oleksii 2012-01-17 13:05:48

+0

@oleskii,不,我已经确定了这一点。记事本仅作为一个“大家都知道”的过程在此处使用,无论该过程使用哪个文件,都会发生此问题。 – Rotem 2012-01-17 13:07:03

+0

@oleskii“proc.WaitForExit()可能会立即返回,如果进程无法创建或由于某些原因被直接终止” - 在这种情况下,进程是否也会被终止? – Rotem 2012-01-17 13:10:14

回答

7

的问题是,在默认情况下Process.StartInfo.UseShellExecute设置为true。将此变量设置为true,而不是自己启动进程,而是要求shell为您启动它。这可以说是相当useful-它可以让你做这样的事情“执行”的HTML文件(shell将使用相应的默认应用程序)。当你想执行它(如你发现)后跟踪应用中,由于启动应用程序有时会弄不清楚应该跟踪哪个实例

它不是那么好。

为什么发生这种情况的内部细节可能超出了我的回答能力 - 我知道,当UseShellExecute == true时,框架使用ShellExecuteEx Windows API,并且在使用UseShellExecute == false时,它使用CreateProcessWithLogonW,但为什么会导致可跟踪的流程,另一个我不知道,因为他们似乎都返回流程ID。

编辑:小挖后:

This question向我指出的SEE_MASK_NOCLOSEPROCESS标志时,使用的ShellExecute时确实似乎可以套。掩码值的文档状态如下:

在某些情况下,例如通过DDE 会话执行时,不会返回句柄。呼叫应用程序 负责在不再需要时关闭手柄。

所以它确实表明返回进程句柄是不可靠的。尽管如此,我仍然没有深入到足以知道你可能会在这里遇到哪种特殊的边缘情况。

+0

谢谢!虽然你的解决方案解决了我的问题,但我很想找到它仅仅对大约50个组中的一台机器产生影响的原因。 – Rotem 2012-01-17 15:44:31

+0

我希望@EricLippert能够在这里获得并且“为什么会发生这种情况“部分。我不那么尖锐。 – 2012-01-17 15:47:01

+2

我没有最微不足道的想法。我是C#语言及其编译器的设计和实现方面的专家。我几乎不知道Windows如何管理进程。 – 2012-01-17 16:21:14

1

原因可能是病毒,它取代notepad.exe以隐藏自己。 如果执行,它会产生记事本并退出(只是猜测)。

尝试此代码:

 var process = Process.Start("notepad.exe"); 
     var process2 = Process.GetProcessById(process.Id); 
     while (!process2.HasExited) 
     { 
      Thread.Sleep(1000); 
      try 
      { 
       process2 = Process.GetProcessById(process.Id); 
      } 
      catch (ArgumentException) 
      { 

       break; 
      } 

     } 

     MessageBox.Show("done"); 

的Process.Start()后检查的notepad.exe的进程ID与任务管理器,并验证它是一样的process.Id;

哦,你真的应该使用完整路径NOTEPAD.EXE

var notepad = Path.Combine(Environment.GetFolderPath(
        Environment.SpecialFolder.Windows), "notepad.exe"); 
Process.Start(notepad); 
相关问题