Perform Ctrl-C on specific window without focusing it - c#

I have an application to which I want to send the Ctrl-C keys combination. I am trying with SendMesssage, but I know that the application checks for Ctrl-C combination using GetKeyState and GetAsyncKeyState so SendMessage is pretty useless... How can I send the Ctrl-C combination to this window without calling SetForegroundWindow(hWnd)? I need a solution which works without focusing/bringing to front the window.
I am temporarily using this code (but requires focus):
SetForegroundWindow(hWnd);
SendKeys.SendWait("^(c)");
I am using C#, but C++ code is ok.

A long time ago, back when I was doing Sys Admin automation.. I used AutoIT. It's been a long time, but if you don't mind picking up their .dll...
This is the method I'd use.. it mentions you can send directly to a window/control without focus.. in some cases you can't..
AutoIT ControlSend Method

Related

Sending Commands to a Windowless Command Line process (started from the C# Application)

I've got a command line application that starts up and does some work. During that time, it listens to keystrokes (s => show status). It's not the typical command prompt where you press 's' and <ENTER> - it's the type which reacts as soon as the key is pressed the status is shown.
Now I'm trying to "control" that command line application from a fancy GUI application by sending keystrokes. I've tried the more conventional approach of writing to the Process' StandardInput but that doesn't seem to have an effect at all. Also, because the actual process doesn't have a window (it's started with CreateNoWindow=true) I can't try the Win32 API for sending keystrokes to a window.
Is there any other way of doing it?
Fancy console applications are problematic.
They have a tendency to directly read the keyboard input, instead of going through stdin. They also have a tendency to directly control their console, instead of going through stdout.
AFAIK, there is no way to programmatically control these apps. If you really, really need to, I would explore something like AutoHotKey controlling the app on a private desktop (AHK uses a virtual keyboard/mouse driver). I'm not sure how you would read the results off the console, though; it may be possible to create an intermediate console app that's started by your program (in the private desktop) and starts the target app. The intermediate app would then share its console with the target app and use low-level I/O to detect changes.
Or you could use Detours to bend the target app to your will.
Well, I seem to have found an answer to my own question.
It's a real "kludged together" solution, but it works - and for all the intents and purposes of the application I'm building, it doesn't matter.
So, what I did was use two WinAPI functions called
static extern bool ShowWindow(IntPtr WindowHandle, int nCmdShow);
static extern bool SetForegroundWindow(IntPtr WindowHandle);
The first one can be used to Show/Hide a window by changing nCmdShow to 1 and 0 respectively. The other one puts the window (determined by WindowHandle) to the front. Combining these two together, I was able to programmaticly bring the console window up front, do a simple SendKeys.Send(); operation and then hide it again.
// Use a WIN API command to bring the command line to front
SetForegroundWindow(workerProcess.MainWindowHandle);
// Send a keystore to re-display the STATUS of the worker
SendKeys.Send("s");
// Hide the window again.
ShowWindow(workerProcess.MainWindowHandle, 0);
Now, it's a real kludge job, but it gets the job done. One potential pitfall would be if a user is using the computer for something else, and would nail that 1 in a 10000000 moment when the window is active with a 'q' - it would quit the worker program. But the application is intended to be used on dedicated machines that most likely won't even have monitors, keyboards or mice attached to them so it wouldn't be an issue.
Thanks to all who answered, since you did - in one way or another, steer me towards the right solution.
I found an even better way to accomplish the functionality without the theoretical risk of causing problems with simultaneous user input and window-switching.
The trick is to use the WinAPI functions called PostMessage to send up KeyDown (or KeyUp) message to the process which does the same thing. No need to bring the process window to the front and hide it immediately afterwards!
I'm sending the key-down command with key 'S' as the argument:
// 0x0100 - VM_KEYDOWN
// 0x0101 - VM_KEYUP
// 0x53 - S-key
PostMessage(workerProcess.MainWindowHandle, 0x0100, 0x53, 0);
PostMessage(workerProcess.MainWindowHandle, 0x0101, 0x53, 0);

SendInput to minimized window

Is it possible to utilize the sendInput function on windows that currently do not have focus, and maybe through the use of multithreading, sendinput to multiple minimized windows at the same time, or send input to one window while you're working on another window?
I'd like to do something like this in c#
thanks in advance.
You can only use SendInput to send input to the HWND with keyboard focus. Furthermore the window must be attached to the calling thread's message queue, so one cannot simply SetFocus either.
You'll need to get the window's thread id with GetProcessIdOfThread.
When you have the thread id you can use the AttachThreadInput function to attach your thread to the other threads input processing.
After all this you can probably use SetFocus and SendInput.
You'll probably want to detach your thread when you've sent your input.
To get access to these method you'll have to use P/Invoke for C# or C++/CLI. PInvoke.net is very handy as a reference. It will be a small chore importing all those functions, but when you are done you should be able to send input to whatever "window" you want.
Also as a side note, I'm not sure if you are aware of this, but in pure Win32 everything is regarded as a window, even a button. If you are unlucky you may have to send the input to the handle of the text control belonging to the notepad application.
That is not possible with SendInput. What you probably want to do is find the messages that were sent to the window by the OS when that particular event was performed then emulate them. You can use Spy++ to attach to the target window and perform your event. Then use SendMessage() and PostMessage() to reproduce the messages that were generated by your event. This will work fine for notepad.
If you do use this method, note that you need to send messages to notepad's child window which you can find with FindWindowEx() with a classname of "edit". For example to type text you could try WM_KEYDOWN. You should note that this method is not necessarily reliable:
http://blogs.msdn.com/b/oldnewthing/archive/2005/05/30/423202.aspx

Mouse hook with C#

I am trying to emulate "hardware" mouse clicks as it appears that some software blocks input from PostMessage for instance. I know there's SendInput, but that's not an option as I need this to be compatible in background windows as well. The solution seems to be a low-level mouse hook but I've searched around and couldn't find anything other than just the loggers, no manipulation of moving mouse, clicking etc. I'd like this to happen without having to write some sort of C++/C wrapper to use as a fake mouse driver.
http://support.microsoft.com/kb/318804, I found this but it doesn't seem to be of any further help.
Any help appreciated :)
Not sure what 'some software' might be, but sure, UAC stops you from poking messages into the windows of elevated programs. It is called UIPI, User Interface Privilege Isolation.
In general, faking input with PostMessage doesn't work well at all. It is especially a problem for keyboard input but mouse input has trouble too. There is no good way to alter the keyboard state for another process. That matters when the program checks the state of the Shift, Ctrl and Alt keys when it processes the input message. Many do.
The only real solution is to emulate input with SendInput(). Now you got a focus problem to solve.
mouse_event or SendInput used to inject mouse input. But just like a real mouse it's global input and can't work on hidden windows.
A low-level-mouse-hook is global too, but it is used to intercept and manipulate mouse-input, not to inject input.
When targeting a specific window you'll need to use SendMessage, but as you noted it doesn't work for everything.
You can also use dll hooking(for example an IAT hook) to intercept calls to APIs which return the gobal cursor position or the state of the mousebuttons. But for that you need to inject a dll into the target application, and that dll shouldn't use .net.
When I have to simulate mouse input I first try with SendMessage but sometimes some control or the application could eat the message.
In that situations I use spy++ to intercept messages of the window that holds the control, I do exactly what I want to simulate and then, I just use:
GetWindowLong(hwnd, GWL_WNDPROC);
to get window proc and then call the wnd proc(process) directly with:
CallWindowProc(WNDPROC lpPrevWndFunc, HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
Sending exactly those messages that I saw using Spy++. That always work because the window proc is called immediately instead of queued in the message loop.
Take a look at this library http://globalmousekeyhook.codeplex.com/.
It is 100% managed c# code to install global mouse and keyboard hooks.

FindWindow doesn't return IntPtr.Zero, although the window is already closed

I'm trying to control a Java application from my C# program. Before the program begins to input data, it checks if there are any pervious data input windows, and tries to close them.
The code for checking if a window exists is:
public static bool WindowExists(string WindowName)
{
IntPtr hWnd = FindWindow(null, WindowName);
return (hWnd != IntPtr.Zero);
}
Until now, I simply used this method in a while loop (sending Alt+F4 to the windows), until there was no open input window left.
A while ago the Java application got an update, and this method no longer works. For some reason, WindowExists keeps returning true, even after the data input window is closed. This only happens if the input window existed at least once.
I even tried to add Thread.Sleep() to the loop, to make sure this isn't caused by some latency in the Java app, but it didn't work.
Sometimes simply calling WindowExists crashes the input window.
There's no problem with the code, because it has worked before, and it still works with other programs, so it must be a problem with the update in the Java program.
Is there any alternative/more reliable way to check if a window exists?
Changing sending Alt+F4 to "close window event" might also worth a try, but I have no idea how to send this event to another program's window.
I'm a newbie, so please keep the answer simple.
Thanks in advance.
I would use Spy++ to watch the window handle of the Java app, and see if you can figure out what else is going on - I agree there has to be a way to tell that it is closed.
I assume watching the process list is out of the question...
I would hazard a guess that whilst the Java app is running and consequently, the JVM, the 'handle' to the window has not yet been garbaged collected and as such appears to the underlying pointer mechanism as still being valid.
If it was me writing that stuff (and if I was able to change the Java code) I'd probably add a means of querying the java app to see if its windows are showing.
A sockets interface or something.
My guess is that either the window hasn't been completely disposed of by the Java code/VM, or it's handling Alt+F4 in some special way (i.e. maybe making itself invisible rather than closing).
Creation/deletion of windows is out of your control. If you want to reliably detect the presence of 'someone else' using the same resource a you want, have that other party communicate it explicitly.
The other party may signal it's presence by creating a file, opening a port, whatever, and can release/delete/close it on it's exit.
Try to make additional check using IsWindow API, on hWnd value returned by FindWindow.

Emulate Key Presses On an App that takes no Win Messages

I want to send an Application Key Presses, To Automate some stuff that has to be done repeatedly and So I don't always have to cramp my fingers.
In C#, it's nice to use SendKeys.Send(), but this won't work because the Application doesn't take Windows Messages. SendKeys.SendWait() does nothing at all.
How would I STILL Simulate the Keyboard events?
Come To Think of It, I was going to use some P/Invoke to simulate Mouse Events too, but If it takes no messages, How Can I get around that?
EDIT - I can use mouse and keyboard to interact with the program, I just cannot manipulate it with Windows Messages sent from my own Code.
Have you tried AutoIt?
Is it a console app? If so, maybe you should be SendKeys'ing to the command shell instance it is running in.

Categories

Resources