您能以编程方式更改现有Windows服务的显示名称(和其他属性)吗?

时间:2015-04-03 16:51:24

标签: c# windows-services

我希望用户能够使用我们的配置工具更改现有Windows服务的显示名称。在代码中,给定相应ServiceController对象的实例,设置其DisplayName属性似乎有效。尝试调用Refresh,这似乎没有任何效果。关于Refresh的作用,MSDN文档有点不清楚 - 它是重新读取当前的服务设置还是将更改写入服务?代码很简单:

ServiceController sc = GetServiceController(CurrentInterfaceData.ServiceName);
sc.DisplayName = "MyService";
sc.Refresh();

2 个答案:

答案 0 :(得分:1)

使用WMI。为此,您必须添加对System.Management程序集的引用。以下是我用于通用安装程序的工作代码的摘录:

class Program
{
    static void Main(string[] args)
    {
        UpdateService("ipsecd");
    }

    private const int LOGON32_LOGON_NEW_CREDENTIALS = 9;
    private const int LOGON32_PROVIDER_WINNT50 = 3;
    private const int SERVICE_ALL_ACCESS = 0xF01FF;
    private const int SC_MANAGER_ALL_ACCESS = 0xF003F;
    private const uint SERVICE_NO_CHANGE = 0xFFFFFFFF;
    private const uint SERVICE_WIN32_OWN_PROCESS = 0x00000010;
    private const uint SERVICE_INTERACTIVE_PROCESS = 0x00000100;
    // Win32 function to connect to remote machine
    [DllImport("advapi32.dll", SetLastError = true)]
    private static extern Boolean LogonUser(string lpUsername, string lpDomain, string lpPassword, int dwLogonType,
                                            int dwLogonProvider, out IntPtr phToken);

    // Win32 function to connect to impersonate user
    [DllImport("advapi32.dll", SetLastError = true)]
    static extern int ImpersonateLoggedOnUser(IntPtr hToken);

    // Win32 function to open the service control manager
    [DllImport("advapi32.dll")]
    private static extern IntPtr OpenSCManager(string lpMachineName, string lpDatabaseName, int dwDesiredAccess);

    // Win32 function to open a service instance
    [DllImport("advapi32.dll")]
    private static extern IntPtr OpenService(IntPtr hSCManager, string lpServiceName, int dwDesiredAccess);

    // Win32 function to change the service config
    [DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
    public static extern Boolean ChangeServiceConfig(
        IntPtr hService,
        UInt32 nServiceType,
        UInt32 nStartType,
        UInt32 nErrorControl,
        String lpBinaryPathName,
        String lpLoadOrderGroup,
        IntPtr lpdwTagId,
        [In] char[] lpDependencies,
        String lpServiceStartName,
        String lpPassword,
        String lpDisplayName);


    public static void UpdateService(string serviceName)
    {
        ManagementScope scope = null;            
        ObjectQuery filter = new ObjectQuery(string.Format("SELECT * FROM Win32_Service WHERE Name = '{0}'", serviceName));
        ManagementObjectSearcher query = new ManagementObjectSearcher(scope, filter);
        try
        {
            ManagementObjectCollection services = query.Get();
            // No match = failed condition
            if (services.Count == 0)                
                return;
            foreach (ManagementObject service in services)
            {
                SetServiceDisplayName(serviceName, "new disp name");
                service.Dispose();
            }
        }
        catch (Exception ex)
        {
            //Could not set property
        }

    }

    private static void SetServiceDisplayName(string name, string dispName)
    {            
        IntPtr svcHndl = OpenService("", "", name);
        // Call the ChangeServiceFailureActions() abstraction of ChangeServiceConfig2()
        bool rslt = ChangeServiceConfig(svcHndl, SERVICE_NO_CHANGE,
            SERVICE_NO_CHANGE, SERVICE_NO_CHANGE, null, null, IntPtr.Zero, null, null, null, dispName);            
    }

    private static IntPtr OpenService(string userName, string password, string serviceName)
    {
        IntPtr scmHndl = IntPtr.Zero;
        IntPtr svcHndl = IntPtr.Zero;
        // Open the service control manager
        scmHndl = OpenSCManager("", null, SC_MANAGER_ALL_ACCESS);

        if (scmHndl.ToInt32() <= 0)
            return IntPtr.Zero;

        // Open the service
        svcHndl = OpenService(scmHndl, serviceName, SERVICE_ALL_ACCESS);

        if (svcHndl.ToInt32() <= 0)
            return IntPtr.Zero;

        return svcHndl;
    }
}

试试吧。它应该工作。

答案 1 :(得分:0)

我相信在安装服务时会设置Windows服务的名称。我不认为以后改变它会产生任何影响。