如何在现有C#代码中获取Windows服务可执行文件的物理路径?
获取Windows服务名称及对应可执行文件路径
Great question! The built-in ServiceController class doesn't include the executable path out of the box—Windows stores that configuration in the Registry. Here's how to extend your code to pull both the display name and the physical path of each service:
First, let's create a simple class to hold our service details (this keeps things organized):
public class ServiceInfo { public string DisplayName { get; set; } public string ExecutablePath { get; set; } }
Next, update your GetServices method to read from the Windows Registry. We'll target the HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\[ServiceName] key, where the ImagePath value stores the service's executable path:
using Microsoft.Win32; using System.Collections.Generic; using System.ServiceProcess; using System.Text.RegularExpressions; public static void GetServices() { var serviceInfoList = new List<ServiceInfo>(); ServiceController[] services = ServiceController.GetServices(); foreach (var service in services) { string executablePath = string.Empty; try { // Open the Registry key for the current service using (RegistryKey key = Registry.LocalMachine.OpenSubKey($@"SYSTEM\CurrentControlSet\Services\{service.ServiceName}")) { if (key != null) { // Retrieve the ImagePath value from the Registry object imagePathObj = key.GetValue("ImagePath"); if (imagePathObj != null) { string rawPath = imagePathObj.ToString(); // Clean up the path: remove quotes and any trailing command-line arguments executablePath = Regex.Match(rawPath, @"^""?([^""]+)""?").Groups[1].Value; } } } } catch (System.Security.SecurityException) { // Handle cases where we don't have permission to access the service's Registry key executablePath = "Permission denied"; } catch (Exception ex) { executablePath = $"Error: {ex.Message}"; } serviceInfoList.Add(new ServiceInfo { DisplayName = service.DisplayName, ExecutablePath = executablePath }); // Dispose the ServiceController to free up system resources service.Dispose(); } // Sort the list alphabetically by display name serviceInfoList.Sort((x, y) => string.Compare(x.DisplayName, y.DisplayName)); // Print the formatted results int serviceCount = 0; foreach (var serviceInfo in serviceInfoList) { serviceCount++; Console.WriteLine($"{serviceCount} - {serviceInfo.DisplayName}"); Console.WriteLine($" Executable Path: {serviceInfo.ExecutablePath}\n"); } }
Important Notes:
- Admin Rights Required: You need to run your application as an administrator. Many service Registry keys are restricted and can't be accessed without elevated permissions.
- Path Cleaning: The
ImagePathvalue often includes quotes (e.g.,"C:\Windows\System32\svchost.exe" -k netsvcs) and command-line arguments. The regex extracts the actual executable path by capturing the content inside quotes (or the full path if no quotes exist). - Error Handling: We added try/catch blocks to handle permission issues and unexpected errors, so your program won't crash if it encounters a service it can't access.
内容的提问来源于stack exchange,提问作者Dharmindar
相关产品推荐
相关产品推荐

