我正在尝试创建一个通用函数来获取进程的主窗口句柄,并给出进程句柄, 我想使用 LINQ(避免使用 FOR),但它在“Where”子句中抛出“拒绝访问”异常。
我做错了什么吗?
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)
最佳答案
第一个问题:您正在尝试访问您没有必要权限的进程句柄。通常,这是系统和空闲进程,但取决于您正在运行的进程,因为很可能还有其他进程。
您的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 进行比较。请改用进程 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(我有点生疏)。
关于.net - 尝试获取进程的窗口句柄的异常消息,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19373582/