【问题标题】:Add a description to windows service向 Windows 服务添加描述
【发布时间】:2014-03-26 14:06:58
【问题描述】:

我通过以下代码安装了一个windows服务。

 #region Private Variables

    #endregion Private Variables
    #region DLLImport
    [DllImport("advapi32.dll")]
    public static extern IntPtr OpenSCManager(string lpMachineName, string lpSCDB, int scParameter);
    [DllImport("Advapi32.dll")]
    public static extern IntPtr CreateService(IntPtr SC_HANDLE, string lpSvcName, string lpDisplayName,
    int dwDesiredAccess, int dwServiceType, int dwStartType, int dwErrorControl, string lpPathName,
    string lpLoadOrderGroup, int lpdwTagId, string lpDependencies, string lpServiceStartName, string lpPassword);
    [DllImport("advapi32.dll")]
    public static extern void CloseServiceHandle(IntPtr SCHANDLE);
    [DllImport("advapi32.dll")]
    public static extern int StartService(IntPtr SVHANDLE, int dwNumServiceArgs, string lpServiceArgVectors);
    [DllImport("advapi32.dll", SetLastError = true)]
    public static extern IntPtr OpenService(IntPtr SCHANDLE, string lpSvcName, int dwNumServiceArgs);
    [DllImport("advapi32.dll")]
    public static extern int DeleteService(IntPtr SVHANDLE);
    [DllImport("kernel32.dll")]
    public static extern int GetLastError();
    #endregion DLLImport
    public static bool  InstallService(string svcPath, string svcName, string svcDispName)
    {
        #region Constants declaration.
        int SC_MANAGER_CREATE_SERVICE = 0x0002;
        int SERVICE_WIN32_OWN_PROCESS = 0x00000010;
        //int SERVICE_DEMAND_START = 0x00000003;
        int SERVICE_ERROR_NORMAL = 0x00000001;
        int STANDARD_RIGHTS_REQUIRED = 0xF0000;
        int SERVICE_QUERY_CONFIG = 0x0001;
        int SERVICE_CHANGE_CONFIG = 0x0002;
        int SERVICE_QUERY_STATUS = 0x0004;
        int SERVICE_ENUMERATE_DEPENDENTS = 0x0008;
        int SERVICE_START = 0x0010;
        int SERVICE_STOP = 0x0020;
        int SERVICE_PAUSE_CONTINUE = 0x0040;
        int SERVICE_INTERROGATE = 0x0080;
        int SERVICE_USER_DEFINED_CONTROL = 0x0100;
        int SERVICE_ALL_ACCESS = (STANDARD_RIGHTS_REQUIRED |
        SERVICE_QUERY_CONFIG |
        SERVICE_CHANGE_CONFIG |
        SERVICE_QUERY_STATUS |
        SERVICE_ENUMERATE_DEPENDENTS |
        SERVICE_START |
        SERVICE_STOP |
        SERVICE_PAUSE_CONTINUE |
        SERVICE_INTERROGATE |
        SERVICE_USER_DEFINED_CONTROL);
        int SERVICE_AUTO_START = 0x00000002;
        #endregion Constants declaration.
        try
        {
            IntPtr sc_handle = OpenSCManager(null, null, SC_MANAGER_CREATE_SERVICE);
            if (sc_handle.ToInt32() != 0)
            {
                IntPtr sv_handle = CreateService(sc_handle, svcName, svcDispName, SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS, SERVICE_AUTO_START, SERVICE_ERROR_NORMAL, svcPath, null, 0, null, null, null);
                if (sv_handle.ToInt32() == 0)
                {
                    CloseServiceHandle(sc_handle);
                    return false;
                }
                else
                {
                    //now trying to start the service
                    int i = StartService(sv_handle, 0, null);
                    // If the value i is zero, then there was an error starting the service.
                    // note: error may arise if the service is already running or some other problem.
                    if (i == 0)
                    {
                        Console.WriteLine("Couldnt start service");
                        return false;
                    }
                    Console.WriteLine("Service started successfully");
                    CloseServiceHandle(sc_handle);
                    return true;
                }
            }
            else
            {
                Console.WriteLine("SCM not opened successfully");
                return false;
            }
        }
        catch (Exception e)
        {
            throw e;
        }
    }

但是 SCM 中的描述是空白的,请不要使用 ServiceInsatller,因为我想修改生产中的现有代码。感谢代码贡献。

更新:

如果忘记上面的代码,使用ManagedInstallerClass或其他方法,怎么办?

【问题讨论】:

    标签: c# windows-services registry


    【解决方案1】:

    回答的代码不起作用。这是一个对我有用的版本:

    const int SERVICE_CONFIG_DESCRIPTION = 0x01;
    
    [DllImport("advapi32.dll", SetLastError=true, CharSet=CharSet.Auto)]
    [return: MarshalAs(UnmanagedType.Bool)]
    public static extern bool ChangeServiceConfig2(IntPtr hService, int dwInfoLevel, [MarshalAs(UnmanagedType.Struct)] ref SERVICE_DESCRIPTION lpInfo);
    
    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
    public struct SERVICE_DESCRIPTION
    {
        public string lpDescription;
    }
    
    var pinfo = new SERVICE_DESCRIPTION
    {
        lpDescription = "My Service Description"
    };
    
    ChangeServiceConfig2(service, SERVICE_CONFIG_DESCRIPTION, ref pinfo);
    

    【讨论】:

    • 为我工作 - VS 2015 今天针对 FW 4.0。注意:您必须使用 ChangeConfig 权限打开服务:IntPtr service = OpenService(scm, ServiceName, ServiceRights.QueryStatus | ServiceRights.ChangeConfig);
    【解决方案2】:

    原答案位于here,为方便起见,在此重复。

    调用 ChangeServiceConfig2 传递 SERVICE_CONFIG_DESCRIPTION 作为 dwInfoLevel 参数。您还需要服务的句柄,但是 CreateService 为您提供其中之一。

    DllImport 而言,您可以找到ChangeServiceConfig2 here 的规范。

    编辑:

    如果您想完全放弃现有的方法,使用ManagedInstallerClass 不是正确的方法,因为 MSDN 明确规定不要在您的代码中使用它。据我估计,正确的方法是使用 ServiceInstaller 组件,但您最初的问题说您不想使用这种方法。

    假设您放弃了不使用ServiceInstaller。然后我建议按照我在回答 here 中提供的说明进行操作,特别注意步骤 6-9。在第 8 步中,您可以将任何您喜欢的描述添加到属性网格中的 ServiceInstaller 组件中。

    如果您仍然不想采用这种方法,那么我最初的答案是有效的。它看起来像这样(请注意,我还没有测试过):

    [DllImport("advapi32.dll", SetLastError=true, CharSet=CharSet.Auto)]
    [return: MarshalAs(UnmanagedType.Bool)]
    public static extern bool ChangeServiceConfig2(
        IntPtr hService, 
        int dwInfoLevel,
        IntPtr lpInfo);
    
    int SERVICE_CONFIG_DESCRIPTION = 0x01;
    ChangeServiceConfig2(sv_handle, SERVICE_CONFIG_DESCRIPTION, "a test description");
    

    【讨论】:

    • 我在想,如果使用 ManagedInstallerClass 而不是老式的,我该如何添加服务名称、显示名称和描述?
    • 算我一头雾水。 MSDN 说 ManagedInstallerClass 应该直接从生产代码中使用。在您最初的问题中,您说您不想使用ServiceInstaller,并且该示例显示了老式的方法,即通过 p/invoke。目前还不清楚你想要什么,至少对我来说是这样。
    • /@Mattsorry 关于它。虽然我的问题是针对老式的,但我仍然觉得它很复杂。所以我不会放弃任何与 ManagedInstallerClass 相关的想法。我只想在代码中添加描述。
    • 对。如果您只想按照描述的代码工作,您需要导入 ChangeServiceConfig2 调用,就像使用 OpenSCManagerCreateService 等一样。然后使用参数中描述的参数调用它回答。应该这样做。
    猜你喜欢
    • 2016-04-14
    • 1970-01-01
    • 2012-03-29
    • 1970-01-01
    • 2021-10-19
    • 2021-10-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多