I am working on VS 2010 Ultimate. I have created a simple console application about 25-30 rows. So I want in the Main() function simply to simulate pressing "ALT+TAB" in a while cycle. Hoh can I do that - I cant use SendKeys class cause it "Provides methods for sending keystrokes to an application." I want just when I start my console application to simulate 1000 times pressing "ALT+TAB" without attaching it to anny applications. Something like this:
using System;
using System.Windows.Forms;
namespace nagradite
{
class Program
{
static void Main()
{
int i = 1000;
while( i > 0 )
{
// PRESS "ALT+TAB"
i--;
}
}
}
}
what should I type instead of // PRESS "ALT+TAB"
Use "%{TAB}" for Alt+TAB
SendKeys.Send("%{TAB}");
SendKeys.Send("%{TAB} 1000"); //if you want to do same by 1000 times as you stated
Reference http://msdn.microsoft.com/en-us/library/system.windows.forms.sendkeys.send.aspx
I think you can use SendMessage for finding keys you can see http://www.blizzhackers.cc/viewtopic.php?t=396398, your parent window is null (desktop)
[DllImport("user32.dll", CharSet = CharSet.Auto)]
static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, IntPtr lParam);
You can try a Win32 API called SendInput. It allows you to simulate keyboard/mouse input events and does not require a HWND target. However, I don't know if this will actually trigger system-wide keyboard shortcuts such as ALT+TAB.
MSDN - http://msdn.microsoft.com/en-us/library/ms646310(v=vs.85).aspx
PInvoke.Net - http://www.pinvoke.net/default.aspx/user32.sendinput
Related
Both the callback and the AccessibleObjectFromEvent call appear to be working as intended, and I'm not using any locking mechanisms, but if AccessibleObjectFromEvent is present in the callback the winforms form will occasionally lock up.
I noticed when it freezes it has this odd property where right-clicking on its taskbar icon unfreezes it.
Pausing with the debugger just takes you to Application.Run(new Form1()), and nothing appears blocked on the .Net side - the debugger's window updates can even trigger some Active Accessibility events and then let you step through those events in the callback - working - all while the form remains frozen!
I note that AccessibleObjectFromEvent works by sending a WM_GETOBJECT message, but the .Net side is never stuck at the AccessibleObjectFromEvent call, and calling AccessibleObjectFromEvent from inside a SetWinEventHook callback is AFAIK a normal way to do Active Accessibility.
I've not noticed any correlation with Active Accessibility events when it freezes, but I don't really have enough information to rule that out. I also tried it compiled x86 (instead of Any), and that made no difference.
I boiled it down to its most minimal form:
using Accessibility;
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Windows.Forms;
namespace WindowsFormsApp1 {
static class Program {
// PInvoke declarations, see http://www.pinvoke.net/default.aspx/user32.setwineventhook
[DllImport("user32.dll")]
static extern IntPtr SetWinEventHook(uint eventMin, uint eventMax, IntPtr hmodWinEventProc, WinEventDelegate lpfnWinEventProc, uint idProcess, uint idThread, WinEventFlag dwFlags);
public delegate void WinEventDelegate(IntPtr hWinEventHook, uint eventType, IntPtr hwnd, int idObject, int idChild, uint dwEventThread, uint dwmsEventTime);
[DllImport("oleacc.dll")]
public static extern uint AccessibleObjectFromEvent(IntPtr hwnd, uint dwObjectID, uint dwChildID, out IAccessible ppacc, [MarshalAs(UnmanagedType.Struct)] out object pvarChild);
[Flags]
public enum WinEventFlag : uint {
/// <summary>Events are ASYNC</summary>
Outofcontext = 0x0000,
/// <summary>Don't call back for events on installer's thread</summary>
Skipownthread = 0x0001,
/// <summary>Don't call back for events on installer's process</summary>
Skipownprocess = 0x0002,
/// <summary>Events are SYNC, this causes your dll to be injected into every process</summary>
Incontext = 0x0004
}
static IntPtr hookHandle = IntPtr.Zero;
static GCHandle garbageCollectorHandle;
static void AccessibilityEventHandler(IntPtr hWinEventHook, uint eventType, IntPtr hWnd, int idObject, int idChild, uint dwEventThread, uint dwmsEventTime) {
try {
object objChild = null;
IAccessible accWindow = null;
AccessibleObjectFromEvent(hWnd, (uint)idObject, (uint)idChild, out accWindow, out objChild);
Debug.WriteLine("Hook was invoked");
} catch (Exception ex) {
Debug.WriteLine("Exception " + ex);
}
}
[STAThread]
static void Main() {
WinEventDelegate callback = new WinEventDelegate(AccessibilityEventHandler);
// Use the member garbageCollectorHandle to keep the delegate object in memory. Might not be needed, and can't properly pin it because it's not a primitive type.
garbageCollectorHandle = GCHandle.Alloc(callback);
SetWinEventHook(
0x7546, // eventMin (0x7546 = PropertyChanged_IsOffscreen)
0x7546, // eventMax
IntPtr.Zero,
callback,
0,
0,
WinEventFlag.Outofcontext
);
// Two hooks are not necessary to cause a freeze, but with two it can happen much faster - sometimes within minutes
SetWinEventHook(
0x0001, // eventMin (0x0001 = System_Sound)
0x0001, // eventMax
IntPtr.Zero,
callback,
0,
0,
WinEventFlag.Outofcontext
);
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
}
}
With such a minimal app it's harder to notice the message pump freeze, but you won't be able to drag the window or bring it to the foreground once it's locked. The bug is intermittent, often it happens within 5 minutes, sometimes it takes so long I give up, if you leave it overnight and the form is still responsive in the morning then it might depend on machine/OS (tried on Win 10.0.17174 and 10.0.17763, .net 4.5.2 and 4.6.1).
I'm 99% sure the call to AccessibleObjectFromEvent is required for the app to freeze, but with intermittent freezes there's no way to absolutely know for sure.
Reentrancy
Following Jimi's suggestions in the comments, I ran the minimal app with the flags
WinEventFlag.Outofcontext | WinEventFlag.Skipownthread | WinEventFlag.Skipownprocess
It took a while to freeze, but has still frozen. The Debug.WriteLine() calls indicate it's still responding to Active Accessibility events normally - i.e. no recursive busy-loop is happening through that callback (at least not now that I'm looking), but the form is frozen. It's using 0% CPU in the task manager.
The freeze is slightly different now, in that the task manager doesn't list it as "not responding" and I can bring it to the foreground by left-clicking the taskbar icon - normally the taskbar can't even bring it to the foreground. However the form still can't be moved or resized, and you can't bring the form to the foreground by clicking on it.
I'd also added some Debug.WriteLine in front of the AccessibleObjectFromEvent call, and tracked reentrancy depth, I can see that it is occasionally reentrant, but usually to a depth of only one before unwinding, and no deeper than 13 before fully unwinding. This appears to be caused by there being many events already in the message queue, rather than the hook handler recursively causing events it must then handle. The UI is currently frozen and the hook handler is 0 deep (i.e. not currently reentrant).
I've been using SendMessage to send mouse clicks to a couple of windows. One being a game(everything works perfectly), but the other window, being a 3rd party tool for the game is having trouble with SendMessage. If the window is 'not minimized' everything works fine, don't matter if window is completely covered up by another. But if that same window is minimized then nothing happens, I checked with spy++ and the messages are indeed getting received but not being processed (correct term?). I've tried to solve this last couple days, doing both searches on here and Google alike, many of topics but nothing helped?
//MyImports
[DllImport("user32.dll", CharSet = CharSet.Auto)]
static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, IntPtr lParam);
[DllImport("user32.dll", SetLastError = true)]
static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
And this is how I have it wrapped
public static void LClick(string windowclass, int x, int y)
{
IntPtr WHandle = FindWindow(windowclass, null);
SendMessage(WHandle, (int)WMessages.WM_LBUTTONDOWN, (IntPtr)1, (IntPtr)MakeLParam(x, y));
SendMessage(WHandle, (int)WMessages.WM_LBUTTONUP, (IntPtr)0, (IntPtr)MakeLParam(x, y));
}
I have tried focus, activate. One thing that might be useful info is that the third party program is being loaded as module("Qt5QWindowIcon") of the game.
I tried PostMessage as well, and it does the same thing as SendMessage() same problem when minimized.
This game does allow for macroing and unattended macroing, Hints the third part tool designed to execute the macros (published by the creators) I'm just trying to simulate a mouse click on the program to start the macro.
I would just use SendInput, but the entire purpose of my program is to run in background.
I 've faced same problem .Please change assembly name and project name (Changed name not started with name on that you are throwing/posting windows message)then rebuild it and check it. Now you will able to debug.
I'm trying to send a key to an application. I tested the Handlewindow value used breakpoints to understand what I'm doing wirong but i cant find a solution. To be more detailed, its a little game and when I activate the chatbar ingame, the key I want to send will be written there, but I want to make it functionaly when I am playing to use the commands. The game doesnt have a guard or some protections.
Here is my code:
[DllImport("user32.dll")]
static extern bool PostMessage(IntPtr hWnd, uint Msg, int wParam, int lParam);
const uint WM_KEYDOWN = 0x0100;
private void button1_Click(object sender, EventArgs e)
{
string pName = textBox1.Text;
//Get Processes
Process[] processes = Process.GetProcessesByName(pName);
//Main part
foreach (Process p in processes)
if (p.ProcessName == (string)pName)
{
PostMessage(p.MainWindowHandle, WM_KEYDOWN, (int)Keys.W, 0);
}
}
Like I said, it can be sent 1000000 times successfully but nothing happens.
Is there another way how I can send keys to an Windows application that works minimized or even hidden? It should be only send to my app.
If i understand correctly, you want to send keys to a game.
In this case i think that the game is not fetching the keys from the Windows Message queue, it is probably reading the keyboard status directly using DirectX or similar ways.
See this similar question:
Send Key Strokes to Games
You can't fake messages like this and expect it to work reliably - all you are doing is sending a message, nothing fancy.
What this means is that if the target program tests for input in a different way (for example by directly checking the key state, reacting to different messages or just using a completely different mechanism) the target program at best may just completely ignore your input and at worst get totally confused.
Use the SendInput function instead (I'm not sure if this exposed as part of the .Net framework or not).
Some interesting blog articles which are fairly relevant:
You can't simulate keyboard input with PostMessage
Simulating input via WM_CHAR messages may fake out the recipient but it won't fake out the input system
Just note that the correct import of PostMessage is:
[DllImport("user32.dll")]
static extern bool PostMessage(HandleRef hWnd, uint Msg, IntPtr wParam, IntPtr lParam);
Sending the keys like you are doing might not work, but you can use spy++ to capture the actual messages that are being posted to the application by windows and use those.
https://learn.microsoft.com/en-us/visualstudio/debugger/introducing-spy-increment?view=vs-2022
Often programmers will react to KeyUp events rather than down; did you try sending WM_KEYUP?
You should be using SendInput to simulate input into another window.
See this blog post for more details.
I want to add a KeyPress event on Application level which checks certain key combination whenever it is pressed.
If keycombination is matched. I want to open a window on the current window that is executing.
How can I do this.
Edit
I want to add KeyPress event on Application class so that it can capture key pressed on all the windows.
One way to do is, I can go to every Window and add event on each window.
But what if number of windows is large enough. this is what my scenario is.
So I was trying to do something on Application class to do the same work.
How can I do
Use the PreviewKeyDown event. This is sent by each control before they process the key themselves.
As an alternative, you can use CommandBindings.
Maybe you can try to use Low-level Windows API hooks from C#
something like this:
http://www.codeproject.com/KB/system/CSLLKeyboard.aspx
this will involve code using System.Runtime.InteropServices and user32.dll
...
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr SetWindowsHookEx(int idHook, LowLevelKeyboardProc lpfn, IntPtr hMod, uint dwThreadId);
// and the code to create the event handler, etc... See more on the referred article.
...
As a clean and simple solution, maybe you could use something like this:
Instead of you manually add the event on every window, you make the computer do it for you.
private void AssignEventHandlers()
{
foreach (Window window in Application.Current.Windows)
{
//if (window != Application.Current.MainWindow)
window.KeyDown += new System.Windows.Input.KeyEventHandler(window_KeyDown);
}
}
void window_KeyDown(object sender, System.Windows.Input.KeyEventArgs e)
{
// MessageBox.Show(e.Key.ToString());
if (System.Windows.Input.Keyboard.Modifiers == (System.Windows.Input.ModifierKeys.Control | System.Windows.Input.ModifierKeys.Alt)
&& e.Key == System.Windows.Input.Key.O)
{
MessageBox.Show(System.Windows.Input.Keyboard.Modifiers.ToString() + " " + e.Key.ToString());
}
}
Sources:
http://www.eggheadcafe.com/sample-code/SilverlightWPFandXAML/aeac920b-a64f-43b3-976b-2f7c91a5212b/wpf-get-all-windows-in-an-application.aspx
http://www.codegain.com/articles/wpf/miscellaneous/how-to-detect-ctrl-alt-key-combinations-in-wpf.aspx
I am trying to bring a window foreground. I am using this code. But its not working. Could someone please help?
ShowWindowAsync(wnd.hWnd, SW_SHOW);
SetForegroundWindow(wnd.hWnd);
// Code from Karl E. Peterson, www.mvps.org/vb/sample.htm
// Converted to Delphi by Ray Lischner
// Published in The Delphi Magazine 55, page 16
// Converted to C# by Kevin Gale
IntPtr foregroundWindow = GetForegroundWindow();
IntPtr Dummy = IntPtr.Zero;
uint foregroundThreadId = GetWindowThreadProcessId(foregroundWindow, Dummy);
uint thisThreadId = GetWindowThreadProcessId(wnd.hWnd, Dummy);
if (AttachThreadInput(thisThreadId, foregroundThreadId, true))
{
BringWindowToTop(wnd.hWnd); // IE 5.5 related hack
SetForegroundWindow(wnd.hWnd);
AttachThreadInput(thisThreadId, foregroundThreadId, false);
}
if (GetForegroundWindow() != wnd.hWnd)
{
// Code by Daniel P. Stasinski
// Converted to C# by Kevin Gale
IntPtr Timeout = IntPtr.Zero;
SystemParametersInfo(SPI_GETFOREGROUNDLOCKTIMEOUT, 0, Timeout, 0);
SystemParametersInfo(SPI_SETFOREGROUNDLOCKTIMEOUT, 0, Dummy, SPIF_SENDCHANGE);
BringWindowToTop(wnd.hWnd); // IE 5.5 related hack
SetForegroundWindow(wnd.hWnd);
SystemParametersInfo(SPI_SETFOREGROUNDLOCKTIMEOUT, 0, Timeout, SPIF_SENDCHANGE);
}
Code Explained
Making a window the foreground window
requires more than just calling the
SetForegroundWindow API. You must
first determine the foreground thread
and attach it to your window, using
AttachThreadInput, then call
SetForegroundWindow. That way they can
share input states.
First I call GetForegroundWindow to
get the handle of the current
foreground window. Then a few calls to
GetWindowThreadProcessId retrieve the
threads associated with the current
foreground window and the window I
want to bring to the foreground. If
these threads are the same a simple
call to SetForegroundWindow is all
that is necessary. Otherwise, the
foreground thread is attached to the
window that I am bringing to the front
and detached from what was the current
foreground window. The
AttachThreadInput API handles this.
Content Taken from here
Thanks.
I've used this method before:
[DllImport("user32.dll")]
static extern bool SetForegroundWindow(IntPtr hWnd);
Process[] processes = Process.GetProcessesByName("processname");
SetForegroundWindow(processes[0].MainWindowHandle);
More information: http://pinvoke.net/default.aspx/user32.SetForegroundWindow
This code restores and set focus to a window:
[DllImport("User32.dll")]
static extern int SetForegroundWindow(IntPtr hWnd);
[DllImport("user32.dll")]
internal static extern bool SendMessage(IntPtr hWnd, Int32 msg, Int32 wParam, Int32 lParam);
static Int32 WM_SYSCOMMAND = 0x0112;
static Int32 SC_RESTORE = 0xF120;
And use it like this:
var proc = Process.GetProcessesByName("YourProgram").FirstOrDefault();
if (proc != null)
{
var pointer = proc.MainWindowHandle;
SetForegroundWindow(pointer);
SendMessage(pointer, WM_SYSCOMMAND, SC_RESTORE, 0);
}
In order for SetForegroundWindow to work consistently, you have to meet a few criteria. The first is your process that would run the command must be in the foreground. Only foreground process can make another process foreground. In order to make your process foreground first, you have to bring the main window to the front, if it is not. You minimise it first and then SetForegroundWindow it, to make it foreground. Now find the target process and bring it to the front
The steps are
Minimise the current window
SetForegroundWindow it
Find the target process
SetForegroundWindow it
I've got an example, though it's a slightly different use case.
You should use SetForegroundWindow. Also it may be interesting for you C# Force Form Focus
I'll be brief: Form.BringToFront()
As of Windows 7 these features dont behave quite so well. If there is an application such as Excel in front of the application you want to bring to the front then Windows 7 blocks this and flashes the window. You can set a registry timeout setting ForegroundLockTimeout=0 in HKEY_CURRENT_USER\Control Panel\Desktop but these is known as stealing focus. To set the behaviour of how XP "should" behave and will behave in Windows 7 by default you can create/set the value to 0x00030D40 (200000ms).
I'd like to know what is the preferred solution for trusted Windows applications. eg. If I trust application B to take focus when I double click something in Application A, and some other app is obscuring the window of Application B.