C++:在不禁用 UAC 的情况下截取 Windows 登录屏幕/UAC 提示的屏幕截图

问题描述 投票:0回答:2

我一直在网上寻找这个问题的答案,但似乎没有直接答案,所以我想我会问。

案例场景:我想截取当前电脑屏幕上的内容。如果是 Windows 登录屏幕,我希望它就是这样。如果它是活动用户的桌面,我希望成为它。如果用户提升他们的应用程序,并且出现 UAC 提示,我希望就是这样。

根据大量阅读和反复试验,我当前的设置如下:

  • 程序作为 Windows 服务运行
  • 获取活跃用户的token
  • 使用用户的令牌运行 CreateProcessAsUser 以生成其自身的另一个实例
  • 截取屏幕截图并通过管道传回。

现在这对于登录用户来说效果很好,除了启用 UAC 提示时屏幕截图是黑色的。

此外,这种方法显然不适用于获取登录屏幕。

从根本上来说,我想知道 TeamViewer 究竟是如何实现此类目标的?它能够在登录屏幕和用户会话之间完美切换,同时还捕获 UAC 提示。我非常好奇它是如何实现这一目标的。

谢谢大家!

c++ windows screenshot teamviewer
2个回答
0
投票

根据戴维森的建议,我已经弄清楚如何做到这一点,并且涉及多个步骤。

首先,必须使用 CreateProcessAsUser 在控制台会话中创建一个进程(从 WTSGetActiveConsoleSessionId 获取)。需要注意的是,这个进程必须具有管理权限,仅仅获取用户令牌的句柄是不行的。显然,解决这个问题的方法是获取以管理权限运行的进程的句柄,获取该进程的令牌,复制它,并将其与 CreateProcessAsUser 一起使用。我为此使用的进程是 Winlogon。

这之后,剩下的就很简单了;使用 OpenInputDesktop 获取用户当前看到的桌面的句柄(对于实际桌面,它将是 Default,对于 UAC 提示和登录屏幕,它将是 Winlogon)。之后,使用 SetThreadDesktop 将进程的线程设置到适当的桌面,并捕获屏幕。假设您的进程有权创建 Winlogon 桌面的句柄,您将能够捕获登录屏幕/uac 提示和常规用户桌面。

再次感谢戴维森,他为我指明了正确的方向。


0
投票

我找到了最佳方法,并在本文中进行了总结 https://www.codeproject.com/Articles/5345258/Thank-You-for-Your-Service-Creating-a-Persistent-I

在获取用户的令牌之前,您需要等待用户登录,因此,我编写了以下类:

类用户登录监听器 { 处理 hWait = NULL; 处理 hSubscription = NULL;

公众: ~UserLoginListner() { 关闭句柄(hWait); EvtClose(hSubscription); }

UserLoginListner()
{
    const wchar_t* pwsPath = EVENT_SUBSCRIBE_PATH;
    const wchar_t* pwsQuery = EVENT_SUBSCRIBE_QUERY;

    hWait = CreateEvent(NULL, FALSE, FALSE, NULL);

    hSubscription = EvtSubscribe(NULL, NULL,
        pwsPath, pwsQuery,
        NULL,
        hWait,
        (EVT_SUBSCRIBE_CALLBACK)UserLoginListner::SubscriptionCallback,
        EvtSubscribeToFutureEvents);
    if (hSubscription == NULL)
    {
        DWORD status = GetLastError();

        if (ERROR_EVT_CHANNEL_NOT_FOUND == status)
            wprinf(L"Channel %s was not found.\n", pwsPath);
        else if (ERROR_EVT_INVALID_QUERY == status)
            wprintf(L"The query \"%s\" is not valid.\n", pwsQuery);
        else
            wprintf(L"EvtSubscribe failed with %lu.\n", status);

        CloseHandle(hWait);
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.