"SERVICE_CONTROL_SESSIONCHANGE" Windows 10 中的 C++ 服务应用程序从未收到通知
"SERVICE_CONTROL_SESSIONCHANGE" notification is never received in C++ service application in Windows 10
我一直在尝试开发一个服务应用程序来连接 windows 的 login/logout 事件。我的开发环境是 Windows 10. 由于它是一个服务应用程序,根据 Whosebug 和其他开发平台中一些现有帖子的建议,我注册了该服务以在不同事件中得到通知。下面是我试过的片段。
SERVICE_STATUS_HANDLE gSvcStatusHandle;
VOID WINAPI SvcCtrlHandlerEx(DWORD dwControl, DWORD dwEventType, LPVOID lpEventData, LPVOID lpContext)
{
switch (dwControl)
{
case SERVICE_CONTROL_STOP:
writeEventLog(utils.GetDefaultTitle(), L"Service About to end");
ReportSvcStatus(SERVICE_STOP_PENDING, NO_ERROR, 0);
// Signal the service to stop.
SetEvent(ghSvcStopEvent);
ReportSvcStatus(gSvcStatus.dwCurrentState, NO_ERROR, 0);
applicationLogger.LogWarning("Service stopped.");
break;
return;
case SERVICE_CONTROL_INTERROGATE:
writeEventLog(GetDefaultTitle(), L"Service=interrogate");
applicationLogger.LogWarning("Service Interrogate.");
break;
case SERVICE_CONTROL_PAUSE:
writeEventLog(GetDefaultTitle(), L"Service=paused");
applicationLogger.LogWarning("Service pasued.");
break;
case SERVICE_CONTROL_CONTINUE:
writeEventLog(GetDefaultTitle(), L"Service=continued");
applicationLogger.LogWarning("Service continued.");
break;
case SERVICE_CONTROL_SESSIONCHANGE:
writeEventLog(GetDefaultTitle(), L"Service=Session=Changed");
applicationLogger.LogWarning("Session changed");
if (WTS_SESSION_LOGOFF == (dwEvtype & WTS_SESSION_LOGOFF))
{
WTSSESSION_NOTIFICATION* pSessionNotification = static_cast<WTSSESSION_NOTIFICATION*>(pEvtData);
}
else if (WTS_SESSION_LOGON == (dwEvtype & WTS_SESSION_LOGOFF))
{
WTSSESSION_NOTIFICATION* pSessionNotification = static_cast<WTSSESSION_NOTIFICATION*>(pEvtData);
break;
default:
writeEventLog(GetDefaultTitle(), L"Service=Dfault");
applicationLogger.LogWarning("Service default.");
break;
}
}
VOID WINAPI SvcMain(DWORD dwArgc, LPTSTR* lpszArgv)
{
gSvcStatusHandle = RegisterServiceCtrlHandlerEx(SVCNAME, reinterpret_cast<LPHANDLER_FUNCTION_EX>(SvcCtrlHandlerEx), NULL);
}
出于调试目的,每当服务收到任何事件通知时,我都会尝试记录事件名称。但是,我收到的唯一通知是我尝试停止服务,“case SERVICE_CONTROL_STOP”将被执行。我有兴趣接收“SERVICE_CONTROL_SESSIONCHANGE”事件,以便我可以检索用户的登录信息。
所以,你能指出我做错的地方吗? “SERVICE_CONTROL_SESSIONCHANGE”中的方法也是从 windows 获取 login/logout 事件的正确方法吗?
我尝试在 windows10 系统中登录和注销,但事件查看器中没有写入日志。
要在 HandlerEx
回调中接收 SERVICE_CONTROL_SESSIONCHANGE
通知,您需要调用 SetServiceStatus()
并在 SERVICE_STATUS::dwControlsAccepted
字段中启用 SERVICE_ACCEPT_SESSIONCHANGE
标志。
Control code
Meaning
SERVICE_ACCEPT_SESSIONCHANGE 0x00000080
The service is notified when the computer's session status has changed. This enables the system to send SERVICE_CONTROL_SESSIONCHANGE notifications to the service.
至于您的处理程序本身,您不应将 operator&
与 dwEventType
参数一起使用,因为它不是位掩码。使用 operator==
代替(或 switch
):
case SERVICE_CONTROL_SESSIONCHANGE:
writeEventLog(GetDefaultTitle(), L"Service=Session=Changed");
applicationLogger.LogWarning("Session changed");
if (dwEventType == WTS_SESSION_LOGOFF)
{
WTSSESSION_NOTIFICATION* pSessionNotification = static_cast<WTSSESSION_NOTIFICATION*>(lpEventData);
// ...
}
else if (dwEventType == WTS_SESSION_LOGON)
{
WTSSESSION_NOTIFICATION* pSessionNotification = static_cast<WTSSESSION_NOTIFICATION*>(lpEventData);
// ...
}
break;
我一直在尝试开发一个服务应用程序来连接 windows 的 login/logout 事件。我的开发环境是 Windows 10. 由于它是一个服务应用程序,根据 Whosebug 和其他开发平台中一些现有帖子的建议,我注册了该服务以在不同事件中得到通知。下面是我试过的片段。
SERVICE_STATUS_HANDLE gSvcStatusHandle;
VOID WINAPI SvcCtrlHandlerEx(DWORD dwControl, DWORD dwEventType, LPVOID lpEventData, LPVOID lpContext)
{
switch (dwControl)
{
case SERVICE_CONTROL_STOP:
writeEventLog(utils.GetDefaultTitle(), L"Service About to end");
ReportSvcStatus(SERVICE_STOP_PENDING, NO_ERROR, 0);
// Signal the service to stop.
SetEvent(ghSvcStopEvent);
ReportSvcStatus(gSvcStatus.dwCurrentState, NO_ERROR, 0);
applicationLogger.LogWarning("Service stopped.");
break;
return;
case SERVICE_CONTROL_INTERROGATE:
writeEventLog(GetDefaultTitle(), L"Service=interrogate");
applicationLogger.LogWarning("Service Interrogate.");
break;
case SERVICE_CONTROL_PAUSE:
writeEventLog(GetDefaultTitle(), L"Service=paused");
applicationLogger.LogWarning("Service pasued.");
break;
case SERVICE_CONTROL_CONTINUE:
writeEventLog(GetDefaultTitle(), L"Service=continued");
applicationLogger.LogWarning("Service continued.");
break;
case SERVICE_CONTROL_SESSIONCHANGE:
writeEventLog(GetDefaultTitle(), L"Service=Session=Changed");
applicationLogger.LogWarning("Session changed");
if (WTS_SESSION_LOGOFF == (dwEvtype & WTS_SESSION_LOGOFF))
{
WTSSESSION_NOTIFICATION* pSessionNotification = static_cast<WTSSESSION_NOTIFICATION*>(pEvtData);
}
else if (WTS_SESSION_LOGON == (dwEvtype & WTS_SESSION_LOGOFF))
{
WTSSESSION_NOTIFICATION* pSessionNotification = static_cast<WTSSESSION_NOTIFICATION*>(pEvtData);
break;
default:
writeEventLog(GetDefaultTitle(), L"Service=Dfault");
applicationLogger.LogWarning("Service default.");
break;
}
}
VOID WINAPI SvcMain(DWORD dwArgc, LPTSTR* lpszArgv)
{
gSvcStatusHandle = RegisterServiceCtrlHandlerEx(SVCNAME, reinterpret_cast<LPHANDLER_FUNCTION_EX>(SvcCtrlHandlerEx), NULL);
}
出于调试目的,每当服务收到任何事件通知时,我都会尝试记录事件名称。但是,我收到的唯一通知是我尝试停止服务,“case SERVICE_CONTROL_STOP”将被执行。我有兴趣接收“SERVICE_CONTROL_SESSIONCHANGE”事件,以便我可以检索用户的登录信息。
所以,你能指出我做错的地方吗? “SERVICE_CONTROL_SESSIONCHANGE”中的方法也是从 windows 获取 login/logout 事件的正确方法吗? 我尝试在 windows10 系统中登录和注销,但事件查看器中没有写入日志。
要在 HandlerEx
回调中接收 SERVICE_CONTROL_SESSIONCHANGE
通知,您需要调用 SetServiceStatus()
并在 SERVICE_STATUS::dwControlsAccepted
字段中启用 SERVICE_ACCEPT_SESSIONCHANGE
标志。
Control code Meaning SERVICE_ACCEPT_SESSIONCHANGE 0x00000080 The service is notified when the computer's session status has changed. This enables the system to send SERVICE_CONTROL_SESSIONCHANGE notifications to the service.
至于您的处理程序本身,您不应将 operator&
与 dwEventType
参数一起使用,因为它不是位掩码。使用 operator==
代替(或 switch
):
case SERVICE_CONTROL_SESSIONCHANGE:
writeEventLog(GetDefaultTitle(), L"Service=Session=Changed");
applicationLogger.LogWarning("Session changed");
if (dwEventType == WTS_SESSION_LOGOFF)
{
WTSSESSION_NOTIFICATION* pSessionNotification = static_cast<WTSSESSION_NOTIFICATION*>(lpEventData);
// ...
}
else if (dwEventType == WTS_SESSION_LOGON)
{
WTSSESSION_NOTIFICATION* pSessionNotification = static_cast<WTSSESSION_NOTIFICATION*>(lpEventData);
// ...
}
break;