从无应用程序的应用程序启动Windows服务(c ++)

我写了一个Windows服务(它运行良好)。 现在我有一个单独的应用程序,我想要启动这项服务,但似乎这是不可能的,没有pipe理员权限。

如何正确的解决scheme看起来像用户可以开始/停止服务(例如从托盘或应用程序)

恕我直言,它的不好,应用程序必须始终以pipe理员权限开始。

您只需要更改服务对象上的权限,最好是在安装它的同时。

wchar_t sddl[] = L"D:" L"(A;;CCLCSWRPWPDTLOCRRC;;;SY)" // default permissions for local system L"(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;BA)" // default permissions for administrators L"(A;;CCLCSWLOCRRC;;;AU)" // default permissions for authenticated users L"(A;;CCLCSWRPWPDTLOCRRC;;;PU)" // default permissions for power users L"(A;;RP;;;IU)" // added permission: start service for interactive users ; PSECURITY_DESCRIPTOR sd; if (!ConvertStringSecurityDescriptorToSecurityDescriptor(sddl, SDDL_REVISION_1, &sd, NULL)) { fail(); } if (!SetServiceObjectSecurity(service, DACL_SECURITY_INFORMATION, sd)) { fail(); } 

我假设你已经打开了服务句柄。 您需要WRITE_DAC权限。

如果您还希望非管理员用户能够停止服务,请添加WP权限,即,

 L"(A;;RPWP;;;IU)" // added permissions: start service, stop service for interactive users 

Wayne Martin的博客文章“ 服务控制管理器安全性”(针对非管理员的安全性)中提供了有关服务权限的SDDL代码。

以编程方式启动服务是使用StartService函数完成的。 在开始服务的标题下还有一个全面的使用示例,该示例还说明了如何:

  • 检测到服务是由于某种原因关闭的
  • 等到服务处于稳定状态(开始/停止)
  • 以编程方式启动服务

至于管理员权限,这是必要的,因为如果任何应用程序关闭服务(或者更重要的是安装和启动新的服务 ),将会有非常真实和非常严重的安全问题。

@哈里·约翰斯顿,除了回应。

这里是c ++ builder的例子。

 void __fastcall TService1::ServiceAfterInstall(TService *Sender) { wchar_t lpBuffer[256]; long errorCode; SC_HANDLE hSCManager,hService; hSCManager = OpenSCManager(0, 0, SC_MANAGER_CONNECT); if (hSCManager == NULL) { errorCode = GetLastError(); FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM, NULL, errorCode,MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), lpBuffer, 256, NULL); LogMessage("OpenSCManager Error "+AnsiString(lpBuffer), EVENTLOG_ERROR_TYPE); return; } hService = OpenService(hSCManager, this->Name.c_str(), READ_CONTROL | WRITE_DAC); if (hService == NULL) { errorCode = GetLastError(); FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM, NULL, errorCode,MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), lpBuffer, 256, NULL); LogMessage("OpenService Error "+AnsiString(lpBuffer), EVENTLOG_ERROR_TYPE); CloseServiceHandle(hSCManager); } wchar_t sddl[] = L"D:" L"(A;;CCLCSWRPWPDTLOCRRC;;;SY)" // default permissions for local system L"(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;BA)" // default permissions for administrators L"(A;;CCLCSWLOCRRC;;;AU)" // default permissions for authenticated users L"(A;;CCLCSWRPWPDTLOCRRC;;;PU)" // default permissions for power users L"(A;;RP;;;IU)" // added permission: start service for interactive users ; PSECURITY_DESCRIPTOR sd; if (!ConvertStringSecurityDescriptorToSecurityDescriptor(AnsiString(sddl).c_str(), SDDL_REVISION_1, &sd, NULL)) { errorCode = GetLastError(); FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM, NULL, errorCode,MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), lpBuffer, 256, NULL); LogMessage("ConvertStringSecurityDescriptorToSecurityDescriptor Error "+AnsiString(lpBuffer), EVENTLOG_ERROR_TYPE); } if (!SetServiceObjectSecurity(hService, DACL_SECURITY_INFORMATION, sd)) { errorCode = GetLastError(); FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM, NULL, errorCode,MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), lpBuffer, 256, NULL); LogMessage("SetServiceObjectSecurity Error "+AnsiString(lpBuffer), EVENTLOG_ERROR_TYPE); } CloseServiceHandle(hService); CloseServiceHandle(hSCManager); } 

@Harry Johnston对我来说工作的很好,万一有人想用C#做这个:

 [DllImport("advapi32.dll", SetLastError = true)] static extern bool SetServiceObjectSecurity(SafeHandle serviceHandle, UInt32 secInfos, IntPtr lpSecDesrBuf); [DllImport("advapi32.dll", EntryPoint = "ConvertStringSecurityDescriptorToSecurityDescriptorW", SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] public static extern Boolean ConvertStringSecurityDescriptorToSecurityDescriptor( [MarshalAs(UnmanagedType.LPWStr)] String strSecurityDescriptor, UInt32 sDRevision, ref IntPtr securityDescriptor, ref UInt32 securityDescriptorSize); public static void SetServicePermissions(string service) { System.ServiceProcess.ServiceController sc = new System.ServiceProcess.ServiceController(service); bool ok; IntPtr pSD = IntPtr.Zero; uint securityDescriptorSize = 0; string secDesc = "D:(A;;CCLCSWRPWPDTLOCRRC;;;SY)(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;BA)(A;;CCLCSWLOCRRC;;;AU)(A;;CCLCSWRPWPDTLOCRRC;;;PU)(A;;RPWP;;;IU)"; ok = ConvertStringSecurityDescriptorToSecurityDescriptor(secDesc, 1, ref pSD, ref securityDescriptorSize); if (!ok) { throw new ApplicationException("error calling ConvertStringSecurityDescriptorToSecurityDescriptor(): error code=" + Marshal.GetLastWin32Error()); } ok = SetServiceObjectSecurity(sc.ServiceHandle, 4 , pSD); if (!ok) { throw new ApplicationException("error calling SetServiceObjectSecurity(); error code=" + Marshal.GetLastWin32Error()); } }