C# 以编程方式在远程计算机上安装Windows服务
与演示如何在远程计算机上启动和停止现有Windows服务类似,我正在尝试在远程计算机上安装Windows服务。我可以在远程机器上启动和停止服务,但如果不调用sc.exe进程(),我无法找到如何远程安装新服务,如果可能的话,我希望避免调用sc.exe进程() 我知道存在System.Configuration.Install.ManagedInstallerClass.InstallHelper方法,但我无法在远程计算机上安装该方法。而且,我无法确定是否可以使用System.ServiceProcess.ServiceInstaller或System.ServiceProcess.ServiceProcessInstaller。执行此操作的C代码如下所示:C# 以编程方式在远程计算机上安装Windows服务,c#,.net,service,windows-services,C#,.net,Service,Windows Services,与演示如何在远程计算机上启动和停止现有Windows服务类似,我正在尝试在远程计算机上安装Windows服务。我可以在远程机器上启动和停止服务,但如果不调用sc.exe进程(),我无法找到如何远程安装新服务,如果可能的话,我希望避免调用sc.exe进程() 我知道存在System.Configuration.Install.ManagedInstallerClass.InstallHelper方法,但我无法在远程计算机上安装该方法。而且,我无法确定是否可以使用System.ServiceProc
using (var scmHandle = NativeMethods.OpenSCManager("MachineName", null, NativeMethods.SCM_ACCESS.SC_MANAGER_CREATE_SERVICE))
{
if (scmHandle.IsInvalid)
{
throw new Win32Exception();
}
using (
var serviceHandle = NativeMethods.CreateService(
scmHandle,
"ServiceName",
"Service Display Name",
NativeMethods.SERVICE_ACCESS.SERVICE_ALL_ACCESS,
NativeMethods.SERVICE_TYPES.SERVICE_WIN32_OWN_PROCESS,
NativeMethods.SERVICE_START_TYPES.SERVICE_AUTO_START,
NativeMethods.SERVICE_ERROR_CONTROL.SERVICE_ERROR_NORMAL,
"Path to your service.exe",
null,
IntPtr.Zero,
null,
null,
null))
{
if (serviceHandle.IsInvalid)
{
throw new Win32Exception();
}
NativeMethods.StartService(serviceHandle, 0, null);
}
}
安全手柄
处理非托管句柄时,应使用安全句柄,以确保在C#中正确释放资源
签名
您需要的函数的所有签名都可以在上找到,整个服务控制API都可以在MSDN上找到:
使用系统;
使用System.Runtime.InteropServices;
公共静态类NativeMethods
{
[DllImport(“advapi32.dll”)]
公共静态外部服务控制句柄OpenSCManager(字符串lpMachineName、字符串lpSCDB、SCM\U ACCESS scParameter);
[DllImport(“Advapi32.dll”)]
公共静态外部服务ControlHandle CreateService(
ServiceControlHandle serviceControlManagerHandle,
字符串lpSvcName,
字符串lpDisplayName,
服务访问请求访问,
服务类型dwServiceType,
服务\启动\类型dwStartType,
服务错误控制数据错误控制,
字符串lpPathName,
字符串lpLoadOrderGroup,
IntPtr lpdwTagId,
字符串依赖项,
字符串lpServiceStartName,
字符串(密码);
[DllImport(“advapi32.dll”)]
公共静态外部布尔CloseServiceHandle(IntPtr serviceHandle);
[DllImport(“advapi32.dll”,SetLastError=true)]
[返回:Marshallas(UnmanagedType.Bool)]
公共静态外部布尔控制服务(IntPtr hService、服务控制dwControl、参考服务状态lpServiceStatus);
[DllImport(“advapi32.dll”)]
公共静态外部int StartService(ServiceControlHandle serviceHandle、int dwNumServiceArgs、字符串LPServiceArgVector);
[DllImport(“advapi32.dll”,SetLastError=true)]
公共静态外部服务控制句柄OpenService(ServiceControlHandle serviceControlManagerHandle,字符串lpSvcName,服务访问dwDesiredAccess);
[DllImport(“advapi32.dll”)]
公共静态外部内部删除服务(ServiceControlHandle serviceHandle);
[DllImport(“kernel32.dll”)]
公共静态外部int GetLastError();
[旗帜]
公共枚举访问\u掩码:uint
{
删除=0x00010000,
读取控制=0x00020000,
写入_DAC=0x00040000,
写入所有者=0x00080000,
同步=0x00100000,
标准权限要求=0x000F0000,
标准版权读取=0x00020000,
标准写入权限=0x00020000,
标准权限执行=0x00020000,
标准版权所有=0x001F0000,
特定权利所有=0x0000FFFF,
访问系统安全性=0x01000000,
允许的最大值=0x02000000,
一般读取=0x8000000,
一般写入=0x40000000,
通用_EXECUTE=0x20000000,
通用_ALL=0x10000000,
桌面\u READOBJECTS=0x00000001,
桌面\u CREATEWINDOW=0x00000002,
桌面创建菜单=0x00000004,
桌面钩子控件=0x00000008,
桌面日志记录=0x00000010,
DESKTOP_JOURNALPLAYBACK=0x00000020,
桌面枚举=0x00000040,
桌面_WRITEOBJECTS=0x00000080,
桌面\u SWITCHDESKTOP=0x00000100,
WINSTA_ENUMDESKTOPS=0x00000001,
WINSTA_READATTRIBUTES=0x00000002,
WINSTA_ACCESSCLIPBOARD=0x00000004,
WINSTA_CREATEDESKTOP=0x00000008,
WINSTA_WRITEATTRIBUTES=0x00000010,
WINSTA_ACCESSGLOBALATOMS=0x00000020,
WINSTA_EXITWINDOWS=0x00000040,
WINSTA_ENUMERATE=0x00000100,
WINSTA_READSCREEN=0x00000200,
WINSTA_ALL_ACCESS=0x0000037F
}
[旗帜]
公共枚举SCM_访问:uint
{
///
///需要连接到服务控制管理器。
///
SC_管理器_连接=0x00001,
///
///需要调用CreateService函数来创建服务
///对象并将其添加到数据库中。
///
SC_管理器_创建_服务=0x00002,
///
///调用EnumServicesStatusEx函数以列出
///数据库中的服务。
///
SC_管理器_枚举_服务=0x00004,
///
///调用LockServiceDatabase函数以获取
///锁定数据库。
///
SC_管理器_锁=0x00008,
///
///调用QueryServiceLockStatus函数以检索
///数据库的锁定状态信息。
///
SC_管理器_查询_锁定_状态=0x00010,
///
///需要调用NotifyBootConfigStatus函数。
///
SC_管理器_修改_引导_配置=0x00020,
///
///除所有访问权限外,还包括所需的标准权限
///此表中的权限。
///
SC_经理_所有访问权限=
访问|掩码.标准|所需权限| SC |管理|连接| SC |管理|创建|服务| SC |管理|枚举|服务| SC |管理|锁定| SC |管理|查询|锁定|
|SC_管理器_修改_引导_配置,
通用读取=访问掩码标准权限读取SC管理器枚举服务SC管理器查询锁定状态,
GENERIC_WRITE=ACCESS_MASK.STANDARD_RIGHTS_WRITE|SC_MANAGER|u CREATE|u SERVICE|SC_MANAGER_MODIFY_BOOT_CONFIG,
泛型执行
[SecurityPermission(SecurityAction.InheritanceDemand, UnmanagedCode = true)]
[SecurityPermission(SecurityAction.Demand, UnmanagedCode = true)]
public class ServiceControlHandle : SafeHandleZeroOrMinusOneIsInvalid
{
// Create a SafeHandle, informing the base class
// that this SafeHandle instance "owns" the handle,
// and therefore SafeHandle should call
// our ReleaseHandle method when the SafeHandle
// is no longer in use.
private ServiceControlHandle()
: base(true)
{
}
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
override protected bool ReleaseHandle()
{
// Here, we must obey all rules for constrained execution regions.
return NativeMethods.CloseServiceHandle(this.handle);
// If ReleaseHandle failed, it can be reported via the
// "releaseHandleFailed" managed debugging assistant (MDA). This
// MDA is disabled by default, but can be enabled in a debugger
// or during testing to diagnose handle corruption problems.
// We do not throw an exception because most code could not recover
// from the problem.
}
}
using System;
using System.Runtime.InteropServices;
public static class NativeMethods
{
[DllImport("advapi32.dll")]
public static extern ServiceControlHandle OpenSCManager(string lpMachineName, string lpSCDB, SCM_ACCESS scParameter);
[DllImport("Advapi32.dll")]
public static extern ServiceControlHandle CreateService(
ServiceControlHandle serviceControlManagerHandle,
string lpSvcName,
string lpDisplayName,
SERVICE_ACCESS dwDesiredAccess,
SERVICE_TYPES dwServiceType,
SERVICE_START_TYPES dwStartType,
SERVICE_ERROR_CONTROL dwErrorControl,
string lpPathName,
string lpLoadOrderGroup,
IntPtr lpdwTagId,
string lpDependencies,
string lpServiceStartName,
string lpPassword);
[DllImport("advapi32.dll")]
public static extern bool CloseServiceHandle(IntPtr serviceHandle);
[DllImport("advapi32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool ControlService(IntPtr hService, SERVICE_CONTROL dwControl, ref SERVICE_STATUS lpServiceStatus);
[DllImport("advapi32.dll")]
public static extern int StartService(ServiceControlHandle serviceHandle, int dwNumServiceArgs, string lpServiceArgVectors);
[DllImport("advapi32.dll", SetLastError = true)]
public static extern ServiceControlHandle OpenService(ServiceControlHandle serviceControlManagerHandle, string lpSvcName, SERVICE_ACCESS dwDesiredAccess);
[DllImport("advapi32.dll")]
public static extern int DeleteService(ServiceControlHandle serviceHandle);
[DllImport("kernel32.dll")]
public static extern int GetLastError();
[Flags]
public enum ACCESS_MASK : uint
{
DELETE = 0x00010000,
READ_CONTROL = 0x00020000,
WRITE_DAC = 0x00040000,
WRITE_OWNER = 0x00080000,
SYNCHRONIZE = 0x00100000,
STANDARD_RIGHTS_REQUIRED = 0x000F0000,
STANDARD_RIGHTS_READ = 0x00020000,
STANDARD_RIGHTS_WRITE = 0x00020000,
STANDARD_RIGHTS_EXECUTE = 0x00020000,
STANDARD_RIGHTS_ALL = 0x001F0000,
SPECIFIC_RIGHTS_ALL = 0x0000FFFF,
ACCESS_SYSTEM_SECURITY = 0x01000000,
MAXIMUM_ALLOWED = 0x02000000,
GENERIC_READ = 0x80000000,
GENERIC_WRITE = 0x40000000,
GENERIC_EXECUTE = 0x20000000,
GENERIC_ALL = 0x10000000,
DESKTOP_READOBJECTS = 0x00000001,
DESKTOP_CREATEWINDOW = 0x00000002,
DESKTOP_CREATEMENU = 0x00000004,
DESKTOP_HOOKCONTROL = 0x00000008,
DESKTOP_JOURNALRECORD = 0x00000010,
DESKTOP_JOURNALPLAYBACK = 0x00000020,
DESKTOP_ENUMERATE = 0x00000040,
DESKTOP_WRITEOBJECTS = 0x00000080,
DESKTOP_SWITCHDESKTOP = 0x00000100,
WINSTA_ENUMDESKTOPS = 0x00000001,
WINSTA_READATTRIBUTES = 0x00000002,
WINSTA_ACCESSCLIPBOARD = 0x00000004,
WINSTA_CREATEDESKTOP = 0x00000008,
WINSTA_WRITEATTRIBUTES = 0x00000010,
WINSTA_ACCESSGLOBALATOMS = 0x00000020,
WINSTA_EXITWINDOWS = 0x00000040,
WINSTA_ENUMERATE = 0x00000100,
WINSTA_READSCREEN = 0x00000200,
WINSTA_ALL_ACCESS = 0x0000037F
}
[Flags]
public enum SCM_ACCESS : uint
{
/// <summary>
/// Required to connect to the service control manager.
/// </summary>
SC_MANAGER_CONNECT = 0x00001,
/// <summary>
/// Required to call the CreateService function to create a service
/// object and add it to the database.
/// </summary>
SC_MANAGER_CREATE_SERVICE = 0x00002,
/// <summary>
/// Required to call the EnumServicesStatusEx function to list the
/// services that are in the database.
/// </summary>
SC_MANAGER_ENUMERATE_SERVICE = 0x00004,
/// <summary>
/// Required to call the LockServiceDatabase function to acquire a
/// lock on the database.
/// </summary>
SC_MANAGER_LOCK = 0x00008,
/// <summary>
/// Required to call the QueryServiceLockStatus function to retrieve
/// the lock status information for the database.
/// </summary>
SC_MANAGER_QUERY_LOCK_STATUS = 0x00010,
/// <summary>
/// Required to call the NotifyBootConfigStatus function.
/// </summary>
SC_MANAGER_MODIFY_BOOT_CONFIG = 0x00020,
/// <summary>
/// Includes STANDARD_RIGHTS_REQUIRED, in addition to all access
/// rights in this table.
/// </summary>
SC_MANAGER_ALL_ACCESS =
ACCESS_MASK.STANDARD_RIGHTS_REQUIRED | SC_MANAGER_CONNECT | SC_MANAGER_CREATE_SERVICE | SC_MANAGER_ENUMERATE_SERVICE | SC_MANAGER_LOCK | SC_MANAGER_QUERY_LOCK_STATUS
| SC_MANAGER_MODIFY_BOOT_CONFIG,
GENERIC_READ = ACCESS_MASK.STANDARD_RIGHTS_READ | SC_MANAGER_ENUMERATE_SERVICE | SC_MANAGER_QUERY_LOCK_STATUS,
GENERIC_WRITE = ACCESS_MASK.STANDARD_RIGHTS_WRITE | SC_MANAGER_CREATE_SERVICE | SC_MANAGER_MODIFY_BOOT_CONFIG,
GENERIC_EXECUTE = ACCESS_MASK.STANDARD_RIGHTS_EXECUTE | SC_MANAGER_CONNECT | SC_MANAGER_LOCK,
GENERIC_ALL = SC_MANAGER_ALL_ACCESS,
}
[Flags]
public enum SERVICE_CONTROL : uint
{
STOP = 0x00000001,
PAUSE = 0x00000002,
CONTINUE = 0x00000003,
INTERROGATE = 0x00000004,
SHUTDOWN = 0x00000005,
PARAMCHANGE = 0x00000006,
NETBINDADD = 0x00000007,
NETBINDREMOVE = 0x00000008,
NETBINDENABLE = 0x00000009,
NETBINDDISABLE = 0x0000000A,
DEVICEEVENT = 0x0000000B,
HARDWAREPROFILECHANGE = 0x0000000C,
POWEREVENT = 0x0000000D,
SESSIONCHANGE = 0x0000000E
}
[Flags]
public enum SERVICE_ACCESS : uint
{
STANDARD_RIGHTS_REQUIRED = 0xF0000,
SERVICE_QUERY_CONFIG = 0x00001,
SERVICE_CHANGE_CONFIG = 0x00002,
SERVICE_QUERY_STATUS = 0x00004,
SERVICE_ENUMERATE_DEPENDENTS = 0x00008,
SERVICE_START = 0x00010,
SERVICE_STOP = 0x00020,
SERVICE_PAUSE_CONTINUE = 0x00040,
SERVICE_INTERROGATE = 0x00080,
SERVICE_USER_DEFINED_CONTROL = 0x00100,
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)
}
[Flags]
public enum SERVICE_TYPES : int
{
SERVICE_KERNEL_DRIVER = 0x00000001,
SERVICE_FILE_SYSTEM_DRIVER = 0x00000002,
SERVICE_WIN32_OWN_PROCESS = 0x00000010,
SERVICE_WIN32_SHARE_PROCESS = 0x00000020,
SERVICE_INTERACTIVE_PROCESS = 0x00000100
}
public enum SERVICE_ERROR_CONTROL : int
{
/// <summary>
/// The startup program logs the error in the event log, if possible. If the last-known-good configuration is being started, the startup operation fails. Otherwise, the system is restarted with the last-known good configuration.
/// </summary>
SERVICE_ERROR_CRITICAL = 0x00000003,
/// <summary>
/// The startup program ignores the error and continues the startup operation.
/// </summary>
SERVICE_ERROR_IGNORE = 0x00000000,
/// <summary>
/// The startup program logs the error in the event log but continues the startup operation.
/// </summary>
SERVICE_ERROR_NORMAL = 0x00000001,
/// <summary>
/// The startup program logs the error in the event log. If the last-known-good configuration is being started, the startup operation continues. Otherwise, the system is restarted with the last-known-good configuration.
/// </summary>
SERVICE_ERROR_SEVERE = 0x00000002,
}
public enum SERVICE_START_TYPES : int
{
/// <summary>
/// A service started automatically by the service control manager during system startup. For more information, see Automatically Starting Services.
/// </summary>
SERVICE_AUTO_START = 0x00000002,
/// <summary>
/// A device driver started by the system loader. This value is valid only for driver services.
/// </summary>
SERVICE_BOOT_START = 0x00000000,
/// <summary>
/// A service started by the service control manager when a process calls the StartService function. For more information, see Starting Services on Demand.
/// </summary>
SERVICE_DEMAND_START = 0x00000003,
/// <summary>
/// A service that cannot be started. Attempts to start the service result in the error code ERROR_SERVICE_DISABLED.
/// </summary>
SERVICE_DISABLED = 0x00000004,
/// <summary>
/// A device driver started by the IoInitSystem function. This value is valid only for driver services.
/// </summary>
SERVICE_SYSTEM_START = 0x00000001
}
public enum SERVICE_STATE : uint
{
SERVICE_STOPPED = 0x00000001,
SERVICE_START_PENDING = 0x00000002,
SERVICE_STOP_PENDING = 0x00000003,
SERVICE_RUNNING = 0x00000004,
SERVICE_CONTINUE_PENDING = 0x00000005,
SERVICE_PAUSE_PENDING = 0x00000006,
SERVICE_PAUSED = 0x00000007
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct SERVICE_STATUS
{
public static readonly int SizeOf = Marshal.SizeOf(typeof(SERVICE_STATUS));
public SERVICE_TYPES dwServiceType;
public SERVICE_STATE dwCurrentState;
public uint dwControlsAccepted;
public uint dwWin32ExitCode;
public uint dwServiceSpecificExitCode;
public uint dwCheckPoint;
public uint dwWaitHint;
}
}