.net - 如何在显示 UAC 对话框窗口时运行我的应用程序?

标签 .net windows vb.net uac

我有一个用 .NET 编写的应用程序。它需要保持运行并访问 UAC 对话窗口打开的桌面,并使用键盘和鼠标事件与该桌面交互。

它有点像 VNC 程序。想象一下,您正在运行一个 VNC 程序并弹出一个 UAC 窗口,您希望您的 VNC 程序仍然能够控制 带有 UAC 窗口的桌面,以便用户可以移动鼠标并单击UAC 对话框上的确定按钮。谁能告诉我该怎么做?

谢谢

最佳答案

我建议您先阅读 documentation .我想也许你可以打开窗口站并将你的进程附加到它,但我对 Windows 的这个领域不是很熟悉。

编辑 1:

在 Windows XP 中,当以 SYSTEM 身份运行时,我能够通过 OpenDesktop 访问安全桌面(“winlogon”);安全桌面上的 ACL 只允许访问 SYSTEM 帐户。打开它后,我可以一一列举上面的 window ,尽管只有少数几个。也许您可以设置一个窗口 Hook 并监听特定对话框的创建。我不确定 Vista 是否更改了此模型,所以它可能不起作用;我面前没有用于测试的 Vista 机器。

编辑 2:

好的,我找到了大部分可用的东西(在 Windows 7 上测试过)。首先,您必须有一个以 SYSTEM 身份运行的服务。从该服务,您需要在用户 session 中启动一个单独的应用程序。为此,枚举所有查找 winlogon.exe 的进程,打开其 token ,然后创建 ProcessAsUser。为 STARTUPINFO 的 lpDesktop 参数指定“WinSta0\Winlogon”。现在,您在“Winlogon”桌面上的用户 session 中有一个以 SYSTEM 身份运行的进程。在新流程中,您可以为所欲为;我用 EnumDesktopWindows 做了一个快速测试,我能够获得各种 UAC 相关窗口的窗口类和文本(“$$$Secure UAP Background Window”、“$$$Secure UAP Background Fake Client Window”等)。不过,我不确定如何确定何时显示 UAC 提示;作为快速破解,您可以每 100 毫秒运行一个循环来寻找 UAC 窗口或其他东西。如果有帮助,我可以粘贴一些代码。

编辑 3:

好的。我编写了一个采用以下参数的 Win32 服务:

/install - 安装服务
/uninstall - 卸载服务
/service - 作为服务运行;通过 SCM 调用
/client - 作为客户端运行;通过 CreateProcessAsUser 调用

唯一有趣的代码是/service 和/client 模式。

在/service 模式下,它通过 EnumProcesses 和 GetModuleFileNameEx 枚举正在运行的进程,寻找“winlogon.exe”。当它找到一个时,它会打开它的 token 并通过 CreateProcessAsUser 在/client 模式下启动自己:

HANDLE hProcess = ...;
// winlogon.exe runs as SYSTEM in user's session; we need to run the same way
HANDLE hToken = NULL;
if(OpenProcessToken(hProcess, TOKEN_QUERY | TOKEN_DUPLICATE | TOKEN_ASSIGN_PRIMARY, &hToken))
{
    TCHAR szCommandLine[MAX_PATH];
    GetModuleFileName(NULL, szCommandLine, MAX_PATH);
    PathQuoteSpaces(szCommandLine);
    // run in /client mode
    _tcscat_s(szCommandLine, MAX_PATH, _T(" /client"));
    STARTUPINFO StartupInfo;
    ZeroMemory(&StartupInfo, sizeof(STARTUPINFO));
    StartupInfo.cb = sizeof(STARTUPINFO);
    // run on the Winlogon desktop
    StartupInfo.lpDesktop = _T("WinSta0\\Winlogon");
    PROCESS_INFORMATION ProcessInformation;
    ZeroMemory(&ProcessInformation, sizeof(PROCESS_INFORMATION));
    if(CreateProcessAsUser(hToken, NULL, szCommandLine, NULL, NULL, FALSE, 0, NULL, NULL, &StartupInfo, &ProcessInformation))
    {
        CloseHandle(ProcessInformation.hThread);
        ProcessInformation.hThread = NULL;
        CloseHandle(ProcessInformation.hProcess);
        ProcessInformation.hProcess = NULL;
    }
    CloseHandle(hToken);
    hToken = NULL;
}

在/client 模式下,它通过一系列 FindWindow 和 FindWindowEx 调用单击 UAC 提示符上的"is"按钮。您可以使用 Spy++ 找出窗口层次结构。

HWND hWnd = ...;
HWND hWndButton = FindWindowEx(hWnd, NULL, _T("Button"), NULL);
if(hWndButton != NULL)
{
    // see if this is the "Yes" button
    TCHAR szText[32];
    if(GetWindowText(hWndButton, szText, 32) && _tcsicmp(szText, _T("&Yes")) == 0)
    {
        // click it
        SendMessage(hWndButton, BM_CLICK, 0, 0);
    }
}

我测试这个的方法是坚持 sleep (5000);在/client 代码中。然后我启动服务并立即执行触发 UAC 提示的操作(即运行 regedit)。 5 秒后/client 代码将唤醒并找到并单击"is"按钮。可以在Winlogon桌面上运行其他进程; cmd.exe 和 spyxx.exe (Spy++) 最有用。不幸的是,explorer.exe 在 Winlogon 桌面上运行时会出现很多问题,而且不是很有用。要进入 Winlogon 桌面,您可以运行 regedit,然后按 Alt+Tab 切换到其他应用程序。如果你想变得有趣,你可以编写自己的桌面切换实用程序(使用 SwitchDesktop 函数),这样你就不必触发 UAC 提示符就可以进入 Winlogon 桌面。如果你真的很喜欢,你可以设置一个全局窗口钩子(Hook)来监控窗口的创建;当即将显示 UAC 对话框时,您可以准备单击其"is"按钮。不过,我并没有走那么远。

关于.net - 如何在显示 UAC 对话框窗口时运行我的应用程序?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2821667/

相关文章:

c# - 如何获取包含 ItemsControl 内容的 Panel 实例?

c# - 使用 AppDomain.AssemblyResolve 事件

java - 文件名中的日期返回在 Windows 计算机上运行的错误

.net - 使用EPPLUS隐藏Excel网格线

arrays - VB中对象数组的使用方法

visual-studio - 在没有 Visual Studio 的情况下编译 .vbproj 或 .csproj 项目文件

c# - 在 Entity Framework 上创建外键关系的问题

c# - WPF : Assigning to RichTextBox. 文档极慢(7 分钟!)

windows - Windows 中的最大驱动器数量?

c - 为什么 NdisFRegisterFilterDriver 在 Windows 8 下失败并出现 NDIS_STATUS_FAILURE?