Summary
The project currently uses WMI (System.Management / Win32_Service) to query service metadata. This can be fully replaced by ServiceController and native P/Invoke calls via advapi32.dll, which are faster, more reliable, and remove the System.Management dependency.
Current WMI usage
All WMI usage flows through IWmiSearcher in ServiceManager:
| Method |
WMI Query |
Property retrieved |
GetServiceStartupType() |
SELECT * FROM Win32_Service WHERE Name = '...' |
StartMode |
GetServiceDescription() |
SELECT * FROM Win32_Service WHERE Name = '...' |
Description |
GetServiceUser() |
SELECT StartName FROM Win32_Service WHERE Name = '...' |
StartName |
GetAllServices() |
SELECT Name, State, StartMode, StartName, Description FROM Win32_Service |
Bulk: Name, State, StartMode, StartName, Description |
Proposed replacement
| WMI Property |
Replacement |
| State |
ServiceController.Status (already used elsewhere) |
| StartMode |
ServiceController.StartType (.NET 6+) |
| Description |
QueryServiceConfig2 with SERVICE_CONFIG_DESCRIPTION (P/Invoke) |
| StartName |
QueryServiceConfig P/Invoke (QUERY_SERVICE_CONFIG.lpServiceStartName) |
The P/Invoke infrastructure (NativeMethods.cs, WindowsServiceApi.cs) already exists in the project — only QueryServiceConfig and the description info level need to be added.
Benefits
- Performance:
ServiceController + P/Invoke is significantly faster than WMI queries
- Reliability: eliminates dependency on WMI service health (WMI repository corruption, service not running)
- Smaller deployment:
System.Management NuGet package can be removed (~trimming/AOT friendly)
- Simpler linker config:
linker.xml files no longer need to preserve System.Management
Dead code to clean up
WindowsServiceApi.QueryService() and IWindowsServiceApi.QueryService() — defined but never called
WindowsServiceProvider + IWindowsServiceProvider — appear to be legacy/unused
IManagementObject + ManagementObjectWrapper — only needed for WMI
Files affected
src/Servy.Core/Services/ServiceManager.cs — main consumer
src/Servy.Core/Services/WmiSearcher.cs — remove
src/Servy.Core/Services/IWmiSearcher.cs — remove
src/Servy.Core/Services/ManagementObjectWrapper.cs — remove
src/Servy.Core/Services/IManagementObject.cs — remove
src/Servy.Core/Services/WindowsServiceApi.cs — remove QueryService(), add QueryServiceConfig
src/Servy.Core/Services/IWindowsServiceApi.cs — remove QueryService()
src/Servy.Core/Services/WindowsServiceProvider.cs — remove (unused)
src/Servy.Core/Services/IWindowsServiceProvider.cs — remove (unused)
src/Servy.Core/Servy.Core.csproj — remove System.Management PackageReference
src/Servy.CLI/linker.xml — remove System.Management entry
src/Servy.Restarter/linker.xml — remove System.Management entry
src/Servy.CLI/Program.cs — remove WmiSearcher instantiation
src/Servy/Views/MainWindow.xaml.cs — remove WmiSearcher instantiation
src/Servy.Manager/Views/MainWindow.xaml.cs — remove WmiSearcher instantiation
tests/Servy.Core.UnitTests/Services/ServiceManagerTests.cs — update mocks
Summary
The project currently uses WMI (
System.Management/Win32_Service) to query service metadata. This can be fully replaced byServiceControllerand native P/Invoke calls viaadvapi32.dll, which are faster, more reliable, and remove theSystem.Managementdependency.Current WMI usage
All WMI usage flows through
IWmiSearcherinServiceManager:GetServiceStartupType()SELECT * FROM Win32_Service WHERE Name = '...'StartModeGetServiceDescription()SELECT * FROM Win32_Service WHERE Name = '...'DescriptionGetServiceUser()SELECT StartName FROM Win32_Service WHERE Name = '...'StartNameGetAllServices()SELECT Name, State, StartMode, StartName, Description FROM Win32_ServiceProposed replacement
ServiceController.Status(already used elsewhere)ServiceController.StartType(.NET 6+)QueryServiceConfig2withSERVICE_CONFIG_DESCRIPTION(P/Invoke)QueryServiceConfigP/Invoke (QUERY_SERVICE_CONFIG.lpServiceStartName)The P/Invoke infrastructure (
NativeMethods.cs,WindowsServiceApi.cs) already exists in the project — onlyQueryServiceConfigand the description info level need to be added.Benefits
ServiceController+ P/Invoke is significantly faster than WMI queriesSystem.ManagementNuGet package can be removed (~trimming/AOT friendly)linker.xmlfiles no longer need to preserveSystem.ManagementDead code to clean up
WindowsServiceApi.QueryService()andIWindowsServiceApi.QueryService()— defined but never calledWindowsServiceProvider+IWindowsServiceProvider— appear to be legacy/unusedIManagementObject+ManagementObjectWrapper— only needed for WMIFiles affected
src/Servy.Core/Services/ServiceManager.cs— main consumersrc/Servy.Core/Services/WmiSearcher.cs— removesrc/Servy.Core/Services/IWmiSearcher.cs— removesrc/Servy.Core/Services/ManagementObjectWrapper.cs— removesrc/Servy.Core/Services/IManagementObject.cs— removesrc/Servy.Core/Services/WindowsServiceApi.cs— removeQueryService(), addQueryServiceConfigsrc/Servy.Core/Services/IWindowsServiceApi.cs— removeQueryService()src/Servy.Core/Services/WindowsServiceProvider.cs— remove (unused)src/Servy.Core/Services/IWindowsServiceProvider.cs— remove (unused)src/Servy.Core/Servy.Core.csproj— removeSystem.ManagementPackageReferencesrc/Servy.CLI/linker.xml— removeSystem.Managemententrysrc/Servy.Restarter/linker.xml— removeSystem.Managemententrysrc/Servy.CLI/Program.cs— removeWmiSearcherinstantiationsrc/Servy/Views/MainWindow.xaml.cs— removeWmiSearcherinstantiationsrc/Servy.Manager/Views/MainWindow.xaml.cs— removeWmiSearcherinstantiationtests/Servy.Core.UnitTests/Services/ServiceManagerTests.cs— update mocks