.net - 尝试获取进程的窗口句柄的异常消息

标签 .net vb.net winforms linq process

我正在尝试创建一个通用函数来获取进程的主窗口句柄,并给出进程句柄, 我想使用 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/

相关文章:

c# - RDLC报告: Apply Filter to Report

c# - 用于 C# 的 HTML 5 CSS 3 Web 浏览器控件

C# - 是否可以从字符串中解析类型 - 例如(伪代码)Type t = Type.Parse ("Int32");

c# - 是什么导致这个 HTTPS WebRequest 即使在浏览器中工作也会超时?

vb.net - “应用程序”不是 'My' 的成员

c# - 如何使用linq读取xml文件

java - 将 .Net 解密转换为 Java

c# - Powershell 替换功能在替换时将逗号视为点

.net - 了解 VB.NET P/Invoke 声明中的 VBByRefStr

.net - Return 语句是否会对 Using block 产生负面影响?