Send Keystrokes to a program even if its in background using c# - c#

I wanna send key stroke to a program even if it is running in background. But I can do this only for NOTEPAD like this,
[DllImport("user32.dll")]
protected static extern byte VkKeyScan(char ch);
[DllImport("user32.dll", SetLastError = true)]
protected static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow);
[DllImport("User32.Dll", EntryPoint = "PostMessageA")]
protected static extern bool PostMessage(IntPtr hWnd, uint msg, int wParam, int lParam);
char Key = // key value to send
IntPtr hWnd = FindWindowEx(_handle, IntPtr.Zero, "edit", null); // _handle is the windows handle of the program (here its notepad)
PostMessage(hWnd, WM_KEYDOWN, VkKeyScan(Key), 0);
But for all other applications I can't send keystrokes if its in background. Since I don't know the lpszClass of that program (I think this is the userControl name of the typing area in that program. For NotePad it is "edit". I found this surfing internet).
For all other applications what I'm doing is, get the application to foreground, then send the key, then again get my program foreground. I need my program to be run as foreground always.
[DllImport("USER32.DLL")]
public static extern bool SetForegroundWindow(IntPtr hWnd);
SetForegroundWindow(_handle); // _handle is the windows handle of the program
System.Threading.Thread.Sleep(50); // Waiting few milliseconds till application coming to foreground.
wsh.SendKeys(Key.ToString(), ref wait); // wsh is WshShellClass wsh= new WshShellClass();
SetForegroundWindow(_mainHandle); // _mainHandle is the windows handle of my application
But this way is not working. some keys getting missed and the program foreground->background->foregound->background...... like its dancing...
How to send keys to other applications if its running in background.
or are there any way/source to find the lpszClass of a program ?
Sorry if I have missed any required information. this is a large application. I have posted only required parts here. If someone needs any additional information, pls ask.

I think you'll need to have the background program install a low-level keyboard hook via the win32 function SetWindowsHookEx().
Here's the MSDN documentation for SetWindowsHookEX()
http://msdn.microsoft.com/en-us/library/ms644990(v=vs.85).aspx
And here's the KB article on how to do it from C#
http://support.microsoft.com/kb/318804
This article goes into some detail, too: http://www.codeguru.com/columns/vb/article.php/c4829
I expect your app will get caught by various spyware/anti-virus software as a keyboard logger, though.
Good luck.

You may be able to figure out the lpszClass of the program using an inspection tool such as WinSpy++. It gives you a crosshair that you can drag and position over the desired control. This was able to easily provide me with the "edit" class name for notepad.
If things aren't working, click the "More>>" button in the lower right of WinSpy++, then click the "Locate" button to view the control hierarchy; you may need to post the WM_KEYDOWN message to one of the parent or child controls instead.

Related

is there easy way to check some process is activated?

I sent a WM_ACTIVE message using postmessage api to some programs.
When a program is deactivated, sending a message does not actually activate the window, but the program thinks it is active. ( It actually succeeded. )
However, I think it is very inefficient to send postmessage regularly.
If I want to check the WM_ACTIVE value of the program and it is inactivated, I try to send a WM_ACTIVE message again using the POSTMESSAGE API to confuse the program itself with being active, but I can't think of a way. Although there is an idea that hooking would be easy to use, C# did not support other types of global hooking except for the keyboard and mouse.
Can anyone come up with any other ideas? please help me.
To check if a process is focused you should use GetForegroundWindow to get the focused window handle and then use GetWindowThreadProcessId to get the process from that window handle:
[DllImport("user32.dll")]
private static extern IntPtr GetForegroundWindow();
[DllImport("user32.dll")]
static extern uint GetWindowThreadProcessId(int hWnd, out int ProcessId);
IntPtr focusedWindow = GetForegroundWindow(); //get the focused window
int focusedProcessID = 0;
GetWindowThreadProcessID(focusedWindow, out focusedProcessID); //get it's process id
Process focusedProcess = Process.GetProcessById(focusedProcessID);//get the focused process
Console.WriteLine("Current Focused Process:" + focusedProcess.ProcessName);

Showing Outlook instead of displaying a message in C#.Net [duplicate]

We only want one instance of our app running at any one time. So on start up it looks to see if the app is running and if it is, it calls SetForegroundWindow on the Main Window.
This is all good and well ... for the most part..
When our app starts up it will show a Splash screen and a Logon form. Both of these forms have ShowInTaskBar = false.
Because of this, if you try to start up another copy of the app when the Logon form is showing, that Logon form is not brought to the front!
Especially as the user cant see anything in the taskbar as well, all they figure is that the app is duff and cannot start. There is no indication that there is another instance running.
Is there any way around this problem?
Well, code is here. Even if the ShowInTaskBar is false, you should be able to bring it to the front.
[DllImport("USER32.DLL", CharSet = CharSet.Unicode)]
public static extern IntPtr FindWindow(String lpClassName, String lpWindowName);
[DllImport("USER32.DLL")]
public static extern bool SetForegroundWindow(IntPtr hWnd);
public static void bringToFront(string title) {
// Get a handle to the Calculator application.
IntPtr handle = FindWindow(null, title);
// Verify that Calculator is a running process.
if (handle == IntPtr.Zero) {
return;
}
// Make Calculator the foreground application
SetForegroundWindow(handle);
}
Note: you should FindWindow using the form's class and not by name as the splash screen forms sometimes do not have titles or even the controlbox. Use Spy++ to dig deeper.
Use FindWindow on splash. I think this is what you want to do - bring the splash screen in front while loading of the main form.
I think this is the better solution because its restores from minimized state:
public static class WindowHelper
{
public static void BringProcessToFront(Process process)
{
IntPtr handle = process.MainWindowHandle;
if (IsIconic(handle))
{
ShowWindow(handle, SW_RESTORE);
}
SetForegroundWindow(handle);
}
const int SW_RESTORE = 9;
[System.Runtime.InteropServices.DllImport("User32.dll")]
private static extern bool SetForegroundWindow(IntPtr handle);
[System.Runtime.InteropServices.DllImport("User32.dll")]
private static extern bool ShowWindow(IntPtr handle, int nCmdShow);
[System.Runtime.InteropServices.DllImport("User32.dll")]
private static extern bool IsIconic(IntPtr handle);
}
Simple call:
WindowHelper.BringProcessToFront(process);
FindWindow(null, title);
Will find the first window that matches the query. This may lead to unexpected behavior if another window uses the same title.
Although the chances of this to happen may seem rare or impossible (single instance application) this can easily occur. The windows explorer for instance uses the name of the selected directory as window title (although invisible). Now if the window title is a common term or matches the name of the application directory this can be an issue.

Artificially generate key events in other programs

Can a C# program that has focus artificially generate a key event that will be handled by another open application?
For those who are curious, this is why I'm asking:
I'm currently working on a demo/mockup for a design idea for a gesture based media player, using the Kinect as a primary input device. This is something I decided to do on as a favor, and it neither needs nor deserves a ton of my time as far as programming goes.
So to speed things along, I'm using the FAAST tool which you can use to easily bind key events to certain gestures. So, you turn on this program, tell it what key maps to what gesture, then when you make the gesture the key is registered as pressed by the current application.
What I would like to create is a go-between that will display a simple GUI that I'll display to the audience. At a certain point, the user will make the "select" gesture, and I want music to start playing in an open media player. So, I would check their place in the menu hierarchy, see that they've selected "music" based on some key I choose to arbitrarily mean select, then generate a key event with the MediaPlayPause key.
It requires a little p/invoke work to do from C# but it's not complicated. You'll use the FindWindow API to get an hWnd for the target program, then the PostMessage API to send key events:
[return: MarshalAs(UnmanagedType.Bool)]
[DllImport("user32.dll", SetLastError = true)]
private static extern bool PostMessage(IntPtr hWnd, uint Msg, int wParam, int lParam);
private const UInt32 WM_KEYDOWN = 0x0100;
private const UInt32 WM_KEYUP = 0x0101;
public static void SendSelect(IntPtr HWnd)
{
PostMessage(HWnd, WM_KEYDOWN, KeyInterop.VirtualKeyFromKey(System.Windows.Input.Key.Enter), 0);
}

How do I get the active ChildWindow of an application?

I want to send a pressKey event to a certain application which is not the active application IN Windows so I have to use the sendMessage/postMessage api calls.
However, I need to know the exact child window that is active IN the application and send the pressKey message to it...
I was using GetTopWindow and GetWindow(GW_CHILD) api calls to get the top child window of the main window, and do it again with the obtained child window to get the top grandchildWindow, and keep doing it until I found a childwindow with no more childwindows. This works great for some applications but in some cases it doesn't. Sometimes the parent window is the active window, not one of its childwindows, so getting the parent's top child window will not work cause I will be sending a message to the wrong window.
The only way I found of doing this (getting the handler of the actual active window) was using the GuiThreadInfo api call but it only works if the target application is the active one IN Windows. As I mentioned in the beginning, it isn't so the handler comes null.
I can bring the application to the top using setForegroundWindow api call but I DON'T want to do this. I also tried the AttachThreadInput and GetFocus api calls, but again, they only work if the target application is the active application IN windows.
Any ideas? Thanks
I assume from the things that you have tried that you know how to get a handle to your main window, but if you don't just leave a comment and I will post a snippet for that.
I combined a few things that I found on the net to figure this out, but the main one is this one. I don't have a great app to test this with, but it works in a simple case. One exception is that I think if you use tool windows in your application it will not find that as it is coded because I think the GetLastActivePopup method doesn't include them (not sure about that, and didn't test that case).
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool IsWindowVisible(IntPtr hWnd);
[DllImport("user32.dll")]
static extern IntPtr GetLastActivePopup(IntPtr hWnd);
[DllImport("user32.dll", ExactSpelling = true)]
static extern IntPtr GetAncestor(IntPtr hwnd, uint gaFlags);
const uint GA_PARENT = 1;
const uint GA_ROOT = 2;
const uint GA_ROOTOWNER = 3;
public static IntPtr GetAppActiveWindow(IntPtr hwnd)
{
IntPtr activeAppWindow = IntPtr.Zero;
if (hwnd != IntPtr.Zero)
{
//Get the root owner window (make sure we are at the app window
//if you already have a handle to the main window shouldn't have
//to do this but I put it in just in case
hwnd = GetAncestor(hwnd, GA_ROOTOWNER);
while ((activeAppWindow =
GetLastActivePopup(hwnd)) != activeAppWindow)
{
if (IsWindowVisible(activeAppWindow))
break;
hwnd = activeAppWindow;
}
}
return activeAppWindow;
}
If you know the Window title and the Window class name, take a look at FindWindow() and FindWindowEx() and see if those meet your needs.
FindWindow(): http://msdn.microsoft.com/en-us/library/ms633499.aspx
FindWindowEx(): http://msdn.microsoft.com/en-us/library/ms633500(VS.85).aspx

How do I prevent print screen

I have a requirement that an application I am working on prevent the user from being able to easily capture the contents of the screen.
I have communicated that there is no feasible way to completely prevent this from happening, but I'm looking for methods to introduce some hurdles to the process.
I'm using C#/.NET 2.0 and WinForms
You can't.
The best you can do is render to a hardware accelerated device on an overlay, similar to what video players used to do. Basically, you paint your entire window blue, and render your graphics onto the video card, and internally the video card will replace the blue with the graphics. The downside to this is you have to give up using winforms controls, and I don't know of any way to do this with .NET easily. I think if you use DirectShow.NET, one of their samples is putting your own graphics into a stream.
Even after doing all of that, it's still possible to get a screenshot. Just take a picture of the screen with a digital camera.
From here:
A. Windows implements Print Screen using a registered hotkey. Windows
uses the predefined hotkeys IDHOT_SNAPDESKTOP and IDHOT_SNAPWINDOW to
handle Print Screen. These correspond to Print Screen, which captures
the entire screen, and Alt+Print Screen, which captures only the
active window. To disable these functions all you have to do is
register the hotkeys, which causes Windows to send your app a
WM_HOTKEY message when the user presses either hotkey. Your
implementation can ignore the message to bypass the default
screen-capture behavior. A good place to do it is in your mainframe
class.
FWIW, it is possible. Here's some code:
This would be a dll that you create, then call the HookKeyboard method from your application. I've tested it and it works. Granted, if someone takes a picture with a camera it can't help, but, point made. NYAH!
namespace KeyboardHook
{
public class Hooker
{
[StructLayout(LayoutKind.Sequential)]
public struct KBDLLHOOKSTRUCT
{
public int vkCode;
public int scanCode;
public int flags;
public int time
;
public int extraInfo;
}
public delegate int HookProc(int nCode, int wParam, IntPtr ptrKBDLLHOOKSTRUCT);
[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall, SetLastError = true)]
public static extern IntPtr SetWindowsHookEx(int idHook, HookProc callBack, IntPtr hMod, int threadId);
[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall, SetLastError = true)]
public static extern int CallNextHookEx(IntPtr hhk, int nCode, int wParam, IntPtr lParam);
private static IntPtr kbh_Handle;
private static HookProc kbh_HookProc;
private const int VK_SNAPSHOT = 0x2C;
private const int WM_KEYDOWN = 0x0100;
private const int WM_SYSKEYDOWN = 0x0104;
private const int WH_KEYBOARD_LL = 13;
private static int LowLevelKeyboardProc(int nCode, int wParam, IntPtr lParam)
{
if (nCode < 0)
{
CallNextHookEx(kbh_Handle, nCode, wParam, lParam);
return 0;
}
if (wParam == WM_KEYDOWN)
{
IntPtr kbdll = lParam;
KBDLLHOOKSTRUCT kbdllstruct = (KBDLLHOOKSTRUCT)Marshal.PtrToStructure(kbdll, typeof(KBDLLHOOKSTRUCT));
if (kbdllstruct.vkCode == VK_SNAPSHOT)
return -1;
}
return CallNextHookEx(kbh_Handle, nCode, wParam, lParam);
}
public static void HookKeyboard()
{
try
{
kbh_HookProc = LowLevelKeyboardProc;
kbh_Handle = SetWindowsHookEx(WH_KEYBOARD_LL, kbh_HookProc, Marshal.GetHINSTANCE(Assembly.GetExecutingAssembly().GetModules()[0]), 0);
if (kbh_Handle != IntPtr.Zero)
System.Diagnostics.Debug.WriteLine(String.Format("It worked! HookHandle: {0}", kbh_Handle));
else
{
throw new Win32Exception(Marshal.GetLastWin32Error());
}
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine(String.Format("ERROR: {0}", ex.Message));
}
}
}
}
You can try using IpcProtectWindow provided in msipc.dll.
[DllImport("msipc.dll", SetLastError = false, CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall)]
internal static extern int IpcProtectWindow([In] IntPtr hwnd);
Download the SDK from Microsoft
Call the function above and provide the handle of the form you would like to protect. (Form.Handle property)
You'll have two cases here that you need to worry about. One, when your window/application has focus, the other when it doesn't have focus.
When it doesn't have focus, there's not a whole lot you can do, i.e. if the user clicks off of your app and onto the desktop, keys aren't sent to your app so you'll never see them. In that case, you can minimize to the tray when your app loses focus (or, perhaps, place a "blank" panel over the form to prevent users from seeing anything on it which will also prevent a print-screen from being useful).
In the other case, when you have focus, capture keystrokes and examine them. If the Alt key is down and the PrintScreen key is down, reset the value so that a print-screen doesn't occur. (Come to think of it, that may not work. I'd need to test it to be sure.)
You could look into what movie players do. I believe they render directly to a hardware surface (via DirectX). I suspect that you'd need to do this.
This doesn't really answer the questions, but keep in mind that there exists tools to capture screen, and that a simple camera breaks everything.
I mean ok you "have to", but I would (but I'm young and still student, so I don't know much about what can be said) answer that this is just stupid.
Check out the new tech - sivizion.com, they prevent print screen all together - no way to bypass it. If anyone will figure out a way how to hack it, please post here, I couldn't. I think they also license their tech, not sure, check it out.
Well, you could try capturing the button, but I'm not sure how well that will work.
One thing that always annoyed me was that whenever I played a movie, it would never take screenshots of it. If you can render through a separate context, it would make it really annoying to take a picture of it. Perhaps you can send your screen output through something like that?
There are applications that can capture the screen from OpenGL and DirectX apps ! (depending (they are used for recording game movies)
ps. windows aero is DirectX
http://www.fraps.com/
i think thats the application
You can make any casual Print Screen useless using Visual Cryptography and taking advantage of retinal persistence (see this article for details, and bit.ly/vcrypto for a web demo).
The idea is to alternate at high frequency between two or more random noise images, that will combine through persistence of vision to reveal the content. A screen capture will only grab one image, with meaningless random noise.
This comes at the cost of flickering and inducing user headaches, can be defeated by a camera taking a picture of the screen, or by a less casual user that knows photoshop, but will defeat any kind of casual screen capture or frame grabbing.
Might occasionally be useful, in an academic meaning of the term!
It is too late but there is a quick work around,
Simply use it in MDI form
Set TopMost Property of form True, then write below event
private void frmMDI_Deactivate(object sender, EventArgs e){Clipboard.Clear();}
after taking print screen user have to minimize the application, the moment user minimize the app, we are clearing clipboard.
you can use this in logout function or when screen move or resize or any other form event as required :)
Snipping tool also can't copy screens by this if TopMost Property is true.
Yes we can't stop user from capturing screen from external device like phone or cam.
In windows form application, Use this code in form keyup event,
if (e.KeyCode == Keys.PrintScreen)
{
Clipboard.Clear();
}
Form keypreview should be TRUE
Microsoft has been developed an API named SetWindowDisplayAffinity to support the window content protection. This feature enables applications to protect application content from being captured or copied through a specific set of public operating system features and APIs
SetWindowDisplayAffinity(hWnd, WDA_MONITOR);
I solved it using a Timer object and Clipboard.Clear() method.
First add a Timer to your main form with Interval=1 (Very fast), then add the following code in its event:
Clipboard.Clear();

Categories

Resources