4

目前,我可以使用System.Diagnostics.Process.GetProcesses()和执行一个简单的 LINQ 查询来获得一个带有主窗口的正在运行的进程列表。

然后,我可以导入函数user32.dllSetWindowPos操作其他进程的窗口参数。

好的,它有效。现在我想通过单击来选择一个进程的窗口,比如说 calc.exe。换句话说,我想获得一个带有钩子的 Process 对象(然后是 MainWindowHandle),当我单击它的窗口时,该钩子会捕获进程名称。

我怎样才能做到这一点?

4

2 回答 2

5

我不知道这是如何在 C# 中完成的,但你也标记了这个问题 WinAPI,所以我可以在那里提供帮助。在 WinAPI 中,可以这样做:

#include <stdio.h>
#include <Windows.h>
#include <Psapi.h>
#pragma comment(lib, "Psapi.lib")

int main(void)
{
  /* Hacky loop for proof of concept */
  while(TRUE) {
    Sleep(100);

    if(GetAsyncKeyState(VK_F12)) {
      break;
    }

    if(GetAsyncKeyState(VK_LBUTTON)) {
      HWND  hwndPt;
      POINT pt;

      if(!GetCursorPos(&pt)) {
        wprintf(L"GetCursorPos failed with %d\n", GetLastError());
        break;
      }

      if((hwndPt = WindowFromPoint(pt)) != NULL) {
        DWORD  dwPID;
        HANDLE hProcess;

        GetWindowThreadProcessId(hwndPt, &dwPID);

        hProcess = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, dwPID);

        if(hProcess == NULL) {
          wprintf(L"OpenProcess failed with error: %d\n", GetLastError());
        } else {
          wchar_t lpFileName[MAX_PATH];
          DWORD   dwSize = _countof(lpFileName);

          QueryFullProcessImageName(hProcess, 0, lpFileName, &dwSize);
          wprintf(L"%s\n", lpFileName);

          CloseHandle(hProcess);
        }
      }
    }
  }

  return EXIT_SUCCESS;
}

示例结果:

结果

在这种情况下,我只是轮询鼠标点击。更合适的方法是使用某种 windows 钩子。

于 2012-04-25T15:23:43.347 回答
1

正如 Mike Kwan 所说,虽然这两种方法都有各自的缺点,但你最好写一个钩子,但 bjarneds 已经在这方面做了很好的工作。看看@DotNET 对象间谍。它是用 C# 编写的,可以满足您的需求等等。

您还应该注意,使用钩子正变得越来越多余。根据您想要做什么,其他类似的 winapisGetForegroundWindow可能会更好。

于 2012-04-25T20:07:15.857 回答