I would like to get list of programs running and visible in windows task manager's Applications Tab (not processes tab) and get their locations on HDD?
I need it to be done in Delphi. Anybody can help?
As far as I know, Application tab in Task Manager is a list of top-level windows which are not owned by other windows, have no parent, and are not tool windows. In my Process Info, I have a unit called AppInfo.pas which returns a list of windows with such characteristics, and the list matches what you see in Task Manager. Here is the main part of the code which is written as a call-back function for EnumWindows API function:
{$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;
For the full source code, you can refer to AppInfo.pas.
and get their locations on HDD
These are just windows. If you want to get path of EXE file corresponding to each item, you should first find the process which is owning this window, using GetWindowThreadProcessID API function. That is what I did in the above code. Once you have the process ID, you can get a process handle from it, and enumerate its modules. The first module is the main EXE file. I implemented that in my TProcessInfo component which is included in the same package with AppInfo.pas.
Here is a complete standalone solution (no more broken links)
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With