如何获取winexec或shellexecute中执行的Handle?

发布于 2024-09-05 20:53:54 字数 104 浏览 8 评论 0原文

我用来创建一个自定义函数,如 winexec(...):Hwnd ,它将重新调整执行的应用程序的句柄。

我确实使用了 findwindow() 但如果它更改窗口标题就会出现问题。

i use to create a custom function like winexec(...):Hwnd that will retun the handle of executed application.

i did use the findwindow() but having problem if it change window caption.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

海之角 2024-09-12 20:53:54

没有一种通用方法可以获取应用程序的“该”窗口句柄,因为不能保证任何程序都有一个窗口句柄。一个程序可能有许多顶级句柄(即,Microsoft Word,每个文档一个),或者它可能根本没有窗口。您可能会问您真正需要窗口句柄的目的是什么?可能有更好的方法来做你想做的事情,不需要任何特定的窗口句柄。

WinExec(它已被弃用近 15 年了,因此您应该认真考虑不再使用它)和 ShellExecute 绝对不返回有关它们启动的程序的信息,如果它们确实如此启动任何程序。 (ShellExecute 可能使用 DDE 将命令发送到已运行的应用程序实例。)如果他们启动应用程序,它可能会在您的程序继续运行之前完成运行。

您可以使用 CreateProcessShellExecuteEx 代替。如果他们启动一个程序,他们会给您一个代表他们启动的程序的进程句柄。您可以使用它来帮助您获取有关该程序的其他信息,例如其窗口列表。不用费心FindWindow;标题和窗口类不保证是唯一的;一个程序可能对许多不同的窗口使用相同的类名,并且程序的多个实例将使用相同的类名,而没有太多方法来选择您真正想要的类名。

EnumWindows 是一个可用于获取候选窗口句柄列表的函数。您给它一个函数指针,它将为桌面上的每个顶级窗口调用该函数一次。您需要一种方法来告诉它您对哪个进程感兴趣,以及一种让它返回结果列表的方法。该函数只接受一个参数,因此该参数必须是一个指向包含更多信息的结构的指针:

type
  PWindowSearch = ^TWindowSearch;
  TWindowSearch = record
    TargetProcessID: DWord;
    ResultList: TWndList;
  end;

TWndList 是我创建的一种类型,用于保存 HWnd 列表> 价值观。如果您有 Delphi 2009 或更高版本,则可以使用 TList;对于早期版本,您可以使用 TList 后代或您选择的任何其他内容。

CreateProcess 将告诉您它填充的 TProcessInformation 记录的 dwProcessID 成员中的新进程 ID; ShellExecuteEx 仅返回进程句柄,因此请使用 GetProcessID 就可以了。窗口枚举函数需要一个与此签名匹配的回调函数:

function SelectWindowByProcessID(Wnd: HWnd; Param: LParam): Bool; stdcall;

您可以使用 EnumWindows 来获取如下句柄列表:

function GetWindowListByProcessID(pid: DWord): TWndList;
var
  SearchRec: TWindowSearch;
begin
  Result := TWndList.Create;
  try
    SearchRec.TargetProcessID := pid;
    SearchRec.ResultList := Result;
    Win32Check(EnumWindows(SelectWindowByProcessID, LParam(@SearchRec)));
  except
    Result.Free;
    raise;
  end;
end;

您将像这样实现回调函数:

function SelectWindowByProcessID(Wnd: HWnd; Param: LParam): Bool; stdcall;
var
  SearchRec: PWindowSearch;
  WindowPid: DWord;
begin
  SearchRec := PWindowSearch(Param);
  Assert(Assigned(SearchRec));
  GetWindowThreadProcessID(Wnd, WindowPid);
  if WindowPid = SearchRec.TargetProcessID then
    SearchRec.ResultList.Add(Wnd);
  Result := True;
end;

一旦获得列表,您就可以检查窗口的其他属性以确定哪些属性确实是您想要的。您可以通过窗口标题或类名,或者通过属于该窗口的其他控件来确定它。

使用完进程句柄后,请确保对其调用 CloseHandle ,以便操作系统可以清理进程的簿记信息。

There is no general way to get "the" window handle of an application because there's no guarantee that any program has one window handle. A program may have many top-level handles (i.e., Microsoft Word, one for each document), or it may have no windows at all. You might question what you really need the window handle for; there could be better ways of doing whatever it is you're trying to do that don't require any specific window handle.

WinExec (which has been deprecated for nearly 15 years, so you should seriously consider not using it anymore) and ShellExecute return absolutely no information about the programs they start, if indeed they start any program at all. (ShellExecute might use DDE to send a command to an already-running instance of the application.) And if they start an application, it might finish running before your program gets to run anymore.

You can use CreateProcess or ShellExecuteEx instead. If they start a program, they will give you a process handle representing the program they started. You can use that to help you get additional information about the program, such as a list of its windows. Don't bother with FindWindow; the caption and window class aren't guaranteed to be unique; a program might use the same class name for many different windows, and multiple instances of a program would use the same class name without much way to select the one you really want.

EnumWindows is a function you can use to get a list of candidate window handles. You give it a function pointer, and it will call that function once for each top-level window on the desktop. You'll need a way of telling it which process you're interested in, and a way for it to return a list of results. The function only accepts one parameter, so the parameter will have to be a pointer to a structure that holds more information:

type
  PWindowSearch = ^TWindowSearch;
  TWindowSearch = record
    TargetProcessID: DWord;
    ResultList: TWndList;
  end;

TWndList is a type I made up to hold a list of HWnd values. If you have Delphi 2009 or later, you could use TList<HWnd>; for earlier versions, you could use a TList descendant or whatever else you choose.

CreateProcess will tell you the new process ID in the dwProcessID member of the TProcessInformation record it fills; ShellExecuteEx only returns a process handle, so use GetProcessID on that. The window-enumerating function needs a callback function matching this signature:

function SelectWindowByProcessID(Wnd: HWnd; Param: LParam): Bool; stdcall;

You can use EnumWindows to get a handle list like this:

function GetWindowListByProcessID(pid: DWord): TWndList;
var
  SearchRec: TWindowSearch;
begin
  Result := TWndList.Create;
  try
    SearchRec.TargetProcessID := pid;
    SearchRec.ResultList := Result;
    Win32Check(EnumWindows(SelectWindowByProcessID, LParam(@SearchRec)));
  except
    Result.Free;
    raise;
  end;
end;

You'll implement the callback function like this:

function SelectWindowByProcessID(Wnd: HWnd; Param: LParam): Bool; stdcall;
var
  SearchRec: PWindowSearch;
  WindowPid: DWord;
begin
  SearchRec := PWindowSearch(Param);
  Assert(Assigned(SearchRec));
  GetWindowThreadProcessID(Wnd, WindowPid);
  if WindowPid = SearchRec.TargetProcessID then
    SearchRec.ResultList.Add(Wnd);
  Result := True;
end;

Once you have the list, you can inspect other attributes of the window to determine which ones are really the ones you want. You might determine it by window title or class name, or perhaps by the other controls that are one that window.

When you're finished using the process handle, make sure you call CloseHandle on it so the OS can clean up the process's bookkeeping information.

夏花。依旧 2024-09-12 20:53:54

有一个名为 EnumWindows 的函数。
我认为这对你有用。

检查以下链接以获取更多信息

http://delphi.about.com/od /windowsshellapi/l/aa080304a.htm

http://www. swissdelphicenter.ch/terry/showcode.php?id=327

There is function named EnumWindows.
I think it will be useful to you.

Check the following links for more information

http://delphi.about.com/od/windowsshellapi/l/aa080304a.htm

http://www.swissdelphicenter.ch/torry/showcode.php?id=327

夜巴黎 2024-09-12 20:53:54

尝试此页面 (http://delphidabbler.com/tips/134) 中的示例 6,然后对其进行修改一点点。我就是这么做的。

如果你想分开你检查的地方和你审查结果的地方,你可以做类似的事情,

var
  //...
  runNext : Boolean;
  //...

begin
{ startup code from other sample here }

// but instead of if
runNext := ShellExecuteEx(@SEInfo);

{ some more code here }

    // need delay before running next process
    // run loop until window with Handle is closed
if runNext then
    with SEInfo do
     repeat
      GetExitCodeProcess(SEInfo.hProcess, ExitCode);
      Sleep(20);
      Application.ProcessMessages;
      CheckSynchronize();
    until (ExitCode <> STILL_ACTIVE) or Application.Terminated;

{ next process code here }
end;

我意识到你们中的一些人会因为扔进 Sleep() 而在这上面投下仇恨邮件,但我不想锁定窗口,直到执行完毕当我正在处理一大堆东西并等待时就完成了。

Try example 6 from this page (http://delphidabbler.com/tips/134) and just modify it a little bit. That's what I did.

if you want to split where you check and where you review your result you can do something like

var
  //...
  runNext : Boolean;
  //...

begin
{ startup code from other sample here }

// but instead of if
runNext := ShellExecuteEx(@SEInfo);

{ some more code here }

    // need delay before running next process
    // run loop until window with Handle is closed
if runNext then
    with SEInfo do
     repeat
      GetExitCodeProcess(SEInfo.hProcess, ExitCode);
      Sleep(20);
      Application.ProcessMessages;
      CheckSynchronize();
    until (ExitCode <> STILL_ACTIVE) or Application.Terminated;

{ next process code here }
end;

I realize some of you will drop hate mail on this for throwing in Sleep(), but I'd rather not lock windows up until that execute is finished when I'm processing a boatload of stuff and waiting.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文