我已按照此说明创建了我的第一个Windows服务。我可以从“管理”->“我的电脑”中的“服务”面板启动或停止我的服务,而不会出现问题。该服务帐户是“ LocalSystem”,因此,我认为我可以使用特权。现在,我想通过另一个应用程序与我的服务进行通信,但是首先,我想停止或启动我的服务。
在此示例之后,我编写以下代码:
SC_HANDLE schSCManager;
SC_HANDLE schService;
LPCWSTR szSvcName = _T("MyNewService");
// Get a handle to the SCM database.
schSCManager = OpenSCManager(
NULL, // local computer
NULL, // ServicesActive database
SC_MANAGER_ALL_ACCESS); // full access rights
if (NULL == schSCManager)
{
printf("OpenSCManager failed (%d)\n", GetLastError());
return;
}
// Get a handle to the service.
schService = OpenService(
schSCManager, // SCM database
szSvcName, // name of service
SERVICE_CHANGE_CONFIG); // need change config access
if (schService == NULL)
{
printf("OpenService failed (%d)\n", GetLastError());
CloseServiceHandle(schSCManager);
return;
}
//OK until now
// Check the status in case the service is not stopped.
SERVICE_STATUS_PROCESS ssStatus;
DWORD dwBytesNeeded;
if (!QueryServiceStatusEx(
schService, // handle to service
SC_STATUS_PROCESS_INFO, // information level
(LPBYTE) &ssStatus, // address of structure
sizeof(SERVICE_STATUS_PROCESS), // size of structure
&dwBytesNeeded ) ) // size needed if buffer is too small
{
//printf("QueryServiceStatusEx failed (%d)\n", GetLastError());
CString str;
str.Format(_T("QueryServiceStatusEx failed (%d)\n"), GetLastError()); //ERROR 5: ERROR_ACCESS_DENIED
CloseServiceHandle(schService);
CloseServiceHandle(schSCManager);
return;
}
// Check if the service is already running. It would be possible
// to stop the service here, but for simplicity this example just returns.
if(ssStatus.dwCurrentState != SERVICE_STOPPED && ssStatus.dwCurrentState != SERVICE_STOP_PENDING)
{
printf("Cannot start the service because it is already running\n");
CloseServiceHandle(schService);
CloseServiceHandle(schSCManager);
return;
}
无论如何,我都会得到错误号5,即“ ERROR_ACCESS_DENIED:句柄没有SERVICE_QUERY_STATUS访问权限”,但是我不确定问题出在哪里。该服务具有LocalSystem帐户选项,这意味着所有特权,我是计算机的管理员。.怎么了?
我也尝试使用ControlService尝试启动或停止该服务,但在权限方面却遇到了相同的错误
BOOL success = ::ControlService(schService, SERVICE_CONTROL_STOP, &ss);
我正在使用Visual Studio 2013 Update2。谢谢
您似乎对术语“特权”和“访问权限”感到困惑。您是对的,至少对于本地计算机上的操作而言,LocalSystem帐户实际上是特权帐户。但是,即使是特权用户,也必须知道如果特权(事物如何工作)如何利用。
当应用程序要使用对象(例如服务)时,必须向Windows内核声明其意图(通过OpenSCManager
和OpenService
在代码中完成)。该应用程序可以识别对象(例如,通过服务名称),还可以通知内核它计划对该对象进行哪些操作。这些“事物”被称为“访问权限”,而kenrel决定应用程序是否具有足够的特权以获取其所请求的访问权限。在您的代码中,您正在请求SC_MANAGER_ALL_ACCESS
SC管理器的所有访问权限()和更改服务配置的访问权限(SERVICE_CHANGE_CONFIG
)。然后,您尝试查询服务的状态,但在请求访问服务时未向内核声明此意图(OpenService
称呼)。这就是为什么您会收到“访问被拒绝”错误的原因。
这是为服务和SC管理员定义的访问权限的列表:https : //msdn.microsoft.com/zh-cn/library/windows/desktop/ms685981 ( v=vs.85 ) .aspx。该文档还包含有关您需要执行哪些操作的访问权限的信息。
要打开服务,您仅需要SC_MANAGER_CONNECT
对其SC管理器的访问权限。要查询服务状态,SERVICE-QUERY_STATUS
需要访问权限。要停止服务,请请求SERVICE_STOP
权限。
因此,简短的版本是:SERVICE_STOP | SERVICE_QUERY_STATUS
在调用时指定所需的访问掩码OpenService
,并且可以SC_MANAGER_CONNECT
在调用中指定访问掩码OpenSCManager
。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句