You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在管理员上下文进程的DLL中获取触发回调的当前用户会话?

解决管理员上下文DLL中获取触发回调的登录用户问题

这个问题我之前处理过,核心难点在于你的DLL运行在管理员进程的上下文里,默认身份是管理员,但回调是由登录用户的操作触发的,所以需要绕过默认上下文,精准关联到触发操作的用户会话。

关键思路:从回调线程关联到用户会话

当用户操作触发你的DLL回调时,执行回调的线程实际上属于该用户的会话(除非你的回调是完全在系统线程里触发的,但大部分用户操作相关的回调都会在用户线程上下文执行)。所以我们可以通过当前线程的会话ID来定位到对应的用户,而不是枚举所有会话或者依赖控制台会话ID。

具体实现步骤

  1. 获取当前线程所属的会话ID
    使用WTSGetThreadSessionId函数,传入当前线程ID,就能拿到触发回调的用户会话ID:

    DWORD dwSessionId = 0;
    if (!WTSGetThreadSessionId(GetCurrentThreadId(), &dwSessionId)) {
        // 处理错误,调用GetLastError()查看具体原因
        return;
    }
    
  2. 通过会话ID查询用户名
    拿到会话ID后,用WTSQuerySessionInformation获取该会话的用户名:

    LPWSTR pUserName = nullptr;
    DWORD dwBytesReturned = 0;
    if (WTSQuerySessionInformation(WTS_CURRENT_SERVER_HANDLE, dwSessionId, WTSUserName, &pUserName, &dwBytesReturned)) {
        // 这里的pUserName就是触发回调的登录用户用户名
        // 示例:输出用户名
        wprintf(L"触发回调的用户:%s\n", pUserName);
        // 用完记得释放内存
        WTSFreeMemory(pUserName);
    } else {
        // 处理查询失败的情况
        DWORD err = GetLastError();
        // 可能需要检查权限,比如是否有SE_TCB_NAME权限
    }
    
  3. 权限补充(如果查询失败)
    如果WTSQuerySessionInformation调用失败,大概率是权限不足。管理员进程默认可能没有SE_TCB_NAME权限,需要临时启用:

    HANDLE hToken;
    if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) {
        TOKEN_PRIVILEGES tp;
        tp.PrivilegeCount = 1;
        LookupPrivilegeValue(nullptr, SE_TCB_NAME, &tp.Privileges[0].Luid);
        tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
        AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(tp), nullptr, nullptr);
        CloseHandle(hToken);
    }
    

    启用权限后再尝试查询会话信息。

为什么之前的方法不行?

  • WTSEnumerateSessions只能枚举所有活跃会话,但无法直接关联到当前回调对应的会话,除非你有额外的上下文信息(比如窗口句柄)来匹配。
  • WTSGetActiveConsoleSessionId仅针对物理控制台登录的用户,RDP登录的用户属于远程会话,所以不会被这个函数返回。

特殊情况处理

如果你的回调是在系统服务线程里触发的(没有关联到用户线程),可以尝试通过回调的上下文信息(比如用户操作的窗口句柄)来获取进程ID,再转换为会话ID:

// 假设你有回调传入的窗口句柄hWnd
DWORD dwProcessId = 0;
GetWindowThreadProcessId(hWnd, &dwProcessId);
DWORD dwSessionId = 0;
ProcessIdToSessionId(dwProcessId, &dwSessionId);
// 之后再用WTSQuerySessionInformation查询用户名

内容的提问来源于stack exchange,提问作者user3145865

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.08 07:57:48