2

プロセスのメイン ウィンドウ ハンドルを取得するための汎用関数を作成しようとしています。プロセス ハンドルを指定します。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)

アップデート:

私がやろうとしているこの他の関数では、同じ例外が発生し、それ以上に、メインウィンドウハンドルが見つかりません。何が間違っていますか?:

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)
4

1 に答える 1

2

最初の問題: 必要な権限を持っていないプロセスのハンドルにアクセスしようとしています。通常、これは System プロセスと Idle プロセスですが、実行しているプロセスによっては、他のプロセスが存在する可能性もあります。

LINQGetProcesses()クエリは、すべてのプロセスのハンドルにアクセスして、包含基準に一致するかどうかを確認しようとします。ハンドル アクセス権を持っているプロセスの一覧を取得する場合は、次のようにします。申し訳ありませんが、これは VB ではなく C# ですが、簡単に変換できるはずです。

        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
                }
            }
        }

第 2 に、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 に変換する必要があります (私は少しさびています)。

于 2013-10-15T14:17:40.270 に答える