2013-04-24 44 views
7

đây là mã của tôi:C# Process.MainWindowHandle luôn trả IntPtr Zero,

  using (Process game = Process.Start(new ProcessStartInfo() { 
     FileName="DatabaseCheck.exe", 
     RedirectStandardOutput = true, 
     CreateNoWindow = true, 
     UseShellExecute = false })) 
     { 
      lblLoad.Text = "Loading"; 
      int Switch = 0; 

      while (game.MainWindowHandle == IntPtr.Zero) 
      { 
       Switch++; 
       if (Switch % 1000 == 0) 
       { 
        lblLoad.Text += "."; 
        if (lblLoad.Text.Contains("....")) 
         lblLoad.Text = "Loading."; 

        lblLoad.Update(); 
        game.Refresh(); 
       } 
      } 

Vấn đề là, rằng game.MainWindowHandle luôn là IntPtr.Zero. Tôi cần phải tìm IntPtr của quá trình chạy để xác nhận rằng trò chơi đã được khởi động bởi các phóng, vì vậy tôi làm cho trò chơi gửi nó IntPtr và để cho các phóng trả lời nếu nó không sao. Nhưng đối với điều đó, tôi phải biết IntPtr của quá trình chạy cụ thể.

Cảm ơn trước!

Trả lời

10

Cửa sổ chính là cửa sổ được mở bởi quá trình hiện có tiêu điểm (biểu mẫu TopLevel). Bạn phải sử dụng phương thức Refresh để làm mới đối tượng Quy trình thành lấy tay cầm cửa sổ chính hiện tại nếu đã thay đổi.

Bạn chỉ có thể nhận thuộc tính MainWindowHandle cho các quy trình đang chạy trên máy tính cục bộ. Thuộc tính MainWindowHandle là một giá trị xác định duy nhất cửa sổ được liên kết với quy trình.

Quy trình có cửa sổ chính được liên kết với nó chỉ khi quá trình có giao diện đồ họa. Nếu quá trình liên quan không có cửa sổ chính, giá trị MainWindowHandle là 0. Giá trị cũng bằng 0 cho các tiến trình đã bị ẩn, tức là các tiến trình không hiển thị trong thanh tác vụ. Điều này có thể là trường hợp cho các quá trình xuất hiện dưới dạng biểu tượng trong vùng thông báo, ở phía xa bên phải của thanh tác vụ.

Nếu bạn vừa bắt đầu quy trình và muốn sử dụng tay cầm cửa sổ chính, hãy cân nhắc sử dụng phương thức WaitForInputIdle để cho phép quá trình bắt đầu hoàn thành, đảm bảo rằng cửa sổ chính đã được tạo. Nếu không, một ngoại lệ sẽ được ném.

+0

Sẽ cố gắng mà khi tôi về nhà. Cảm ơn – Kfirprods

+0

Cảm ơn, nó đã hoạt động. – Kfirprods

+0

Lưu ý rằng trên 4.5 này không còn cần thiết (giai thoại - mã của tôi làm việc trên 4.5 và thất bại khi tôi giảm xuống còn 3.5 cho đến khi tôi thêm '.Refresh()') – Basic

2
while (!proc.HasExited) 
{ 
    proc.Refresh(); 
    if (proc.MainWindowHandle.ToInt32() != 0) 
    { 
     return proc.MainWindowHandle; 
    } 
} 
+1

Xin chào, bài đăng của bạn đã bị gắn cờ là "chất lượng thấp", có lẽ vì nó chỉ bao gồm mã. Bạn có thể cải thiện một cách ồ ạt câu trả lời của mình bằng cách cung cấp giải thích chính xác cách thức và lý do giải thích câu hỏi này? – Ben

3

Một cách giải quyết là để liệt kê thông qua tất cả các cửa sổ cấp cao nhất và kiểm tra id quá trình của họ cho đến khi bạn tìm thấy một trận đấu ...


    [DllImport("user32.dll")] 
    public static extern IntPtr FindWindowEx(IntPtr parentWindow, IntPtr previousChildWindow, string windowClass, string windowTitle); 

    [DllImport("user32.dll")] 
    private static extern IntPtr GetWindowThreadProcessId(IntPtr window, out int process); 

    private IntPtr[] GetProcessWindows(int process) { 
     IntPtr[] apRet = (new IntPtr[256]); 
     int iCount = 0; 
     IntPtr pLast = IntPtr.Zero; 
     do { 
      pLast = FindWindowEx(IntPtr.Zero, pLast, null, null); 
      int iProcess_; 
      GetWindowThreadProcessId(pLast, out iProcess_); 
      if(iProcess_ == process) apRet[iCount++] = pLast; 
     } while(pLast != IntPtr.Zero); 
     System.Array.Resize(ref apRet, iCount); 
     return apRet; 
    }