How to (if at all possible) bring the Vista/Win7 UAC consent dialog to the foreground, when it is minimized in the taskbar?
For instance, consider the following scenario:
My application checks for updates during startup, it downloads the new update file and it executes it by providing the administrator's password in the Process.StartInfo, after that my application closes.
At this point, if the user or Windows itself manages to lose focus from the MSI installer window (perhaps by clicking on the desktop or another window), UAC sees that installer window is not the foreground window and thus pops a blinking consent dialog into the taskbar.
Some not so brightminded customers don't understand that my application hasn't yet finished updating and try to relaunch the application. At this stage, I can enumerate the running processes and find the consent.exe which is blinking in the taskbar.
The problem is I can't bring it to the foreground. I tried to invoke ShowWindow() from user32.dll with different paramaters (restore, show, normal), but nothing happens. I did check the process MainWindowHandle and it seems ok (it isn't zero or negative). I'm guessing that the problem lies with UAC creating a different desktop session for the consent dialog (secure desktop).
If the user can click the blinking icon in the taskbar to bring the consent dialog to the foreground, then it should also be possible to simulate this via code?
PS! I'm using C#
Did you try SetForegroundWindow ? Also, in native win32 there is not really anything called a main window, a process can have 0 or any number of "main windows" but in the case of consent.exe, I'm guessing it has just one...
Edit:
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);
This will switch to the secure desktop, but I would not recommend using this because:
It uses the undocumented $$$Secure UAP... window class
Using SwitchToThisWindow is evil, you should never switch focus when the user does not want to
If more than one UAC confirmation dialog is active, you can't be sure which consent.exe you will be switching to
The problem is that the consent window is not a owned popup, if it was you could be sure you got the correct HWND. Hopefully Win8 will have consent act as a owned popup, or even better, a modal dialog.
There is a discussion here that may help you: How do you maximize User Account control(UAC) window?
The official documentation about that subject is here: Redesign for UAC Compatibility (UAC)
Related
When I open any dialog in my Winforms application then Windows 10 behaves oddly in these ways:
ALT-TAB no longer displays the list of windows
I cannot switch to hidden applications using taskbar icons - if I select a taskbar icon of a window that is not currently visible (even if it is not hidden by the winforms app) the icon just flashes and then stays highlighted, but is not brought to the foreground. I can use other applications that are visible. As soon as I close the dialog form the other I can use the windows of other applications correctly
If I switch to the application window that is behind the winforms application by clicking on it, I cannot go back to the winforms app either by ALT-TAB or by clicking on the taskbar icon. I can get back to it by minimizing the other application
I'm opening the dialogs with
dialogFormName.ShowDialog(this);
TopMost is set false on all forms and is not set in the code.
I've read about 50 related articles and the only problems seem to be either TopMost is set or ShowDialog is not called with the parent form. I'm not a regular Winforms developer so I'm probably doing something stupid. This is driving me crazy, so I'd really appreciate any help!
Edit: The same issues occur with MessageBox.Show(this, "test"). The issue does not occur with a newly created app just with a single button calling MessageBox.Show(this, "test"). The problem application uses EntityFramework but no other packages and the problem existed before I added EF.
After trying different scenarios I eventually found the issue. In my case I was calling ShowDialog() after a user clicks an item on a ContextMenu. The blocking of ALT-TAB was caused by the following code that attached the ContextMenu to the ListView that the menu was contextually for:
lstList.ContextMenu = myContextMenu;
As soon as I removed that association, the ShowDialog no longer blocked ALT-TAB.
Form.ShowDialog() blocks the parent form until it's closed.
Use Show() to display the form separately without blocking its parent.
I am trying to determine if User Account Control is currently blacking out the screen/asking for permission.
I have an application which uses SlimDX and when UAC takes over the screen it causes the DirectX device to be lost, I can recreate the device once the UAC window has been closed, if I try this before(even in a try{}catch{} and loop the application crashes)
I have looked over at pinvoke and msdn and I can't seem to find anything about this. Does anyone have an ideas?
As a note: I do not want to interact with these prompts in any way, I only want to check if they are open so I can delay the creation of my DirectX device.
Sorry for making a late answer. But I think it may help.
As far as I see, you are not looking for a way to see if UAC is running, but a way to check whether UAC is blocking the screen.
I've confirmed that UAC is using SwitchDesktop to change to another desktop, so you can just use GetInputDesktop to get the 'active' desktop. Then use GetUserObjectInformation to check its name. The 'normal' desktop should be default, while UAC will be running on the WinLogon desktop.
Wish it will help.
If a UAC prompt is currently on screen then C:\Windows\System32\consent.exe will be running. There are ways to be notified with a event when a program starts or stops, you can use them and have your program perform the action to recreate the DirectX device after the consent.exe program terminates.
I seem to be running into a dead end here. I have a project that does the following:
just runs and stays in notification area
when user presses middle mouse button, it shows a form
user can then chose whatever from the form, and be happy.
This is working just fine, however what is NOT working is that when the form is shown, it does NOT activate.
Now, prior to me modifying the app.manifest to requireAdmin, it was working fine. Any time the form was shown, boom it was active.
But now that i'm running the form as Administrator, given that I need to be able to control one of our other applications with it (that is ran as admin as well), the form comes up just fine, but doesn't activate.
I have tried:
- TopMost = true inside of the Form_Load method
- Calling SetForegroundWindow with the forms handle on Form_Load
- Calling ShowDialog both on Form_Load and also tried it when the form was built.
- Calling Activate on Form_Load as well as when the form was built
Here's my layout:
Program runs, requires UAC permissions due to the manifest, user agrees, and it kicks off
Only a notification icon appears, shows a nice little bubble saying it's running
Program.cs monitors the keyboard/mouse hooks
When middle mouse button, or any of the keyboard hooks are triggered, it creates a new form object
sets the location of where the form should appear
and then finally shows the form.
Again, without UAC and requireAdmin inside of the app.manifest, this works fine. But once it is running as admin, nope, wont stay in front.
I know that MS has made the SetForegroundWindow requirements much stricter with later versions of windows (Vista, 7, 8), but i really need to be able to make this form show as the top most, active window (like a context menu).
How can i do that properly?
You could split your program into two, a non-admin requiring half that sits in the tray and watches for the middle button, and the half that requires admin permission that you launch when the mouse button is pressed. The non-elevated half could then call SetForegroundWindow or AllowSetForegroundWindow as needed.
If you want to avoid a UAC prompt every time you can cache a COM elevation object via the CoCreateInstanceAsAdmin method and use it repeatedly.
I'm interested in launching a window in a temporary session, like how UAC prompts appear. There's been some interest in this concept from a few people, so I figured I'd ask here. Essentially what we're going for is an elevated window like the UAC "are you sure you want to <...>" prompts, but with an arbitrary window. The end goal is to prevent window event hooks and all sorts of other issues that might occur during password entry.
I've had a quick look at the UAC APIs and a few other places, but there's nothing particularly useful out there. Obviously the UAC prompts get elevated to their own desktop session somehow, so there must be a way to create windows in such a way.
You can create a desktop using CreateDesktop. You can use SwitchDesktop to switch to the new desktop. Then you can call SetThreadDesktop on your main thread and draw your window. To get back get the handle of the default desktop by calling OpenDesktop with "Default" as lpszDesktop and use SwitchDesktop with this handle. You can also run Processes on a certain desktop. In order to do this you have to set lpDesktop member of the STARTUPINFO structure to the name of the desktop the process should be run on. Close the handles to the desktops after using them (CloseDesktop).
You can show your own window on an own desktop in this way.
The secure desktop used by UAC and by the Logon UI is called "Winlogon". In order to access it you need system rights. Luke provided an example in one of his answers.
Brian R. Bondy wrote a blog entry on desktops and window stations which is worth reading.
we would like to build a screensaver that shows the desktop and the running applications but prevents user input by showing the login screen. The idea was to build a windows app with no window or a transparent window. However, as soon as the screensaver gets activated the desktop and all applications are hidden from the screen.
Is it possible to start the screensaver without hiding the desktop?
Thx,
bja
Is it possible for you to implement this as something other than a screensaver? I'm assuming that the Windows API does have a method that allows you to tell how long the computer has been idle (otherwise, how does the stuff that manages screensavers do it?), so if you use that you could just set up your application such that it's continuously running as a background process, and will pop up a modal dialog box (or your idea of a transparent window) or something that prompts for the user's login info when the computer has been idle for a certain amount of time.
Why can't you just grab an image of the screen when the SS kicks off. Then use that as the backdrop of your SS.
Vista has a bubbles screen saver that just starts putting bubbles on the screen. Not sure how they do it.
You are better off just creating a full-screen application with a transparent window that starts up on a timer like a screensaver. The screensaver functionality while similar to what you are doing, functions much differently.
As an alternative suggestion, you could always use a service (or background app) to gather the information you want these monitoring tools to display, or even just to grab periodic screenshots of the (hidden) desktop, and then have your screensaver query that app to get the data it needs to display.
That way, you get the benefit (the secure desktop, the usual Windows login sequence, etc.) of a screensaver, but still get to display what you need to.