Monitoring for specific Keystrokes in C# - c#

I need to write a Windows application which monitors keystrokes regardless of focus. When it detects a particular keystroke (Ctrl + V, specifically), it needs to perform certain actions.
How can I monitor keystrokes in Windows from C# regardless of focus?

I am not fully understand your question, but If you would like to register global key regardless of your window focus you can use RegisterHotKey windows API.

A really easy way to do it is with GetASyncKeyState.
I use it only for games but I think it would work here.
Import this:
[DllImport("user32.dll")]
static extern short GetAsyncKeyState(System.Windows.Forms.Keys vKey);
Then you can just do (in a loop or timer)
if(GetAsyncKeyState(Keys.ControlKey) && GetAsyncKeyState(Keys.K))
{
//DO SOME STUFF!!
}
If you need it to happen just once when it's pressed you can declare
bool oldK; //at class scope
then in your loop/timer
if(!oldK && GetAsyncKeyState(Keys.ControlKey) && GetAsyncKeyState(Keys.K))
{
//DO SOME STUFF!!
}
oldK = GetAsyncKeyState(Keys.K);

checkout this article Detecting and recording key strokes in C#
you need to write the code into a class.Then add this class to a windows service.Instaniate into start() method of windows service.olace the buffering code into some timer
e.g
this.timerBuffFlush = new System.Timers.Timer();
this.timerBuffFlush.Enabled = true;
this.timerBuffFlush.Elapsed += new System.Timers.ElapsedEventHandler(this.timerBuffFlush_Elapsed);
this.timerBufferFlush.Interval = 60000;
}

Related

C#: Get informed when any new process is started / any new window is opened

I need to check when a new process with a new visible main window handle is started (as the mouse hook of my app is lost on some applications and is restored only on a short internal restart).
I have tried to use EnumWindows and EnumDesktopWindows but those give me many many windows and child windows I do not need. I only need the visible main window handles. Therefore (and to find out if they are belonging to a new process) I decided to directly check the processes within an own update-check-thread. But this approach (as well as to permanently check EnumWindows) is extremely cpu consuming (1-3 % at Ryzen 5600X) and in my opinion, completely overblown.
Therefore I'd like to know if there is any other, slick approach to find out whenever any new process is started or window is opened to only execute the check when it is necessary.
Polling is never a good solution.
If you are already hooking, why not use WH_SHELL, WH_CBT or SetWinEventHook()?
I solved it by using/extracting the ApplicationWatcher from this Package with minor adjustments to run it within .NET v4.5.2 and to get rid of all unnecessary things.
The application event hook only works for apps/windows which are started after the event hook has been launched which is sufficient for my purposes. If one needs all existing windows as well, you once need to add all existing windows to the activeWindows property of the ApplicationWatcher class.
Furthermore, the WindowsActivated event seems to be bugged. Herefore, you need to adjust the following things:
Within the ApplicationWatcher class
private void WindowActivated(WindowData wnd) {
if (_ActiveWindows.ContainsKey(wnd.HWnd)) {
if (!_LastEventWasLaunched) { // < if condition adjusted
ApplicationStatus(_ActiveWindows[wnd.HWnd], ApplicationEvents.Activated);
}
}
_LastEventWasLaunched = false;
}
and within the ShellHook class
protected override void WndProc(ref Message m) {
if (m.Msg == _wmShellHook) {
switch ((User32.ShellEvents)m.WParam) {
...
case User32.ShellEvents.HSHELL_RUDEAPPACTIVATED: // < line added
case User32.ShellEvents.HSHELL_WINDOWACTIVATED:
if (WindowActivated != null) {
WindowActivated.Invoke(this, m.LParam);
}
break;
}
}
base.WndProc(ref m);
}
Works like a charme and my CPU usage went down to 0 %.

Get the window handle of the Windows setup process

I am trying to automate Windows 10 installation by first mounting the .iso file on the drive. And then using c# to start windows 10 installation by using this below code which passes the keys to the installation application
[DllImport("user32.dll")]
static extern int SetForegroundWindow(IntPtr point);
public static void Main(String[] args){
Process p1 = Process.Start("h:\\setup.exe");
IntPtr h = p1.MainWindowHandle;
SetForegroundWindow(h);
Thread.Sleep(30000);
SendKeys.SendWait("{ENTER}");
Thread.Sleep(1000);
SendKeys.SendWait("{ENTER}");
Thread.Sleep(1000);
SendKeys.SendWait("{ENTER}");
}
But the problem is that the setup window is not taking the signal of the ENTER key in the code. The setup window is starting with this code. After that, nothing is happening.
Process p1 = Process.Start("h:\\setup.exe");
I tried using notepad instead of setup.exe in the code which is taking all the ENTER keys. Please tell me if anyone has a solution. Thank you
Disclaimer:
I would advise against automating a Windows setup using something like
SendKeys as you can't guarantee a consistent behavior and could
easily mess things up. You may consider looking for different
approaches as suggested by lan Kemp in the comments. This answer
only shows you how to get the handle of the setup window correctly.
You may use it at your own risk.
Update:
Apparently, the Windows 10 setup executable ("Setup.exe") starts another process called "SetupPrep.exe" which starts a third process called "SetupHost.exe" (the one you're after). So, what you can do is start the main process, wait for the target process to start and obtain a MainWindowHandle before executing the remaining code:
Process p1 = Process.Start("H:\\setup.exe");
Process targetProcess;
do
{
Thread.Sleep(500);
targetProcess = Process.GetProcessesByName("SetupHost").FirstOrDefault();
} while (targetProcess == null || targetProcess.MainWindowHandle == IntPtr.Zero);
IntPtr h = targetProcess.MainWindowHandle;
// ...
This should solve your problem, however, it's not a wise idea to use SendKeys for this purpose. Please refer to the disclaimer above.
Original answer:
Did you make sure that h does actually have a value (other than IntPtr.Zero)? Because it probably doesn't have the actual window handle since you don't give the process enough time to start and obtain a window handle.
Try something like this:
Process p1 = Process.Start("h:\\setup.exe");
while (p1.MainWindowHandle == IntPtr.Zero)
{
Thread.Sleep(500);
}
IntPtr h = p1.MainWindowHandle;
// ...

C# Detect Keystrokes and Send to Background Windows

I've looked around for six hours today in search of a method to complete the task I'm looking to accomplish. However with little luck every method I've tried has come out not working.
So the program I'm working on is a multiboxing application for video games. Essentially I want to have my created application running in the background. The user will check on checkbox's to state which keys they want to be captured, so not every key is being captured. Then while they are playing the main game, the application will send the keys that are checked to the games running in the background.
I've tried global hotkeys however never could get more than one key working. I've also tried to hook keys but for some reason, couldn't get that functional. I also dabbled into sendmessage with little luck there either.
Was just curious if anyone else had some ideas for going about doing this. To give an example of another program that does this same thing would be HotKeyNet, KeyClone, and ISboxer. I know there are more out there but that gives you an idea of what I'm trying to do with my application.
Alright, after quite a bit of research into different methods for sending keystrokes and reading keystrokes. I finally was able to splice to different types of coding together to provide the results I was looking for.
I'm posting up the answer, so anyone that is looking for the answer to this question later down the road has it available to them.
My two references for splicing this code together are the following:
http://www.codeproject.com/Articles/19004/A-Simple-C-Global-Low-Level-Keyboard-Hook
Send combination of keystrokes to background window
I used the global low level hook and postmessage for sending keystrokes to the background application.
So first you will need to follow the instructions from the first
link, to get the starting code working.
Download the working source code from link one, and use the
globalKeyboardHook.cs in your application.
Then in references place the following:
using System.Runtime.InteropServices; //Grabs for your DLLs
using Utilities; //Grabs from the file you added to your application.
Now you will want to place the following code in your class:
globalKeyboardHook gkh = new globalKeyboardHook();
[DllImport("user32.dll")] //Used for sending keystrokes to new window.
public static extern IntPtr PostMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);
[DllImport("user32.dll", EntryPoint = "FindWindow", CharSet = CharSet.Ansi)] //Used to find the window to send keystrokes to.
public static extern IntPtr FindWindow(string className, string windowName);
Now go ahead place your keystrokes you want to be grabbed this I
found is best in Form1_Loaded:
gkh.HookedKeys.Add(Keys.A);//This collects the A Key.
gkh.HookedKeys.Add(Keys.B);//This collects the B Key.
gkh.HookedKeys.Add(Keys.C);//This collects the C Key.
gkh.KeyDown += new KeyEventHandler(gkh_KeyDown); //Event for pressing the key down.
gkh.KeyUp += new KeyEventHandler(gkh_KeyUp); //Event for the release of key.
After that you will want to go ahead and place in the following in
your code as well:
void gkh_KeyUp(object sender, KeyEventArgs e) //What happens on key release.
{
lstLog.Items.Add("Up\t" + e.KeyCode.ToString());
e.Handled = false; //Setting this to true will cause the global hotkeys to block all outgoing keystrokes.
}
void gkh_KeyDown(object sender, KeyEventArgs e) //What happens on key press.
{
lstLog.Items.Add("Down\t" + e.KeyCode.ToString());
e.Handled = false;
}
Once that is in place just put this little bit in the gkh_KeyDown to
get your keystrokes to send to another window of your choosing:
const uint WM_KEYDOWN = 0x100;
IntPtr hWnd = FindWindow(null, "Example1"); //Find window Example1 for application.
switch (e.KeyCode)
{
case Keys.A: //Makes it so it only sends that key when it's pressed and no other keys.
if(chkA.Checked == true)
{
PostMessage(hWnd, WM_KEYDOWN, (IntPtr)(Keys.A), IntPtr.Zero); //Sends to key A to new window assigned hWnd which equals Example1.
}
break;
}
}
The code that I have provided is setup so people can use checkbox's to tell the program which keys they want to send over to the second application.
If you have any questions regarding to this post just let me know, and I will do my best to walk you through the process. Hope this helps someone out later down the road.
My suggestion is to go with "mapped memory" (in operating system concepts: shared memory)
First process creates (may be your check state program) creates a mapped memory and writes values to it.
All other game process reads the value from memory map created by first process.
Here is a very nice example regarding how to do it.
https://msdn.microsoft.com/en-us/library/dd267552(v=vs.110).aspx

Why does closing a console that was started with AllocConsole cause my whole application to exit? Can I change this behavior?

What I want to have happen is that the console window just goes away, or better yet that it is hidden, but I want my application to keep running. Is that possible? I want to be able to use Console.WriteLine and have the console serve as an output window. I want to be able to hide and show it, and I don't want the whole app to die just because the console was closed.
EDIT
Code:
internal class SomeClass {
[DllImport("kernel32")]
private static extern bool AllocConsole();
private static void Main() {
AllocConsole();
while(true) continue;
}
}
EDIT 2
I tried the accepted solution here [ Capture console exit C# ], per the suggestion in the comments on this question. The example code is bugged in that the DLLImport needs to be "kernel32.dll" or "kernel32", not "Kernel32". After making that change, I'm getting a message to my handler for CTRL_CLOSE_EVENT when I click the X on the console window. However, calling FreeConsole and/or returning true doesn't prevent the application from terminating.
Ah, yes, this is one of the caveats of using the Windows console subsystem. When the user closes the console window (regardless of how the console was allocated), all of the processes that are attached to the console are terminated. That behavior makes obvious sense for console applications (i.e., those that specifically target the console subsystem, as opposed to standard Windows applications), but it can be a major pain in cases like yours.
The only workaround that I know of is to use the SetConsoleCtrlHandler function, which allows you to register a handler function for Ctrl+C and Ctrl+Break signals, as well as system events like the user closing the console window, the user logging off, or the system shutting down. The documentation says that if you're only interested in ignoring these events, you can pass null for the first argument. For example:
[DllImport("kernel32")]
static extern bool SetConsoleCtrlHandler(HandlerRoutine HandlerRoutine, bool Add);
delegate bool HandlerRoutine(uint dwControlType);
static void Main()
{
AllocConsole();
SetConsoleCtrlHandler(null, true);
while (true) continue;
}
That works perfectly for Ctrl+C and Ctrl+Break signals (which would have otherwise caused your application to terminate as well), but it doesn't work for the one you're asking about, which is the CTRL_CLOSE_EVENT, generated by the system when the user closes the console window.
Honestly, I don't know how to prevent that. Even the sample in the SDK doesn't actually allow you to ignore the CTRL_CLOSE_EVENT. I tried it in a little test app, and it beeps when you close the window and prints the message, but the process still gets terminated.
Perhaps more worryingly, the documentation makes me think it is not possible to prevent this:
The system generates CTRL_CLOSE_EVENT, CTRL_LOGOFF_EVENT, and CTRL_SHUTDOWN_EVENT signals when the user closes the console, logs off, or shuts down the system so that the process has an opportunity to clean up before termination. Console functions, or any C run-time functions that call console functions, may not work reliably during processing of any of the three signals mentioned previously. The reason is that some or all of the internal console cleanup routines may have been called before executing the process signal handler.
It's that last sentence that catches my eye. If the console subsystem starts cleaning up after itself immediately in response to the user attempting to close the window, it may not be possible to halt it after the fact.
(At least now you understand the problem. Maybe someone else can come along with a solution!)
Unfortunately there's nothing you can do to really alter this behaviour.
Console windows are "special" in that they're hosted by another process and do not allow sub-classing. This limits your ability to modify their behaviour.
From what I know, your two options are:
1. Disable the close button altogether. You can do this with the following code fragment:
HWND hwnd = ::GetConsoleWindow();
if (hwnd != NULL)
{
HMENU hMenu = ::GetSystemMenu(hwnd, FALSE);
if (hMenu != NULL) DeleteMenu(hMenu, SC_CLOSE, MF_BYCOMMAND);
}
2. Stop using consoles altogether, and implement your own text output solution.
Option #2 is the more complicated option but would provide you the greatest control. I found an article on CodeProject that implements a console-like application using a rich edit control to display the text (rich edit controls have the ability to stream text like the console, so they are well suited to this sort of application).
On closing the console window obtained using AllocConsole or AttachConsole, the associated process will exit. There is no escape from that.
Prior to Windows Vista, closing the console window would present a confirmation dialogue to the user asking him whether the process should be terminated or not but Windows Vista and later do not provide any such dialogue and the process gets terminated.
One possible solution to work around this is avoiding AttachConsole altogether and achieving the desired functionality through other means.
For instance in the case described by OP, console window was needed to output some text on Console using Console static class.
This can be achieved very easily using inter-process communication. For example a console application can be developed to act as an echo server
namespace EchoServer
{
public class PipeServer
{
public static void Main()
{
var pipeServer = new NamedPipeServerStream(#"Com.MyDomain.EchoServer.PipeServer", PipeDirection.In);
pipeServer.WaitForConnection();
StreamReader reader = new StreamReader(pipeServer);
try
{
int i = 0;
while (i >= 0)
{
i = reader.Read();
if (i >= 0)
{
Console.Write(Convert.ToChar(i));
}
}
}
catch (IOException)
{
//error handling code here
}
finally
{
pipeServer.Close();
}
}
}
}
and then instead of allocating/attaching a console to the current application, the echo server can be started from within the application and Console's output stream can be redirected to write to the pipe server.
class Program
{
private static NamedPipeClientStream _pipeClient;
static void Main(string[] args)
{
//Current application is a Win32 application without any console window
var processStartInfo = new ProcessStartInfo("echoserver.exe");
Process serverProcess = new Process {StartInfo = processStartInfo};
serverProcess.Start();
_pipeClient = new NamedPipeClientStream(".", #"Com.MyDomain.EchoServer.PipeServer", PipeDirection.Out, PipeOptions.None);
_pipeClient.Connect();
StreamWriter writer = new StreamWriter(_pipeClient) {AutoFlush = true};
Console.SetOut(writer);
Console.WriteLine("Testing");
//Do rest of the work.
//Also detect that the server has terminated (serverProcess.HasExited) and then close the _pipeClient
//Also remember to terminate the server process when current process exits, serverProcess.Kill();
while (true)
continue;
}
}
This is just one of the possible solutions. In essence the work around is to allot the console window to its own process so that it can terminate without affecting the parent process.
You can do this by disabling keyboard mouse input by external program called Keyfreez.
you can use it multiple times in your program where no user input required. And if any user input require u can add a process Takskkill /f /IM .
https://www.sordum.org/7921/bluelife-keyfreeze-v1-4-block-keyboard-and-mouse/
Hope this helps all of you

How to prevent Windows from entering idle state?

I am working on a C# application which runs in the background without any Windows control.
I want to notify Windows that my application is still alive to prevent Windows from going into the idle state.
Are there any APIs available to call from my application which notify the Windows OS that my application is still alive?
Thanks in advance.
You've to use SetThreadExecutionState function. Something like this:
public partial class MyWinForm: Window
{
private uint fPreviousExecutionState;
public Window1()
{
InitializeComponent();
// Set new state to prevent system sleep
fPreviousExecutionState = NativeMethods.SetThreadExecutionState(
NativeMethods.ES_CONTINUOUS | NativeMethods.ES_SYSTEM_REQUIRED);
if (fPreviousExecutionState == 0)
{
Console.WriteLine("SetThreadExecutionState failed. Do something here...");
Close();
}
}
protected override void OnClosed(System.EventArgs e)
{
base.OnClosed(e);
// Restore previous state
if (NativeMethods.SetThreadExecutionState(fPreviousExecutionState) == 0)
{
// No way to recover; already exiting
}
}
}
internal static class NativeMethods
{
// Import SetThreadExecutionState Win32 API and necessary flags
[DllImport("kernel32.dll")]
public static extern uint SetThreadExecutionState(uint esFlags);
public const uint ES_CONTINUOUS = 0x80000000;
public const uint ES_SYSTEM_REQUIRED = 0x00000001;
}
You have a couple of options:
Use SetThreadExecutionState, which:
Enables an application to inform the system that it is in use, thereby preventing the system from entering sleep or turning off the display while the application is running.
Where you could use the ES_SYSTEM_REQUIRED flag to
Forces the system to be in the working state by resetting the system idle timer.
Use SendInput to fake keystroke, mouse motion/clicks
Another alternative would be to change your app to be a Windows service.
SetThreadExecutionState example
// Television recording is beginning. Enable away mode and prevent
// the sleep idle time-out.
SetThreadExecutionState(
ES_CONTINUOUS |
ES_SYSTEM_REQUIRED |
ES_AWAYMODE_REQUIRED);
// Wait until recording is complete...
// Clear EXECUTION_STATE flags to disable away mode and allow the system
// to idle to sleep normally.
SetThreadExecutionState(ES_CONTINUOUS);
You can use SetThreadExecutionState described here:
SetThreadExecutionState Function
Since it is a Win32 API function, to use it from C# you'll need to PInvoke it. The steps are described here, including a sample method PreventSleep to temporarily disable sleep mode:
PInvoke.net: setthreadexecutionstate (kernel32)
I don't think there's any way to do this directly in managed code.
A quick search reveals this post from 2 years ago. Basically you'd need to do some interop to call a raw windows API.
Here is SetThreadExecutionState C# implementation

Categories