Linux环境下Lazarus通过第三方进程PID获取窗口句柄的方法
在Linux Lazarus中通过PID获取窗口句柄的实现方法
在Linux平台下,并没有和Windows EnumThreadWindows 完全对应的函数——因为X11窗口系统的模型和Windows不同。但可以通过遍历所有X11窗口,读取窗口的_NET_WM_PID属性来匹配目标进程的PID,从而找到对应的窗口句柄(X11中对应Window类型,等价于Windows的HWND)。
实现步骤与代码示例
依赖准备
确保你的Lazarus项目链接了X11库:在项目设置的Linking选项中,添加-lX11到Other linker options。同时需要在代码中引用X, Xlib, Xutil单元。核心实现代码
uses X, Xlib, Xutil, Classes; function GetWindowsByPID(Display: PDisplay; TargetPID: LongWord): TList<Window>; var RootWindow, ParentWindow: Window; ChildWindows: PWindow; ChildCount: Cardinal; WM_PID_Atom: TAtom; PropType: TAtom; PropFormat: Integer; PropItems: Cardinal; PropBytesAfter: Cardinal; PropData: PLongWord; i: Integer; CurrentWindow: Window; CurrentPID: LongWord; begin Result := TList<Window>.Create; if Display = nil then Exit; WM_PID_Atom := XInternAtom(Display, '_NET_WM_PID', False); if WM_PID_Atom = None then Exit; // 获取根窗口的子窗口列表 if not XQueryTree(Display, DefaultRootWindow(Display), @RootWindow, @ParentWindow, @ChildWindows, @ChildCount) then Exit; try for i := 0 to ChildCount - 1 do begin CurrentWindow := ChildWindows^[i]; // 获取当前窗口的_NET_WM_PID属性 if XGetWindowProperty(Display, CurrentWindow, WM_PID_Atom, 0, 1, False, XA_CARDINAL, @PropType, @PropFormat, @PropItems, @PropBytesAfter, PPointer(@PropData)) = Success then begin if (PropType = XA_CARDINAL) and (PropFormat = 32) and (PropItems = 1) then begin CurrentPID := PropData^; if CurrentPID = TargetPID then Result.Add(CurrentWindow); end; XFree(PropData); end; // 递归遍历子窗口 Result.AddRange(GetWindowsByPID(Display, TargetPID)); end; finally XFree(ChildWindows); end; end; // 使用示例 procedure TForm1.Button1Click(Sender: TObject); var Display: PDisplay; TargetPID: LongWord; WindowList: TList<Window>; i: Integer; begin Display := XOpenDisplay(nil); if Display = nil then begin ShowMessage('无法连接到X服务器'); Exit; end; try TargetPID := 1234; // 替换为目标进程的PID WindowList := GetWindowsByPID(Display, TargetPID); try if WindowList.Count > 0 then begin ShowMessage(Format('找到 %d 个属于PID %d 的窗口', [WindowList.Count, TargetPID])); for i := 0 to WindowList.Count - 1 do ShowMessage(Format('窗口句柄: %d', [WindowList[i]])); end else ShowMessage('未找到对应PID的窗口'); finally WindowList.Free; end; finally XCloseDisplay(Display); end; end;
关键说明
_NET_WM_PID是X11标准扩展属性,绝大多数现代桌面程序都会设置这个属性,用来关联窗口和所属进程。- 递归遍历是为了覆盖所有嵌套的窗口(比如应用程序的子对话框、工具栏窗口等)。
- X11的
Window类型就是Linux下的窗口句柄,和Windows的HWND作用一致,可以用来执行窗口操作(比如移动、关闭等)。
注意事项
- 部分老旧或极简X11程序可能没有实现
_NET_WM_PID属性,这种情况无法通过该方法匹配PID。 - 确保程序运行时
DISPLAY环境变量正确设置(通常默认已经配置好,远程桌面场景需要手动指定)。
内容的提问来源于stack exchange,提问作者prostor
相关产品推荐
相关产品推荐

