Существует несколько способов сделать это, в зависимости от того, насколько "чистым" является решение, которое вы хотите. Вот несколько вариантов. Обратите внимание, что все эти решения требуют прав администратора и должны работать в процессе с повышенными правами.
Используйте командную строку через 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 из . СЕТЬ. Однако для этого необходимо сначала вызвать 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);
}
}
}
person
bobbymcr
schedule
01.02.2010