C++:在不禁用UAC的情况下对Windows屏幕截图/UAC截图

knpiaxh1  于 11个月前  发布在  Windows
关注(0)|答案(2)|浏览(172)

我一直在网上寻找这个问题的答案,但似乎没有直接的答案,所以我想我会问。
案例情景:我想对当前计算机屏幕上的内容进行截图。如果它是Windows XP屏幕,我希望它是该屏幕。如果它是活动用户的桌面,我希望它是该桌面。如果用户提升其应用程序,并显示UAC提示,我希望它是该桌面。
根据大量的阅读和试验和错误,我目前的设置如下:

  • 程序作为Windows服务运行
  • 获取活动用户的令牌
  • 使用用户的令牌调用ProcessAsUser以生成其自身的另一个示例
  • 截图并通过管道传输回来。

现在这对于登录的用户来说工作得很好,除了当启用UAC提示时屏幕截图是黑色的。
此外,这种方法显然不能用于获取登录屏幕。
从根本上说,我想知道TeamViewer究竟是如何实现这类事情的?它能够在登录屏幕和用户会话之间无缝切换,同时还捕获UAC提示。我非常好奇它是如何实现这一点的。
谢谢大家!

laximzn5

laximzn51#

根据戴维森的建议,我已经想出了如何做到这一点,它涉及到多个步骤。
首先,必须使用JavaProcessAsUser在控制台会话中创建一个进程(从WTSGetActiveConsoleSessionId获得)。需要注意的是,此进程必须具有管理权限,而仅仅获得用户令牌的句柄是不行的。显然,解决此问题的方法是获得以管理权限运行的进程的句柄,获得此进程的令牌,复制它,并将其与Windows ProcessAsUser一起使用。我为此使用的进程是Winlogon。
在这之后,剩下的就很简单了;使用OpenInputDesktop获取用户当前看到的桌面的句柄(它将是默认的实际桌面,和Winlogon的UAC提示和登录屏幕).在此之后,使用SetThreadDesktop设置您的进程'线程到适当的桌面,并捕获屏幕.假设您的进程有权限创建一个句柄Winlogon桌面,您将能够捕获登录屏幕/uac提示和常规用户桌面。
再次感谢戴维森,他为我指明了正确的方向。

csga3l58

csga3l582#

我找到了实现这一点的最佳方法,并在本文https://www.codeproject.com/Articles/5345258/Thank-You-for-Your-Service-Creating-a-Persistent-I中进行了总结
在获取用户的token之前,你需要等待用户登录,因此,我编写了以下类:

class UserLoginListner
{
    HANDLE hWait = NULL;
    HANDLE hSubscription = NULL;

public:
    ~UserLoginListner()
    {
        CloseHandle(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);
        }
    }
};

字符串

相关问题