Page 1 of 1

How to get file path of a window handle?

PostPosted: August 29th, 2005, 8:54 am
by Sina
HI
please help me
I want to get file path of a window handle
i don't want to use any library
I use GetModuleFileName function but i could just get my own program path
thank u
bye

PostPosted: August 29th, 2005, 4:46 pm
by Kambiz
I use the following unit in my applications to show version information to the user.

Code: Select all
//------------------------------------------------------------------------------
//
// AppInfo.pas -- Gathers Application's Version Information
//
// Copyright (C) Kambiz R. Khojasteh
// kambiz@qualilife.com
//
//------------------------------------------------------------------------------


unit AppInfo;

interface

uses
  Windows, Classes;

// :: Returns the full version information of the operating system
function GetOperatingSystemVersion: String;

// :: Returns the value of version iformation specified by ValueName parameter
//    from the file specified by the FileName parameter.
function GetVersionInfo(const FileName, ValueName: String): String;

// :: Fills the strings specified by Modules parameterwith the path of modules
//    loaded by the process specified by the ProcessID parameter.
// :: Returns the number of modules used by the process.
// :: Returns -1 on failure.
function GetModulesFromProcessID(ProcessID: THandle; Modules: TStrings): Integer;

// :: Fills the strings specified by Modules parameter with the path of modules
//    loaded by the process of the window specified by the hWnd parameter.
// :: Returns the number of modules used by the process.
// :: Returns -1 on failure.
function GetModulesFromWindowHandle(hWND: HWND; Modules: TStrings): Integer;

// :: Formats output of either GetModulesFromProcessID or GetModulesFromWindowHandle
//    procedures. This procedue includes version number of the modules to the list.
//    Mouldes and FormattedModules can point to same variable.
procedure FormatModuleList(Modules, FormattedModules: TStrings);

implementation

uses
  PSAPI, SysUtils;

function GetOperatingSystemVersion: String;
begin
  if (Win32Platform = VER_PLATFORM_WIN32_WINDOWS) and (Win32MajorVersion = 4) then
  begin
    if (Win32MinorVersion = 90) and (Win32BuildNumber = 3000) then
      Result := 'Windows Me'
    else if (Win32MinorVersion = 1) and (Win32BuildNumber = 2222) then
      Result := 'Windows 98 SE'
    else if Win32MinorVersion = 0 then
      Result := 'Windows 95 ' + Win32CSDVersion
    else
      Result := Format('Windows %d.%d (Build %d) %s', [Win32MajorVersion,
        Win32MinorVersion, Win32BuildNumber, Win32CSDVersion]);
  end
  else if Win32Platform = VER_PLATFORM_WIN32_NT then
  begin
    if (Win32MajorVersion = 5) and (Win32MinorVersion = 0) then
      Result := Format('Windows 2000 (Build %d) %s', [Win32BuildNumber, Win32CSDVersion])
    else if (Win32MajorVersion = 5) and (Win32MinorVersion = 1) then
      Result := Format('Windows XP (Build %d) %s', [Win32BuildNumber, Win32CSDVersion])
    else
      Result := Format('Windows NT %d.%d (Build %d) %s', [Win32MajorVersion,
        Win32MinorVersion, Win32BuildNumber, Win32CSDVersion]);
  end
  else
    Result := Format('Windows %d.%d (Build %d) %s', [Win32MajorVersion,
      Win32MinorVersion, Win32BuildNumber, Win32CSDVersion]);
end;

function GetVersionInfo(const FileName, ValueName: String): String;
var
  Trans: PDWORD;
  VerInfoSize, ValSize, Dummy: DWORD;
  VerInfo, Value: Pointer;
  TransStr, InfoStr: String;
begin
  Result := '';
  VerInfoSize := GetFileVersioninfoSize(PChar(FileName), Dummy);
  if VerInfoSize <> 0 then
  begin
    GetMem(VerInfo, VerInfoSize);
    try
      if GetFileVersionInfo(PChar(FileName), Dummy, VerInfoSize, VerInfo) then
      begin
        VerQueryValue(VerInfo, '\VarFileInfo\Translation', Pointer(Trans), valSize);
        TransStr := IntToHex(LoWord(Trans^), 4) + IntToHex(HiWord(Trans^), 4);
        if CompareText(ValueName, 'Language') <> 0 then
        begin
          InfoStr := '\StringFileInfo\' + TransStr + '\' + ValueName;
          if VerQueryValue(VerInfo, PChar(InfoStr), Value, ValSize) then
            Result := StrPas(Value);
        end
        else
        begin
          SetLength(Result, 256);
          VerLanguageName(LoWord(Trans^), PChar(Result), 256);
          SetLength(Result, StrLen(PChar(Result)));
        end;
      end;
    finally
      FreeMem(VerInfo);
    end;
  end;
end;

function GetModulesFromProcessID(ProcessID: THandle; Modules: TStrings): Integer;
var
  hProcess: THandle;
  NeededBytes: DWORD;
  phModules, phModule: PDWORD;
  ModuleName: array[0..1024] of Char;
  I: DWORD;
begin
  Result := -1;
  hProcess := OpenProcess(PROCESS_QUERY_INFORMATION or PROCESS_VM_READ, False, ProcessID);
  if hProcess <> 0 then
  begin
    try
      Result := 0;
      phModules := nil;
      if EnumProcessModules(hProcess, phModules, 0, NeededBytes) then
      begin
        GetMem(phModules, NeededBytes);
        try
          if EnumProcessModules(hProcess, phModules, NeededBytes, NeededBytes) then
          begin
            Result := NeededBytes div SizeOf(THandle);
            if Modules <> nil then
            begin
              phModule := phModules;
              Modules.BeginUpdate;
              try
                for I := 0 to Result - 1 do
                begin
                  if GetModuleFileNameEx(hProcess, phModule^, @ModuleName, SizeOf(ModuleName)) > 0 then
                    Modules.Add(ModuleName);
                  Inc(phModule);
                end;
              finally
                Modules.EndUpdate;
              end;
            end;
          end;
        finally
          FreeMem(phModules);
        end;
      end;
    finally
      CloseHandle(hProcess);
    end;
  end;
end;

function GetModulesFromWindowHandle(hWND: HWND; Modules: TStrings): Integer;
var
  ProcessID: THandle;
begin
  if GetWindowThreadProcessId(hWND, ProcessID) <> 0 then
    Result := GetModulesFromProcessID(ProcessID, Modules)
  else
    Result := -1;
end;

procedure FormatModuleList(Modules, FormattedModules: TStrings);
var
  I, N: Integer;
  MaxFileNameLen: Integer;
  MaxVersionLen: Integer;
  FileName: String;
  FilePath: String;
  Version: String;
  Line: String;
begin
  FormattedModules.BeginUpdate;
  try
    MaxFileNameLen := 0;
    MaxVersionLen := 0;
    for I := 0 to Modules.Count - 1 do
    begin
       FileName := ExtractFileName(Modules[I]);
       FilePath := ExcludeTrailingPathDelimiter(ExtractFilePath(Modules[I]));
       Version := GetVersionInfo(Modules[I], 'FileVersion');
        if Length(FileName) > MaxFileNameLen then
          MaxFileNameLen := Length(FileName);
        if Length(Version) > MaxVersionLen then
          MaxVersionLen := Length(Version);
        Line := FileName + #1 + Version + #1 + FilePath;
       if I < FormattedModules.Count then
         FormattedModules[I] := Line
       else
         FormattedModules.Add(Line);
    end;
    for I := FormattedModules.Count - 1 downto Modules.Count do
      FormattedModules.Delete(I);
    for I := 0 to FormattedModules.Count - 1 do
    begin
      Line := FormattedModules[I];
      N := Pos(#1, Line);
      Line := StringReplace(Line, #1, StringOfChar(' ', MaxFileNameLen + 2 - N) + ^I, []);
      N := Pos(#1, Line);
      Line := StringReplace(Line, #1, StringOfChar(' ', MaxFileNameLen + 2 + MaxVersionLen + 2 - N) + ^I, []);
      FormattedModules[I] := Line;
    end;
  finally
    FormattedModules.EndUpdate;
  end;
end;

end.

As an exmaple:

Code: Select all
uses
  AppInfo;

procedure TForm1.FormCreate(Sender: TObject);
begin
  GetModulesFromWindowHandle(Handle, ListBox1.Items);
  FormatModuleList(ListBox1.Items, Memo1.Lines);
  Caption := GetOperatingSystemVersion;
end;

If the specified ProcessID or Window Handle belongs to an application, the first item in the list is the application's path, otherwise it's the library path.

Cheers

Thank u

PostPosted: August 30th, 2005, 8:29 am
by Sina
Thanks a lot