【问题标题】:How to bring UAC's consent.exe to the foreground programmatically?如何以编程方式将 UAC 的许可.exe 带到前台?
【发布时间】:2011-05-30 08:32:31
【问题描述】:

当 Vista/Win7 UAC 同意对话框在任务栏中最小化时,如何(如果可能)将其置于前台?

例如,考虑以下场景:
我的应用程序在启动期间检查更新,它下载新的更新文件并通过在 Process.StartInfo 中提供管理员密码来执行它,然后我的应用程序关闭。

此时,如果用户或 Windows 本身设法从 MSI 安装程序窗口失去焦点(可能是通过单击桌面或其他窗口),UAC 会发现安装程序窗口不是前台窗口,因此会弹出一个闪烁的同意对话框进入任务栏。

一些不太聪明的客户不了解我的应用程序尚未完成更新并尝试重新启动该应用程序。在这个阶段,我可以枚举正在运行的进程,找到任务栏中闪烁的consent.exe。

问题是我不能把它带到前台。我尝试使用不同的参数(恢复、显示、正常)从 user32.dll 调用 ShowWindow(),但没有任何反应。我确实检查了 MainWindowHandle 进程,它似乎没问题(它不是零或负数)。我猜测问题在于 UAC 为同意对话框(安全桌面)创建了不同的桌面会话。

如果用户可以点击任务栏中闪烁的图标将同意对话框带到前台,那么也应该可以通过代码来模拟这个?

PS!我正在使用 C#

【问题讨论】:

  • 这一定是我的 #1 UAC 最讨厌的地方。

标签: c# uac


【解决方案1】:

这里有一个讨论可以帮助你:How do you maximize User Account control(UAC) window?

关于该主题的官方文档在这里:Redesign for UAC Compatibility (UAC)

【讨论】:

  • 您提供的链接谈到应用程序具有不正确的 HWND,这就是 UAC 转到任务栏的原因。我遇到的问题是 HWND 是正确的,只是安装程序失去了焦点,这就是 UAC 转到任务栏的原因。这本身不是问题,但是当用户尝试重新启动我的应用程序时,我想以编程方式将其带到前台...
【解决方案2】:

你试过SetForegroundWindow 吗?此外,在本机 win32 中,实际上并没有什么叫做主窗口的东西,一个进程可以有 0 个或任意数量的“主窗口”,但在许可.exe 的情况下,我猜它只有一个......

编辑:

BOOL CALLBACK EnumWindowsProc(HWND hwnd,LPARAM lParam) 
{
    char buf[50];
    *buf=0;
    GetClassName(hwnd,buf,50);
    buf[sizeof("$$$Secure UAP")-1]=0;
    if (!lstrcmp("$$$Secure UAP",buf)) 
    {
        SwitchToThisWindow(hwnd,true);
    }
    return true;
}
...
EnumWindows(EnumWindowsProc,0);

这将切换到安全桌面,但我不建议使用它,因为:

  • 它使用未记录的 $$$Secure UAP... 窗口类
  • 使用 SwitchToThisWindow 是邪恶的,你不应该在用户不想的时候切换焦点
  • 如果多个 UAC 确认对话框处于活动状态,您无法确定要切换到哪个许可.exe

问题在于同意窗口不是自有弹出窗口,如果是,您可以确定您获得了正确的 HWND。希望 Win8 能够将同意作为一个拥有的弹出窗口,或者更好的是,一个模态对话框。

【讨论】:

  • SetForegroundWindow 只是一个建议,在具有 UAC 的 Vista 和 Seven 上通常会被忽略。它应该闪烁任务栏按钮,假设有一个任务栏按钮。
  • @Tergiver: 好吧,SetForegroundWindow 取决于你是否在前台,如果你在前台,你可以将任何窗口带到前台,如果不是,它所做的只是刷新任务栏,但是这是你最好的选择,除非你使用可怕的黑客来劫持焦点并激怒你的用户
  • @Anders:是的,但是 OP 的问题是他们的窗口不是前景,所以 SetForegroundWindow 不会有帮助。
  • @Tergiver:在我看来,他会在“一些不太聪明的客户不明白我的应用程序尚未完成更新并尝试重新启动应用程序”的情况下锁定前台"
  • 你错了,因为你的陈述——“OP的问题是他们的窗口不是前景”。我的应用程序窗口位于前台。其次,我知道如果我的应用程序在前台,我可以将其他窗口带到前台等。但问题是,出于某种原因,这些规则不适用于许可.exe,因此是我的问题。如何以编程方式将其带到前台? ShowWindow() 或 SetForegroundWindow() 都不起作用,而且我不知道另一种将窗口置于前台的方法...
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-08-14
  • 2020-12-14
  • 1970-01-01
  • 2010-10-15
  • 1970-01-01
  • 2017-06-26
  • 2013-07-06
相关资源
最近更新 更多