2010-08-01 11 views

回答

3

据我所知,任务管理器中的“应用程序”选项卡是顶级窗口列表,它不属于其他窗口,没有父项,也不是工具窗口。在我的Process Info中,我有一个名为AppInfo.pas的单元,它返回具有这些特征的窗口列表,并且该列表与您在任务管理器中看到的内容相匹配。这里是一个被写成了EnumWindows的API函数的调用回调函数的代码的主要部分:

{$IFDEF DELPHI2007UP} 
class function TAppWindowCollection.EnumWinProc(wHandle: HWND; lparam: integer): Bool; 
{$ELSE} 
function EnumWinProc(wHandle: HWND; lparam: integer): Bool; stdcall; 
{$ENDIF} 
Const 
    MAX_TEXT = MAX_PATH; 
var 
    WindowItem : TWindowItem; 
    strText,strClass : array [0..MAX_TEXT] of char; 
    IsAppMainWin : Boolean; 
begin 
    //Check if the window is a visible application main window. 
    IsAppMainWin := IsWindowVisible(wHandle)   AND      //Visible 
        (GetWindow(wHandle,GW_OWNER) = 0) AND      //Not owned by other windows 
        (GetParent(wHandle) = 0)   AND      //Does not have any parent 
        (GetWindowLong(wHandle,GWL_EXSTYLE) AND WS_EX_TOOLWINDOW = 0); //Not a tool window 

    if IsAppMainWin then 
    begin 
    WindowItem := TAppWindowCollection(lparam).Add; 

    GetWindowText(wHandle,strText,MAX_TEXT); 
    GetClassName(wHandle,strClass,MAX_TEXT); 

    WindowItem.FCaption := strText; 
    WindowItem.FHandle := wHandle; 
    WindowItem.FWindowClass := strClass; 
    GetWindowThreadProcessId(wHandle,WindowItem.FProcessID); 
    end; 

    Result := True; 
end; 

对于完整的源代码,你可以参考AppInfo.pas

,并得到他们的HDD

位置这些不仅仅是Windows。如果你想得到每个项目对应的EXE文件的路径,你应该首先使用GetWindowThreadProcessID API函数找到拥有这个窗口的过程。这就是我在上面的代码中所做的。一旦你有了进程ID,你可以从中获得一个进程句柄,并枚举它的模块。第一个模块是主EXE文件。我在我的TProcessInfo组件中实现了该组件,该组件与AppInfo.pas包含在同一个包中。

+0

感谢名单这么多! – chubbyk 2010-08-01 15:59:41

+1

相关链接已过期! – Kermia 2013-01-06 15:50:38

2

下面是一个完整独立的解决方案(没有更多的坏链接)

program ApplicationList; 

{$APPTYPE CONSOLE} 
{$R *.res} 

uses 
    System.SysUtils, 
    Winapi.Windows, 
    Winapi.PsAPI; 

function GetPathFromPID(const PID : cardinal) : string; 
var 
    hProcess : THandle; 
    path :  array [0 .. MAX_PATH - 1] of char; 
begin 
    hProcess := OpenProcess(PROCESS_QUERY_INFORMATION or PROCESS_VM_READ, false, PID); 
    if hProcess <> 0 
    then 
    try 
     if GetModuleFileNameEx(hProcess, 0, path, MAX_PATH) = 0 
     then 
     RaiseLastOSError; 
     Result := path; 
    finally 
     CloseHandle(hProcess) 
    end 
    else 
    RaiseLastOSError; 
end; 

function EnumWinProc(wHandle : hWnd; lparam : integer) : Bool; stdcall; 
Const 
    MAX_TEXT = MAX_PATH; 
var 
    strText, strClass : array [0 .. MAX_TEXT] of char; 
    strPath :   string; 
    IsAppMainWin :  Boolean; 
    ProcId :   cardinal; 
begin 
    // Check if the window is a visible application main window. 
    IsAppMainWin := IsWindowVisible(wHandle) AND // Visible 
    (GetWindow(wHandle, GW_OWNER) = 0) AND // Not owned by other windows 
    (GetParent(wHandle) = 0) AND    // Does not have any parent 
    (GetWindowLong(wHandle, GWL_EXSTYLE) AND WS_EX_TOOLWINDOW = 0); // Not a tool window 

    if IsAppMainWin 
    then 
    begin 

     GetWindowText(wHandle, strText, MAX_TEXT); 
     GetClassName(wHandle, strClass, MAX_TEXT); 

     GetWindowThreadProcessID(wHandle, ProcId); 

     try 
     strPath := GetPathFromPID(ProcId); 
     except 
     strPath := '???'; 
     end; 

     WriteLn(ProcId, ' - ', strClass, ' - ', strText, ' - ', strPath); 
    end; 

    Result := True; 
end; 

procedure DoEnumWindows; 
var 
    FirstWnd : cardinal; 
begin 
    EnumWindows(@EnumWinProc, cardinal(@FirstWnd)); 
end; 

begin 
    try 
    DoEnumWindows; 
    except 
    on E : Exception do 
     WriteLn(E.ClassName, ': ', E.Message); 
    end; 

    ReadLn; 

end. 
+0

不是真实可用的代码。我无法使用它 – Kermia 2013-01-07 12:45:47

+0

@Kermia什么是不可用于此代码?它编译和检索所有想要的信息(德尔福XE3) – 2013-01-07 13:17:32

+3

@Kermia - 应该怎么找出与你的评论代码有什么问题,我想知道.. – 2013-01-07 17:35:50

相关问题