I've been messing around with some code, to allow for getting the Window Handle of a running process, and the handles of all child objects within it - e.g. running it against calc.exe gives the hWnd of calc, plus the handle of each button, etc, which is all straight foward enough. Alongside this, I'm using ProcessWatcher to watch for specific processes launching.
Now, where I'm having issues, is figuring out if it's possible to subscribe in some way, to be notified of the creation / deletion of Window Handles.
The intention is to use the 'new' Window Handle to get details about the object, and compare it to a list of items that the application should be watching for, e.g. the application would be sitting waiting for the notepad.exe process to launch, once it sees this process, it knows it should be watching out for a new window being created titled 'Save As', that is someone related to the notepad.exe process.
At the moment, the only way I can think of would be via a timer, after a short period, enumerate all Window Handles manually, sorting through them for what I want, but I'd imagine this would be very resource hungry, and inefficient.
Thanks in advance...
Related
I've written a WPF/C#-based "shell" which launches WPF apps or other apps.
What would be the best method for checking if the process is finally fully launched or no longer "busy"? I've noticed that the mouse cursor for the launched process stays at the busy cursor from initial launch until I can finally see the UI for the process. Could I use User32.SetCapture API to set the mouse capture to the external process, then somehow check if the mouse cursor is the busy cursor? Or perhaps there's a mechanism in the System.Diagnostics.Process class that I'm unaware of?
As some of the launched apps are pre-compiled third-party apps, I absolutely cannot implement a mechanism in the external processes to message if it is finally ready, such as: Microsoft PowerPoint 2010 Viewer, Adobe Acrobat, or Adobe Flash Player Standalone.
I can't just check if the process has been created, because then I have a blank, unresponding window and a busy cursor. I hope to hide my WPF app the moment the external process is done launching.
The WaitForInputIdle Win32 APi function will wait until given process enters the message loop (with no input pending).
Quote: "Before trying to communicate with the child process, the parent process can use the WaitForInputIdle function to determine when the child's initialization has been completed."
You can call it via P/Invoke.
Not very cear what do you mean saying "beasy", but hear are several considerations:
There is no known (clear) way, at least that I'm aware of, that can let you do something like that. The thing is that process is perfectly isolated OS kernel citizen. So you can not write something that works for all type processes, especially if they are 3rd part binaries.
What you can try to do, is get the MainWindow of the process (if there is any), get its handle, and filter OS messages untill you get for example WM_ACTIVATED.
But even if this could work in certain situations, in others can measurably fail. For example, process loaded but the program is not active, cause for some reason License window of the application appeared.
Let's see what others suggest, in my opinion, there is no generic and no single solution to cover minority of possible cases.
Good luck
I'm starting a external application with System.Diagnostics.Process, this external process at one moment opens up a dialog where user has type something and then click OK. What i need is to wait with my application(the one where i started the external process) until the user has inserted something and clicked OK. After that OK i have to do some more task on that external process and then close it.
Yes, it's possible. There are a number of ways to get window information starting with a process handle and/or ID. See this question and responses for getting started. You will most likely end up using P/Invoke to the Win32 API to get this accomplished but there are dozens of good examples for getting this done.
Once you have the window handle you can use a timer polling scheme to test for the presence, or in your case, presence and then the disappearance of a window.
This is possible but there are some work behind it. First you need to run your code as unmanaged code as you will need to hook on Windows OS events with the Win32 API.
So an option would be to have a loop looking for the dialog to open, pause what ever your code are doing and continue when the dialog are gone.
If the application you are starting exists after the user interacts with the dialog, then you can just call Process.WaitFroExit() and your code will not continue until the process you started has quit.
There are quite a few helpful functions for interacting with processes in the System.Diagnostics.Process class (that I assume you are using to start this external application)
When enumerating windows using EnumWindows, I get hundreds of handles instead of one per open window on my desktop.
First of all, i am curious if this is the correct behavior.
Secondly, trying to get a difference between open windows before and after launching a process returns 15-20 new handles. I am wondering if there is a way to filter these based on some flag, i really need just the mainwindow handle.
Any ideas?
To get the main window of a process, use the Process.MainWindowHandle property.
To answer your question, you can see exactly what all of the handles are using Spy++.
In short, many applications will create hidden windows to run message loops.
You can filter within the enum callback by checking IsWindowVisible() & ignoring invisible system/message sink windows.
This may be a long short or not even possible but no harm in asking.
What I am trying to do is monitor an application for any new windows it creates in its MDI control. I have implemented hooking in C# and can capture the MDICREATE window message but because I need to get information about the window after is has been created the MDICREATE message isn't much help because at that stage the window hasn't been created in the other application yet.
Without going into to much detail I just need to be able to see when a new window has been created.
Is this possible?
Thanks
I'm not aware of another message that gets the info that you are looking for off hand. But if that message works for you, you could hook that message and then do another scan of the windows to find the one you are missing. You can enumerate the child windows of the parent window. Use Spy++ to see the exact window hierarchy.
If you can watch for a particular function call, I would use some kind of hooking library to grab that (EasyHook comes to mind).
You can hook the MDI create function (assuming there is one), watch for that, then inn your code, call the original and do any lookups using the returned value. You'll have access to the returned value and any parameters, so you should be able to get some info out of those.
Two options off the top of my head.
Hook the WM_MDIACTIVATE event, the first time the window is being activated, use a flag to determine the first time the window is being activated.
If you need to run your code after the WM_MDICREATE or WM_MDIACTIVATE, you can post a new custom message from one of these messages, which is then handled after these messages have completed. You then write your code to handle the custom message.
I am trying to track visible windows from all currently running processes. My program interacts with these windows and the faster it can detect them the better. My goal is to move visible windows to a certain location on screen before they even draw in the default position if that is possible. If not I want to move them as quickly as possible after they are created.
Right now I enumerate through the visble windows using EnumWindows (p/invoked from user32.dll) in a loop with as small a delay in between iterations as I can justify.
I am looking for a method to hook into 'something' which will allow me to wait for a 'window opening up' event to fire instead of constantly polling.
Are there any methods to achieve this?
You need the SetWindowsHookEx() API function, setting a WH_SHELL hook. The callback gets a HSHELL_WINDOWCREATED notification when a new toplevel window is created.
This is a global hook, you cannot write the code for this hook in C#. It requires a DLL that can be injected in a process, the CLR cannot be initialized properly to support managed code. You'll need an unmanaged DLL to get the job done, this project offers one.