在服务中感知用户登录

来源:互联网 发布:java实现局域网聊天 编辑:程序博客网 时间:2024/06/06 02:56

前言

今天和同事聊起感知用户登录的方法. 想起以前做过一个<<在服务中以当前用户身份启动一个程序>>的试验, 里面有当不同用户身份登录(在服务程序中轮询时, 得到不一样的SessionID)时, 会以当前用户身份启动一个示例程序.这就已经感知了不同用户登录.

回家做了一个试验, 验证不同用户登录时, 收集用户登录的信息, 只是做验证(记录当前用户登录的用户名, 其他用户信息没取(可以取到更多的信息)).

Demo下载点

DetectUserLogin.zip
有些函数在vc6里没有,改起来需要花更多时间, 就用vs2013做了一个工程.

关键API

WTSEnumerateSessions
WTSQuerySessionInformation
WTSFreeMemory

程序片段

试验结果

[09588] 2017-02-23 00:09:51 << CProcessStarter::FindActiveSessionId(), bFindActiveSession = [TRUE], dwSessionId = 1[09588] 2017-02-23 00:09:51 m_strSessionInfo = LostSpeed[09588] 2017-02-23 00:09:53 >> CProcessStarter::FindActiveSessionId()[09588] 2017-02-23 00:09:53 << CProcessStarter::FindActiveSessionId(), bFindActiveSession = [TRUE], dwSessionId = 1[09588] 2017-02-23 00:12:43 m_strSessionInfo = stdUser1[09588] 2017-02-23 00:12:46 >> CProcessStarter::FindActiveSessionId()[09588] 2017-02-23 00:12:46 << CProcessStarter::FindActiveSessionId(), bFindActiveSession = [TRUE], dwSessionId = 2[09588] 2017-02-23 00:13:48 m_strSessionInfo = stduser2[09588] 2017-02-23 00:13:51 >> CProcessStarter::FindActiveSessionId()[09588] 2017-02-23 00:13:51 << CProcessStarter::FindActiveSessionId(), bFindActiveSession = [TRUE], dwSessionId = 3[09588] 2017-02-23 00:14:30 m_strSessionInfo = LostSpeed

服务程序

// @file LsServcie.cpp// @brief 在服务中感知用户登录#include "stdafx.h"#include <windows.h>#include "ThreadManager.h"#include "UtilityHelper.h"#include "SCM.h"#include "ProcessStarter.h"#define SERVICE_NAME_W L"ls_test_service"#define SERVICE_VER_W L"1, 0, 0, 2"#define PROJECT_MODIFY_TIME L"2017-0222-1959"#define LOG_FILE_NAME_DLG_NOTIFY L"log_dlg_notify.txt"#define LOG_FILE_NAME_LSSERVICEFORTEST L"log_lsServiceForTest.txt"#define FILE_NAME_NOTIFY _T("notepad.exe")// X64下的notepad.exe的原始名称为NOTEPAD.EXE.MUI#define FILE_ORGNAME_NOTIFY _T("NOTEPAD.EXE.MUI")VOID WINAPI ServiceMain(DWORD dwArgc, LPWSTR* lpszArgv);SERVICE_TABLE_ENTRYW lpServiceStartTable[] = {    { SERVICE_NAME_W, ServiceMain },    { NULL, NULL }};SERVICE_STATUS_HANDLE g_hServiceCtrlHandler = NULL;SERVICE_STATUS g_ServiceStatus;std::wstring g_strPathNameMe = L"";std::wstring g_strCmdLine = L"";ns_base::CThreadManager g_ThreadManager;VOID ServiceMainProc();static UINT WINAPI ThreadProcWorker(void* pParam);BOOL ThreadProcStart_Worker();BOOL ThreadProcStop_Worker();VOID ExecuteAsService();VOID WINAPI ServiceHandler(DWORD fdwControl);std::wstring GetLogPathName_lsServiceForTest();int APIENTRY _tWinMain(HINSTANCE hInstance,                       HINSTANCE hPrevInstance,                       LPTSTR    lpCmdLine,                       int       nCmdShow){    std::wstring strLogFilePathName = L"";    ns_base::GetFilePathName_Me(g_strPathNameMe);    g_strCmdLine = (NULL != lpCmdLine) ? lpCmdLine : L"";    strLogFilePathName = GetLogPathName_lsServiceForTest().c_str();    SetLogFilePathName(strLogFilePathName.c_str());    ServiceMainProc();    return 0;}VOID ServiceMainProc(){    WriteLogEx(L">> ServiceMainProc() [%s][%s][%s]", SERVICE_NAME_W, SERVICE_VER_W, PROJECT_MODIFY_TIME);    if (ns_base::StringCompare_equ(g_strCmdLine.c_str(), L"-i")            || ns_base::StringCompare_equ(g_strCmdLine.c_str(), L"-I")) {        ns_base::ServiceInstall(g_strPathNameMe.c_str(), SERVICE_NAME_W);    } else if (ns_base::StringCompare_equ(g_strCmdLine.c_str(), L"-s")               || ns_base::StringCompare_equ(g_strCmdLine.c_str(), L"-S")) {        ns_base::ServiceStart(SERVICE_NAME_W);    } else if (ns_base::StringCompare_equ(g_strCmdLine.c_str(), L"-k")               || ns_base::StringCompare_equ(g_strCmdLine.c_str(), L"-K")) {        ns_base::ServiceStop(SERVICE_NAME_W);    } else if (ns_base::StringCompare_equ(g_strCmdLine.c_str(), L"-u")               || ns_base::StringCompare_equ(g_strCmdLine.c_str(), L"-U")) {        ns_base::ServiceUnInstall(SERVICE_NAME_W);    } else {        ExecuteAsService();    }    //  #ifdef _DEBUG    //  // 要调试线程时, 这里要等着, 要不主线程退出时, 子线程也结束了    //      while(1) {    //          Sleep(10);    //      }    //  #endif    WriteLogEx(L"<< ServiceMainProc() [%s][%s][%s]", SERVICE_NAME_W, SERVICE_VER_W, PROJECT_MODIFY_TIME);}VOID ExecuteAsService(){    WriteLogEx(L">> ExecuteAsService");    if (!ThreadProcStart_Worker()) {        WriteLogEx(L"ThreadProcStart_Worker failed[%d]", GetLastError());    }    if (!StartServiceCtrlDispatcherW(lpServiceStartTable)) {        WriteLogEx(L"StartServiceCtrlDispatcher failed[%d]", GetLastError());    }    WriteLogEx(L"<< ExecuteAsService");}VOID WINAPI ServiceMain(DWORD dwArgc, LPWSTR* lpszArgv){    WriteLogEx(L">> ServiceMain(%d, lpszArgv)", dwArgc);    do {        g_ServiceStatus.dwServiceType = SERVICE_WIN32;        g_ServiceStatus.dwCurrentState = SERVICE_START_PENDING;        g_ServiceStatus.dwControlsAccepted =            SERVICE_ACCEPT_STOP            | SERVICE_ACCEPT_PAUSE_CONTINUE            | SERVICE_ACCEPT_SHUTDOWN            | SERVICE_ACCEPT_PARAMCHANGE            | SERVICE_ACCEPT_NETBINDCHANGE            | SERVICE_ACCEPT_HARDWAREPROFILECHANGE            | SERVICE_ACCEPT_POWEREVENT            | SERVICE_ACCEPT_SESSIONCHANGE            | SERVICE_ACCEPT_PRESHUTDOWN            | SERVICE_ACCEPT_TIMECHANGE            | SERVICE_ACCEPT_TRIGGEREVENT;        g_ServiceStatus.dwWin32ExitCode = 0;        g_ServiceStatus.dwServiceSpecificExitCode = 0;        g_ServiceStatus.dwCheckPoint = 0;        g_ServiceStatus.dwWaitHint = 0;        g_hServiceCtrlHandler = RegisterServiceCtrlHandlerW(SERVICE_NAME_W, ServiceHandler);        if (NULL == g_hServiceCtrlHandler) {            ns_base::NotifyFailed_RegisterServiceCtrlHandler(GetLastError(), SERVICE_NAME_W);            break;        }        // Initialization complete - report running status        g_ServiceStatus.dwCurrentState = SERVICE_RUNNING;        g_ServiceStatus.dwCheckPoint = 0;        g_ServiceStatus.dwWaitHint = 0;        if (!SetServiceStatus(g_hServiceCtrlHandler, &g_ServiceStatus)) {            ns_base::NotifyFailed_SetServiceStatus(GetLastError(), SERVICE_NAME_W);        }    } while (0);    WriteLogEx(L"<< ServiceMain(%d, lpszArgv)", dwArgc);}VOID WINAPI ServiceHandler(DWORD fdwControl){    int iIndex = 0;    WriteLogEx(L">> ServiceHandler(%d)", fdwControl);    switch (fdwControl) {        case SERVICE_CONTROL_STOP:        case SERVICE_CONTROL_SHUTDOWN:            g_ThreadManager.StopThread(TRUE, L"g_ThreadManager");            g_ServiceStatus.dwWin32ExitCode = 0;            g_ServiceStatus.dwCurrentState = SERVICE_STOPPED;            g_ServiceStatus.dwCheckPoint = 0;            g_ServiceStatus.dwWaitHint = 0;            break;        case SERVICE_CONTROL_PAUSE:            g_ServiceStatus.dwCurrentState = SERVICE_PAUSED;            break;        case SERVICE_CONTROL_CONTINUE:            g_ServiceStatus.dwCurrentState = SERVICE_RUNNING;            break;        default:            WriteLogEx(L"Unrecognized opcode %d\n", fdwControl);    };    if (!SetServiceStatus(g_hServiceCtrlHandler, &g_ServiceStatus)) {        ns_base::NotifyFailed_SetServiceStatus(GetLastError(), SERVICE_NAME_W);    }    WriteLogEx(L"<< ServiceHandler(%d)", fdwControl);}static UINT WINAPI ThreadProcWorker(void* pParam){    BOOL bFirstRun = TRUE; // 标记-首次运行    BOOL bLog = TRUE;    DWORD dwSessionIdPrev = -1;    DWORD dwSessionId = -1;    size_t nSleepTotal = 0;    UINT uRc = S_FALSE;    std::wstring strObjPathName = L"";    std::wstring strOrgObjPathName = L"";    std::wstring strCmdLine = L"";    std::wstring strCmdLineAll = L"";    ns_base::TAG_THREAD_MANAGER_PARAM ThreadManagerParam;    ns_base::TAG_THREAD_MANAGER_PARAM* pThreadManagerParam = NULL;    CProcessStarter ProcessStarter;    WriteLogEx(L">> lsServiceForTest ThreadProcWorker");    do {        if (NULL == pParam) {            break;        }        pThreadManagerParam = (ns_base::TAG_THREAD_MANAGER_PARAM*)pParam;        ThreadManagerParam.copy((ns_base::TAG_THREAD_MANAGER_PARAM*)pParam);        SAFE_DELETE(pThreadManagerParam);        if (NULL == ThreadManagerParam.pThreadManager) {            break;        }        while (!ThreadManagerParam.pThreadManager->IsNeedQuitThread()) {            if (bFirstRun) {                bFirstRun = FALSE;            } else {                if (!ns_base::SleepContinueEx(2000, 100, nSleepTotal)) {                    continue;                }            }            /// 保证 只有在SessionId变化的时候, 才打印 FindActiveSessionId 的日志            if (!ProcessStarter.FindActiveSessionId(dwSessionId, bLog)                    || (dwSessionIdPrev == dwSessionId)) {                if (bLog) {                    bLog = FALSE;                }                continue;            }            if (!bLog) {                bLog = TRUE;            }            dwSessionIdPrev = dwSessionId;            // 只是演示, 验证可以在服务中, 经过轮询, 得知SessionID的变化(不同用户登录的SessionID不同)            // 由SessionID可以得到登录的用户名和其他登录信息            // 通过记录日志, 来演示不同用户登录时, 可以在服务中感知到.            WriteLogEx(_T("m_strSessionInfo = %s\r\n"), ProcessStarter.GetSessionInfo());            continue;        }        uRc = S_OK;    } while (0);    WriteLogEx(L"<< FzAppService ThreadProcWorker");    return uRc;}BOOL ThreadProcStart_Worker(){    BOOL bRc = FALSE;    ns_base::TAG_THREAD_MANAGER_PARAM* pThreadManagerParam = NULL;    if (!g_ThreadManager.IsNeedQuitThread()            && !g_ThreadManager.IsThreadRunning()) {        do {            pThreadManagerParam = new ns_base::TAG_THREAD_MANAGER_PARAM;            if (NULL == pThreadManagerParam) {                break;            }            pThreadManagerParam->pThreadManager = &g_ThreadManager;            g_ThreadManager.SetThreadHandle(                (HANDLE)_beginthreadex(                    NULL,                    0,                    &ThreadProcWorker,                    (void*)pThreadManagerParam,                    0,                    NULL));            bRc = TRUE;        } while (0);    }    return bRc;}BOOL ThreadProcStop_Worker(){    g_ThreadManager.StopThread(TRUE, L"g_ThreadManager");    return TRUE;}std::wstring GetLogPathName_lsServiceForTest(){    std::wstring strPathName = L"";    ns_base::GetPathName_Me(strPathName);    strPathName += LOG_FILE_NAME_LSSERVICEFORTEST;    return strPathName;}

取登录信息的工具类

#ifndef _PROCESS_STARTER_H_#define _PROCESS_STARTER_H_#include "stdafx.h"class CProcessStarter{    public:        CProcessStarter();        /// 如果没有找到"已经激活的SessionId", 说明还没有进入桌面        BOOL FindActiveSessionId(OUT DWORD& dwSessionId, BOOL bNeedLog);        BOOL Run(LPCWSTR pcProcessPathName, LPCWSTR pcCmdLine);        const TCHAR* GetSessionInfo() {            return m_strSessionInfo.c_str();        }    private:        HANDLE GetCurrentUserToken();    private:        std::wstring m_strProcessPathName;        std::wstring m_strCmdLine;        std::wstring m_strSessionInfo;};#endif //_PROCESS_STARTER_H_
#include "stdafx.h"#include "ProcessStarter.h"#include <userenv.h>#pragma comment(lib, "Userenv.lib")#include <wtsapi32.h>#pragma comment(lib, "Wtsapi32.lib")CProcessStarter::CProcessStarter()    : m_strProcessPathName(_T("")),      m_strCmdLine(_T("")),      m_strSessionInfo(_T("")){}BOOL CProcessStarter::FindActiveSessionId(OUT DWORD& dwSessionId, BOOL bNeedLog){    BOOL bFindActiveSession = FALSE;    DWORD dwIndex = 0;    PWTS_SESSION_INFO pWtsSessionInfo = NULL;    DWORD dwCntWtsSessionInfo = 0;    LPTSTR pBuffer = NULL;    DWORD dwRc = 0;    if (bNeedLog) {        WriteLogEx(L">> CProcessStarter::FindActiveSessionId()");    }    m_strSessionInfo = _T("");    do {        dwSessionId = (DWORD)(-1);        if ((!WTSEnumerateSessions(WTS_CURRENT_SERVER_HANDLE, 0, 1, &pWtsSessionInfo, &dwCntWtsSessionInfo))                || (NULL == pWtsSessionInfo)) {            if (bNeedLog) {                WriteLogEx(L"break 0 CProcessStarter::FindActiveSessionId()");            }            break;        }        for (dwIndex = 0; dwIndex < dwCntWtsSessionInfo; dwIndex++) {            if (WTSActive == pWtsSessionInfo[dwIndex].State) {                dwSessionId = pWtsSessionInfo[dwIndex].SessionId;                bFindActiveSession = TRUE;                if (WTSQuerySessionInformation(WTS_CURRENT_SERVER_HANDLE,                                               dwSessionId,                                               WTSUserName,                                               &pBuffer, &dwRc)) {                    if (NULL != pBuffer) {                        m_strSessionInfo += (LPTSTR)pBuffer;                        m_strSessionInfo += _T("\r\n");                    }                }                if (NULL != pBuffer) {                    WTSFreeMemory(pBuffer);                }                break;            }        }        WTSFreeMemory(pWtsSessionInfo);        if (!bFindActiveSession) {            if (bNeedLog) {                WriteLogEx(L"break 1 CProcessStarter::FindActiveSessionId()");            }            break;        }    } while (0);    if (bNeedLog) {        WriteLogEx(L"<< CProcessStarter::FindActiveSessionId(), bFindActiveSession = [%s], dwSessionId = %d",                   bFindActiveSession ? L"TRUE" : L"FALSE",                   dwSessionId);    }    return bFindActiveSession;}HANDLE CProcessStarter::GetCurrentUserToken(){    DWORD dwSessionId = 0;    HANDLE hCurrentToken = NULL;    HANDLE hPrimaryToken = NULL;    WriteLogEx(L">> CProcessStarter::GetCurrentUserToken()");    do {        if (!FindActiveSessionId(dwSessionId, TRUE)) {            WriteLogEx(L"break 0 CProcessStarter::GetCurrentUserToken()");            break;        }        if (!WTSQueryUserToken(dwSessionId, &hCurrentToken)                || (NULL == hCurrentToken)) {            WriteLogEx(L"break 2 CProcessStarter::GetCurrentUserToken()");            break;        }        if (!DuplicateTokenEx(hCurrentToken, TOKEN_ASSIGN_PRIMARY | TOKEN_ALL_ACCESS, 0, SecurityImpersonation, TokenPrimary, &hPrimaryToken)) {            WriteLogEx(L"break 3 CProcessStarter::GetCurrentUserToken()");            break;        }    } while (0);    WriteLogEx(L"<< CProcessStarter::GetCurrentUserToken(), hCurrentToken = 0x%p, hPrimaryToken = 0x%p",               hCurrentToken,               hPrimaryToken);    SAFE_CLOSE_HANDLE(hCurrentToken);    return hPrimaryToken;}BOOL CProcessStarter::Run(LPCWSTR pcProcessPathName, LPCWSTR pcCmdLine){    BOOL bRc = FALSE;    BOOL bTmp = FALSE;    HANDLE hPrimaryToken = NULL;    STARTUPINFOA StartupInfo = {0};    PROCESS_INFORMATION processInfo = {0};    std::wstring command = L"";    LPVOID lpEnvironment = NULL;    WriteLogEx(L">> CProcessStarter::Run");    do {        if ((NULL == pcProcessPathName) /*|| (!ns_base::IsFileExist(pcProcessPathName))*/) {            WriteLogEx(L"break 0 CProcessStarter::Run");            break;        }        this->m_strProcessPathName = pcProcessPathName;        this->m_strCmdLine = (NULL != pcCmdLine) ? pcCmdLine : L"";        hPrimaryToken = GetCurrentUserToken();        if (NULL == hPrimaryToken) {            WriteLogEx(L"break 1 CProcessStarter::Run");            break;        }        StartupInfo.cb = sizeof(STARTUPINFO);        command = L"\"";        command += m_strProcessPathName.c_str();        command += L"\"";        if (m_strCmdLine.length() != 0) {            command += L" ";            command += m_strCmdLine.c_str();        }        WriteLogEx(L"command = [%s]", command.c_str());        if (!CreateEnvironmentBlock(&lpEnvironment, hPrimaryToken, TRUE)) {            WriteLogEx(L"!CreateEnvironmentBlock by hPrimaryToken");        }        bTmp = CreateProcessAsUserA(                   hPrimaryToken,                   0,                   (LPSTR)ns_base::W2Aex(command.c_str()).c_str(),                   NULL,                   NULL,                   FALSE,                   NORMAL_PRIORITY_CLASS | CREATE_UNICODE_ENVIRONMENT,                   lpEnvironment, // __in_opt    LPVOID lpEnvironment,                   0,                   &StartupInfo,                   &processInfo);        if (NULL != lpEnvironment) {            DestroyEnvironmentBlock(lpEnvironment);        }        WriteLogEx(L"CreateProcessAsUserA = %s", bTmp ? L"TRUE" : L"FALSE");        if (!bTmp) {            break;        }        bRc = TRUE;    } while (0);    SAFE_CLOSE_HANDLE(hPrimaryToken);    WriteLogEx(L"<< CProcessStarter::Run, bRc = [%s]", bRc ? L"TRUE" : L"FALSE");    return bRc;}
0 0