2011-01-18 3 views
9

IPC 채널을 설정하기 위해 코드에서 프로세스를 시작하는 상황이 있습니다. 내가 시작하는 프로세스는 CLR을 지원하지 않는 MFC 애플리케이션이다. 이 프로세스를 시작하는 응용 프로그램은 WPF 응용 프로그램의 C# 모듈입니다 (내 문제가 필연적이라고 생각합니다). 이것은 CLR을 지원하는 응용 프로그램 버전에서 작동하며 Windows 7이 설치된 터치 스크린 컴퓨터 인 배포 대상을 제외한 모든 컴퓨터에서 작동합니다. 그러나 어떤 이유로이 정확한 시나리오로 시도 할 때 Process 개체는 절대로 사용하지 마십시오. 주 창 핸들 (Process.MainWindowHandle)을 해결합니다. 이 작업을 수행하는 또 다른 방법이 있을까요? 보안 문제인가요? 나는 그 과정을 응시하는 사람이다. 프로세스의 주 창 핸들이 존재합니다. 나는 무엇이 잘못 될지 모른다.시작한 프로세스의 주 창 핸들을 가져올 수없는 이유는 무엇입니까?

도움이된다면 여기에 내 코드가 있습니다.

 _applicationProcess = new Process(); 
     _applicationProcess.StartInfo.FileName = _strProcessPath; 
     _applicationProcess.StartInfo.Arguments = _strProcessArguments; 
     _applicationProcess.Start(); 

     long nTicks = Environment.TickCount; 
     if (_applicationProcess.WaitForInputIdle(1 /*minute(s)*/ * 60000)) 
     { 
      try 
      { 
       do 
       { 
        // Don't let total processing take more than 1 minute(s). 
        if (Environment.TickCount > nTicks + 1 /*minute(s)*/ * 60000) 
         throw new ApplicationException("MFCApplication.Startup failed! The main window handle is zero!"); 

        _applicationProcess.Refresh(); 
       } 
       while (_applicationProcess.MainWindowHandle.ToInt32() == 0); 

       _applicationHandle = new IntPtr(_applicationProcess.MainWindowHandle.ToInt32()); 
      } 
      catch (Exception ex) 
      { 
       //Do some stuff... 
       throw; 
      } 
     } 
     else 
     { 
      // Do exception handling. 
     } 

ApplicationException는 0 이외의 메인 윈도우 핸들을 얻으려고 노력하는 분 후 공격한다.

+1

MSDN 문서에서 제안하는대로 'WaitForInputIdle'을 사용하여 지치셨습니까? 또한'throw ex' 대신'throw'를 사용하는 것이 가장 좋습니다. 'throw ex' ('throw ex'는 예외를 throw하고 스택 트레이스를 다시 시작합니다)와 함께 스택 추적 정보를 잃게됩니다. –

+0

편집 내용을 확인하십시오. :) – Jordan

+0

@ jordan 나는 당신의 편집을 본다. @username을 주석에 포함 시켜서 응답하는 다른 사용자에게 통지해야합니다. –

답변

6

Process.MainWindowHandle에서 얻은 가치는 불행히도 추측입니다. 프로그램에 사용할 수있는 API 기능이 없으므로 Windows에 "내 메인 창"이라고 알릴 수 있습니다. 프로세스가 사용하는 규칙은 문서화되어 있으며 프로세스가 시작될 때 만들어지는 첫 번째 창입니다. 첫 번째 창이 로그인 창이나 스플래시 화면 인 경우 문제가 발생합니다.

별로 할 수있는 일이 없으므로 프로그램이 동작하는 방식에 대해 자세히 알아야 기본 창을 찾을 수 있습니다. EnumThreadWindows()를 사용하여 창을 열거하면 첫 번째 창이 주 창과 동일한 스레드에서 작성되는 한 찾을 수 있습니다. 더 정교한 EnumWindows()가 필요하지 않은 경우 필요합니다.

3

내 습관은 GetWindowThreadProcessId와 결합 된 루프에서 EnumWindows를 호출하여 창 핸들을 찾는 것입니다.

C Code, adapt to your language 


DWORD TargetHWND; 

//... 
    while (EnumWindows(EnumWndProc, (LPARAM)(DWORD)pid)) { 
     Sleep(100); 
    } 


//... 

BOOL EnumWndProc(HWND hWnd, LPARAM lParam) { 
    DWORD pid = (DWORD)-1; 
    GetWindowThreadProcessId(hWnd, &pid); 
    if (pid == (DWORD)lParam) { 
     TargetHWND = hWnd; 
     return FALSE; 
    } 
    return TRUE; 
} 
+0

어떻게하면 도움이 될까요? 다른 프로세스에서 창 핸들을 얻으려고합니다. 몇 가지 코드를 제게 제공해 주시겠습니까? – Jordan

+0

그래서 기본적으로 이것은 흥미로운 주어진 프로세스 ID에 대한 모든 창을 가져옵니다. – Jordan

1

나는 그것이 다를 수 있습니다 이유를 알고 있지만,이 과정을 만든 후, 일을하려고하지 않습니다

Process[] allProcesses = Process.GetProcessesByName("YourWindowTitle"); 

을 반환 프로세스의이 MainWindowHandle이있는 경우를 참조하십시오.

+0

그것은 다르지만 반대 방향입니다. 이런 식으로 프로세스를 유지하면 완전한 신뢰가 없으므로 아무 것도 할 수없고 확실하게 처리 할 수 ​​없습니다. 프로세스를 시작할 때만 의미있는 의미로 프로세스와 상호 작용할 수 있습니다. – Jordan

2

프로세스에 의해 MainWindowHandle을 얻기 위하여, 당신의 WPF 응용 프로그램을 작업 표시 줄 즉 ShowInTaskbar="True"에 표시하고 메인 창으로 설정하고 싶은 창으로 Application.Current.MainWindow 속성을 설정되어 있는지 확인하십시오.

ShowInTaskbar="True" 설정하지 않고 내 WPF 기본 창에서 코드를 실행하면 내 WPF 창이 전체 화면이었고 작업 표시 줄에 표시되지 않기 때문에 항상 MainWindowHandle으로 0이 표시됩니다.

Application.Current.MainWindow = this; 
    var Query = System.Diagnostics.Process.GetProcessesByName("ProcessName"); 

    if (Query.Any()) 
    { 
     Query.FirstOrDefault().Refresh(); 
     MessageBox.Show(Query.FirstOrDefault().MainWindowHandle.ToInt32().ToString()); 
    } 
관련 문제