2013-10-15 27 views
2

我試圖做一個通用函數來獲取進程的主窗口句柄,給出了進程句柄,我想使用LINQ(避免使用FOR ),但它在'Where'clausule引發'拒絕訪問'的異常。異常消息試圖獲得一個進程的窗口句柄

我做錯了什麼?

Private Function Get_Process_MainWindowHandle(ByVal ProcessHandle As IntPtr) As IntPtr 

    Try 
     Return Process.GetProcesses _ 
       .Where(Function(p) p.Handle.Equals(ProcessHandle)) _ 
       .Cast(Of Process) _ 
       .First _ 
       .MainWindowHandle 

    Catch ex As Exception 
     MsgBox(ex.Message) ' ex Message: Access denied 
     Return IntPtr.Zero 
    End Try 

End Function 

用法:

Get_Process_MainWindowHandle(Process.GetProcessesByName("calc").First.Handle) 

UPDATE:

在我試圖做我得到相同的異常此功能等,更重要的是,主窗口句柄沒有找到,我在做什麼錯了?:

Private Sub Resize_Process_Window(ByVal ProcessHandle As IntPtr, _ 
            ByVal Weight As Integer, _ 
            ByVal Height As Integer) 

    Dim rect As Rectangle = Nothing 
    Dim procs As Process() = Nothing 
    Dim hwnd As IntPtr = IntPtr.Zero 

    Try 
     ' Find the process 
     procs = Process.GetProcesses 

     For Each p As Process In procs 
      Try 
       If p.Handle.Equals(ProcessHandle) Then 
        MsgBox("Handle found!") ' Msgbox will never be displayed :(
        hwnd = p.MainWindowHandle 
        Exit For 
       End If 
      Catch : End Try ' Catch for 'Denied acces' Win32Exception. 
     Next 

     Msgbox(hwnd) ' hwnd always is '0' :(

     ' Store the Left, Right, Bottom and Top positions of Window, into the Rectangle. 
     GetWindowRect(hwnd, rect) 

     ' Resize the Main Window 
     MoveWindow(hwnd, rect.Left, rect.Top, Weight, Height, True) 

    Catch ex As InvalidOperationException 
     'Throw New Exception("Process not found.") 
     MessageBox.Show("Process not found.", Nothing, MessageBoxButtons.OK, MessageBoxIcon.Error) 

    Finally 
     rect = Nothing 
     procs = Nothing 
     hwnd = Nothing 

    End Try 

End Sub 

用法:

Resize_Process_Window(Process.GetProcessesByName("notepad").First.Handle, 500, 500) 

回答

2

第一個問題:您試圖訪問,而您沒有必要的權限的進程句柄。通常,這是系統和空閒進程,但取決於您運行的是誰,因爲可能有其他人。

您的GetProcesses() LINQ查詢將嘗試訪問每個進程的句柄,以確定它們是否符合包含條件。如果你想獲得你有處理訪問權限的進程列表,你可以做如下的事情。很抱歉,這是C#不是VB,但你會發現它瑣碎把它轉換:

 private void EnumeratePermittedProcesses() 
     { 

      Process[] Procs = Process.GetProcesses(); 

      foreach (Process P in Procs) 
      { 
       try 
       { 
        IntPtr Ptr = P.Handle; 
        Debug.WriteLine("Processed Process " + P.ProcessName); 
       } 
       catch (Exception Ex) 
       { 
        // Ignore forbidden processes so we can get a list of processes we do have access to 
       } 
      } 
     } 

其次,MSDN告訴我們,進程句柄不是唯一的,所以你不應該使用它們使用比較.Equals來。改爲使用Process Id。這唯一,並具有額外的優點,當請求Id屬性時,您不會得到訪問被拒絕錯誤。

這裏是你將如何得到IntPtr的同時避免訪問進程的句柄,你沒有權限訪問:

 private IntPtr GetMainWindowHandle(int processId) 
     { 

      Process[] Procs = Process.GetProcesses(); 

      foreach (Process P in Procs) 
      {    
       if (P.Id == processId) 
       {      
        MessageBox.Show("Process Id Found!"); 

        return P.MainWindowHandle; 
       }          
      } 

      return IntPtr.Zero; 
     } 

用法:

IntPtr P = GetMainWindowHandle(Process.GetProcessesByName("calc").First().Id);  

同樣,你需要轉換爲VB(我有點生疏)。