I want to write some code, that can automatically do actions on active windows.
For example, if i want to press the ignore button once the window that pops if I insert a new DOK.
i thought of a code that once a specific (known) window pops, it presses a few TABs, and presses Enter.
Can I implement such a code? preferrable in C#.
I thought of several answers to your question because it isn't clear what you are asking. One of these topics might be an area for research:
If you want to press keys for the active window in an application other than the one you are running, you might read about elevated privileges, interprocess communication, and accessing the keyboard with Windows function calls. You can not normally do anything to other applications other than to cause Windows to send it various messages. Thought: how will you indicate when the press the keys if your application is not the active window?
If the active window is one within your application, then you will be better off in the long run by finding a solution that fits C#'s object-oriented model. If you want certain code to be run at times for certain windows (when one is active), you can share code by putting it into a common superclass and having your window classes inherit it. Looking at it this way will be instructive, but you may have to find a somewhat different solution, since it sounds like your window should be inheriting Window's Window class (you can only have one parent class in C#). You could look up "class inheritance" and perhaps "interfaces."
Another solution that isn't so object-oriented for sharing code is to put it into a static function and call this function as needed in the code of your active windows. But ideally, it is code in the active window class that should be manipulating the window. You can put it into a function and then call the function from anywhere in the application that has the "this" reference for the active window.
Related
I'm currently using a delegate to poll the current active control from the currently focused external form every few milliseconds, which works badly.
The title of the question is somewhat confusing, as this does not actually have anything to do with Application.OpenForms. That property just exposes a collection of all the currently open forms. If a new form is opened that had not previously been opened, it will be added to the collection. But the operating system allows only one active window at a time on the desktop, so what you really want is to get notified when the active window changes. Polling will work for this, but it isn't a good solution.
You will either need to install a global hook (WH_CBT is likely the one you want), or take advantage of the WinEvents infrastructure (via the SetWinEventHook function) intended for accessibility tools. Both of these will provide you with a notification when the active window changes. Of course, their scope won't be limited to the application that you are testing. You'll get notification when the active window on the desktop changes to any other window. It will be up to you to filter that down to the application you care about.
I don't have time at the moment to translate any of the required code to C#/.NET, but you can probably find it somewhere online, once you know what to search for. Additionally, WinEvents is already wrapped for you in the System.Windows.Automation namespace.
In my WPF application, I have multiple classes each of which implements a message loop. All of these message loops then run in parallel when I create objects of these classes. These objects may show a dialog box at times. The main application thread must keep an eye on these objects and make sure none of them is stuck with the dialog (and press Cancel (Escape key) if it determines such cases). What is the correct way to determine the active foreground window of a thread? I know there is a GetForegroundWindow() API, but it appears as if it works at system level and not thread level.
There's no such thing as the per-thread active foreground window. So what you are explicitly asking for does not have an answer.
Probably the right way to go here, using Win32 at least, is to enumerate top-level windows with EnumWindows. Then use GetWindowThreadProcessId to identify that the window is associated with one of your threads. Finally use GetClassName to identify that the window is a file dialog. Then feel free to do whatever dastardly thing it is you want to do to the window!
On the other hand, this sounds like a perfect candidate for UIAutomation. You are automating testing of UI. UIAutomation will be able to find these file dialog windows and press buttons on them.
I'm having a bit of a trouble trying to create a multi window'ed console application. Currently, my application's main console window is used to collect user input and display output.
Much of this output comes from a separate thread, as live data comes in. I was wondering if there is a way for me to separate my application into two windows, where the second window was either a console window or even any other kind of window that could display the text of the incoming strings... In particular, the main console window would be where the user input commands etc, and the second window displayed what the system was currently working on. This second window could be entirely readonly.
Any suggestions would be greatly appreciated! I would post code, but I don't really have anything relevant (that I can think of) to post....
This will be hard to do.
Here is answer for similar question: Can you have multiple .net Consoles (as in Console.Writeline)
If you really want to do it, you can find logic here: http://www.codeproject.com/KB/cpp/MultipleConsoles.aspx
Maby better approach will be to start another process (console app) and communicate between them thru IPC ( Interprocess communication ) - like named pipes .
More about IPC you can find: http://www.infoq.com/news/2008/01/wcf-comm-options
It is probably easier to just pop-up a Windows Form with a TextBox containing the data you wish to show. You can simply start a new thread and call Form.ShowDialog() to get the form to show.
I am developing a (in-process) plug-in to application and as part of my plug-in I want to replace the application's tool-tips with my own. However, there is no API available for me to do so, so I've decided to go low-level.
I know the window class of the tool tip, but the question is, how do I detect it being created and how do I close it afterward?
Here's what I thought to do so far:
Create a system-wide hook on WM_CREATE
When caught, check the class and the process of the WM_CREATE target
Verify it is indeed the window I care about:
If the process is the one my plug-in is sitting in
And if the class is of the correct type
And if the correct application is in focus (in case of multiple applications)
Send a WM_DESTROY to the created window and create my own window at its position instead
How does it sound? Assuming there is indeed no API to handle the tooltips, is there a simpler way for what I need?
Thanks!
P.S Tagged as C++/C# as I intend to write it in these 2 languages (C++ for system-wide hook, C# for everything else)
If you know the type of the window you want to block, you can simply subclass it and handle the destruction in your own WndProc. Use GetClassLongPtr() with GCL_WNDPROC on the tooltip class, use SetClassLongPtr() with GCL_WNDPROC to set your own WndProc and have it call DestroyWindow() on WM_CREATE and call the old WndProc for the rest..
This won't work. Consider the view of the application that you're replacing the tooltips of and assuming that you could tell it to destroy windows. What will happen when the app decides that it needs to close the tooltip? It doesn't have the handle of your new window, it has the handle of the old window, which you've destroyed. Time for things to go wrong.
Your plugin system needs to explicitly support replacing the tooltips if you want this to work smoothly. Perhaps an optional part of the plugin framework could be a RequestTooltip function. If it doesn't exist, or returns null, or whatever then the default tooltips are used, otherwise your plugin provided ones are used.
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.)