How does Windows force "minimized" state from a desktop shortcut? - c#

I have an application that is designed to minimize to the system tray. No issues there.
The problem I am having is that I cannot determine what Windows is doing to force the minimized state when I set up a desktop shortcut to that executable and launch it, such as:
I put some debug outputs in the form's constructor and launched via the shortcut. I get no command line arguments and a check of WindowState yields Normal. Yet the app starts minimized to the taskbar.
However, that's the rub: I want it to start minimized to the system tray, just as it would if the form were on-screen and the user minimized it. Not all the time, just when a "minimize" shortcut is used, or when the user clicks Minimize on the form, of course.
EDIT: for the curious...my initial testing was flawed because I checked in the constructor. Placing the test in the Load method produced a Minimized state, to which I could then react and call my code to perform the "minimize-to-tray".

Windows is starting the process with parameters to minimize the main window.
In C#, you can do the same by setting WindowStyle (MSDN) at ProcessStartInfo for use in Process.Start().
In the native world, you would use the CreateProcess (MSDN) API and pass a STARTUPINFO, setting wShowWindow to SW_MINIMIZE.
To query the window state, use GetWindowInfo (MSDN), look at dwStyle and check if WS_MINIMIZEis set. In C#, this should be in Form.WindowState.

Related

C#.Net Check if 'Process' has a gui

Is there any way to check if a variable of type Process currently has an opened GUI/window.
I'm using this to try and get all open application (with an open GUI) and then render their icons
I will try to answer this.
After a bit a research, I came across the following article in UserInteractive Property
So maybe you can try something like this:
Environment.UserInteractive
The above property is a boolean, which returns true if the current process is running in user interactive mode
And also you can look on this article: MainWindowHandle Property
which gets the window handle of the main window of the associated process, especially IntPtr which is the system-generated window handle of the main window of the associated process.

How to open an application on active display while using Process.Start()?

I am using
System.Diagnostics.Process.Start(ProcessInfo);
to open a TEXT file in notepad from within my windows form application.
Detailed code snippet is
ProcessStartInfo PSI = new ProcessStartInfo("notepad.exe", LogFile);
PSI.WindowStyle = ProcessWindowStyle.Normal;
System.Diagnostics.Process p = System.Diagnostics.Process.Start(PSI);
However, it opens notepad on the default desktop but not on the extended desktop on which the main application is running.
Now, the question is, how to open notepad on the active desktop i.e. Window on which the current application is running?
Other that specifying the initial window state (normal, hidden, etc), you have basically no control over how the newly launched application starts up and where it shows itself.
The best bet here is to launch the application, then use its window handle to tell it to move. This all requires using P/Invoke, to call MoveWindow. The C# signatures for all of those functions are on pinvoke.net.
Here's a very simple (VB.NET) example that shows the basic idea. In this case, as #Lloyd points out, the window handle you need is the Process.MainWindowHandle you get back from Process.Start. Note that Process.MainWindowHandle isn't filled in immediately; you typically need to call WaitForInputIdle to make sure the window actually gets created. If MainWindowHandle is 0 then you'll know it's too soon.

UAC Window On Top

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.

How to check if a window handle is for a console window?

I have an application, using one process, that has two windows. Both these windows have the same title. One is the main app window, that the user does all their interaction with. The other is a console window which is used purely for live logging of commands executed in the main window.
I'm currently implementing a Mutex and if the application is open already, I want to restore & switch to the currently running main application window (not the console window). However, given that both windows have the same title and the same process, it's proven hard to distinguish between the two.
Is there a way to determine if a window is a console window? Or any other way to distinguish between these two windows?

How to bring UAC's consent.exe to the foreground programmatically?

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)

Categories