Forum > Windows

[Solved] list all Windows services.

(1/2) > >>

jw:
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...


--- Quote ---procedure 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;               
--- End quote ---



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:
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  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---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  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} --- 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.


--- Quote ---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.

--- End quote ---

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.


--- Quote ---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.
--- End quote ---

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:

--- Quote from: friend on May 30, 2022, 02:03:42 am ---
--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---function ServiceStateName (statusCode: Integer): String;begin  case statusCode of       SERVICE_STOPPED: Result := 'Stopped';       SERVICE_RUNNING: Result := 'Running';       SERVICE_PAUSED : Result := 'Paused';  end;end;
--- End quote ---

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  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---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 am ---
--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---servicemanager1.Access := SC_MANAGER_ALL_ACCESS;
--- End quote ---

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  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---servicemanager1.Access := SC_MANAGER_ENUMERATE_SERVICE;
Principle of least privilege

Enhance security with the principle of least privilege

friend:

--- 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:
--- End quote ---

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  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---servicemanager1.Access := SC_MANAGER_ENUMERATE_SERVICE;
Principle of least privilege

Enhance security with the principle of least privilege

--- End quote ---

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):


--- Quote ---The principle of least privilege (POLP) requires giving each user, service and application only the permissions needed to perform their work and no more.
--- End quote ---

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:

--- Quote from: friend on June 01, 2022, 09:38:38 am ---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?

--- End quote ---

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.

Navigation

[0] Message Index

[#] Next page

Go to full version