public static void Install(string path, string username, string password) { try { logger.Info($"Opening service control manager"); var serviceManager = AdvApi32.OpenSCManager(null, null, AdvApi32.ScManagerAccessTypes.SC_MANAGER_ALL_ACCESS); string[] dependencies = new[] { "http" }; logger.Info($"Opened service control manager"); AdvApi32.SafeSC_HANDLE serviceHandle; if (!path.StartsWith("\"")) { path = "\"" + path; } if (!path.EndsWith("\"")) { path = path + "\""; } try { logger.Info($"Checking for existing {Constants.ServiceName} service"); serviceHandle = AdvApi32.OpenService(serviceManager, Constants.ServiceName, AdvApi32.ServiceAccessTypes.SERVICE_ALL_ACCESS); if (serviceHandle.IsNull) { throw new Win32Exception(Marshal.GetLastWin32Error()); } logger.Info($"Found existing {Constants.ServiceName} service"); } catch (Win32Exception ex) { if (ex.NativeErrorCode == 1060) { logger.Info($"Existing {Constants.ServiceName} service not found"); logger.Info($"Attempting to create server {Constants.ServiceName} for user {username} at {path}"); serviceHandle = AdvApi32.CreateService(serviceManager, Constants.ServiceName, Constants.ServiceDisplayName, (uint)AdvApi32.ServiceAccessTypes.SERVICE_ALL_ACCESS, AdvApi32.ServiceTypes.SERVICE_WIN32_OWN_PROCESS, AdvApi32.ServiceStartType.SERVICE_DEMAND_START, AdvApi32.ServiceErrorControlType.SERVICE_ERROR_NORMAL, path, null, IntPtr.Zero, dependencies, username, password); if (serviceHandle.IsNull) { throw new Win32Exception(Marshal.GetLastWin32Error()); } logger.Info($"Created {Constants.ServiceName} service"); } else { throw; } } var description = new AdvApi32.SERVICE_DESCRIPTION() { lpDescription = Constants.ServiceDescription }; logger.Info($"Updating service description"); if (!AdvApi32.ChangeServiceConfig2(serviceHandle, AdvApi32.ServiceConfigOption.SERVICE_CONFIG_DESCRIPTION, description)) { throw new Win32Exception(Marshal.GetLastWin32Error()); } var sidConfig = new AdvApi32.SERVICE_SID_INFO() { dwServiceSidType = 0x1 }; logger.Info($"Updating service SID configuration"); if (!AdvApi32.ChangeServiceConfig2(serviceHandle, AdvApi32.ServiceConfigOption.SERVICE_CONFIG_SERVICE_SID_INFO, sidConfig)) { throw new Win32Exception(Marshal.GetLastWin32Error()); } logger.Info($"Updated existing {Constants.ServiceName} service parameters"); TryGrantLogonAsAService(username); } catch (Exception ex) { logger.Error(ex, "Unable to install service"); throw; } }