Recent

Author Topic: [SOLVED] Get unique constant identifier  (Read 3443 times)

pcurtis

  • Hero Member
  • *****
  • Posts: 951
Re: Get unique constant identifier
« Reply #15 on: May 18, 2021, 06:18:27 pm »
May be I'm stupid, but I can't find any code.
Windows 10 20H2
Laz 2.2.0
FPC 3.2.2

440bx

  • Hero Member
  • *****
  • Posts: 3921
Re: Get unique constant identifier
« Reply #16 on: May 18, 2021, 06:25:18 pm »
May be I'm stupid, but I can't find any code.
you need to expand the archive.  The .7z file is a compressed archive, you need 7zip to decompress it.  7zip is a free download, I recommend it, very nice utility.

Once expanded, you'll find there is a .lpr file (and the .lps, lpi).  The .lpr is the entire program.
(FPC v3.0.4 and Lazarus 1.8.2) or (FPC v3.2.2 and Lazarus v3.2) on Windows 7 SP1 64bit.

pcurtis

  • Hero Member
  • *****
  • Posts: 951
Re: Get unique constant identifier
« Reply #17 on: May 18, 2021, 06:50:58 pm »
OK, got it. Compiles and runs.

It's way out of my competence  :o
Windows 10 20H2
Laz 2.2.0
FPC 3.2.2

440bx

  • Hero Member
  • *****
  • Posts: 3921
Re: Get unique constant identifier
« Reply #18 on: May 18, 2021, 07:03:44 pm »
OK, got it. Compiles and runs.

It's way out of my competence  :o
Good on both counts.  That it's out of your competence is a good thing.  Use the debugger to step through the program.  This might help
Code: Pascal  [Select][+][-]
  1. function EnumWindowsProc(Wnd : HWND; WindowListInt : ptruint) : BOOL; stdcall;
  2.   { this function is called by the EnumWindows call. It fills the a window    }
  3.   { list with the window information we are interested in.                    }
  4.  
  5. var
  6.   WindowList            : PWindowList absolute WindowListInt;
  7.  
  8.   ProcessHandle         : THANDLE;
  9.  
  10.   TimeOfNoInterest      : TFILETIME;
  11.   ProcessExecutableSize : DWORD;
  12.  
  13. begin
  14.   EnumWindowsProc := TRUE;       { continue enumerating until no more windows }
  15.  
  16.   with WindowList^.WindowInfo[WindowList^.WindowCount] do
  17.   begin
  18.     WindowHandle  := Wnd;
  19.  
  20.     WindowThreadId := GetWindowThreadProcessId(Wnd, @WindowProcessId);
  21.     WindowVisible  := IsWindowVisible(Wnd);
  22.     GetWindowText(Wnd, WindowCaption, sizeof(WindowCaption));
  23.  
  24.     { get the process times for this process.  NOTE: the method used here is  }
  25.     { very inefficient since a handle for the same process is obtained for    }
  26.     { every window the process has created.                                   }
  27.  
  28.     ProcessHandle := OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION,
  29.                                  FALSE,
  30.                                  WindowProcessId);
  31.  
  32.     if ProcessHandle <> 0 then
  33.     begin
  34.       { IMPORTANT: the size must be reset every time because QueryFullProcess }
  35.       {            ImageName sets it to the length of the returned string     }
  36.       {            every time it's called.                                    }
  37.  
  38.       ProcessExecutableSize := sizeof(WindowProcessExecutable);
  39.  
  40.       QueryFullProcessImageName(ProcessHandle,
  41.                                 0,
  42.                                 WindowProcessExecutable,
  43.                                 ProcessExecutableSize);
  44.  
  45.       GetProcessTimes(ProcessHandle,
  46.                       WindowProcessCreationTime,
  47.                       TimeOfNoInterest,
  48.                       TimeOfNoInterest,
  49.                       TimeOfNoInterest);
  50.  
  51.       CloseHandle(ProcessHandle);
  52.     end;
  53.   end;
  54.  
  55.   with WindowList^ do
  56.   begin
  57.     WindowInfoPointers[WindowCount] := @WindowInfo[WindowCount];
  58.     inc(WindowCount);
  59.  
  60.     if WindowCount > high(WindowInfo) then
  61.     begin
  62.       EnumWindowsProc := FALSE;   { no more room, stop enumerating            }
  63.     end;
  64.   end;
  65. end;
  66.  


and

Code: Pascal  [Select][+][-]
  1.     WM_COMMAND:
  2.     begin
  3.       case LOWORD(wParam) of
  4.         IDM_UPDATE_WINDOW_LIST:
  5.         begin
  6.           ZeroMemory(WindowList, sizeof(WindowList^));
  7.  
  8.           { fill it with the window handles and their caption text            }
  9.  
  10.           EnumWindows(@EnumWindowsProc,
  11.                       ptruint(WindowList));           { pass the WindowList   }
  12.  
  13.           { if the "sort by process" menu item is checked then the new window }
  14.           { list must be sorted by process before the listbox is updated.     }
  15.  
  16.           MenuItemState := GetMenuState(GetMenu(Wnd),
  17.                                         IDM_PROCESS_SORT,
  18.                                         MF_BYCOMMAND);
  19.  
  20.           if MenuItemState and MF_CHECKED <> 0 then
  21.           begin
  22.             { sort the window list                                            }
  23.  
  24.             with WindowList^ do
  25.             begin
  26.               qsort(@WindowInfoPointers,
  27.                      WindowCount,
  28.                      sizeof(WindowInfoPointers[low(WindowInfoPointers)]),
  29.                      TCompareFunction(@CompareWindowInfoProcessId));
  30.             end;
  31.  
  32.             PostMessage(Wnd, WM_COMMAND, IDM_UPDATE_LISTBOX, 0);
  33.             exit;
  34.           end;
  35.  
  36.           { if the "sort by process creation time" is checked then the new    }
  37.           { window list must be sorted accordingly.                           }
  38.  
  39.           MenuItemState := GetMenuState(GetMenu(Wnd),
  40.                                         IDM_PROCESS_CREATION_SORT,
  41.                                         MF_BYCOMMAND);
  42.  
  43.           if MenuItemState and MF_CHECKED <> 0 then
  44.           begin
  45.             { sort the window list                                            }
  46.  
  47.             with WindowList^ do
  48.             begin
  49.               qsort(@WindowInfoPointers,
  50.                      WindowCount,
  51.                      sizeof(WindowInfoPointers[low(WindowInfoPointers)]),
  52.                      TCompareFunction(@CompareWindowInfoProcessTimes));
  53.             end;
  54.  
  55.             PostMessage(Wnd, WM_COMMAND, IDM_UPDATE_LISTBOX, 0);
  56.             exit;
  57.           end;
  58.  
  59.           { unnecessary but safe                                              }
  60.  
  61.           PostMessage(Wnd, WM_COMMAND, IDM_UPDATE_LISTBOX, 0);
  62.  
  63.           exit;
  64.         end;
  65.  

Put a breakpoint at each of the highlighted lines, debug the program and step through the code when the breakpoints are hit.  Hover over the variables and you'll see how it all works.

You'll figure it out.


(FPC v3.0.4 and Lazarus 1.8.2) or (FPC v3.2.2 and Lazarus v3.2) on Windows 7 SP1 64bit.

pcurtis

  • Hero Member
  • *****
  • Posts: 951
Re: Get unique constant identifier
« Reply #19 on: May 18, 2021, 07:12:26 pm »
I think I've got it  :)

Code: Pascal  [Select][+][-]
  1. function GetCurrentActiveProcessPath: String;
  2. var
  3.   ProcessHandle : DWORD;
  4.   ProcessExecutableSize     : DWORD;
  5.   WindowHandle              : HWND;
  6.   WindowProcessId           : DWORD;
  7.   WindowThreadId            : DWORD;
  8.   WindowProcessCreationTime : TFILETIME;                     { inefficient  }
  9.   WindowProcessExecutable   : packed array[0..511] of char;  { inefficient  }
  10.   WindowVisible             : BOOL;
  11.   WindowCaption             : packed array[0..127] of char;
  12. begin
  13.   WindowHandle := GetForegroundWindow;
  14.  
  15.   WindowThreadId := GetWindowThreadProcessId(WindowHandle, @WindowProcessId);
  16.  
  17.   ProcessHandle := OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION,
  18.                                  FALSE,
  19.                                  WindowProcessId);
  20.  
  21.   if ProcessHandle <> 0 then
  22.     begin
  23.       ProcessExecutableSize := Length(WindowProcessExecutable);  // a buffer you declare anywhere you want.
  24.  
  25.       QueryFullProcessImageName(ProcessHandle,
  26.                                0,
  27.                                WindowProcessExecutable,
  28.                                @ProcessExecutableSize);
  29.  
  30.     end;
  31.   Result := WindowProcessExecutable;
  32. end;
  33.  
Windows 10 20H2
Laz 2.2.0
FPC 3.2.2

440bx

  • Hero Member
  • *****
  • Posts: 3921
Re: Get unique constant identifier
« Reply #20 on: May 18, 2021, 07:24:04 pm »
That looks like it should work.
(FPC v3.0.4 and Lazarus 1.8.2) or (FPC v3.2.2 and Lazarus v3.2) on Windows 7 SP1 64bit.

pcurtis

  • Hero Member
  • *****
  • Posts: 951
Re: [SOLVED] Get unique constant identifier
« Reply #21 on: May 19, 2021, 10:25:02 am »
Indeed it does. Thanks.
Windows 10 20H2
Laz 2.2.0
FPC 3.2.2

 

TinyPortal © 2005-2018