在服务中感知用户登录
来源:互联网 发布: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
- 在服务中感知用户登录
- 在服务中模拟当前登录用户读取HKEY_CURRENT_USER
- linux在终端中登录不同用户?
- 服务中创建当前登录用户名下的进程
- 服务中打开当前登录用户注册表项方法
- 在用户控件中用户登录后台脚本判断写法
- 限制sftp服务用户登录
- 在SQL Server中 新建登录用户 并指定该用户登录的数据库及权限
- 如何在 Journal Template 中得到当前登录用户
- 在ssh中限制用户从固定ip登录
- 在注册表中修改IE的用户自动登录模式
- 虚拟机中Ubuntu在命令行下用户无法登录
- 在开发过程中如何设置运行登录用户
- 在filter中检测用户是都登录并且跳转
- 如何在其他servlet中获取用户登录id
- 在tp中实现单个用户禁止重复登录
- 在Ubuntu中为root用户启用界面登录
- 用WSE在Web服务中验证用户身份
- maven+Spring+Struts2+Hibernate 整合 xml配置
- Unity客户端框架笔记(状态模式和策略模式在游戏中的应用)
- 学生选课抽签管理系统设计
- Android 自定义照相机
- JAVA JDBC 源码总结
- 在服务中感知用户登录
- 构造最大数
- 268. Missing Number
- Android 闹钟和通知
- Android实现拍照功能,使用SurfaceView+camera
- Python中列表的操作
- 增加和删除数据时,为什么LinkedList通常比ArrayList快?
- 72. Edit Distance
- 直接插入排序讲解