windows 如何在显示 UAC 对话框窗口时运行我的应用程序?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2821667/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How do I run my application while a UAC dialog window is showing?
提问by Ray
I have an application that I wrote in .NET. It needs to remain running and have access the desktop that the UAC dialog windows open on and interact with that desktop using keyboard and mouse events.
我有一个用 .NET 编写的应用程序。它需要保持运行并访问 UAC 对话框窗口打开的桌面,并使用键盘和鼠标事件与该桌面交互。
It's sort of like a VNC program. Imagine you are running a VNC program and a UAC window pops up, you want your VNC program to still be able to control the desktop with the UAC window in itso that the user can move the mouse and click the OK button on the UAC dialog. Can anyone tell me how I would go about doing that?
它有点像 VNC 程序。想象一下你正在运行一个 VNC 程序并且弹出一个 UAC 窗口,你希望你的 VNC 程序仍然能够控制带有 UAC 窗口的桌面,这样用户可以移动鼠标并点击 UAC 对话框上的确定按钮. 谁能告诉我我将如何去做?
Thanks
谢谢
回答by Luke
I would suggest you start by reading the documentation. I would guess that maybe you could open the window station and attach your process to it, but I am not very familiar with this area of Windows.
我建议您从阅读文档开始。我想也许您可以打开窗口站并将您的进程附加到它,但我对 Windows 的这一领域不是很熟悉。
Edit 1:
编辑1:
In Windows XP I was able to access the secure desktop ("winlogon") via OpenDesktop when running as SYSTEM; the ACL on the secure desktop allows access only to the SYSTEM account. After opening it I could enumerate the windows on it, though there were only a handful. Perhaps you could set a window hook and listen for creation of the specific dialog. I'm not sure if Vista changed this model, so maybe it won't work; I don't have a Vista machine in front of me to test against.
在 Windows XP 中,当以 SYSTEM 身份运行时,我能够通过 OpenDesktop 访问安全桌面(“winlogon”);安全桌面上的 ACL 只允许访问 SYSTEM 帐户。打开它后,我可以列举它上面的窗户,尽管只有少数几个。也许您可以设置一个窗口挂钩并监听特定对话框的创建。我不确定 Vista 是否改变了这个模型,所以它可能行不通;我面前没有一台 Vista 机器可以测试。
Edit 2:
编辑2:
Ok, I got something that mostly works (tested on Windows 7). First you have to have a service running as SYSTEM. From that service, you need to launch a separate application in the user's session. To do this, enumerate all the processes looking for winlogon.exe, open its token, and CreateProcessAsUser. Specify "WinSta0\Winlogon" for the lpDesktop parameter of STARTUPINFO. Now you have a process running as SYSTEM in the user's session on the "Winlogon" desktop. In the new process you can do whatever you want; I did a quick test with EnumDesktopWindows and I was able to get the window class and text for various UAC related windows ("$$$Secure UAP Background Window", "$$$Secure UAP Background Fake Client Window", etc). I'm not sure how to determine when a UAC prompt is being displayed, though; as a quick hack you could just run a loop every 100 ms looking for UAC windows or something. I could paste some code if it would help.
好的,我得到了大部分有效的东西(在 Windows 7 上测试)。首先,您必须有一个以 SYSTEM 身份运行的服务。通过该服务,您需要在用户会话中启动一个单独的应用程序。为此,请枚举所有寻找 winlogon.exe 的进程,打开其令牌,然后创建 CreateProcessAsUser。为 STARTUPINFO 的 lpDesktop 参数指定“WinSta0\Winlogon”。现在您有一个进程在“Winlogon”桌面上的用户会话中以 SYSTEM 身份运行。在新流程中你可以为所欲为;我用 EnumDesktopWindows 做了一个快速测试,我能够获得各种 UAC 相关窗口的窗口类和文本(“$$$Secure UAP 后台窗口”、“$$$Secure UAP 后台假客户端窗口”等)。不过,我不确定如何确定何时显示 UAC 提示;作为一个快速的黑客,你可以每 100 毫秒运行一个循环来寻找 UAC 窗口或其他东西。如果有帮助,我可以粘贴一些代码。
Edit 3:
编辑3:
Ok. I have written a Win32 service that takes the following parameters:
好的。我编写了一个采用以下参数的 Win32 服务:
/install - installs the service
/uninstall - uninstalls the service
/service - runs as a service; invoked via SCM
/client - runs as a client; invoked via CreateProcessAsUser
/install - 安装服务
/uninstall - 卸载服务
/service - 作为服务运行;通过 SCM
/client调用- 作为客户端运行;通过 CreateProcessAsUser 调用
The only interesting code is in the /service and /client modes.
唯一有趣的代码是在 /service 和 /client 模式中。
In /service mode it enumerates the running processes via EnumProcesses and GetModuleFileNameEx looking for "winlogon.exe". When it finds one it opens its token and launches itself in /client mode via CreateProcessAsUser:
在 /service 模式下,它通过 EnumProcesses 和 GetModuleFileNameEx 枚举正在运行的进程,以查找“winlogon.exe”。当它找到一个时,它会打开它的令牌并通过 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;
}
In /client mode it clicks the "Yes" button on the UAC prompt via a bunch of FindWindow and FindWindowEx calls. You can use Spy++ to figure out the window hierarchy.
在 /client 模式下,它通过一堆 FindWindow 和 FindWindowEx 调用单击 UAC 提示上的“是”按钮。您可以使用 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);
}
}
The way I test this is to stick a Sleep(5000); in the /client code. Then I start the service and immediately do something that triggers a UAC prompt (i.e. run regedit). After 5 seconds the /client code will wake up and find and click the "Yes" button. You can run other processes on the Winlogon desktop; cmd.exe and spyxx.exe (Spy++) are most useful. Unfortunately, explorer.exe exhibits a lot of problems when running on the Winlogon desktop and isn't very useful. To get to the Winlogon desktop you can run regedit and then Alt+Tab to switch to the other application. If you want to get fancy you can write your own desktop switching utility (using the SwitchDesktop function) so you don't have to trigger a UAC prompt to get to the Winlogon desktop. If you want to get really fancy you can set a global window hook to monitor window creation; when the UAC dialog is about to be displayed you can prepare to click its "Yes" button. I didn't take it quite that far, though.
我测试的方法是坚持 Sleep(5000); 在 /client 代码中。然后我启动该服务并立即执行触发 UAC 提示的操作(即运行 regedit)。5 秒后 /client 代码将唤醒并找到并单击“是”按钮。可以在Winlogon桌面上运行其他进程;cmd.exe 和 spyxx.exe (Spy++) 是最有用的。不幸的是,explorer.exe 在 Winlogon 桌面上运行时会出现很多问题并且不是很有用。要进入 Winlogon 桌面,您可以运行 regedit,然后按 Alt+Tab 切换到其他应用程序。如果您想玩得开心,您可以编写自己的桌面切换实用程序(使用 SwitchDesktop 功能),这样您就不必触发 UAC 提示来访问 Winlogon 桌面。如果你想变得更漂亮,你可以设置一个全局窗口钩子来监视窗口的创建;当即将显示 UAC 对话框时,您可以准备单击其“是”按钮。不过,我并没有走那么远。
回答by Powerlord
The problem is that the UAC prompt doesn't open on the current desktop, but rather in a completely new Secure Desktop, which suspends any currently open desktops.
问题是 UAC 提示不会在当前桌面上打开,而是在一个全新的Secure Desktop 中打开,它会暂停任何当前打开的桌面。
This is intentional, as programs are not allowed to interact with this dialog.
这是有意为之,因为不允许程序与此对话框交互。
There is one exception: "trusted SYSTEM processes can run on the Secure Desktop," according to this blog entry.
有一个例外:“受信任的 SYSTEM 进程可以在安全桌面上运行”,根据这篇博客文章。
回答by John Grey
I believe everything you see on your screen during UAC prompt is a screenshot(except the dialog itself)
我相信您在 UAC 提示期间在屏幕上看到的所有内容都是屏幕截图(对话框本身除外)
回答by Jason Williams
I would imagine that you probably need to be running as a Windows Service to be allowed to execute while UAC is active.
我想您可能需要作为 Windows 服务运行才能在 UAC 处于活动状态时允许执行。
回答by Scott Dorman
You can't do this. By default, when a UAC prompt appears, it is actually running in an isolated WinStation that is different from the one that runs "normal" applications. This WinStation is isolated specifically to prevent user applications from interacting with the UAC prompt. It looks like your desktop because the background of that WinStation is actually a static bitmap image of your desktop as it was just before the UAC prompt was displayed.
你不能这样做。默认情况下,当出现 UAC 提示时,它实际上是在与运行“正常”应用程序的 WinStation 不同的独立 WinStation 中运行的。此 WinStation 是专门隔离的,以防止用户应用程序与 UAC 提示交互。它看起来像您的桌面,因为该 WinStation 的背景实际上是您桌面的静态位图图像,就像在显示 UAC 提示之前一样。
I suspect this might be a problem in the version of VNC you are running as I'm fairly certain the Remote Desktop provides the correct behavior and allows you the user to still interact with the UAC prompt through the remote desktop client. Keep in mind, when running any kind of remote client (remote desktop, VNC, etc.) the idea is taht the client should allow you to do anything you would normally be able to do if you were physically sitting at the keyboard.
我怀疑这可能是您运行的 VNC 版本中的问题,因为我相当确定远程桌面提供了正确的行为,并允许您的用户仍然通过远程桌面客户端与 UAC 提示进行交互。请记住,在运行任何类型的远程客户端(远程桌面、VNC 等)时,这个想法是客户端应该允许您做任何您通常坐在键盘前可以做的事情。