我有一个名为int
的{{1}}。我想使用pid
来调用来自此过程的任何窗口的函数。我从pinvoke整理了这段代码:
hwnd
该代码尚无法使用。在第一行中,它告诉我没有报告的重载与委托CallBackPtr相匹配。解决此问题的正确方法是什么?我从here
获取了代码答案 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)中的所有子元素。
此方法要求项目引用UIAutomationClient
和UIAutomationTypes
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;
}