我的公司提供此 Windows 服务:
我想从后面的代码中获取服务描述!但由于某种原因它没有返回服务描述。
任何人都可以帮我解决这个问题吗?
这是我的代码,以及它返回的内容:
Dim MyServices As ServiceController = New ServiceController("AccTech Exchange Rate Import")
Dim Status As String = MyServices.Status.ToString
Dim Name As String = MyServices.ServiceName
以及 MyService 变量返回的内容。
我如何从这里获取服务说明?
问候,
编辑:
这是 Miki Shah 为我指明正确方向后的代码!
Dim MyServices As ServiceController = New ServiceController("AccTech Exchange Rate Import")
Dim Status As String = MyServices.Status.ToString
Dim Name As String = MyServices.ServiceName
Dim Description As String
Dim objPath As String = String.Format("Win32_Service.Name='{0}'", Name)
Using service As New ManagementObject(New ManagementPath(objPath))
Description = service("Description")
End Using
可以通过以下方式获取,并且必须添加System.Management的引用
string serviceName = MyServices.ServiceName
string objPath = string.Format("Win32_Service.Name='{0}'", serviceName);
using (ManagementObject service = new ManagementObject(new ManagementPath(objPath)))
{
Console.WriteLine(service["Description"]);
}
您可以使用
QueryServiceConfig2
Win32 API 来获取 Windows 服务描述。与 WMI 解决方案相比,此方法要快得多。
下面的代码是用 C# 编写的,但可以轻松转换为 VB.NET converter.telerik.com
指定服务名称。
使用
OpenSCManager
Win32 方法获取 SCM 数据库句柄。
使用
OpenService
Win32 API 打开服务句柄,指定服务名称和 SCM 句柄。
以空缓冲区调用
QueryServiceConfig2
,pcbBytesNeeded
参数接收所需的缓冲区大小。
使用
Marshal.AllocHGlobal
分配所需大小的缓冲区。
使用分配的缓冲区和缓冲区大小再次调用
QueryServiceConfig2
。
将缓冲区转换为
SERVICE_DESCRIPTION
结构。
释放缓冲区并关闭所有打开的句柄。
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
namespace Test
{
internal class Program
{
#region "Constants"
const uint ERROR_INSUFFICIENT_BUFFER = 122;
const uint SERVICE_QUERY_CONFIG = 0x0001;
const uint STANDARD_RIGHTS_REQUIRED = 0x000F0000;
const uint SC_MANAGER_CONNECT = 0x0001;
const uint SC_MANAGER_CREATE_SERVICE = 0x0002;
const uint SC_MANAGER_ENUMERATE_SERVICE = 0x0004;
const uint SC_MANAGER_LOCK = 0x0008;
const uint SC_MANAGER_QUERY_LOCK_STATUS = 0x0010;
const uint SC_MANAGER_MODIFY_BOOT_CONFIG = 0x0020;
const uint SC_MANAGER_ALL_ACCESS = STANDARD_RIGHTS_REQUIRED | SC_MANAGER_CONNECT | SC_MANAGER_CREATE_SERVICE | SC_MANAGER_ENUMERATE_SERVICE | SC_MANAGER_LOCK | SC_MANAGER_QUERY_LOCK_STATUS | SC_MANAGER_MODIFY_BOOT_CONFIG;
#endregion
#region "Win32 APIs"
[DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
static extern IntPtr OpenSCManager(string lpMachineName, string lpDatabaseName, uint dwDesiredAccess);
[DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Auto)]
static extern IntPtr OpenService(IntPtr hSCManager, string lpServiceName, uint dwDesiredAccess);
[DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Auto)]
static extern bool QueryServiceConfig2(IntPtr hService, SERVICE_CONFIG dwInfoLevel, IntPtr lpBuffer, uint cbBufSize, out uint pcbBytesNeeded);
[DllImport("advapi32.dll", SetLastError = true)]
static extern bool CloseServiceHandle(IntPtr hSCObject);
#endregion
#region "Enumerations"
public enum SERVICE_CONFIG : uint
{
SERVICE_CONFIG_DESCRIPTION = 1,
SERVICE_CONFIG_FAILURE_ACTIONS = 2,
SERVICE_CONFIG_DELAYED_AUTO_START_INFO = 3,
SERVICE_CONFIG_FAILURE_ACTIONS_FLAG = 4,
SERVICE_CONFIG_SERVICE_SID_INFO = 5,
SERVICE_CONFIG_REQUIRED_PRIVILEGES_INFO = 6,
SERVICE_CONFIG_PRESHUTDOWN_INFO = 7,
SERVICE_CONFIG_TRIGGER_INFO = 8,
SERVICE_CONFIG_PREFERRED_NODE = 9,
SERVICE_CONFIG_LAUNCH_PROTECTED = 12
}
#endregion
#region "Structures"
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct SERVICE_DESCRIPTION
{
public string lpDescription;
}
#endregion
static void Main(string[] args)
{
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
string svcName = "Power"; // Change this to the service name you want to get its description
// Get the SCM database handle
IntPtr schSCManager = OpenSCManager(null, null, SERVICE_QUERY_CONFIG);
// Get the service handle
IntPtr schService = OpenService(schSCManager, svcName, SERVICE_QUERY_CONFIG);
if (schService == IntPtr.Zero)
{
Console.WriteLine("Win32 API OpenService failed ({0})", Marshal.GetLastWin32Error());
return;
}
// Query the service description
IntPtr buffer;
bool success = QueryServiceConfig2(schService, SERVICE_CONFIG.SERVICE_CONFIG_DESCRIPTION, IntPtr.Zero, 0, out uint bytesNeeded);
if (!success && Marshal.GetLastWin32Error() == ERROR_INSUFFICIENT_BUFFER)
{
buffer = Marshal.AllocHGlobal((int)bytesNeeded);
bool success2 = QueryServiceConfig2(schService, SERVICE_CONFIG.SERVICE_CONFIG_DESCRIPTION, buffer, bytesNeeded, out bytesNeeded);
if (!success2)
{
Console.WriteLine("Win32 API QueryServiceConfig2 failed ({0})", Marshal.GetLastWin32Error());
return;
}
}
else
{
Console.WriteLine("Win32 API QueryServiceConfig2 failed ({0})", Marshal.GetLastWin32Error());
return;
}
// Read the description from the buffer
SERVICE_DESCRIPTION description = (SERVICE_DESCRIPTION)Marshal.PtrToStructure(buffer, typeof(SERVICE_DESCRIPTION));
Console.WriteLine("{0} service description: {1}", svcName, description.lpDescription);
// Free the buffer and close the handles
Marshal.FreeHGlobal(buffer);
CloseServiceHandle(schService);
CloseServiceHandle(schSCManager);
stopwatch.Stop();
Console.WriteLine("Elapsed Time: {0} Milliseconds", stopwatch.ElapsedMilliseconds.ToString());
Console.ReadLine();
}
}
}
参考资料: