如何获得在winexec或shellexecute中执行的Handle? [英] How to get the Handle that is executed in winexec or shellexecute?

查看:444
本文介绍了如何获得在winexec或shellexecute中执行的Handle?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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

我使用了findwindow()但是如果更改窗口标题,则会出现问题。

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

推荐答案

没有一般方法来获取应用程序的窗口句柄不能保证任何程序都有一个窗口句柄。程序可以具有许多顶级句柄(即,Microsoft Word,每个文档一个),或者根本没有窗口。你可能会问你真正需要的窗口句柄;可能会有更好的方式做任何你想要做的事情,不需要任何特定的窗口句柄。

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 (已经不推荐使用近15年了,所以你应该认真考虑不要再使用它了)和 ShellExecute 绝对没有关于他们开始的程序的信息,如果确实启动任何程序。 ( ShellExecute 可能会使用DDE向已经运行的应用程序实例发送一个命令)。如果他们启动一个应用程序,它可能会在程序运行之前完成运行

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.

您可以使用 CreateProcess ShellExecuteEx 。如果他们启动一个程序,他们会给你一个代表他们开始的程序的进程句柄。您可以使用它来帮助您获取有关该程序的其他信息,例如其窗口列表。不要打扰 FindWindow ;标题和窗口类不能保证是唯一的;程序可能为许多不同的窗口使用相同的类名,程序的多个实例将使用相同的类名,而无需选择真正需要的类。

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 是一个可以用来获取候选窗口句柄列表的函数。你给它一个函数指针,它将为桌面上的每个顶级窗口调用该函数一次。您需要一种告诉您您感兴趣的过程的方法,并将其返回结果列表。该函数只接受一个参数,因此该参数必须是指向包含更多信息的结构的指针:

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 是一种类型,持有 HWnd 值的列表。如果您有Delphi 2009或更高版本,您可以使用 TList< HWnd> ;对于早期版本,您可以使用 TList 后裔或您选择的任何其他选项。

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 将告诉您 dwProcessID 成员之间的新进程ID, TProcessInformation 记录它填充 ShellExecuteEx 只返回一个进程句柄,所以使用 GetProcessID 。窗口枚举函数需要一个与此签名相匹配的回调函数:

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;

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

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.

完成使用过程句柄后,请确保您可以致电 CloseHandle ,以便操作系统可以清理进程的记账信息。

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.

这篇关于如何获得在winexec或shellexecute中执行的Handle?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆