C++:检查计算机是不是被锁定
Posted
技术标签:
【中文标题】C++:检查计算机是不是被锁定【英文标题】:C++: check if computer is lockedC++:检查计算机是否被锁定 【发布时间】:2015-06-02 07:35:01 【问题描述】:我正在尝试确定计算机是否被锁定。
我查看了LockWorkStation 函数,但我希望找到的函数是IsWorkStationLocked
。
我需要支持所有windows版本>=XP
【问题讨论】:
您想检查计算机是否在程序运行时被锁定,或者计算机是否在程序开始执行时被锁定(如计划)?对于第一个,您可以使用 OnSessionChange 事件。 程序运行时 在 C# 上检查这个相关的question。 有人刚刚发布了执行此操作的代码:***.com/questions/29350013/… 【参考方案1】:对于windows 7及以上可以使用WTS API:
bool IsSessionLocked()
typedef BOOL (PASCAL * WTSQuerySessionInformation)(HANDLE hServer, DWORD SessionId, WTS_INFO_CLASS WTSInfoClass, LPTSTR* ppBuffer, DWORD* pBytesReturned);
typedef void (PASCAL * WTSFreeMemory)( PVOID pMemory);
WTSINFOEXW * pInfo = NULL;
WTS_INFO_CLASS wtsic = DW_WTSSessionInfoEx;
bool bRet = false;
LPTSTR ppBuffer = NULL;
DWORD dwBytesReturned = 0;
LONG dwFlags = 0;
WTSQuerySessionInformation pWTSQuerySessionInformation = NULL;
WTSFreeMemory pWTSFreeMemory = NULL;
HMODULE hLib = LoadLibrary( _T("wtsapi32.dll") );
if (!hLib)
return false;
pWTSQuerySessionInformation = (WTSQuerySessionInformation)GetProcAddress(hLib, "WTSQuerySessionInformationW" );
if (!pWTSQuerySessionInformation)
goto EXIT;
pWTSFreeMemory = (WTSFreeMemory)GetProcAddress(hLib, "WTSFreeMemory" );
if (pWTSFreeMemory == NULL)
goto EXIT;
if(pWTSQuerySessionInformation(WTS_CURRENT_SERVER_HANDLE, g_dwSessionID, wtsic, &ppBuffer, &dwBytesReturned))
if(dwBytesReturned > 0)
pInfo = (WTSINFOEXW*)ppBuffer;
if (pInfo->Level == 1)
dwFlags = pInfo->Data.WTSInfoExLevel1.SessionFlags;
if (dwFlags == WTS_SESSIONSTATE_LOCK)
bRet = true;
pWTSFreeMemory(ppBuffer);
ppBuffer = NULL;
EXIT:
if (hLib != NULL)
FreeLibrary(hLib);
return bRet;
请查看以下文章了解 WTSINFOEX 结构支持的平台: https://technet.microsoft.com/ru-ru/sysinternals/ee621017
【讨论】:
DW_WTSSessionInfoEx
的定义在哪里?【参考方案2】:
从你给的same MSDN link,“备注”第三段说:
此功能与按 Ctrl+Alt+Del 并单击锁定工作站的结果相同。要解锁工作站,用户必须登录。您不能调用任何函数来确定工作站是否被锁定。要在用户登录时接收通知,请使用 WTSRegisterSessionNotification 函数接收 WM_WTSSESSION_CHANGE 消息. 您可以使用会话通知来跟踪桌面状态,以便了解是否可以与用户进行交互。
【讨论】:
【参考方案3】:Alex Vershynin 的版本运行良好,但我必须进行一些代码更改。
我必须:将 DW_WTSSessionInfoEx 更改为 WTSSessionInfoEx(回答 user586399),将“g_dwSessionID”定义为 WTSGetActiveConsoleSessionId(),包括 Wtsapi32.h。我想就是这样……
由于无法评论,我将整个代码粘贴在这里。
#include "Wtsapi32.h"
bool IsSessionLocked()
typedef BOOL( PASCAL * WTSQuerySessionInformation )( HANDLE hServer, DWORD SessionId, WTS_INFO_CLASS WTSInfoClass, LPTSTR* ppBuffer, DWORD* pBytesReturned );
typedef void ( PASCAL * WTSFreeMemory )( PVOID pMemory );
WTSINFOEXW * pInfo = NULL;
WTS_INFO_CLASS wtsic = WTSSessionInfoEx;
bool bRet = false;
LPTSTR ppBuffer = NULL;
DWORD dwBytesReturned = 0;
LONG dwFlags = 0;
WTSQuerySessionInformation pWTSQuerySessionInformation = NULL;
WTSFreeMemory pWTSFreeMemory = NULL;
HMODULE hLib = LoadLibrary( "wtsapi32.dll" );
if( !hLib )
return false;
pWTSQuerySessionInformation = (WTSQuerySessionInformation) GetProcAddress( hLib, "WTSQuerySessionInformationW" );
if( pWTSQuerySessionInformation )
pWTSFreeMemory = (WTSFreeMemory) GetProcAddress( hLib, "WTSFreeMemory" );
if( pWTSFreeMemory != NULL )
DWORD dwSessionID = WTSGetActiveConsoleSessionId();
if( pWTSQuerySessionInformation( WTS_CURRENT_SERVER_HANDLE, dwSessionID, wtsic, &ppBuffer, &dwBytesReturned ) )
if( dwBytesReturned > 0 )
pInfo = (WTSINFOEXW*) ppBuffer;
if( pInfo->Level == 1 )
dwFlags = pInfo->Data.WTSInfoExLevel1.SessionFlags;
if( dwFlags == WTS_SESSIONSTATE_LOCK )
bRet = true;
pWTSFreeMemory( ppBuffer );
ppBuffer = NULL;
if( hLib != NULL )
FreeLibrary( hLib );
return bRet;
【讨论】:
【参考方案4】:正如对 MGamsby 帖子的改进:如果你的目标是 Win8.1 SDK 或 Win10 SDK,那么就没有必要乱搞 GetProcAddress()、LoadLibrary() 和 WTSGetActiveConsoleSessionId(),而且代码变得很多更紧凑:
bool isSessionLocked()
WTSINFOEXW* pInfo = NULL;
WTS_INFO_CLASS wtsic = WTSSessionInfoEx;
LPTSTR ppBuffer = NULL;
DWORD dwBytesReturned = 0;
LONG sessionFlags = WTS_SESSIONSTATE_UNKNOWN; // until we know otherwise. Prevents a false positive since WTS_SESSIONSTATE_LOCK == 0
DWORD dwSessionID = WTSGetActiveConsoleSessionId();
if (WTSQuerySessionInformation(WTS_CURRENT_SERVER_HANDLE, dwSessionID, wtsic, &ppBuffer, &dwBytesReturned))
if (dwBytesReturned > 0)
pInfo = (WTSINFOEXW*)ppBuffer;
if (pInfo->Level == 1)
sessionFlags = pInfo->Data.WTSInfoExLevel1.SessionFlags;
WTSFreeMemory(ppBuffer);
ppBuffer = NULL;
return (sessionFlags == WTS_SESSIONSTATE_LOCK);
注意: 我知道问题是关于 Windows 7,但您仍然可以使用 Win8.1 SDK 定位 Win7,并且它可用于 VS2015 及更高版本。
编辑:糟糕。我刚刚意识到 OP 要求从 WinXP 开始,在这种情况下,是的,你确实需要弄乱 LoadLibrary() 等。对此感到抱歉。 我会把我的代码留在这里,以防它对任何人有用。
【讨论】:
经过一些更改后,这对我有用:- SessionFlags 是一个位集,因此我需要使用 sessionFlags 和 WTS_SESSIONSTATE_LOCK 来解释该值。在上面的示例中,它的工作方式不可靠。 - 在 Windows 7 上,由于错误,这些值被颠倒了。见docs.microsoft.com/en-us/windows/win32/api/wtsapi32/… 我认为将其解释为位掩码是不正确的,Malte。文档说它可以是 WTS_SESSIONSTATE_UNKNOWN (4294967295 (0xFFFFFFFF))、WTS_SESSIONSTATE_LOCK (0 (0x0)) 或 WTS_SESSIONSTATE_UNLOCK (1 (0x1)) 中的“一个或多个”如果您将其解释为位掩码,那么您的代码会将 WTS_SESSIONSTATE_UNKNOWN 解释为两者WTS_SESSIONSTATE_UNLOCK 和 WTS_SESSIONSTATE_LOCK,我认为这不是你想要的!以上是关于C++:检查计算机是不是被锁定的主要内容,如果未能解决你的问题,请参考以下文章