I want to get the path of the Windows Service,
var managementObjectSearcher = new ManagementObjectSearcher(\"Select * from Win32_Service where serviceName = MySe
Since you're retrieving the service by Name
, which a key property of the Win32_Service class, try retrieving the instance directly instead of searching for it:
string GetMyServicePath()
{
string path = "Win32_Service.Name=\"MyService\"";
using (ManagementObject service = new ManagementObject(path))
return (string) service.GetPropertyValue("PathName");
}
Here's a quick benchmark I threw together to compare direct retrieval vs. searching:
private const int LoopIterations = 1000;
private const string ServiceClass = "Win32_Service";
private const string ServiceName = "MyService";
private const string ServiceProperty = "PathName";
private static readonly string ServicePath = string.Format("{0}.Name=\"{1}\"", ServiceClass, ServiceName);
private static readonly string ServiceQuery = string.Format(
"SELECT {0} FROM {1} Where Name=\"{2}\"",
ServiceProperty, ServiceClass, ServiceName
);
private static ManagementObjectSearcher ServiceSearcher = new ManagementObjectSearcher(ServiceQuery);
static void Main(string[] args)
{
var watch = new Stopwatch();
watch.Start();
for (int i = 0; i < LoopIterations; i++)
{
var servicePath = GetServicePathByKey();
}
watch.Stop();
Console.WriteLine(
"{0:N0} iterations of GetServicePathByKey() took {1:N0} milliseconds",
LoopIterations, watch.ElapsedMilliseconds
);
watch.Restart();
for (int i = 0; i < LoopIterations; i++)
{
var servicePath = GetServicePathFromExistingSearcher();
}
watch.Stop();
Console.WriteLine(
"{0:N0} iterations of GetServicePathFromExistingSearcher() took {1:N0} milliseconds",
LoopIterations, watch.ElapsedMilliseconds
);
watch.Restart();
for (int i = 0; i < LoopIterations; i++)
{
var servicePath = GetServicePathFromNewSearcher();
}
watch.Stop();
Console.WriteLine(
"{0:N0} iterations of GetServicePathFromNewSearcher() took {1:N0} milliseconds",
LoopIterations, watch.ElapsedMilliseconds
);
}
static string GetServicePathByKey()
{
using (var service = new ManagementObject(ServicePath))
return (string) service.GetPropertyValue(ServiceProperty);
}
static string GetServicePathFromExistingSearcher()
{
using (var results = ServiceSearcher.Get())
using (var enumerator = results.GetEnumerator())
{
if (!enumerator.MoveNext())
throw new Exception();
return (string) enumerator.Current.GetPropertyValue(ServiceProperty);
}
}
static string GetServicePathFromNewSearcher()
{
using (var searcher = new ManagementObjectSearcher(ServiceQuery))
using (var results = searcher.Get())
using (var enumerator = results.GetEnumerator())
{
if (!enumerator.MoveNext())
throw new Exception();
return (string) enumerator.Current.GetPropertyValue(ServiceProperty);
}
}
Enumerating the searcher results directly is about as fast as I could make it, marginally faster than using a foreach
block and twice as fast as using LINQ
. On my 64-bit Windows 7 Professional system with the ServiceName
constant set to Power
I got these results:
1,000 iterations of GetServicePathByKey() took 8,263 milliseconds
1,000 iterations of GetServicePathFromExistingSearcher() took 64,265 milliseconds
1,000 iterations of GetServicePathFromNewSearcher() took 64,875 milliseconds
The Windows32_Services class doesn't exist, so assuming which you are using the Win32_Service WMI class you can improve the performance only returning the properties which you want to use, in this case the PathName
, so change your WQL sentence to
SELECT PathName FROM Win32_Service Where Name='MyService'
UPDATE
The observation made for @Bacon is quite correct, since you know the name of thes service to retrieve, you can build the object path of the Win32_Service which look like
Win32_Service.Name="ServiceName"
And then using the ManagementObject class you can retrieve the instance to the service in a fastest way.
If it is the "latency" of WMI that is bothering you, you don't have to use WMI to get a service's path, ie. executable name. You can also P/invoke QueryServiceConfig.
http://www.pinvoke.net/default.aspx/advapi32/queryserviceconfig.html