Jump to content

Ian Branch

Members
  • Content Count

    1352
  • Joined

  • Last visited

  • Days Won

    3

Everything posted by Ian Branch

  1. Hi Team, At the moment I use a variable to indicate the Delphi version for an About box in Apps. This looks like this: Delphi Athens 12.2 Patch 2. Is there some meaans within Delphi to return this information, or a reasonable semblance, so I don't have to manually update the About box? Regards & TIA, Ian
  2. As could I, but I was hoping for something more informative from Delphi. That 'uniquely identifying number' is applicable to Delphi 12.0, 12.1, 12.2, 12.2 Patch 1 & 12.2 Patch 2. Never mind. I will stick with manual updates as required.
  3. That will only return 36. Call it a personal preference, I like to have the information in the About dialog. Saying the Application was built with 'Delphi v 36' isn't as informative as 'Delphi Athens v 12.2 Patch 2'.
  4. Ian Branch

    Putting Delphi Application inside web page

    I agree with your comments. I suspect it is a visibility/awareness issue. I have spoken with many of my peers and they were not aware of it. I also think that developers are focussing on Apple & Android for Apps on thos devices rather than what can be done within the PC realm.
  5. Ian Branch

    Updated Webhelp for GExperts available

    Ah Ha! Tks. All good now. Never heard of the 'unblock' 'feature'...
  6. Ian Branch

    Updated Webhelp for GExperts available

    Win 11, 4k monitor. Hmm. Downloaded OK, Opened OK. Left Pane works fine, nothing shows in the main pane. 😞
  7. Ian Branch

    Need help please..

    Thank you one and all. For the record, I have it working with the following code: unit Unit20; interface uses Winapi.Windows, Winapi.TlHelp32, System.SysUtils, System.Classes, Vcl.Controls, Vcl.Forms, Vcl.StdCtrls; type TForm20 = class(TForm) Button1: TButton; Memo1: TMemo; procedure Button1Click(Sender: TObject); private { Private declarations } public { Public declarations } end; var Form20: TForm20; implementation {$R *.dfm} type PTOKEN_USER = ^TOKEN_USER; // function IsFileOpen(const FileName: string): Boolean; var HFile: THandle; begin // Try to open the file with exclusive access (no sharing allowed) HFile := CreateFile(PChar(FileName), GENERIC_READ or GENERIC_WRITE, 0, nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); // Check if the file handle is invalid, which indicates an error if HFile = INVALID_HANDLE_VALUE then // Check if the error is due to a sharing violation Result := GetLastError = ERROR_SHARING_VIOLATION else begin // If the file was successfully opened, it means there’s no sharing violation Result := False; CloseHandle(HFile); // Close the handle if we managed to open the file end; // end; function GetUserNameForProcess(ProcessID: DWORD): string; var hProcess: THandle; TokenHandle: THandle; //TokenUser: PTOKENUSER; ptiUser: PTOKEN_USER; ReturnLength: DWORD; Name: array[0..255] of Char; NameLength: DWORD; Domain: array[0..255] of Char; DomainLength: DWORD; Use: SID_NAME_USE; begin // Result := 'Unknown'; hProcess := OpenProcess(PROCESS_QUERY_INFORMATION, False, ProcessID); // if hProcess <> 0 then begin if OpenProcessToken(hProcess, TOKEN_QUERY, TokenHandle) then try GetTokenInformation(TokenHandle, TokenUser, nil, 0, ReturnLength); ptiUser := AllocMem(ReturnLength); try if GetTokenInformation(TokenHandle, TokenUser, ptiUser, ReturnLength, ReturnLength) then begin NameLength := SizeOf(Name); DomainLength := SizeOf(Domain); if LookupAccountSid(nil, ptiUser.User.Sid, Name, NameLength, Domain, DomainLength, Use) then Result := Format('%s\%s', [Domain, Name]); end; finally FreeMem(ptiUser); end; finally CloseHandle(TokenHandle); end; CloseHandle(hProcess); end; // end; procedure ScanForDBiFiles(const Directory: string; var Results: TStringList); var SearchRec: TSearchRec; ProcessEntry: TProcessEntry32; Snapshot: THandle; FileName: string; begin // Results.Clear; // if FindFirst(IncludeTrailingPathDelimiter(Directory) + 'DBi*.exe', faAnyFile, SearchRec) = 0 then begin try repeat FileName := IncludeTrailingPathDelimiter(Directory) + SearchRec.Name; // Check if the file is open if IsFileOpen(FileName) then begin // Enumerate processes to find the one using this file Snapshot := CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); if Snapshot <> INVALID_HANDLE_VALUE then begin ProcessEntry.dwSize := SizeOf(TProcessEntry32); if Process32First(Snapshot, ProcessEntry) then begin repeat // Check if the process has the same file name as the one we're looking for if SameText(ExtractFileName(ProcessEntry.szExeFile), SearchRec.Name) then begin // Results.Add(Format('File: %s, User: %s', [FileName, GetUserNameForProcess(ProcessEntry.th32ProcessID)])); Results.Add(Format('File: %-17s User: %s', [ExtractFileName(FileName), GetUserNameForProcess(ProcessEntry.th32ProcessID)])); // Break; end; until not Process32Next(Snapshot, ProcessEntry); end; CloseHandle(Snapshot); end; end; until FindNext(SearchRec) <> 0; finally FindClose(SearchRec); end; end; // end; procedure TForm20.Button1Click(Sender: TObject); var Results: TStringList; begin // Results := TStringList.Create; try ScanForDBiFiles('E:\DBiWorkflow', Results); Memo1.Lines.Assign(Results); // This line adds the results to Memo1 finally Results.Free; end; // end; end. My thanks to all for your input. Appreciated. Ian
  8. Ian Branch

    Need help please..

    Win 11, D12.2 P1. 32 bit App. I asked ChatGPT to write a unit that would scan a given drive/directory for all instances of a .exe file starting with 'DBi', and return the name of the file(s) that were currently in use and the name of the User(s). ChatGPT gave me this: uses System.SysUtils, System.Classes, Windows, TlHelp32, PsAPI, JclSysInfo; function IsFileOpen(const FileName: string): Boolean; var HFile: THandle; begin HFile := CreateFile(PChar(FileName), GENERIC_READ or GENERIC_WRITE, 0, nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); Result := (HFile = INVALID_HANDLE_VALUE); if not Result then CloseHandle(HFile); end; function GetUserNameForProcess(ProcessID: DWORD): string; var hProcess: THandle; TokenHandle: THandle; TokenUser: PTOKEN_USER; ReturnLength: DWORD; Name: array[0..255] of Char; NameLength: DWORD; Domain: array[0..255] of Char; DomainLength: DWORD; Use: SID_NAME_USE; begin Result := 'Unknown'; hProcess := OpenProcess(PROCESS_QUERY_INFORMATION, False, ProcessID); if hProcess <> 0 then begin if OpenProcessToken(hProcess, TOKEN_QUERY, TokenHandle) then try GetTokenInformation(TokenHandle, TokenUser, nil, 0, ReturnLength); TokenUser := AllocMem(ReturnLength); try if GetTokenInformation(TokenHandle, TokenUser, ReturnLength, ReturnLength) then begin NameLength := SizeOf(Name); DomainLength := SizeOf(Domain); if LookupAccountSid(nil, TokenUser.User.Sid, Name, NameLength, Domain, DomainLength, Use) then Result := Format('%s\%s', [Domain, Name]); end; finally FreeMem(TokenUser); end; finally CloseHandle(TokenHandle); end; CloseHandle(hProcess); end; end; procedure ScanForDBiFiles(const Directory: string; var Results: TStringList); var SearchRec: TSearchRec; ProcessEntry: TProcessEntry32; Snapshot: THandle; FileName: string; begin Results.Clear; if FindFirst(IncludeTrailingPathDelimiter(Directory) + 'DBi*.exe', faAnyFile, SearchRec) = 0 then begin try repeat FileName := IncludeTrailingPathDelimiter(Directory) + SearchRec.Name; // Check if the file is open if IsFileOpen(FileName) then begin // Enumerate processes to find the one using this file Snapshot := CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); if Snapshot <> INVALID_HANDLE_VALUE then begin ProcessEntry.dwSize := SizeOf(TProcessEntry32); if Process32First(Snapshot, ProcessEntry) then begin repeat // Check if the process has the same file name as the one we're looking for if SameText(ExtractFileName(ProcessEntry.szExeFile), SearchRec.Name) then begin Results.Add(Format('File: %s, User: %s', [FileName, GetUserNameForProcess(ProcessEntry.th32ProcessID)])); Break; end; until not Process32Next(Snapshot, ProcessEntry); end; CloseHandle(Snapshot); end; end; until FindNext(SearchRec) <> 0; finally FindClose(SearchRec); end; end; end; procedure TForm1.Button1Click(Sender: TObject); var Results: TStringList; begin Results := TStringList.Create; try ScanForDBiFiles('C:\YourDirectory', Results); ShowMessage(Results.Text); finally Results.Free; end; end; Whilst most of it is OK, Delphi balks immediately at "TokenUser: PTOKEN_USER;". 😞 Seems it doesn't know about PTOKEN_USER. ?? I think it is part of Windows but I can't pin it down. I would really appreciate any and all help in getting this going. Regards & TIA, Ian
  9. Ian Branch

    Putting Delphi Application inside web page

    This is a Web Page one of my Customers has. It is a generic page created by TF.
  10. Ian Branch

    Putting Delphi Application inside web page

    As a Developer I use it to create Apps and test them. Not daily but regularly. Win 11, 64GB RAM, D12.2, 32 bit apps. My Customers have it running 24/7 so their own staff as well as their Customers can access respective Apps. IIRC, they are using a Windows Server 2012 R2 PC. 2 running an Intel Xeon X3450. 2 x HDD in Raid 1. 16GB RAM. Up to 15 Users att but that may increase soon. RAM usage has got close a couple of times but never got in the road.
  11. Ian Branch

    Need help please..

    My thanks to all. This is clearly all out of my league. 😞 I will drop this idea. Thanks again to all for your input/advice. Ian
  12. Ian Branch

    Need help please..

    Noted. Tks. A minor aspect I can resolve later. Delphi gives me this: [dcc32 Error] Unit20.pas(58): E2010 Incompatible types: 'TTokenInformationClass' and 'PTokenUser'
  13. Ian Branch

    Need help please..

    Tks Lajos. Appreciated. That solved that issue but unfortunately I don't understand enough about using Windows stuff to understand why GetTokenInformation(TokenHandle, TokenUser, nil, 0, ReturnLength); and if GetTokenInformation(TokenHandle, TokenUser, ReturnLength, ReturnLength) then are not hapy in this context. 😞 I perceive it is probably to do with the use of TokenUser.
  14. Ian Branch

    Putting Delphi Application inside web page

    Sorry, no idea what the current pricing is. I got it when it was at KickStarter stage way back in 2014. πŸ™‚ Cost is based on what options you select and how many Users. I have the Developer Pro version but my Customers have the Standard version with 15 Users. IIRC my renewal was around US$30. Drop a line to Cybele and ask. Ian
  15. Ian Branch

    Putting Delphi Application inside web page

    Yep. Use it all the time. So do my Customers. It means that I only need to maintain one App and it can be accessed via LAN, WAN, RDP or WEB. It is accessed on the WEB via any Browser. The only issues I have had was more of issues with portable devices/tablets and some compatabilities that need to be accepted or worked around. Particularly mousing.
  16. Ian Branch

    Delphi 12.2 Patch 1

    My experience today is that if the Library installs or updates by building its .bpl, .dcp & .dcu files than they need to be rebuilt with D12.2 p1. This I suspect is due to the binary incompatability that occurred with D12.2. Now rectified.
  17. Ian Branch

    Delphi 12.2 available for download

    It is also a breaking change for all those 3rd Party libraries that you get their source code for and install by building their files. I have spent a couple of hours rebuilding libraries I had the source for that needed to be re-installed as, presumably, their existing .bpl/.dcp/.dcu files were no longer compatible. Also the existing installed plug-ins - GExperts, Eurekalog, MMX & cnWizards won't load. I rebuilt GExperts and is OK but I will have to wait for the other 3.
  18. Ian Branch

    Delphi 12.2 Patch 1

    Broke the current MMX & cnWizards. 😞
  19. Ian Branch

    Drag Drop via Ole

    FWIW I can recommend the landrix suite, it is based on anders' suite.
  20. Ian Branch

    Uses units qualifiers?

    In which version of Delphi were the uses unit's qualifiers like Vcl. & System. introduced?
  21. Ian Branch

    Uses units qualifiers?

    Sigh!
  22. Ian Branch

    Uses units qualifiers?

    Perish the thought. πŸ™‚ Excellent. Tks.
  23. Ian Branch

    Uses units qualifiers?

    Tks Dave. I didn't realise it was that 'long' ago. ;-) Cheers.
  24. Ian Branch

    Saving Explicit Properties??

    Tks Remy. I suspect the answer is there. I have forwarded the reference to the Developer.
Γ—