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.
Related
We have a simple launcher.cmd script that sets up some prerequisites (network shares, configuration files etc.), depending on command-line arguments, and then starts a third-party application.
It also launches a custom splash screen (Windows Forms application), but that doesn't have any functionality beyond the splash screen. The external application also contains a plugin that we have written.
Imagine something like this:
set appEnvironment=%1
MyCustomSplashScreen\MyCustomSplashScreen.exe %appEnvironment%
net use X: /delete /yes
net use X: \\someserver\%appEnvironment%
copy Configuration\%appEnvironment%.config ExternalApp\ExternalApp.MyPlugin.config
start ExternalApp\ExternalApp.exe
It is invoked like this:
launcher.cmd Production
The challenge we are facing is that some users pin ExternalApp.exe (the actual application, after launcher.cmd and the splash screen have terminated) to the taskbar. The taskbar shortcut then launches ExternalApp.exe directly and not our launcher script - so all kinds of strange things can happen.
As we have control over the plugin, it would be possible to move some of the logic directly into ExternalApp.exe, but that wouldn't solve the issue of losing the environment parameter. The best solution I can come up with would be different ways of making sure the application can only be launched via the launcher script, essentially making it useless for the user to pin the application to the taskbar.
However, I have thought about being a little more creative. I am planning to do the following:
Move the launcher.cmd logic into MyCustomSplashScreen.exe
In MyCustomSplashScreen.exe, start ExternalApp.exe and make it a docked child window (cf. Docking Window inside another Window ).
Instead of using a parameter, create copies (or links) of MyCustomSplashScreen.exe that reflect the environment, e.g. Launch_Production.exe, Launch_Staging.exe etc.
The consequence would be that only MyCustomSplashScreen would appear on the taskbar and be pinnable. Pinning the application would result in the application specific to that environment (e.g. Launch_Staging.exe) being pinned, just what the user expects.
I am quite confident that this would work. But maybe there is a simpler solution? What I'm looking for is some way to make only my launcher application on the taskbar and not the application it launches.
I found similar questions here and here where it was suggested to manipulate the pinning process itself. Maybe that's a better solution? I'm just not sure if my plugin has enough control over ExternalApp.exe to implement this, so would need to test it.
The solution from Control path to pinned exe in Windows taskbar and start menu works just fine.
I put something like this into my plugin and it does exactly what I want:
private static void SetTaskbarRelaunchCommand(string environment)
{
// WARNING, once RelaunchCommand has been set it can't be changed for any given appID.
// Workaround: delete all links here related to our app.
// %AppData%\Microsoft\Internet Explorer\Quick Launch\User Pinned\ImplicitAppShortcuts
// %AppData%\Microsoft\Internet Explorer\Quick Launch\User Pinned\TaskBar
// Source: https://stackoverflow.com/a/28388958/33236
const string appID = "MyAppID";
string path = $#"C:\Launcher.exe {environment}";
IntPtr windowHandle = Process.GetCurrentProcess().MainWindowHandle;
var propGuid = new Guid("{9F4C2855-9F79-4B39-A8D0-E1D42DE1D5F3}");
var id = new PropertyKey(propGuid, 5); // System.AppUserModel.ID
var relaunchCommand = new PropertyKey(propGuid, 2); // System.AppUserModel.RelaunchCommand
var relaunchDisplayNameResource = new PropertyKey(propGuid, 4); // System.AppUserModel.RelaunchDisplayNameResource
WindowProperties.SetWindowProperty(windowHandle, id, appID);
WindowProperties.SetWindowProperty(windowHandle, relaunchCommand, path);
WindowProperties.SetWindowProperty(windowHandle, relaunchDisplayNameResource, $"My App {environment}");
}
It seems like the original version of the Windows API CodePack published by Microsoft in 2009 is no longer officially available. Instead there are a dozen inofficial NuGet packages that (claim to) contain the original library, as well as some where bugs have been fixed.
I ended up using this NuGet package as it seems to be actively maintained.
Of course I am in the fortunate situation that I could manipulate the behavior of the external application through my plugin. Without this, there probably is no other solution than running the application as a docked child window.
UPDATE: It seems like there is another way to achieve thisn when you cannot control the application you're launching. You simply set the System.AppUserModel.Id for the launched application's window. More details here.
I wasn't successful in setting the RelaunchCommand and the RelaunchDisplayNameResource on the newest Windows 10 update. But i have found another possibility to set that the Launcher is pinned to the taskbar: Pinning to the taskbar a "chained process"
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.
I am writing a windows service that I would like to run as a scheduled task.
On Start I want it to read in the chrome processes and kill any that have a particular url..
I can get the processes using
var list = Process.GetProcessesByName("chrome");
but after that I am stumped..
The MainWindowTitle of each process is "" and the MainWindowHandle is 0 so doesn't help me.
I have read numerous posts related to this and it seems there is no api into chrome so am I wasting my time?
Any help appreciated
J
If you look at spy++ you can see that you can find root windows that do have their Caption set to the html page title. Also a child window is the url bar so if you enum the child windows of all the chrome windows you uld be able to find it.
sho
While it is possible to do this, I wouldn't recommend it. Injecting yourself in to other processes and reading their contents can cause unpleasant behavior and is hard to get completely correct, but if I was going to try this, I would use the UI automation tools provided by MS (http://msdn.microsoft.com/en-us/library/ms747327.aspx), or White (http://teststack.github.io/White/). Those are going to be the best bets.
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();
I'm currently working on an access control program in C# and I've come across the problem of blocking windows. The original idea I've come up with is rendering a plain black form over the position given by the IntPtr window handle of the process. The problem within that is updating the form's position smoothly and z-index of the position (being I don't want it topmost). I've also noticed a ridiculously high resource use with my solution as I was using a loop to constantly check position.
Thus why I ask: What would be the best solution for this without eating major resources? The entry point is merely the name of the running process.
Presently the idea is only blocking off browsers (IE: a school application to prevent distraction when a lecture is active).
More Information:
I'm not looking to close a window in
my own application, I'm trying to
obscure windows from other processes.
My application is not a
virus/annoying program, it's
essentially meant to prevent uses of
potentially distracting applications
in a school environment. It's made
for lectures in a school computer
lab.
I'm presently pulling the main window
from the process caught by the
process name of browsers.
I can't completely disable the computers either.
I really hate hate hate any application trying to mess around with other application's windows. Sorry, this comes from very deep.
The only thing I can think of that is somewhat sensible is to lock the current user session, and swith the computer to another desktop belonging to another account with no rights to do anything except what's required under the circumstances.
Or if it is acceptable to disable the use of the computers entirely, you could put all the monitors on a single power switch on the teacher's desk.
If you are looking to hide your application window, I can suggest 3 things. First thing, try setting your form's visible property true and calling the hide() method. Second thing is to set your form's transparency to 100%, which will hide it. The third is, maybe consider your application should be a windows service instead of a windows form application.
If you are looking to hide other windows so that your application is always on top, set the TopMost property to true in your form: http://msdn.microsoft.com/en-us/library/system.windows.forms.form.topmost(VS.71).aspx
This might help too: http://www.codeproject.com/KB/cs/windowhider.aspx
[DllImport("user32.dll")]
static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
static void MinimizeProcess(string procName)
{
foreach (Process p in Process.GetProcesses())
{
if (p.ProcessName == procName)
{
ShowWindow(p.MainWindowHandle,11);
}
}
}
If you have an array of process names you'd obviously want to refactor this to take in an array so that you're not looping through every process for everything you want to minimize, but you get the idea.
You could use the windows api to hide the offending window. user32.showwindow
Not exactly what you've asked for, but might be simpler.
You can do:
this.Hide()
this.Visible = false;
Or if this is the main for you dont want to show, simply dont run the forum when you start the app.