2012-01-17 3 views
16

이 코드는 많은 수의 컴퓨터에서 예상대로 실행됩니다. 그러나 하나의 특정 컴퓨터에서는 WaitForExit()에 대한 호출이 무시 된 것처럼 보이며 사실 프로세스를 종료 된 것으로 표시합니다. SO에 similar question 달리 처리가 호출되고 있음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(); 
} 

주 (시험 이유) notepad.exe에 있으므로 고장이 함께 놓여 어렵다 - 즉,이 제 2 서브 과정과 폐쇄 산란되지 않는다. 그렇다고하더라도 다른 모든 시스템에서 왜 작동하는지 설명하지는 못합니다.

문제가 발생한 컴퓨터에서 두 번째 호출 인 Console.WriteLine(proc.HasExited))은 화면과 작업 관리자에서 메모장이 여전히 명확하게 열려 있어도 true을 반환합니다.

기계에서 Windows 7 및 .NET 4.0을 실행 중입니다.

내 질문은; 특정 컴퓨터의 어떤 조건이 원인 일 수 있습니까? 무엇을 확인해야합니까?

편집 - 내가 지금까지/업데이트/아마 관련 정보를 시도한 것 :

  • 다시 설치 .NET.
  • 작업 관리자에서 모르는 모든 프로세스가 종료되었습니다.
  • Windows가이 컴퓨터에서 아직 활성화되지 않았습니다.
  • 의견에 충실 한 후, 나는 GetProcessesByName을 사용하여 '기존'프로세스 ID를 얻으려고 시도했지만 단순히 문제가있는 컴퓨터에서 빈 배열을 반환합니다. 따라서 WaitForExit을 호출하기 전에도 GetProcessesByName을 호출하여 프로세스가 반환되지 않으므로 문제가 WaitForExit 인 경우에도 마찬가지라고 말할 수 없습니다.
  • 문제가 발생한 컴퓨터에서 결과 메모장 프로세스의 ParentID는 코드가 수동으로 시작하는 메모장 프로세스의 ID입니다. 즉, 메모장은 자식 프로세스를 생성하고 자신을 종료합니다.
+1

메모장이 열렸을 가능성이 있습니까? 그래서 하나 만들고, 하나만 죽이지 만, 여전히 오래된 메모장을 보았습니까? 'proc.WaitForExit()'는 새로운 프로세스를 생성하기위한 원래 코드의 권한이없는 등의 이유로 인해 프로세스가 생성되지 않거나 즉시 종료 된 경우 즉시 반환 될 수 있습니다. – oleksii

+0

@oleskii, 아니요. 메모장은 "모든 사람이 알고있는"프로세스로만 사용됩니다.이 문제는 프로세스에 어떤 파일이 사용되는지에 관계없이 발생합니다. – Rotem

+0

@oleskii "proc.WaitForExit()은 프로세스가 생성되지 않았거나 어떤 이유로 인해 즉시 종료 된 경우 즉시 반환 될 수 있습니다."- 프로세스가 실제로이 경우 종료되지 않겠습니까? – Rotem

답변

7

문제는 기본적으로 Process.StartInfo.UseShellExecute이 true로 설정되어 있는지입니다 NOTEPAD.EXE에 대한 전체 경로를 사용해야합니다. 이 변수를 true로 설정하면 직접 프로세스를 시작하는 대신 쉘이 시작하도록 요청합니다. 이것은 매우 유용 할 수 있습니다 - HTML 파일을 "실행"하는 것과 같은 것을 할 수 있습니다 (쉘은 적절한 기본 응용 프로그램을 사용합니다).

실행중인 응용 프로그램을 추적 한 후에 (실행 한 후에) 응용 프로그램을 추적하려고 할 때 시작 응용 프로그램이 어떤 인스턴스를 추적해야하는지 혼동 할 수 있기 때문에 좋지 않습니다.

내부 왜 여기 왜 내 능력을 넘어 가능성이 있습니다 - 나는 UseShellExecute == true 일 때 프레임 워크가 ShellExecuteEx Windows API를 사용하고 UseShellExecute == false 일 때 CreateProcessWithLogonW를 사용한다는 것을 알고 있습니다. 그러나 왜 둘 모두 프로세스 ID를 반환하는 것처럼 보이기 때문에 추적 가능한 프로세스로 이어지는 이유는 무엇인지 모릅니다.

편집 : 조금 파고 후 :

This question

가 된 ShellExecute를 사용하는 경우 참으로 설정 될 것 같습니다 않는 SEE_MASK_NOCLOSEPROCESS 플래그, 저를 지적했다. 마스크 값에 대한 설명은 다음과 같습니다.

DDE 대화를 통해 실행이 만족되는 경우와 같이 경우에 따라 핸들이 반환되지 않습니다. 호출 응용 프로그램은 핸들이 더 이상 필요하지 않을 때 핸들을 닫을 책임이있는 입니다.

따라서 프로세스 핸들을 반환하는 것이 신뢰할 수 없다고 제안합니다. 나는 아직도 당신이 여기에서 타격을 가하고 있을지도 모르는 특정한 특정 사건을 알기에 충분히 깊이 이해하지 못했다.

+0

감사! 귀하의 솔루션이 내 문제를 해결하는 동안 나는 단지 약 50 대의 그룹에서 단지 한 대의 컴퓨터에만 영향을 미쳤던 이유를 찾고 싶습니다. – Rotem

+0

@EricLippert가 여기에 들어가서 "왜 이런 일이 일어나는가?"하고 기대하고 있습니다. "부분. 나는 그렇게 예리하지 않다. –

+2

나는 아주 희미한 생각이 없습니다. 저는 C# 언어와 컴파일러의 설계 및 구현에 대한 전문가입니다. Windows가 프로세스를 관리하는 방법에 대해서는 거의 알지 못합니다. –

1

원인은 notepad.exe를 바꿔 자신을 숨길 수있는 바이러스 일 수 있습니다. 실행되면 메모장을 생성하고 종료합니다 (추측).

이 코드보십시오 Process.Start를 후

 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"); 

()는 윈도우 작업 관리자와 NOTEPAD.EXE의 프로세스 ID를 확인하고 process.Id와 동일한 검증하는 단계;

아, 그리고 당신이 정말로

var notepad = Path.Combine(Environment.GetFolderPath(
        Environment.SpecialFolder.Windows), "notepad.exe"); 
Process.Start(notepad); 
관련 문제