代码之家  ›  专栏  ›  技术社区  ›  Elan

如何以编程方式启用net.tcp端口共享服务?

  •  3
  • Elan  · 技术社区  · 16 年前

    我希望以编程方式启用并启动C_中的net.tcp端口共享服务。我可以使用ServiceController类轻松启动服务。但是,如何启用默认禁用的服务?

    我在网上找到了一个建议,将以下注册表项设置为2,如下所示,这可能会将服务启动类型设置为自动:

    string path = "SYSTEM\\CurrentControlSet\\Services\\" + serviceName;
    using (RegistryKey key = Registry.LocalMachine.OpenSubKey(path, true)) {
        key.SetValue("Start", 2);
    }
    

    我尝试了这个方法,虽然它似乎将启动类型更改为自动,但它必须有更多的功能,因为服务现在不会启动(以编程方式或手动方式)。我必须通过services.msc手动重置启动类型以重置内容,以便可以启用服务并再次启动。

    有人解决了这个问题吗?

    2 回复  |  直到 15 年前
        1
  •  11
  •   bobbymcr    16 年前

    有多种方法可以做到这一点,这取决于您想要的解决方案的“纯”程度。这里有一些选择。 请注意,所有这些解决方案都需要管理权限,并且必须在提升的过程中运行。

    通过C使用命令提示#

    这将涉及炮击 sc.exe 以及通过命令行参数更改服务的启动类型。这与您上面提到的解决方案类似,只是不需要进行注册表黑客攻击。

    namespace Sample
    {
        using System;
        using System.Diagnostics;
        using System.Globalization;
    
        internal class ServiceSample
        {
            private static bool ChangeStartupType(string serviceName, string startupType)
            {
                string arguments = string.Format(
                    CultureInfo.InvariantCulture,
                    "config {0} start= {1}",
                    serviceName,
                    startupType);
                using (Process sc = Process.Start("sc.exe", arguments))
                {
                    sc.WaitForExit();
                    return sc.ExitCode == 0;
                }
            }
    
            private static void Main()
            {
                ServiceSample.ChangeStartupType("NetTcpPortSharing", "auto");
            }
        }
    }
    

    使用WMI

    这需要程序集引用 System.Management.dll . 这里我们将使用WMI功能 ChangeStartMode 为了服务。

    namespace Sample
    {
        using System;
        using System.Globalization;
        using System.Management;
    
        internal class ServiceSample
        {
            private static bool ChangeStartupType(string serviceName, string startupType)
            {
                const string MethodName = "ChangeStartMode";
                ManagementPath path = new ManagementPath();
                path.Server = ".";
                path.NamespacePath = @"root\CIMV2";
                path.RelativePath = string.Format(
                    CultureInfo.InvariantCulture,
                    "Win32_Service.Name='{0}'",
                    serviceName);
                using (ManagementObject serviceObject = new ManagementObject(path))
                {
                    ManagementBaseObject inputParameters = serviceObject.GetMethodParameters(MethodName);
                    inputParameters["startmode"] = startupType;
                    ManagementBaseObject outputParameters = serviceObject.InvokeMethod(MethodName, inputParameters, null);
                    return (uint)outputParameters.Properties["ReturnValue"].Value == 0;
                }
            }
    
            private static void Main()
            {
                ServiceSample.ChangeStartupType("NetTcpPortSharing", "Automatic");
            }
        }
    }
    

    对Win32 API使用P/Invoke

    对某些人来说,这是最“纯粹”的方法,尽管要想正确处理问题更难。基本上你要打电话 ChangeServiceConfig 来自.NET。但是,这要求您首先打电话 OpenService 对于指定的服务和 那个 需要呼叫 OpenSCManager 事先(别忘了 CloseServiceHandle 等你做完了!).

    注意:此代码仅用于演示目的。它不包含任何错误处理,可能会泄漏资源。应使用适当的实现 SafeHandle 类型以确保正确清理,并应添加适当的错误检查。

    namespace Sample
    {
        using System;
        using System.ComponentModel;
        using System.Runtime.InteropServices;
    
        internal class ServiceSample
        {
            private const uint SC_MANAGER_CONNECT = 0x1;
            private const uint SERVICE_CHANGE_CONFIG = 0x2;
            private const uint STANDARD_RIGHTS_WRITE = 0x20000;
    
            private const uint SERVICE_NO_CHANGE = 0xFFFFFFFF;
    
            private const uint SERVICE_AUTO_START = 0x2;
            private const uint SERVICE_DEMAND_START = 0x3;
            private const uint SERVICE_DISABLED = 0x4;
    
            [DllImport("advapi32.dll", SetLastError = true)]
            private static extern IntPtr OpenSCManager(string lpMachineName, string lpDatabaseName, uint dwDesiredAccess);
    
            [DllImport("advapi32.dll", SetLastError = true)]
            private static extern IntPtr OpenService(IntPtr hSCManager, string lpServiceName, uint dwDesiredAccess);
    
            [DllImport("advapi32.dll", SetLastError = true)]
            private static extern bool ChangeServiceConfig(IntPtr hService, uint dwServiceType, uint dwStartType, uint dwErrorControl, string lpBinaryPathName, string lpLoadOrderGroup, IntPtr lpdwTagId, string lpDependencies, string lpServiceStartName, string lpPassword, string lpDisplayName);
    
            [DllImport("advapi32.dll", SetLastError = true)]
            private static extern bool CloseServiceHandle(IntPtr hSCObject);
    
            private static bool ChangeStartupType(string serviceName, uint startType)
            {
                IntPtr scManager = ServiceSample.OpenSCManager(null, null, ServiceSample.SC_MANAGER_CONNECT);
                IntPtr service = ServiceSample.OpenService(scManager, serviceName, ServiceSample.SERVICE_CHANGE_CONFIG | ServiceSample.STANDARD_RIGHTS_WRITE);
                bool succeeded = ServiceSample.ChangeServiceConfig(service, ServiceSample.SERVICE_NO_CHANGE, startType, ServiceSample.SERVICE_NO_CHANGE, null, null, IntPtr.Zero, null, null, null, null);
                ServiceSample.CloseServiceHandle(service);
                ServiceSample.CloseServiceHandle(scManager);
    
                return succeeded;
            }
    
            private static void Main()
            {
                ServiceSample.ChangeStartupType("NetTcpPortSharing", ServiceSample.SERVICE_AUTO_START);
            }
        }
    }
    
        2
  •  0
  •   Wayne Lo    15 年前

    使用ServiceController有一个简单的答案

    System.ServiceProcess.ServiceController netTcpPortSharingService = new System.ServiceProcess.ServiceController("NetTcpPortSharing");
    
    if (netTcpPortSharingService != null)
                {
                    if(netTcpPortSharingService.Status!=ServiceControllerStatus.Running && netTcpPortSharingService.Status!=ServiceControllerStatus.StartPending)
                    {
                        netTcpPortSharingService.Start();
                    }
                }
    
    推荐文章