【问题标题】:"SERVICE_CONTROL_SESSIONCHANGE" notification is never received in C++ service application in Windows 10在 Windows 10 的 C++ 服务应用程序中从未收到“SERVICE_CONTROL_SESSIONCHANGE”通知
【发布时间】:2021-10-18 03:43:23
【问题描述】:

我一直在尝试开发一个服务应用程序来挂钩 Windows 的登录/注销事件。我的开发环境是 Windows 10。由于它是一个服务应用程序,根据 Stackoverflow 和其他开发平台中一些现有帖子的建议,我注册了该服务以在不同的事件中获得通知。下面是我试过的sn-p。

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 获取登录/注销事件的正确方法吗? 我尝试在windows10系统中登录和注销,但事件查看器中没有写入日志。

【问题讨论】:

    标签: c++ winapi visual-c++ windows-services


    【解决方案1】:

    要在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&amp;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;
    

    【讨论】:

    • 是的,我的代码的问题是我只订阅了 SERVICE_STOP 事件而不是 SERVICE_ACCEPT_SESSIONCHANGE。所以,我链接了选项,现在我可以检索事件。
    猜你喜欢
    • 2015-12-06
    • 2016-04-20
    • 1970-01-01
    • 2017-01-28
    • 1970-01-01
    • 2021-05-01
    • 1970-01-01
    • 2015-10-28
    • 2015-04-20
    相关资源
    最近更新 更多