我创建了一个小型Windows服务来捕获某些事件,包括系统关闭。每次关闭计算机时,不会调用服务事件。但是,当我重新启动计算机时,事件正常进行。
我已经尝试使用:SERVICE_ACCEPT_PRESHUTDOWN
+ SERVICE_CONTROL_PRESHUTDOWN
,但未成功。
我如何捕获计算机关闭事件?
Ps:编译后,我使用以下命令注册了服务:sc.exe创建“ ZSimpleService” binPath =“ C:\ path \ ZSimpleService.exe”
编辑1:我正在使用Windows 10
代码:
SERVICE_STATUS g_ServiceStatus = { 0 };
SERVICE_STATUS_HANDLE g_StatusHandle = NULL;
HANDLE g_ServiceStopEvent = INVALID_HANDLE_VALUE;
VOID WINAPI ServiceMain(DWORD argc, LPTSTR *argv);
DWORD WINAPI ServiceWorkerThread(LPVOID lpParam);
DWORD WINAPI CtrlHandlerEx(DWORD CtrlCode, DWORD eventType, LPVOID eventData, LPVOID context);
#define SERVICE_NAME _T("ZSimpleService")
VOID WINAPI ServiceMain(DWORD argc, LPTSTR *argv) {
g_StatusHandle = RegisterServiceCtrlHandlerEx(SERVICE_NAME, CtrlHandlerEx,
NULL);
if (g_StatusHandle == NULL) {
goto EXIT;
}
// Tell the service controller we are starting
ZeroMemory( & g_ServiceStatus, sizeof(g_ServiceStatus));
g_ServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
g_ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP
| SERVICE_ACCEPT_POWEREVENT | SERVICE_ACCEPT_SESSIONCHANGE
| SERVICE_ACCEPT_SHUTDOWN;
g_ServiceStatus.dwCurrentState = SERVICE_START_PENDING;
g_ServiceStatus.dwWin32ExitCode = 0;
g_ServiceStatus.dwServiceSpecificExitCode = 0;
g_ServiceStatus.dwCheckPoint = 0;
if (SetServiceStatus(g_StatusHandle, &g_ServiceStatus) == FALSE) {
//...
}
g_ServiceStopEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (g_ServiceStopEvent == NULL) {
//...
goto EXIT;
}
g_ServiceStatus.dwCurrentState = SERVICE_RUNNING;
g_ServiceStatus.dwWin32ExitCode = 0;
g_ServiceStatus.dwCheckPoint = 0;
if (SetServiceStatus(g_StatusHandle, &g_ServiceStatus) == FALSE) {
//...
}
HANDLE hThread = CreateThread(NULL, 0, ServiceWorkerThread, NULL, 0, NULL);
WaitForSingleObject(hThread, INFINITE);
CloseHandle(g_ServiceStopEvent);
g_ServiceStatus.dwCurrentState = SERVICE_STOPPED;
g_ServiceStatus.dwWin32ExitCode = 0;
g_ServiceStatus.dwCheckPoint = 3;
if (SetServiceStatus(g_StatusHandle, &g_ServiceStatus) == FALSE) {
}
EXIT: return;
}
void suspending() {
FILE *file = fopen("C:\\test\\suspending.txt", "w+");
if (file)
fprintf(file, "...");
}
void logoff() {
FILE *file = fopen("C:\\test\\logoff.txt", "w+");
if (file)
fprintf(file, "...");
}
void lock_session() {
FILE *file = fopen("C:\\test\\lock_session.txt", "w+");
if (file)
fprintf(file, "...");
}
void poweroff() {
FILE *file = fopen("C:\\test\\poweroff.txt", "w+");
if (file)
fprintf(file, "...");
}
DWORD WINAPI CtrlHandlerEx(DWORD CtrlCode, DWORD eventType, LPVOID eventData,
LPVOID context) {
switch (CtrlCode) {
case SERVICE_CONTROL_STOP: {
g_ServiceStatus.dwCurrentState = SERVICE_STOP_PENDING;
g_ServiceStatus.dwWin32ExitCode = 0;
g_ServiceStatus.dwCheckPoint = 0;
g_ServiceStatus.dwWaitHint = 0;
if (SetServiceStatus(g_StatusHandle, &g_ServiceStatus) == FALSE) {
//...
}
SetEvent(g_ServiceStopEvent);
return NO_ERROR;
}
case SERVICE_CONTROL_POWEREVENT: {
if (eventType == PBT_APMQUERYSUSPEND) {
//Computer is suspending
suspending();
}
return NO_ERROR;
}
case SERVICE_CONTROL_SESSIONCHANGE: {
switch (eventType) {
case WTS_SESSION_LOGOFF:
//User is logging off
logoff();
break;
case WTS_SESSION_LOCK:
//User locks the session
lock_session();
break;
}
return NO_ERROR;
}
case SERVICE_CONTROL_SHUTDOWN: {
//Computer is shutting down
poweroff();
return NO_ERROR;
}
default:
return ERROR_CALL_NOT_IMPLEMENTED;
}
}
DWORD WINAPI ServiceWorkerThread(LPVOID lpParam) {
while (WaitForSingleObject(g_ServiceStopEvent, 0) != WAIT_OBJECT_0) {
//many cool code....
Sleep(3000);
}
return 0;
}
DWORD RunService() {
SERVICE_TABLE_ENTRY serviceTable[] = { { SERVICE_NAME, ServiceMain },
{ 0, 0 } };
if (StartServiceCtrlDispatcher(serviceTable)) {
return 0;
} else {
DWORD erro = GetLastError();
//handler erro...
return 1;
}
}
int _tmain(int argc, TCHAR *argv[]) {
RunService();
return 0;
}