gpt4 book ai didi

c# - 如何以编程方式启用 Net.Tcp 端口共享服务?

转载 作者:行者123 更新时间:2023-11-30 13:34:45 24 4
gpt4 key购买 nike

我想在 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 手动重置启动类型以重置内容,以便可以启用并再次启动该服务。

有人解决了吗?

最佳答案

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

通过 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");
}
}
}

使用 P/Invoke 到 Win32 API

对某些人来说,这是最“纯粹”的方法,尽管它更难以正确使用。基本上你会想调用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);
}
}
}

关于c# - 如何以编程方式启用 Net.Tcp 端口共享服务?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2174882/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com