2016-11-16 180 views
0

我需要在默認瀏覽器中打開一個網站。然後我想在第二個屏幕上顯示瀏覽器。因此我嘗試以下方法:從瀏覽器進程獲取句柄

private void button1_Click(object sender, EventArgs e) 
{ 
    var externalApplication = new Process(); 
    externalApplication.StartInfo.WindowStyle = ProcessWindowStyle.Normal; 
    externalApplication.StartInfo.FileName = "http://www.example.com/"; 
    externalApplication.Start(); 
    externalApplication.WaitForInputIdle(); 

    var handle = externalApplication.MainWindowHandle; 
    Console.Write(handle); 
    Program.MoveWindow(handle, 0, 0, 1500, 1, true); 
} 

[DllImport("user32.dll", SetLastError = true)] 
internal static extern bool MoveWindow(IntPtr hWnd, int X, int Y, int nWidth, int nHeight, bool bRepaint); 

現在我的問題是,無論是WaitForInputIdle()也不MainWindowHandle()似乎在這裏工作。他們都拋出一個InvalidOperationException: No process is associated with this object

+0

Does [this](https://social.msdn.microsoft.com/Forums/en-US/79b6be7e-5f00-474c-a485-50db92feefe2/no-process-is-associated-with-this-object- in-waitforinputidle-and-movewindow-for-audio-files?forum = csharpgeneral)幫助你? –

回答

0

我解決了這個通過獲取利用@Simon Mourier to get the parent

的答案,更改代碼這樣家長手柄:

private void OpenUrl(string url) 
{ 
    var oldProcessIds = Process.GetProcesses().Select(pr => pr.Id); 

    IntPtr handle = OpenApplication(url); 
    if (handle==IntPtr.Zero) 
    { 
     // Find out what Process is new 
     var processes = Process.GetProcesses(); 
     var newProcess = processes.Where(pr => !oldProcessIds.Contains(pr.Id)); 
     var parent = ParentProcessUtilities.GetParentProcess(newProcess.First().Handle); 
     Program.MoveWindow(parent.MainWindowHandle, 0, 500, 500, 300, true); 
    } 
    else 
    { 
     Program.MoveWindow(handle, 0, 0, 1500, 100, true); 
    } 
} 

private IntPtr OpenApplication(string application) 
{ 
    var externalApplication = new Process(); 
    externalApplication.StartInfo.WindowStyle = ProcessWindowStyle.Normal; 
    externalApplication.StartInfo.FileName = "http://www.example.com"; 
    externalApplication.Start();  
    externalApplication.Refresh(); 
    try 
    { 
     externalApplication.WaitForInputIdle(); 
     return externalApplication.MainWindowHandle; 
    } catch 
    { 
     // Cannot get Handle. Application managaes multiple Threads 
     return IntPtr.Zero; 
    } 
} 

代碼以檢索父:

[StructLayout(LayoutKind.Sequential)] 
    public struct ParentProcessUtilities 
    { 
     // These members must match PROCESS_BASIC_INFORMATION 
     internal IntPtr Reserved1; 
     internal IntPtr PebBaseAddress; 
     internal IntPtr Reserved2_0; 
     internal IntPtr Reserved2_1; 
     internal IntPtr UniqueProcessId; 
     internal IntPtr InheritedFromUniqueProcessId; 

     [DllImport("ntdll.dll")] 
     private static extern int NtQueryInformationProcess(IntPtr processHandle, int processInformationClass, ref ParentProcessUtilities processInformation, int processInformationLength, out int returnLength); 

     /// <summary> 
     /// Gets the parent process of the current process. 
     /// </summary> 
     /// <returns>An instance of the Process class.</returns> 
     public static Process GetParentProcess() 
     { 
      return GetParentProcess(Process.GetCurrentProcess().Handle); 
     } 

     /// <summary> 
     /// Gets the parent process of specified process. 
     /// </summary> 
     /// <param name="id">The process id.</param> 
     /// <returns>An instance of the Process class.</returns> 
     public static Process GetParentProcess(int id) 
     { 
      Process process = Process.GetProcessById(id); 
      return GetParentProcess(process.Handle); 
     } 

     /// <summary> 
     /// Gets the parent process of a specified process. 
     /// </summary> 
     /// <param name="handle">The process handle.</param> 
     /// <returns>An instance of the Process class or null if an error occurred.</returns> 
     public static Process GetParentProcess(IntPtr handle) 
     { 
      ParentProcessUtilities pbi = new ParentProcessUtilities(); 
      int returnLength; 
      int status = NtQueryInformationProcess(handle, 0, ref pbi, Marshal.SizeOf(pbi), out returnLength); 
      if (status != 0) 
       return null; 

      try 
      { 
       return Process.GetProcessById(pbi.InheritedFromUniqueProcessId.ToInt32()); 
      } 
      catch (ArgumentException) 
      { 
       // not found 
       return null; 
      } 
     } 

說明:

在打開URL之前,程序會記住之前存在的過程。所以在創建之後,新的過程可以被抓住。從過程中,父母將被搜索,這應該是主要的瀏覽器過程。然後該流程的MainWindowHandle被用來移動窗口。

注:

這是一個 「粗」 第一個解決方案(更像是一個POC)直到現在。缺少錯誤處理例程,它樂觀地認爲沒有其他進程在同一時間開始。

+0

這適用於IE和Chrome,但似乎不適用於FireFox –