答案 0 :(得分:11)
对于Windows 7和abowe,可以使用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
答案 1 :(得分:5)
根据您提供的same MSDN link,“备注”的第三段说:
此功能与按Ctrl + Alt + Del并单击“锁定工作站”的结果相同。要解锁工作站,用户必须登录。您无法调用以确定工作站是否已锁定。要在用户登录时接收通知,请使用WTSRegisterSessionNotification函数接收WM_WTSSESSION_CHANGE消息。 您可以使用会话通知来跟踪桌面状态,以便了解是否可以与用户进行互动。
答案 2 :(得分: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()等。很抱歉。 如果对任何人有用,我将在这里保留我的代码。
答案 3 :(得分: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;
}