internal static extern bool EnumServicesStatusEx( SafeServiceHandle databaseHandle, int infolevel, int serviceType, int serviceState, IntPtr status, int size, out int bytesNeeded, out int servicesReturned, ref int resumeHandle, string?group);
/// Disconnects this object from the service and frees any allocated resources. protected virtual void Dispose(bool disposing) { if (_serviceManagerHandle != null) { _serviceManagerHandle.Dispose(); _serviceManagerHandle = null; } _statusGenerated = false; _type = Interop.mincore.ServiceTypeOptions.SERVICE_TYPE_ALL; _disposed = true; }
/// <summary> /// Starts a service in the machine specified. /// </summary> public void Start(string[] args) { ArgumentNullException.ThrowIfNull(args); using SafeServiceHandle serviceHandle = GetServiceHandle(Interop.Advapi32.ServiceOptions.SERVICE_START); IntPtr[] argPtrs = new IntPtr[args.Length]; int i = 0; try { for (i = 0; i < args.Length; i++) { if (args[i] == null) { throw new ArgumentNullException($"{nameof(args)}[{i}]", SR.ArgsCantBeNull); } argPtrs[i] = Marshal.StringToHGlobalUni(args[i]); } } catch { for (int j = 0; j < i; j++) { Marshal.FreeHGlobal(argPtrs[i]); } throw; } GCHandle argPtrsHandle = default; try { argPtrsHandle = GCHandle.Alloc(argPtrs, GCHandleType.Pinned); bool result = Interop.Advapi32.StartService(serviceHandle, args.Length, argPtrsHandle.AddrOfPinnedObject()); if (!result) { Exception inner = new Win32Exception(); throw new InvalidOperationException(SR.Format(SR.CannotStart, ServiceName, _machineName), inner); } } finally { for (i = 0; i < args.Length; i++) { Marshal.FreeHGlobal(argPtrs[i]); } if (argPtrsHandle.IsAllocated) { argPtrsHandle.Free(); } } }
public static extern bool ChangeServiceConfig( SafeServiceHandle hService, ServiceType dwServiceType, ServiceStartType dwStartType, ServiceErrorControl dwErrorControl, string lpBinaryPathName, string lpLoadOrderGroup, int lpdwTagId, string lpDependencies, string lpServiceStartName, string lpPassword, string lpDisplayName);
/// <summary> /// Closes the handle to the service manager, but does not /// mark the class as disposed. /// </summary> /// <remarks> /// Violates design guidelines by not matching Dispose() -- matches .NET Framework /// </remarks> public void Close() { if (_serviceManagerHandle != null) { _serviceManagerHandle.Dispose(); _serviceManagerHandle = null; } _statusGenerated = false; _startTypeInitialized = false; _type = Interop.Advapi32.ServiceTypeOptions.SERVICE_TYPE_ALL; }
static SecurityDescriptor GetServiceSecurityDescriptor(SafeServiceHandle handle) { int required = 0; byte[] sd = new byte[8192]; if (!QueryServiceObjectSecurity(handle, SecurityInformation.AllBasic, sd, sd.Length, out required)) { throw new Win32Exception(); } return(new SecurityDescriptor(sd)); }
/// <summary> /// Opens a handle for the current service. The handle must be Dispose()'d. /// </summary> /// <param name="desiredAccess">Access level to pass to OpenService()</param> /// <returns></returns> private SafeServiceHandle GetServiceHandle(int desiredAccess) { GetDataBaseHandleWithConnectAccess(); var serviceHandle = new SafeServiceHandle(Interop.Advapi32.OpenService(_serviceManagerHandle, ServiceName, desiredAccess)); if (serviceHandle.IsInvalid) { Exception inner = new Win32Exception(Marshal.GetLastWin32Error()); throw new InvalidOperationException(SR.Format(SR.OpenService, ServiceName, _machineName), inner); } return serviceHandle; }
internal static extern bool ChangeServiceConfigW( /* _In_ SC_HANDLE */ [In] SafeServiceHandle hService, /* _In_ DWORD */ [In] ServiceType dwServiceType, /* _In_ DWORD */ [In] ServiceStartType dwStartType, /* _In_ DWORD */ [In] ServiceErrorControl dwErrorControl, /* _In_opt_ LPCTSTR */ [In] string lpBinaryPathName, /* _In_opt_ LPCTSTR */ [In] string lpLoadOrderGroup, /* _Out_opt_ LPDWORD */ [In][Out] IntPtr lpdwTagId, /* _In_opt_ LPCTSTR */ [In] string lpDependencies, /* _In_opt_ LPCTSTR */ [In] string lpServiceStartName, /* _In_opt_ LPCTSTR */ [In] string lpPassword, /* _In_opt_ LPCTSTR */ [In] string lpDisplayName );
/// <summary>The SetServiceObjectSecurity function sets the security descriptor of a service object.</summary> /// <param name="hService"> /// A handle to the service. This handle is returned by the <see cref="OpenService" /> or /// <see cref="CreateService(SafeServiceHandle,string,string,ACCESS_MASK,ServiceType,ServiceStartType,ServiceErrorControl,string,string,int, string,string,string)" /> function. The access required for this handle depends on the security information /// specified in the <paramref name="dwSecurityInformation" /> parameter. /// </param> /// <param name="dwSecurityInformation"> /// Specifies the components of the security descriptor to set. This parameter can be a /// combination of the following values : <see cref="SECURITY_INFORMATION.DACL_SECURITY_INFORMATION" />, /// <see cref="SECURITY_INFORMATION.GROUP_SECURITY_INFORMATION" />, /// <see cref="SECURITY_INFORMATION.OWNER_SECURITY_INFORMATION" />, /// <see cref="SECURITY_INFORMATION.SACL_SECURITY_INFORMATION" />. Note that flags not handled by /// SetServiceObjectSecurity will be silently ignored. /// </param> /// <param name="lpSecurityDescriptor">The new security information.</param> public static void SetServiceObjectSecurity( SafeServiceHandle hService, SECURITY_INFORMATION dwSecurityInformation, RawSecurityDescriptor lpSecurityDescriptor) { var binaryForm = new byte[lpSecurityDescriptor.BinaryLength]; lpSecurityDescriptor.GetBinaryForm(binaryForm, 0); if (!SetServiceObjectSecurity(hService, dwSecurityInformation, binaryForm)) { throw new Win32Exception(); } }
private void GetDataBaseHandleWithConnectAccess() { if (_disposed) { throw new ObjectDisposedException(GetType().Name); } // get a handle to SCM with connect access and store it in serviceManagerHandle field. if (_serviceManagerHandle == null) { _serviceManagerHandle = new SafeServiceHandle(GetDataBaseHandleWithAccess(_machineName, Interop.mincore.ServiceControllerOptions.SC_MANAGER_CONNECT)); } }
/// Disconnects this object from the service and frees any allocated resources. protected override void Dispose(bool disposing) { if (_serviceManagerHandle != null) { _serviceManagerHandle.Dispose(); _serviceManagerHandle = null; } _statusGenerated = false; _startTypeInitialized = false; _type = Interop.Advapi32.ServiceTypeOptions.SERVICE_TYPE_ALL; _disposed = true; }
private static SafeServiceHandle GetDataBaseHandleWithAccess(string machineName, int serviceControlManagerAccess) { var databaseHandle = new SafeServiceHandle(); Marshal.InitHandle(databaseHandle, machineName.Equals(DefaultMachineName) || machineName.Length == 0 ? Interop.Advapi32.OpenSCManager(null, null, serviceControlManagerAccess) : Interop.Advapi32.OpenSCManager(machineName, null, serviceControlManagerAccess)); if (databaseHandle.IsInvalid) { Exception inner = new Win32Exception(); databaseHandle.Dispose(); throw new InvalidOperationException(SR.Format(SR.OpenSC, machineName), inner); } return(databaseHandle); }
/// <summary> /// Open an instance of the SCM. /// </summary> /// <param name="machine_name">The machine name for the SCM.</param> /// <param name="database_name">The database name. Specify SERVICES_ACTIVE_DATABASE or SERVICES_FAILED_DATABASE. /// If null then SERVICES_ACTIVE_DATABASE is used.</param> /// <param name="desired_access">The desired access for the SCM connection.</param> /// <param name="throw_on_error">True to throw on error.</param> /// <returns>The SCM instance.</returns> public static NtResult <ServiceControlManager> Open(string machine_name, string database_name, ServiceControlManagerAccessRights desired_access, bool throw_on_error) { if (machine_name == string.Empty) { machine_name = null; } if (database_name == string.Empty) { database_name = null; } SafeServiceHandle scm = Win32NativeMethods.OpenSCManager(machine_name, database_name, desired_access); if (!scm.IsInvalid) { return(new ServiceControlManager(scm, machine_name, desired_access).CreateResult()); } return(Win32Utils.CreateResultFromDosError <ServiceControlManager>(throw_on_error)); }
private static SafeServiceHandle GetDataBaseHandleWithAccess(string machineName, int serviceControlManagerAccess) { SafeServiceHandle? databaseHandle; if (machineName.Equals(DefaultMachineName) || machineName.Length == 0) { databaseHandle = new SafeServiceHandle(Interop.Advapi32.OpenSCManager(null, null, serviceControlManagerAccess)); } else { databaseHandle = new SafeServiceHandle(Interop.Advapi32.OpenSCManager(machineName, null, serviceControlManagerAccess)); } if (databaseHandle.IsInvalid) { Exception inner = new Win32Exception(Marshal.GetLastWin32Error()); throw new InvalidOperationException(SR.Format(SR.OpenSC, machineName), inner); } return databaseHandle; }
private void DeleteService() { using (var serviceManagerHandle = new SafeServiceHandle(Interop.Advapi32.OpenSCManager(null, null, Interop.Advapi32.ServiceControllerOptions.SC_MANAGER_ALL))) { if (serviceManagerHandle.IsInvalid) { throw new Win32Exception("Could not open SCM"); } using (var serviceHandle = new SafeServiceHandle(Interop.Advapi32.OpenService(serviceManagerHandle, ServiceName, Interop.Advapi32.ServiceOptions.STANDARD_RIGHTS_DELETE))) { if (serviceHandle.IsInvalid) { throw new Win32Exception($"Could not find service '{ServiceName}'"); } if (!Interop.Advapi32.DeleteService(serviceHandle)) { throw new Win32Exception($"Could not delete service '{ServiceName}'"); } } } }
public SafeServiceHandle OpenService(SafeServiceHandle hSCManager, string lpServiceName, ServiceAccess dwDesiredAccess) => OpenService(hSCManager, lpServiceName, dwDesiredAccess);
public static extern bool ChangeServiceConfig2(SafeServiceHandle serviceHandle, uint infoLevel, ref SERVICE_DELAYED_AUTOSTART_INFO serviceDesc);
public static extern bool FailureActionsOnNonCrashFailures( SafeServiceHandle hService, int dwInfoLevel, [MarshalAs(UnmanagedType.Struct)] ref SERVICE_FAILURE_ACTIONS_FLAG lpInfo);
internal static extern unsafe bool GetServiceDisplayName(SafeServiceHandle SCMHandle, string serviceName, char *displayName, ref int displayNameLength);
internal extern static IntPtr OpenService(SafeServiceHandle databaseHandle, string serviceName, int access);
public static extern bool DeleteService(SafeServiceHandle serviceHandle);
static void Main(string[] args) { bool show_help = false; int pid = Process.GetCurrentProcess().Id; bool show_write_only = false; bool print_sddl = false; bool dump_triggers = false; bool dump_scm = false; ServiceAccessRights service_rights = 0; bool quiet = false; bool map_to_generic = false; try { OptionSet opts = new OptionSet() { { "sddl", "Print full SDDL security descriptors", v => print_sddl = v != null }, { "p|pid=", "Specify a PID of a process to impersonate when checking", v => pid = int.Parse(v.Trim()) }, { "w", "Show only write permissions granted", v => show_write_only = v != null }, { "k=", String.Format("Filter on a specific right [{0}]", String.Join(",", Enum.GetNames(typeof(ServiceAccessRights)))), v => service_rights |= ParseRight <ServiceAccessRights>(v) }, { "t", "Dump trigger information for services", v => dump_triggers = v != null }, { "scm", "Dump SCM security information", v => dump_scm = v != null }, { "g", "Map access mask to generic rights.", v => map_to_generic = v != null }, { "q", "Don't print our errors", v => quiet = v != null }, { "h|help", "show this message and exit", v => show_help = v != null }, }; List <string> service_names = opts.Parse(args); if (show_help) { ShowHelp(opts); } else { if (service_names.Count == 0) { service_names.AddRange(ServiceController.GetServices().Select(s => s.ServiceName)); } using (NtToken token = NtToken.OpenProcessToken(pid)) { using (SafeServiceHandle scm = OpenSCManager(null, null, ServiceControlManagerAccessRights.Connect | ServiceControlManagerAccessRights.ReadControl)) { if (dump_scm) { SecurityDescriptor sd = GetServiceSecurityDescriptor(scm); AccessMask granted_access = GetGrantedAccess(sd, token, AccessMask.Empty, GetSCMGenericMapping()); Console.WriteLine("SCM Granted Access: {0:X08} {1}", granted_access, GrantedAccessToString(granted_access, true, map_to_generic)); if (print_sddl) { Console.WriteLine("SCM SDDL: {0}", sd.ToSddl()); } } foreach (string name in service_names) { try { DumpService(scm, name, token, service_rights, show_write_only, print_sddl, dump_triggers, map_to_generic); } catch (Exception ex) { if (!quiet) { Console.Error.WriteLine("Error querying service: {0} - {1}", name, ex.Message); } } } } } } } catch (Exception e) { Console.Error.WriteLine(e.Message); } }
internal static extern bool StartService(SafeServiceHandle hSCManager, int dwNumServiceArgs, string[] lpServiceArgVectors);
internal static extern bool QueryServiceStatusEx(SafeServiceHandle hService, int InfoLevel, [Out] byte[] pBuffer, int cbBufSize, out int pcbBytesNeeded);
internal static extern bool QueryServiceStatus(SafeServiceHandle hService, out SERVICE_STATUS_PROCESS status);
internal static extern bool QueryServiceConfig(SafeServiceHandle hService, [Out] byte[] pServiceConfig, int cbBufSize, out int pcbBytesNeeded);
public unsafe void Install() { string username = Username; string password = Password; if (ServiceCommandLine == null) { string processName = Process.GetCurrentProcess().MainModule.FileName; string entryPointName = System.Reflection.Assembly.GetEntryAssembly().Location; string arguments = ServiceName; // if process and entry point aren't the same then we are running hosted so pass // in the entrypoint as the first argument if (!string.Equals(processName, entryPointName, StringComparison.OrdinalIgnoreCase)) { arguments = $"\"{entryPointName}\" {arguments}"; } ServiceCommandLine = $"\"{processName}\" {arguments}"; } // Build servicesDependedOn string string servicesDependedOn = null; if (ServicesDependedOn.Length > 0) { StringBuilder buff = new StringBuilder(); for (int i = 0; i < ServicesDependedOn.Length; ++i) { //The servicesDependedOn need to be separated by a null buff.Append(ServicesDependedOn[i]); buff.Append('\0'); } // an extra null at the end indicates end of list. buff.Append('\0'); servicesDependedOn = buff.ToString(); } // Open the service manager using (var serviceManagerHandle = new SafeServiceHandle(Interop.Advapi32.OpenSCManager(null, null, Interop.Advapi32.ServiceControllerOptions.SC_MANAGER_ALL))) { if (serviceManagerHandle.IsInvalid) { throw new InvalidOperationException("Cannot open Service Control Manager"); } // Install the service using (var serviceHandle = new SafeServiceHandle(Interop.Advapi32.CreateService(serviceManagerHandle, ServiceName, DisplayName, Interop.Advapi32.ServiceAccessOptions.ACCESS_TYPE_ALL, Interop.Advapi32.ServiceTypeOptions.SERVICE_TYPE_WIN32_OWN_PROCESS, (int)StartType, Interop.Advapi32.ServiceStartErrorModes.ERROR_CONTROL_NORMAL, ServiceCommandLine, null, IntPtr.Zero, servicesDependedOn, username, password))) { if (serviceHandle.IsInvalid) { throw new Win32Exception("Cannot create service"); } // A local variable in an unsafe method is already fixed -- so we don't need a "fixed { }" blocks to protect // across the p/invoke calls below. if (Description.Length != 0) { Interop.Advapi32.SERVICE_DESCRIPTION serviceDesc = new Interop.Advapi32.SERVICE_DESCRIPTION(); serviceDesc.description = Marshal.StringToHGlobalUni(Description); bool success = Interop.Advapi32.ChangeServiceConfig2(serviceHandle, Interop.Advapi32.ServiceConfigOptions.SERVICE_CONFIG_DESCRIPTION, ref serviceDesc); Marshal.FreeHGlobal(serviceDesc.description); if (!success) { throw new Win32Exception("Cannot set description"); } } // Start the service after creating it using (ServiceController svc = new ServiceController(ServiceName)) { if (svc.Status != ServiceControllerStatus.Running) { svc.Start(); if (!ServiceName.StartsWith("PropagateExceptionFromOnStart")) { svc.WaitForStatus(ServiceControllerStatus.Running, TimeSpan.FromSeconds(120)); } } } } } }
public bool ChangeServiceConfig2(SafeServiceHandle hService, ServiceInfoLevel dwInfoLevel, IntPtr lpInfo) => ChangeServiceConfig2(hService, dwInfoLevel, lpInfo);
public bool DeleteService(SafeServiceHandle hService) => DeleteService(hService);
public bool StartService(SafeServiceHandle hService, int dwNumServiceArgs, string lpServiceArgVectors) => StartService(hService, dwNumServiceArgs, lpServiceArgVectors);
static void DumpTriggers(SafeServiceHandle service) { using (var buf = new SafeStructureInOutBuffer <SERVICE_TRIGGER_INFO>(8192, false)) { int required = 0; if (!QueryServiceConfig2(service, SERVICE_CONFIG_TRIGGER_INFO, buf, 8192, out required)) { return; } SERVICE_TRIGGER_INFO trigger_info = buf.Result; if (trigger_info.cTriggers == 0) { return; } SERVICE_TRIGGER[] trigger_arr; using (SafeHGlobalBuffer triggers = new SafeHGlobalBuffer(trigger_info.pTriggers, trigger_info.cTriggers * Marshal.SizeOf(typeof(SERVICE_TRIGGER)), false)) { trigger_arr = new SERVICE_TRIGGER[trigger_info.cTriggers]; triggers.ReadArray(0, trigger_arr, 0, trigger_arr.Length); } for (int i = 0; i < trigger_arr.Length; ++i) { SERVICE_TRIGGER trigger = trigger_arr[i]; Console.WriteLine("Trigger: {0} - Type: {1} - Action: {2}", i, trigger.dwTriggerType, trigger.dwAction); switch (trigger.dwTriggerType) { case ServiceTriggerType.Custom: Console.WriteLine("Subtype: [ETW UUID] {0:B}", trigger.GetSubType()); break; case ServiceTriggerType.DeviceInterfaceArrival: Console.WriteLine("Subtype: [Interface Class GUID] {0:B}", trigger.GetSubType()); break; case ServiceTriggerType.GroupPolicy: { Guid sub_type = trigger.GetSubType(); if (sub_type == MACHINE_POLICY_PRESENT_GUID) { Console.WriteLine("Subtype: [Machine Policy Present]"); } else if (sub_type == USER_POLICY_PRESENT_GUID) { Console.WriteLine("Subtype: [User Policy Present]"); } else { Console.WriteLine("Subtype: [Unknown Group Policy] {0:B}", sub_type); } } break; case ServiceTriggerType.NetworkEndpoint: { Guid sub_type = trigger.GetSubType(); if (sub_type == RPC_INTERFACE_EVENT_GUID) { Console.WriteLine("Subtype: [RPC Interface]"); } else if (sub_type == NAMED_PIPE_EVENT_GUID) { Console.WriteLine("Subtype: [Named Pipe]"); } else { Console.WriteLine("Subtype: [Unknown Network Endpoint] {0:B}", sub_type); } } break; case ServiceTriggerType.DomainJoin: { Guid sub_type = trigger.GetSubType(); if (sub_type == DOMAIN_JOIN_GUID) { Console.WriteLine("Subtype: [Domain Join]"); } else if (sub_type == DOMAIN_LEAVE_GUID) { Console.WriteLine("Subtype: [Domain Leave]"); } else { Console.WriteLine("Subtype: [Unknown Domain Join] {0:B}", sub_type); } } break; case ServiceTriggerType.IPAddressAvailability: { Guid sub_type = trigger.GetSubType(); if (sub_type == NETWORK_MANAGER_FIRST_IP_ADDRESS_ARRIVAL_GUID) { Console.WriteLine("Subtype: [First IP Address Available]"); } else if (sub_type == NETWORK_MANAGER_LAST_IP_ADDRESS_REMOVAL_GUID) { Console.WriteLine("Subtype: [Last IP Address Available]"); } else { Console.WriteLine("Subtype: [Unknown IP Address Availability] {0:B}", sub_type); } } break; } if (trigger.pDataItems != IntPtr.Zero && trigger.cDataItems > 0) { DumpCustomData(trigger); } } } }
/// <summary> /// Retrieves a copy of the security descriptor associated with a service object. You can also use the /// GetNamedSecurityInfo function to retrieve a security descriptor. /// </summary> /// <param name="hService"> /// A handle to the service control manager or the service. Handles to the service control manager /// are returned by the <see cref="OpenSCManager" /> function, and handles to a service are returned by either the /// <see cref="OpenService" /> or <see cref="CreateService(SafeServiceHandle,string,string,ACCESS_MASK,ServiceType,ServiceStartType,ServiceErrorControl,string,string,int, string,string,string)" /> function. The handle must have the READ_CONTROL access /// right. /// </param> /// <param name="dwSecurityInformation"> /// A set of bit flags that indicate the type of security information to retrieve. This /// parameter can be a combination of the <see cref="SECURITY_INFORMATION" /> flags, with the exception that this /// function does not support the <see cref="SECURITY_INFORMATION.LABEL_SECURITY_INFORMATION" /> value. /// </param> /// <returns> /// A copy of the security descriptor of the specified service object. The calling process must have the /// appropriate access to view the specified aspects of the security descriptor of the object. /// </returns> /// <exception cref="ArgumentNullException"><paramref name="hService" /> is NULL.</exception> /// <exception cref="Win32Exception">If the call to the native method fails fails.</exception> public static RawSecurityDescriptor QueryServiceObjectSecurity(SafeServiceHandle hService, SECURITY_INFORMATION dwSecurityInformation) { if (hService == null) { throw new ArgumentNullException(nameof(hService)); } var securityDescriptor = new byte[0]; int bufSizeNeeded; QueryServiceObjectSecurity(hService, dwSecurityInformation, securityDescriptor, 0, out bufSizeNeeded); var lastError = GetLastError(); if (lastError != Win32ErrorCode.ERROR_INSUFFICIENT_BUFFER) { throw new Win32Exception(lastError); } securityDescriptor = new byte[bufSizeNeeded]; var success = QueryServiceObjectSecurity(hService, dwSecurityInformation, securityDescriptor, bufSizeNeeded, out bufSizeNeeded); if (!success) { throw new Win32Exception(); } return new RawSecurityDescriptor(securityDescriptor, 0); }
public static extern bool ChangeServiceConfig2( SafeServiceHandle hService, int dwInfoLevel, ref SERVICE_PRESHUTDOWN_INFO lpInfo);
internal static extern bool StartService(SafeServiceHandle serviceHandle, int argNum, IntPtr argPtrs);
public ServiceConfig(SafeServiceHandle handle) { _handle = handle; }
public static extern bool ChangeServiceConfig2(SafeServiceHandle hService, ServiceInfoLevel dwInfoLevel, IntPtr lpInfo);
public ServiceManager() { _handle = NativeMethods.OpenSCManager(null, null, NativeMethods.SCM_ACCESS.SC_MANAGER_ENUMERATE_SERVICE); if (_handle.IsInvalid) { Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error()); } }
public static extern bool ChangeServiceFailureActions( SafeServiceHandle hService, int dwInfoLevel, [MarshalAs(UnmanagedType.Struct)] ref SERVICE_FAILURE_ACTIONS lpInfo);
private ServiceControlManager(SafeServiceHandle handle, string machine_name, ServiceControlManagerAccessRights granted_access) { _handle = handle; _machine_name = machine_name; _granted_access = granted_access; }
public static extern bool SetServiceObjectSecurity( SafeServiceHandle hService, SECURITY_INFORMATION dwSecurityInformation, byte[] lpSecurityDescriptor);
internal static extern SafeServiceHandle OpenService(SafeServiceHandle hSCManager, string lpServiceName, int dwDesiredAccess);
public static unsafe extern bool ChangeServiceConfig2(SafeServiceHandle hService, ServiceInfoLevel dwInfoLevel, void* lpInfo);
public static extern IntPtr CreateService(SafeServiceHandle databaseHandle, string serviceName, string displayName, int access, int serviceType, int startType, int errorControl, string binaryPath, string loadOrderGroup, IntPtr pTagId, string dependencies, string servicesStartName, string password);
public static extern SafeServiceHandle CreateService(SafeServiceHandle hSCManager, string lpServiceName, string lpDisplayName, ServiceAccess dwDesiredAccess, ServiceType dwServiceType, ServiceStartType dwStartType, ServiceErrorControl dwErrorControl, string lpBinaryPathName, string lpLoadOrderGroup, int lpdwTagId, string lpDependencies, string lpServiceStartName, string lpPassword);
public static extern SafeServiceHandle OpenService(SafeServiceHandle hSCManager, string lpServiceName, ServiceAccess dwDesiredAccess);
public static extern bool QueryServiceObjectSecurity( SafeServiceHandle hService, SECURITY_INFORMATION dwSecurityInformation, byte[] lpSecurityDescriptor, int cbBufSize, out int pcbBytesNeeded);
public static extern bool ControlService(SafeServiceHandle hService, ServiceControl dwControl, ref SERVICE_STATUS lpServiceStatus);
public static extern bool EnumServicesStatus( SafeServiceHandle hSCManager, ServiceType dwServiceType, ServiceStateQuery dwServiceState, IntPtr lpServices, int cbBufSize, ref int pcbBytesNeeded, ref int lpServicesReturned, ref int lpResumeHandle);
public static extern bool DeleteService(SafeServiceHandle hService);
public static partial bool DeleteService(SafeServiceHandle serviceHandle);
public static extern bool StartService(SafeServiceHandle hService, int dwNumServiceArgs, string lpServiceArgVectors);
/// <summary> /// Creates a service object and adds it to service control manager database o the local computer. /// </summary> /// <param name="lpBinaryPathName"> /// The fully qualified path to the service binary file. If the path contains a space, it must be quoted so that it is correctly interpreted. /// For example, "d:\\my share\\myservice.exe" should be specified as "\"d:\\my share\\myservice.exe\"". /// The path can also include arguments for an auto-start service. /// For example, "d:\\myshare\\myservice.exe arg1 arg2". /// These arguments are passed to the service entry point (typically the main function). /// </param> /// <param name="lpServiceName"> /// The name of the service to install. The maximum string length is 256 characters. /// The service control manager database preserves the case of the characters, but service name comparisons are always case insensitive. /// Forward-slash (/) and backslash (\) are not valid service name characters. /// </param> /// <param name="lpDisplayName"> /// The display name to be used by user interface programs to identify the service. /// This string has a maximum length of 256 characters. The name is case-preserved in the service control manager. /// Display name comparisons are always case-insensitive. /// </param> /// <param name="lpDescription"> /// The description of the service. If this member is NULL, the description remains unchanged. /// If this value is an empty string (""), the current description is deleted. /// The service description must not exceed the size of a registry value of type REG_SZ. /// </param> /// <param name="lpServiceStartName"> /// The name of the account under which the service should run. /// Use an account name in the form DomainName\UserName. The service process will be logged on as this user. /// If the account belongs to the built-in domain, you can specify .\UserName. /// </param> /// <param name="lpPassword"> /// The password to the account name specified by the lpServiceStartName parameter. /// Specify an empty string if the account has no password or if the service runs in the LocalService, NetworkService, or LocalSystem account. /// If the account name specified by the <paramref name="lpServiceStartName"/> parameter is the name of a managed service account or virtual account name, the lpPassword parameter must be NULL. /// </param> /// <exception cref="Win32Exception">If the method fails, returning the calling thread's last-error code value.</exception> /// <exception cref="ArgumentException"><paramref name="lpServiceName" /> or <paramref name="lpBinaryPathName"/> are NULL or empty string.</exception> public static unsafe void CreateService(string lpBinaryPathName, string lpServiceName, string lpDisplayName, string lpDescription, string lpServiceStartName, string lpPassword) { if (string.IsNullOrEmpty(lpBinaryPathName)) { throw new ArgumentException("Binary path name must not be null nor empty", nameof(lpBinaryPathName)); } if (string.IsNullOrEmpty(lpServiceName)) { throw new ArgumentException("Service name must not be null nor empty", nameof(lpServiceName)); } using (SafeServiceHandle scmHandle = OpenSCManager(null, null, ServiceManagerAccess.SC_MANAGER_CREATE_SERVICE)) { if (scmHandle.IsInvalid) { throw new Win32Exception(); } SafeServiceHandle svcHandle = CreateService( scmHandle, lpServiceName, lpDisplayName, ServiceAccess.SERVICE_ALL_ACCESS, ServiceType.SERVICE_WIN32_OWN_PROCESS, ServiceStartType.SERVICE_DEMAND_START, ServiceErrorControl.SERVICE_ERROR_NORMAL, lpBinaryPathName, null, 0, null, lpServiceStartName, lpPassword); using (svcHandle) { if (svcHandle.IsInvalid) { throw new Win32Exception(); } var descriptionStruct = new ServiceDescription { lpDescription = lpDescription }; #if NETSTANDARD1_3_ORLATER fixed(void *lpInfo = new byte[Marshal.SizeOf <ServiceDescription>()]) #else fixed(void *lpInfo = new byte[Marshal.SizeOf(typeof(ServiceDescription))]) #endif { Marshal.StructureToPtr(descriptionStruct, new IntPtr(lpInfo), false); if (!ChangeServiceConfig2(svcHandle, ServiceInfoLevel.SERVICE_CONFIG_DESCRIPTION, lpInfo)) { throw new Win32Exception(); } #if NETSTANDARD1_3_ORLATER Marshal.DestroyStructure <ServiceDescription>(new IntPtr(lpInfo)); #else Marshal.DestroyStructure(new IntPtr(lpInfo), typeof(ServiceDescription)); #endif } } } }
public static extern bool QueryServiceStatus(SafeServiceHandle hService, ref SERVICE_STATUS dwServiceStatus);
static extern SafeServiceHandle OpenService( SafeServiceHandle hSCManager, string lpServiceName, ServiceAccessRights dwDesiredAccess );
internal static unsafe partial bool ControlService(SafeServiceHandle serviceHandle, int control, SERVICE_STATUS *pStatus);
static extern bool QueryServiceObjectSecurity(SafeServiceHandle hService, SecurityInformation dwSecurityInformation, [Out] byte[] lpSecurityDescriptor, int cbBufSize, out int pcbBytesNeeded);