查找与PID对应的HWND

时间:2019-01-06 00:51:11

标签: c# .net

我有一个名为int的{​​{1}}。我想使用pid来调用来自此过程的任何窗口的函数。我从pinvoke整理了这段代码:

hwnd

该代码尚无法使用。在第一行中,它告诉我没有报告的重载与委托CallBackPtr相匹配。解决此问题的正确方法是什么?我从here

获取了代码

2 个答案:

答案 0 :(得分:0)

我有一些类似的东西(YMMV,很旧的代码):

public class UnmanagedCode
{
    [DllImport("user32")]
    public static extern int EnumWindows(EnumWindowsDelegate CallBack, 
      ProcessWatcher processWatcher);

    [DllImport("user32")]
    internal static extern bool IsWindowVisible(int hWnd);

    [DllImport("User32.Dll")]
    public static extern void GetWindowText(int hWnd, StringBuilder sb, int maxCount);

    [DllImport("User32.Dll")]
    public static extern void GetClassName(int hWnd, StringBuilder sb, int maxCount);

    public static bool EnumWindowsCallBack(int Hwnd, ProcessWatcher processWatcher)
    {
        if (!IsWindowVisible(Hwnd))
            return true;

        if (IsAltTabWindow(Hwnd))
        {
            try
            {
                StringBuilder windowClass = new StringBuilder(256);
                UnmanagedCode.GetClassName(Hwnd, windowClass, windowClass.Capacity);

                StringBuilder windowText = new StringBuilder(256);
                UnmanagedCode.GetWindowText(Hwnd, windowText, windowText.Capacity);

                IntPtr pid = (IntPtr)0;
                GetWindowThreadProcessId(Hwnd, ref pid);

                processWatcher.Add(pid.ToInt32(), 
                  Hwnd, 
                  windowClass.ToString(), 
                  windowText.ToString());
            }
            catch //(Exception ex)
            {
                //MessageBox.Show(ex.Message);
            }
        }
        return true;
    }

    internal static bool IsAltTabWindow(int hwnd)
    {
        // Start at the root owner
        int hwndWalk = GetAncestor(hwnd, 3);

        // See if we are the last active visible popup
        int hwndTry;
        while ((hwndTry = GetLastActivePopup(hwndWalk)) != hwndTry)
        {
            if (IsWindowVisible(hwndTry)) break;
            hwndWalk = hwndTry;
        }
        return hwndWalk == hwnd;
    }


}

public class ProcessWatcher
{
  private List<MyProcess> _processes = new List<MyProcess>;

  public UnmanagedCode.EnumWindowsDelegate callback 
    = new UnmanagedCode.EnumWindowsDelegate(UnmanagedCode.EnumWindowsCallBack);

  public void Update()
  {
    foreach (var proc in _processes )
    {
      proc.Updated = false;
    }

    UnmanagedCode.EnumWindows(callback, this);

    _processes = _processes
      .Where(p => p.Updated)
      .ToList();
  }

  public void Add(int processID, 
    int windowHandle, 
    string className, 
    string windowText)
  {

    var currentProcess = _processes.FirstOdDefault(p => p.ProcessId = processId);

    if (currentProcess != null)
    {
      // still running, already found
      currentProcess.Updated = true;
    }
    else // new process
    {
      try
      {
        Process proc = Process.GetProcessById(processId)
        fileName = proc.MainModule.ModuleName;
        _processes.Add(new MyProcess
          {
            ProcessId = processId,
            WindowHandle = windowHandle,
            ClassName = className,
            WindowText = windowText,
            FileName = fileName
          });
      }
      catch {}
    }
}

答案 1 :(得分:0)

使用UI Automation类似。

UIAFindWindows 递归方法使用自定义类作为数据容器返回指定Process ID的所有顶级Windows及其所有子Windows。

可以这样调用该方法:

List<ElementWindows> WindowHandles = UIAFindWindows(ProcessID, null);

null作为参数传递会使搜索从桌面开始,并以AutomationElement的祖先身份开始,对应于AutomationElement.RootElement

AutomationElement.FindAll()方法用于收集范围(TreeScope.Children)中的所有子元素。

此方法要求项目引用UIAutomationClientUIAutomationTypes

using System.Windows.Automation;

public class ElementWindows
{
    public int ProcessId { get; set; }
    public IntPtr MainWindowHandle { get; set; }
    public string MainWindowTitle { get; set; }
    public List<ElementWindows> SubWindows { get; set; }
}

public static List<ElementWindows> UIAFindWindows(int ProcessId, AutomationElement Root)
{
    if (Root == null) Root = AutomationElement.RootElement;
    List <ElementWindows> results = new List<ElementWindows>();
    var MatchingWindows = Root.FindAll(
        TreeScope.Children, new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Window));

    foreach (AutomationElement Window in MatchingWindows)
    {
        object ElementProcessId = Window.GetCurrentPropertyValue(AutomationElement.ProcessIdProperty, true);
        if (ElementProcessId != AutomationElement.NotSupported && ProcessId == (int)ElementProcessId)
        {
            ElementWindows foundElement = new ElementWindows()
            {
                ProcessId = ProcessId,
                MainWindowHandle = (IntPtr)Window.Current.NativeWindowHandle,
                MainWindowTitle = Window.Current.Name,
                SubWindows = UIAFindWindows(ProcessId, Window)
            };
            results.Add(foundElement);
        }
    }
    return results;
}