I am trying to get all the window handles of applications that have a taskbar icon only.
The solutions I have converted to C# that have failed:
Enumerate windows like alt-tab does
Enumerate windows like alt-tab does
Enumerate windows like alt-tab does
And a couple that I lost track of already.
All these solutions either crash or bring up windowless processes like svchost, plugin processes, etc.
Basically I just need the windows that are actively available in the task bar with icons.
I am using the window handle of
Process.MainWindowHandle
What are some working solutions to this? Is there a thread with a working solution that I missed?
Try retrieving all processes where the MainWindowTitle property is set.
It doesn't feel like a particularly elegant solution, but it worked for me, bringing back only those applications which were running and visibly open in the taskbar.
List<Process> taskBarProcesses = Process.GetProcesses().
Where(p => !string.IsNullOrEmpty(p.MainWindowTitle))
.ToList();
Related
As of right now, I am working on a mock up OS via WinForms to use as a prop for movies.
Upon running the application, it kills explorer.exe so that you can't accidentally have the windows task bar show up during a shoot. The issue is, upon closing the mock OS I would like for explorer.exe to be started up again. However, Process.Start("explorer.exe"); brings up an explorer window, and does not re-instate the window taskbar.
I know for a fact, that task manager is more than capable of bringing back the window taskbar via typing "explorer.exe" under a new task, though I've had no luck finding command line arguments to pass to task manager.
Edit:
I'm running under Windows 7. As well, I'm going pretty in depth with this mock OS. I'm taking control of quite a few key presses that Windows uses. For this reason, I kill explorer.exe so that I can use key presses such as "Alt-Tab" and display a mock app switcher, etc. The app already runs in full screen, but it is still possible to have the underlying Windows GUI pop back up. I am essentially replacing explorer.exe with my own mock up explorer. Upon closing my custom explorer, I can't seem to get the regular Windows GUI to come back by launching explorer.exe via Process.Start();.
From here:
Try
Process.Start(Path.Combine(Environment.GetEnvironmentVariable("windir"), "explorer.exe"));
It appears you must specify the full path to explorer to get the taskbar back.
From here:
Explorer must see some fulfilled conditions to launch as shell:
Explorer must not run (which includes Control Panel, for instance)
Explorer must see it is the actual shell - hence you need to replace that value before launching explorer.exe (could change it back a few seconds later)
Sometimes it seems (on newer Windows versions) it depends on the process that launches explorer.exe - if it is "known" to explorer.exe -- I don't have any more details for this part though (and you couldn't change it, unfortunately)
Is there anyway to find what kind of window is opened on the desktop in real time?
It may need C# or C++. What I have found right now is to use C# Process.GetProcesses() method to find the opened windows on desktop.
But the output cannot be changed when the users have opened any new windows. So, is there any method I can use to track the opening windows in real time?
Also, is there any way to track the mouse movement on a specific window by using our web service?
Many many thanks!
I do agree with tnw that this sounds sketchy (possibly an example would be useful to help here). However, you want to look at the windows api calls:
GetForeGroundWindow
GetCursorPos
The first will only give you the current window, and not all open windows, but it sounds like this is what you really want anyway?
Source code to Windows keystroke logger that does this (in C++): http://16s.us/16k/
Edit: It shows the open window the user is typing in (in real time), but not all open Windows, only the active window in use.
Is it possible to run applications on the Windows Desktop? I mean... that it can only be seen in the system tray, and it should be able to run alongside the desktop.
I have no idea how to code it, please help me. I'm kind of new to these things, I am supposed to create something like a "Stardock Fence".
I have seen some examples, but they seem buggy, any strong alternative I could use?
Process.Start() can be used to start a windows application/console app from another win application. There are parameters that allow you to optionally hide the UI as well.
You want your application's windows to be always-on-bottom. In other words, your UI will always appear to be beneath any other open window and just above the Desktop's icons.
To accomplish that, see these related questions.
Once you have a window always on the bottom of the z-order, you'll probably want to remove the non-client window chrome (titlebar/min/max/close buttons) so that your UI can look like a more integrated part of the Desktop. There's plenty of examples around; Googling is left as an exercise for the reader.
Not entirely sure what you mean by background. I expect you mean a Windows Service which is a project type in visual studio, or you might (less likely) mean running a background thread.
Actually, if you want it in the system-tray, you don't want it entirely in the background.
If it was to be fully "in the background", then your best bet is to have it as a service.
System tray icons need a window, but you can just make it non-visible and non-taskbar and that's fine.
A common combo is a service that does the actual heavy-lifting, and a hidden-window application with a systray icon that reports on the service's status (possibly making that same window visible when further interaction is needed).
You want to run your application in the background? Is it on a windows machine? If so then you want to look into running your application as a windows service. Here's an msdn link:
Introduction to Windows Services
There's examples in the article I think - if not it's a good starting point. You can configure services to start automatically on startup of the machine etc. Your application will then run in the background.
Basically you craete your application as normal and then host it in a windows service rather than say a console app or a winforms app.
I have a windows form application which needs to be the TopMost. I've set my form to be the TopMost and my application works as I'd like it to except for in one case.
There is a 3rd party application (referred to as player.exe) that displays SWF movie files on a portion of the screen that popup on top of my application.
Using Process Monitor I determined that player.exe application calls
flash.exe <PositionX> <PositionY> <Width> <Height> <MovieFile>
in my case:
flash.exe 901 96 379 261 somemovie.swf
Since flash.exe is being spawned in a new process after my form has been set to the TopMost it is appearing on top of my application.
First thing I did was make my application minimize the player.exe main application window hoping that this would prevent the Flash from appearing also. But, unfortunately it doesn't... even with the window minimized whenever the flash movie starts it shows up at the pixel location (901,96). I then tried creating a timer to keep setting the form.TopMost property to true every 10ms. This sort of works but you still see a very quick blip of the swf file.
Is there some type of Windows API call which can be used to temporarily prevent player.exe from spawning child processes which are visible? I admit it sounds a little far fetched. But, curious if anyone else has had a similar problem.
Addendum:
This addendum is to provide a reply to some of the suggestions layed out in Mathew's post below.
For the emergency situation described in the comments, I would look at possible solutions along these lines:
1) How does the third party application normally get started and
stopped? Am I permitted to close it
the same way? If it is a service, the
Service Control Manager can stop it.
If it is a regular application,
sending an escape keystroke (with
SendInput() perhaps) or WM_CLOSE
message to its main window may work.
Easiest way to close the app is to CTRL-ALT-DEL, then kill process. -OR-
The proper way is to Hold ESC while clicking the left mouse button... then input your username and password, navigate some menu's to stop the player.
There is no PAUSE command... believe it or not.
I don't think using WM_CLOSE will help since minimizing the application doesn't. Would that kill the process also? If not, how do you reopen it.
2) If I can't close it nicely, am I permitted to kill it? If so,
TerminateProcess() should work.
I can't kill the process for two reasons. 1) Upon relaunch you need to supply username/password credentials... There may be a way to get around this since it doesn't prompt when the machine is rebooted but... 2) Whenever I kill the process in task manager it doesn't die gracefully and asks if you want to send an error report.
3) If I absolutely have to leave the other process running, I would try
to see if I can programmatically
invoke fast user switching to take me
to a different session (in which there
will be no competing topmost windows).
I don't know where in the API to start
with this one. (Peter Ruderman
suggests SwitchDesktop() for this
purpose in his answer.)
I got really excited by this idea... I found this article on CodeProject which provides a lot of the API Wrapper methods. I stopped implementing it because I think that in order for desktop's to work you must have explorer.exe running (which I do not).
EDIT2: On second thought... maybe explorer.exe isn't needed. I'll give it a try and report back.
Edit3: Was unable to get the code in that article working. Will have to put this on hold for a moment.
Answer Summary
As one might have expected, there is no simple answer to this problem. The best solution would be to problematically switch to a different desktop when you need to guarantee nothing will appear over it. I was unable to find a simple C# implementation of desktop switching that worked and I had a looming doubt that I would just be opening a whole new set of worms once it was implemented. Therefore, I decided not to implement the desktop switching. I did find a C++ Implementation that works well. Please post working C# virtual desktop implementations for others.
Setting the TopMost property (or adding the WS_EX_TOPMOST style to a window) does not make it unique in the system. Any number of topmost windows may be created by any number of applications; the only guarantee is that all topmost windows will be drawn 'above' all non-topmost windows. If there are two or more topmost windows, the Z-order still applies. From your description, I suspect that flash.exe is also creating a topmost window.
Aside from periodically forcing your window to the top of the Z-order, I think there is little you can do. Be warned, however, that this approach is dangerous: if two or more windows are simultaneously trying to force themselves to the top of the Z-order, the result will be a flickering mess that the user will likely have to use the task manager to escape.
I recommend that your program not attempt to meddle with other processes on the computer (unless that is its explicit purpose, e.g. a task manager clone). The computer belongs to the user, and he may not value your program more highly than all others.
Addendum:
For the emergency situation described in the comments, I would look at possible solutions along these lines:
How does the third party application normally get started and stopped? Am I permitted to close it the same way? If it is a service, the Service Control Manager can stop it. If it is a regular application, sending an escape keystroke (with SendInput() perhaps) or WM_CLOSE message to its main window may work.
If I can't close it nicely, am I permitted to kill it? If so, TerminateProcess() should work.
If I absolutely have to leave the other process running, I would try to see if I can programmatically invoke fast user switching to take me to a different session (in which there will be no competing topmost windows). I don't know where in the API to start with this one. (Peter Ruderman suggests SwitchDesktop() for this purpose in his answer.)
You can use the Process class to start flash.exe directly - and use an appropriate ProcessStartInfo settings to show the window in a hidden state - or with a WindowStyle of hidden or minimized.
You could also consider using the SetWindowsHookEx API to intercept the process start API calls, and when the process is flash.exe run some code to restore you window to top-most status.
Matthew's answer is excellent, but I suspect you may be asking the wrong question. Why does your application need to be topmost? If you're trying to create a kiosk or some such, then topmost is not the way to go.
Edit: After reading your response to Matthew's comment, I'd suggest creating a new desktop and switching to it before displaying your alert. (See CreateDesktop and SwitchDesktop in MSDN.)
I'm trying to find a way to get the open tasks in C#. I've been searching on google and can only find how to get a list of the processes. I want the only the tasks that would show up on the taskbar.
Also, along with that, it would be cool if I could get the process the task is associated with. And if possible get the thumbnail images that Vista uses for the ALT-TAB menu, like in this image:
I assume that I will have to use pinvokes because it really doesn't look like there are any libraries to do this already. Any ideas?
This article should pretty much tell you exactly what to do, it shows how to build your own task switch and includes the code needed to enumerate all windows and determine if they are "tasks" and it shows you how to use PrintWindow api to get the previews on XP.
http://msdn.microsoft.com/en-us/library/ms997649.aspx
Also, here is a blog post that talks about the algorithm used to determine what shows up in the Alt+Tab view. Basically you need to check the WS_EX_APPWINDOW and WS_EX_TOOLWINDOW along with if the window has an owner.
From an API (Win32) perspective there is no such thing as Tasks (at least not the one that Windows Task Manager/Alt-Tab shows).
Those "Tasks" are actually top level windows.
So in order to get a list of those, you need to enumerate the windows (here is the PInvoke for it).
Then look at the style of the windows to determine if they are actually top level windows.
I haven't tried it, but I suspect something like this:
using System.Diagnostics;
static void MyFunc()
{
Process[] processes = Process.GetProcesses();
foreach(Process p in processes)
{
if (p.MainWindowHandle != 0)
{ // This is a GUI process
}
else
{ // this is a non-GUI / invisible process
}
}
}
The point is to check each process for a WindowHandle.
#abelenky17
I suspect that this will not cover all cases, for example there are processes who have several top level windows (that all appear in the task manager).
Consider for example: FireFox, Windows Explorer, IE, etc... those applications can have multiple windows on the desktop.
Also, it will not handle Terminal Sessions scenario's properly (because you enumerate all the processes running in the system).
#Dan C.
Doing something like this:
p.ProcessName != "explorer"
seems ok to you? It smells, bad.