Ian Branch 127 Posted May 18, 2023 (edited) Hi Team, D11.3.1. I have the following function I am trying to get to work.. function GetApplicationInstances(const FileName: string): TArray<string>; var ProcessList: TProcessList; Process: TProcess; i: Integer; begin Result := TArray<string>.Create; ProcessList := TProcessList.Create; try for i := 0 to ProcessList.Count - 1 do begin Process := ProcessList[i]; if Process.FileName = FileName then begin Result.Add(Process.UserName); end; end; finally ProcessList.Free; end; end; I have bothe System.SysUtils and System.Diagnostics in my Uses clause but I am still gettin an 'undeclared identifier' for TProcessList and TProcess. What have I missed please? Regards & TIA, Ian Edited May 18, 2023 by Ian Branch Share this post Link to post
programmerdelphi2k 237 Posted May 18, 2023 (edited) @Ian Branch in my RAD11.3 UP1 and I dont have this Class/record named TProcessList in all sources!!! verify your project sources or anyother used in your project! Edited May 18, 2023 by programmerdelphi2k Share this post Link to post
Remy Lebeau 1394 Posted May 18, 2023 (edited) 48 minutes ago, Ian Branch said: I have bothe System.SysUtils and System.Diagnostics in my Uses clause but I am still gettin an 'undeclared identifier' for TProcessList and TProcess. What have I missed please? Delphi does not have any native classes named TProcess or TProcessList. Your example is clearly based on 3rd party code that you don't have installed, which is why the classes are undefined. Edited May 18, 2023 by Remy Lebeau Share this post Link to post
Ian Branch 127 Posted May 18, 2023 1 minute ago, Remy Lebeau said: Delphi does not have any native classes named TProcess or TProcessList. This is clearly based on 3rd party code. Bummer. Any suggestions? Share this post Link to post
Ian Branch 127 Posted May 18, 2023 Hi Team, I found that bit of code and thought it would do the trick. Oh well. What I am try to achieve is a delphi function that when given a full application path/name, return how many instances are in use and who is using them. Share this post Link to post
Ian Branch 127 Posted May 18, 2023 (edited) OK. Moving on. Using Enums rather than TProcess. function GetApplicationInstances(const FileName: string): TArray<string>; var ProcessEntry : TProcessEntry32; Snapshot : THandle; ProcessList : TList<string>; begin ProcessList := TList<string>.Create(); try Snapshot := CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); if Snapshot <> INVALID_HANDLE_VALUE then begin ProcessEntry.dwSize := SizeOf(ProcessEntry); if Process32First(Snapshot, ProcessEntry) then begin repeat if (ProcessEntry.szExeFile = FileName) then // Replace with appropriate condition begin ProcessList.Add(ProcessEntry.szExeFile); end; until not Process32Next(Snapshot, ProcessEntry); end; CloseHandle(Snapshot); end; Result := ProcessList.ToArray; finally ProcessList.Free; end; end; I have the following lines. var Instances: TArray<string>; Instances := GetApplicationInstances(sFileName); I can't see a way to get the number of elements in the TArray. I thought "for var i := 0 to TArray(Instances).Count do Memo1.Lines.Add(Instances);" would be a monty, but no. How please? Edited May 18, 2023 by Ian Branch Share this post Link to post
Ian Branch 127 Posted May 18, 2023 Solved. I added the count to the function. function GetApplicationInstances(const FileName: string; out Count: Integer): TArray<string>; var ProcessEntry: TProcessEntry32; Snapshot: THandle; ProcessList: TList<string>; begin ProcessList := TList<string>.Create; try Snapshot := CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); if Snapshot <> INVALID_HANDLE_VALUE then begin ProcessEntry.dwSize := SizeOf(ProcessEntry); if Process32First(Snapshot, ProcessEntry) then begin repeat if (ProcessEntry.szExeFile = FileName) then // Replace with appropriate condition begin ProcessList.Add(ProcessEntry.szExeFile); end; until not Process32Next(Snapshot, ProcessEntry); end; CloseHandle(Snapshot); end; Result := ProcessList.ToArray; Count := ProcessList.Count; finally ProcessList.Free; end; end; Tks Guys. Regards, Ian Share this post Link to post
Remy Lebeau 1394 Posted May 19, 2023 (edited) 1 hour ago, Ian Branch said: I can't see a way to get the number of elements in the TArray. Use the Length() function. Quote I thought "for var i := 0 to TArray(Instances).Count do Memo1.Lines.Add(Instances);" would be a monty, but no. How please? Use this instead: for var i := 0 to Length(Instances)-1 do Memo1.Lines.Add(Instances[i]); Alternatively, you can use the Low()/High() functions to get the first and last indexes of the array: for var i := Low(Instances) to High(Instances) do Memo1.Lines.Add(Instances[i]); Alternatively, you can use a for..in loop instead, no indexes needed: for var elem in Instances do Memo1.Lines.Add(elem); However, in your particular example, the TMemo.Lines property has an overloaded method that accepts a TArray<string> as input, so you don't even need a loop at all: Memo1.Lines.AddStrings(Instances); Quote Solved. I added the count to the function. You don't need that. Dynamic arrays know their own length. Edited May 19, 2023 by Remy Lebeau 2 Share this post Link to post
programmerdelphi2k 237 Posted May 19, 2023 (edited) 2 hours ago, Remy Lebeau said: I thought "for var i := 0 to TArray(Instances).Count do Memo1.Lines.Add(Instances);" would be a monty, but no. How please? // function GetApplicationInstances(const FileName: string; out Count: Integer): TArray<string>; // for var Item in GetApplicationInstances do Memo1.Lines.Add( Item ); // Item = string // or Memo1.Lines.AddStrings( GetApplicationInstances ) // anyway, if result = [] then nothing will be add on Memo! Edited May 19, 2023 by programmerdelphi2k Share this post Link to post
programmerdelphi2k 237 Posted May 19, 2023 (edited) UNnecessary usage: 3 hours ago, Ian Branch said: ProcessList: TList<string>; UNnecessary this! ... ProcessList.Add(ProcessEntry.szExeFile); // boommmm just use this: function GetApplicationInstances(const FileName: string): TArray<string>; var ProcessEntry: TProcessEntry32; Snapshot: THandle; begin Snapshot := CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); if Snapshot <> INVALID_HANDLE_VALUE then begin ProcessEntry.dwSize := SizeOf(ProcessEntry); if Process32First(Snapshot, ProcessEntry) then begin repeat if (ProcessEntry.szExeFile = FileName) then // Replace with appropriate condition begin result := result + [ProcessEntry.szExeFile]; end; until not Process32Next(Snapshot, ProcessEntry); end; CloseHandle(Snapshot); end; end; // on client-code = your form/app/etc... MyArrayFromMyFunc := GetApplicationInstances; ShowMessage( Length(MyArrayFormMyFunc ).ToString ); for var A in MyArrayFromMyFunc do Memo1.Lines.Add( A ) Edited May 19, 2023 by programmerdelphi2k Share this post Link to post
Pat Foley 51 Posted May 19, 2023 (edited) Something like this? It's like Borland's old 'side kick' only expanded to switch between different desktops. The thing can focus GE stuff so very handy. Here's a good start on it. Applister const hour2dot3 ='hr %2.3f '; //hour meter style hour2dot3wS ='hr %2.3f %s'; GoodApps: Tarray<string> = ['Notepad', 'TAppBuilder', 'Window', 'Chrome_WidgetWin_1', 'Notepad++', 'TfrmMultiMain']; type ptrApp = ^TApp; TApp = record Handle: HWnd; ... end; TptrApps = class(Tlist<ptrApp>) AppBuilderCount: Integer; // mark BDS's as loaded slLog: TStrings; //ref to CB.Items sBanner: PString; sgGrid: TStringGrid; //ref to Sg ChBx: TCheckListBox; //ref to chLB ... end; Edited May 19, 2023 by Pat Foley Modified Pix Share this post Link to post
Remy Lebeau 1394 Posted May 19, 2023 12 hours ago, programmerdelphi2k said: UNnecessary usage: Not really. Your way reallocates the array on every item added. Whereas TList has a Capacity so it doesn't reallocate on every individual add, and then the final array is allocated only 1 time based on the TList's final Count. Share this post Link to post
programmerdelphi2k 237 Posted May 19, 2023 7 minutes ago, Remy Lebeau said: so it doesn't reallocate on every individual add for sure, but in sometime it do it! capacity > n = reallocate it please! at end, a List will do it, expand the items like a array! or a array-of-pointers! Share this post Link to post
Remy Lebeau 1394 Posted May 19, 2023 1 minute ago, programmerdelphi2k said: for sure, but in sometime it do it! capacity > n = reallocate it please! at end, a List will do it, expand the items like a array! or a array-of-pointers! Yes, it reallocates when its Capacity is exceeded. And, it uses an array internally. But, that reallocation won't happen on every add, since the Capacity grows algorithmically (see SysUtils.GrowCollection()). It is very inefficient to reallocate on every add. Share this post Link to post
programmerdelphi2k 237 Posted May 19, 2023 (edited) 1 hour ago, Remy Lebeau said: It is very inefficient to reallocate on every add. ok, for sure! but how many "process" can be in a system in a moment? ... 100, 1000, 10000... how many fragmentations we can have on 32GB memory, when using Chrome ? 😂 dont forget "GetApplicationInstances" always return an "array"... same using a TList (with internal array usage) into it! Edited May 19, 2023 by programmerdelphi2k Share this post Link to post