[Solved] list all Windows services. lazarus / 34-Windows ---------------------------------------------------------------------- jw · 2022-05-29 21:37 Windows 10 x64 Lazarus 2.0.10 FPC 3.2.0 The starting point for all service related stuffs . https://forum.lazarus.freepascal.org/index.php?topic=13423.0 https://wiki.freepascal.org/ServiceManager Menu-->System-->Drop a tservicemanager instance on the form.  My instance is named ServiceManager. So I'm trying to simply list all the services in Windows, and their state(running, stopped, starting etc) to a tmemo.  One of the Windows API calls that I think I'm trying to get at via the service manager is EnumServicesStatusA.  But I'm not sure if I've found the correct pascal servicemanager.sub_commands, nor do I know how to properly process TServiceEnteries and or TComponentEnumerator's in order to make simple strings for them for tmemo.  Here's some code that's so bad it's really not worth sharing... Quoteprocedure TForm1.Button1Click(Sender: TObject); var   Num_of_Services: longint; begin   servicemanager.Access := $0001;   ServiceManager.Connect;                //Num_of_Services:= servicemanager.InstanceSize;  //nope that didn't return the correct number of services      //Num_of_Services:=servicemanager.ComponentCount;  //This always returned 0?       for count :=0 to Num_of_Services -1 do      begin             memo1.text:= memo1.text +  try to do something to do with servicemanager.GetEnumerator or           maybe servicemanager.Services;  not really sure?      end;   ServiceManager.free; end;              It think the hardest part for, me at least, is that I know what bytes, words, integers, strings, the basic data types are.  I can often drop to the API's themselves and overcome Microsoft's strange datatypes, at least sometimes, as hwind etc are just integers.  I do really hate when a Microsoft API return a pointer to the data I need, which happens in this case, but I think that's taken care of an repackaged by tservicemanager.  But if anyone can tell me how to get good at figuring out what makes up the ever going PAscal datatypes I keep seeing, such as TComponentEnumaerator's and TserviceEnteries etc, then let me know. ---------------------------------------------------------------------- friend · 2022-05-30 00:03 Hi. I'm sorry that you use M$ Windows 10. Unfortunately this class is not well documented. I had to look at the source code in the path: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i lazarus\fpc\3.2.0\source\packages\fcl-extra\src\winto understand how to use it to list all services. I found the property 'Services', its type, and then searched where it is used. Found the Refresh() function. There is a field called RefreshOnConnect that is false by default. Setting it to true will refresh on connect    Here's a simple example to list services and their states into a Memo: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i  function ServiceStateName (statusCode: Integer): String;begin  case statusCode of       SERVICE_STOPPED: Result := 'Stopped';       SERVICE_RUNNING: Result := 'Running';       SERVICE_PAUSED : Result := 'Paused';  end;end; procedure TForm1.Button1Click(Sender: TObject);var  Num_of_Services: longint;  i: Integer;  entry: TServiceEntry;begin   servicemanager1.Access := SC_MANAGER_ALL_ACCESS;  ServiceManager1.RefreshOnConnect := True;  ServiceManager1.Connect();   Num_of_Services := serviceManager1.Services.Count;   for i := 0 to Num_of_Services -1 do  begin      entry := serviceManager1.Services[i];      memo1.Lines.Add (entry.DisplayName      + ' : '      + ServiceStateName(entry.CurrentState));  end;end; You must include JwaWinSvc in your unit's Uses section. There the constant SC_MANAGER_ALL_ACCESS and others are defined. Notice that you don't really need to Free the component if you add it using the form designer. QuoteI can often drop to the API's themselves and overcome Microsoft's strange datatypes, at least sometimes, as hwind etc are just integers.  I do really hate when a Microsoft API return a pointer to the data I need, which happens in this case, but I think that's taken care of an repackaged by tservicemanager. M$ Windows API is well made. The data types are well defined; numeric identifiers and their pointers mean that the object is managed by the operating system itself, one does not access the members directly, but by using functions. TServiceManager, for example, is just a class that adds an abstraction layer over native structures and functions. QuoteBut if anyone can tell me how to get good at figuring out what makes up the ever going PAscal datatypes I keep seeing, such as TComponentEnumaerator's and TserviceEnteries etc, then let me know. Most of the time I find what I'm looking for by reading the documentation (in Lazarus: Help -> Help), file path: lazarus\docs\chm. In this case I had to see the source code itself. Using default keyboard shortcuts in Lazarus: Alt + Up, Ctrl + F. ---------------------------------------------------------------------- Remy Lebeau · 2022-05-31 16:37 Quote from: friend on May 30, 2022, 02:03:42 amCode: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i function ServiceStateName (statusCode: Integer): String;begin  case statusCode of       SERVICE_STOPPED: Result := 'Stopped';       SERVICE_RUNNING: Result := 'Running';       SERVICE_PAUSED : Result := 'Paused';  end;end; There are several more statuses available, why are you not converting all of them?  At the very least, I would suggest returning statusCode as-is if a match is not found, eg: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i function ServiceStateName (statusCode: Integer): String;begin  case statusCode of    SERVICE_STOPPED: Result := 'Stopped';    SERVICE_RUNNING: Result := 'Running';    SERVICE_PAUSED : Result := 'Paused';    ...  else    Result := IntToStr(statusCode);  end;end; Quote from: friend on May 30, 2022, 02:03:42 amCode: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i servicemanager1.Access := SC_MANAGER_ALL_ACCESS; Just to nitpick, but SC_MANAGER_ALL_ACCESS is asking for too many permissions that you don't really need just to get the statuses.  All you need in this case is SC_MANAGER_ENUMERATE_SERVICE.  Don't ask for more permissions than you actually need. Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i servicemanager1.Access := SC_MANAGER_ENUMERATE_SERVICE; Principle of least privilege Enhance security with the principle of least privilege ---------------------------------------------------------------------- friend · 2022-06-01 07:38 Quote from: Remy Lebeau on May 31, 2022, 06:37:05 pm There are several more statuses available, why are you not converting all of them?  At the very least, I would suggest returning statusCode as-is if a match is not found, eg: To keep it simple. "Running", "paused", "stopped" are the most common states of services. In case the status is different from those, an empty string will be returned. I mentioned where the constants are defined. If someone is interested in more statuses he can look at the list himself. Either in that unit's source code or Windows API's headers. These constants reflect possible values of Win32 API's SERVICE_STATUS structure's dwServiceStatus member. Quote from: Remy Lebeau on May 31, 2022, 06:37:05 pm Just to nitpick, but SC_MANAGER_ALL_ACCESS is asking for too many permissions that you don't really need just to get the statuses.  All you need in this case is SC_MANAGER_ENUMERATE_SERVICE.  Don't ask for more permissions than you actually need. Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i servicemanager1.Access := SC_MANAGER_ENUMERATE_SERVICE; Principle of least privilege Enhance security with the principle of least privilege Thanks for pointing this out, you're right friend, it is not necessary, and better to use the one you mentioned. Again keeping it simple; and one should look at possible values. Also reflects the fact that I like control, am not stupid and don't like when computers try to protect me from myself; being "Administrator" on Window$, I will have all these privileges anyway, despite not needing them just to list the services. This "Principle" is another idea that is part of something called "common sense", just like many things in this area of knowledge. Like the "Single Responsibility Principle" in Object Orientation cr*p. This "Principle" can be summarized in one sentence (one definition I found; others use different words to convey the same idea): QuoteThe principle of least privilege (POLP) requires giving each user, service and application only the permissions needed to perform their work and no more. This is also part of something known as "common sense", a trait of healthy people. No need to post two links, let alone such garbage sources -- W*kipedia and M$'s site. Then again, given the state of certain search engines, and the Internet in general, what can one do? ---------------------------------------------------------------------- PascalDragon · 2022-06-01 11:45 Quote from: friend on June 01, 2022, 09:38:38 amNo need to post two links, let alone such garbage sources -- W*kipedia and M$'s site. Then again, given the state of certain search engines, and the Internet in general, what can one do? Please hold back your tone a bit. They provide valid information about the principle and only because you already know about it - great for you - does not mean that Remy Lebeau knows that you know about it or that other people that might find this thread might know about it. ---------------------------------------------------------------------- Jurassic Pork · 2022-06-01 18:04 hello, with WMI : Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i implementationuses utilwmi, contnrs; {$R *.lfm} { TForm1 } procedure TForm1.Button1Click(Sender: TObject);var  WMIResult         : TFPObjectList;  f,j               : integer;  retVal            : String;begin  WMIResult := GetWMIInfo('Win32_Service', ['Name', 'State','Status']);   for f := 0 to Pred(WMIResult.Count) do  begin  j := 0;  // first entry = Name    retVal := TStringList(WMIResult[f]).ValueFromIndex[j];    Memo1.Append('Name : ' + retVal);    j := 1;  // second entry = State    retVal := TStringList(WMIResult[f]).ValueFromIndex[j];    Memo1.Append('State : ' + retVal);    j := 2;  // second entry = Status    retVal := TStringList(WMIResult[f]).ValueFromIndex[j];    Memo1.Append('Status : ' + retVal);    Memo1.Append('======================================');  end;   WMIResult.Free;end;             utilwmi v0.3 is here Friendly, J.P ---------------------------------------------------------------------- BobDog · 2022-06-02 15:16 List all windows services is locked. [Mod: unlocked and merged; off- topic posts removed.] I cannot ask Jurassic Pork to adjust his code so I can try it (I am using geany and console output) That is with WMI : then creating a unit. I don't really understand the concept of creating a unit to run code, where do you save this unit? Does it go into the distribution units folder? Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i  usesprocess;var s:ansistring=''; beginruncommand('c:\windows\system32 \cmd.exe',['/c','sc queryex type=service state= all'],s);writeln(s);writeln('Pree return to end . . .');readln;end.  Seems to be similar to Jurassic Pork's attatchment https://forum.lazarus.freepascal.org/index.php?action=dlattach;topic=5 9497.0;attach=49168;image To experienced Freepascal people: Sorry to ask such silly questions. [Edited to add Mod note.] ---------------------------------------------------------------------- 440bx · 2022-06-02 17:54 Quote from: BobDog on June 02, 2022, 05:16:49 pmTo experienced Freepascal people: Sorry to ask such silly questions. Please don't be.  IMO, that's the purpose of having this forum.  No one was born knowing everything. ---------------------------------------------------------------------- friend · 2022-06-03 05:27 A mod just removed the autism surplus, that's unfortunate. Quote from: 440bx on June 02, 2022, 07:54:47 pmPlease don't be.  IMO, that's the purpose of having this forum.  No one was born knowing everything. Indeed, absolutely. Quote from: BobDog on June 02, 2022, 05:16:49 pmquestion Units, you put them where they will be used. If you have a project where you want to use a unit, there it goes. ---------------------------------------------------------------------- jw · 2022-06-07 15:28 @Friend: Bless you.  I knew someone knew where the code was hiding, and if I were more proficient, I'd have had a better chance of finding it and perhaps decoding the object.  Also, I have JwaWinSvc, but instead if adding the dependency, I decided to look through it and pull out the values I needed myself; as I like everything my code needs within itself if possible.  Also, when I did add JwaWinSvc, the library itself had more dependencies that I would have had to try and wring out of the hub, and that really bugged me.  I mean, it's not as if adding a download link to the code that I'm looking at would somehow make M$hub any less unscrupulous.  @Remy Lebeau Yes, the principle of least permissions verses I really need to get something done and know what I'm doing except for that deliberately undocumented M$ bug.  Since this post is now available to the whole world, and I only asked for the permissions needed to list processes, yes less permissions; and thanks for the code to show the other nefarious states Windows services may find themselves in... @PascalDragon ???  A friendly ROAR and dragon-ee, dragon, drag, drag fire burp. @Jurassic Pork  Thank you Sir, you've been contributing to the community for a long time now. @BobDog  Like Friend said:  I'd drop Jurassic Pork's utilwmi library directly into the directory of your source code.  Although, from the code you posted, it looks like you're shelling out to get it.  I first started off my code in that direction, and while I haven't yet taken a look at Jurassic Porks library, as you pointed out, that is probably what the library does.  The only comment I have about "Executing External Programs" which over the years has become very well documented, is, whenever possible, try to make TProcess and pipes work for you rather than a command that ends up being a Windows only API call.  Also, I decided that I should instead try to further the Free Pascal Communities knowledge about servicemanager, as the principle of least privilege dictates that it's far better not to shell out to an M$ buggy cmd prompt to run a buggy wmi command, when one can get close to the APi calls themselves via an open source Free Pascal service manger that's been part of the IDE for almost as long as