Broadcast Windows HWND_BROADCAST message - c#

I am working in an application in this application I shall wait for some event in application 1 and when this event happen I shall sendmessage to application 2 which will perform something.
First API declaration
private const int HWND_BROADCAST = 0xffff;
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
public static extern int RegisterWindowMessage(string lpString);
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
static extern bool SendNotifyMessage(int hWnd, int Msg, int wParam, int lParam);
Application 1 Code
private string msgstr = "MYMESSAGE";
public int msg = RegisterWindowMessage(msgstr);
if (msg == 0)
{
MessageBox.Show(Marshal.GetLastWin32Error().ToString());
}
//SendNotifyMessage(HWND_BROADCAST, msg, 4848484, 8484865);
SendNotifyMessage(HWND_BROADCAST, msg, 0, 0);
MessageBox.Show(Marshal.GetLastWin32Error().ToString());
Application 2 Code
static readonly int msg = RegisterWindowMessage("MYMESSAGE");
protected override void WndProc(ref Message m)
{
if (m.Msg == msg)
{
MessageBox.Show(m.Msg.ToString() + " = from wndproc");
}
base.WndProc(ref m);
}
Will somebody point out what is problem with this code.
I suspect there is problem in SendNotifyMessage
lparam and wparam
parameters
Will somebody suggest me any other alternative to achieve this behaviour!

There exists no such thing as code with a problem. There only exists code that does not do what you expected it to do. If you want us to tell you what the problem is with the above code, you should tell us what you expected it to do, (okay, we can guess that,) but most importantly, what it did instead. Did you get an error? Did it just silently fail to work? That's an important part of a question, you know!
You are making use of methods like RegisterWindowMessage() and SendNotifyMessage() the definitions of which you are not showing to us. How are we supposed to tell whether the problem is with SendNotifyMessage() when we do not know how SendNotifyMessage() has been declared?
Your Application 2 has a WndProc in which you expect to receive messages for a window. Has it been properly registered? Are you sure that it works? Does it receive other window messages? Does it receive "MYMESSAGE" if you send it from within Application 2?
HWND_BROADCAST only sends messages to top-level windows. Are you sure your window is a top-level window?
You are not checking whether the call to RegisterWindowMessage() in Application 2 was successful or not. How about checking that first of all?
"MYMESSAGE" is not a very good name for a message. How about using something more unique, like your first name plus last name, or creating a guid and using its string representation as a name for your message?

HWND_BROADCAST is pretty dangerous.. I know it's highly unlikely but what if another application also handled your message??
Anyway, that aside, have you taken a read of http://msdn.microsoft.com/en-us/library/ms644953.aspx
The most basic way to debug an issue with your code (as it's WINAPI based) would be to use GetLastError. You should always be checking the return value of methods to see if they succeed, so ensure it's returning zero (which means it worked). If it's not, and you get an error such as access denied, try running with either UAC Disabled or as an Administrator (Vista+).
When a message is blocked by UIPI the
last error, retrieved with
GetLastError, is set to 5 (access
denied).

The following code works very well,
Server side.
public partial class Server : Form
{
private UInt32 msg;
public Server()
{
InitializeComponent();
}
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
msg = RegisterWindowMessage("THIS_IS_MY_UNIQUE_MESSAGE");
}
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
static extern uint RegisterWindowMessage(string lpString);
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
static extern bool SendNotifyMessage(IntPtr hWnd, uint msg, int wParam, int lParam);
private void SendMessage(object sender, EventArgs e)
{
var retval = SendNotifyMessage(new IntPtr(-1), msg, 0, 0);
}
}
Client Side
public partial class Client : Form
{
public Client()
{
InitializeComponent();
}
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
static extern uint RegisterWindowMessage(string lpString);
private static UInt32 GetMessage()
{
return RegisterWindowMessage("THIS_IS_MY_UNIQUE_MESSAGE");
}
protected override void WndProc(ref Message m)
{
if (m.Msg == (int)GetMessage())
{
MessageBox.Show(#"Hello, from server");
}
base.WndProc(ref m);
}
}

Related

WM_CLOSE message does not seem to close chrome

I am trying to close chrome from my application.
I am using the following method:
public class CloseChrome
{
static int WM_CLOSE = 0x0010;
static int WM_QUIT = 0x0012;
[DllImport("user32.dll", CharSet = CharSet.Auto)]
private static extern int SendMessage(IntPtr hwnd, int wMsg, int wParam, int lParam);
static public void closeCrome()
{
var process = Process.GetProcesses();
foreach (var item in process)
{
if (item.ProcessName.Contains("chrome"))
{
//item.Kill();
int ret = SendMessage(item.Handle, WM_CLOSE, 0, 0);
Console.WriteLine("Chrome Reply: " + a);
}
}
}
}
Using the kill method kills the chrome process, but when I send the WM_CLOSE message nothing happens even though the return value is 0 from sendMessage. Am I doing something wrong is chrome just ignoring my request?
Process.Handle will be the HANDLE of the process, not the HWND of the main window. In fact a process can own many windows, so the concept of a main window doesn't really apply.
What you need to do is call the (csharp equivalent of) EnumWindows and then call GetWindowProcessThreadId to test each HWND to see if it belongs to your target process.
The more usual alternative is to examine a target window with Spy++ to see if the class name is pretty unique, and if it is, you can use FindWindow.

Get process ID of a client that connected to a named pipe server with C#

I'm not sure if I'm just not seeing it, or what? I need to know the process ID of a client that connected via a named pipe to my server from an instance of NamedPipeServerStream. Is such possible?
In the meantime I came up with this function:
[DllImport("kernel32.dll", SetLastError = true)]
internal static extern bool GetNamedPipeClientProcessId(IntPtr Pipe, out UInt32 ClientProcessId);
public static UInt32 getNamedPipeClientProcID(NamedPipeServerStream pipeServer)
{
//RETURN:
// = Client process ID that connected via the named pipe to this server, or
// = 0 if error
UInt32 nProcID = 0;
try
{
IntPtr hPipe = pipeServer.SafePipeHandle.DangerousGetHandle();
GetNamedPipeClientProcessId(hPipe, out nProcID);
}
catch
{
//Error
nProcID = 0;
}
return nProcID;
}
I'm not very strong in "DangerousGetHandles" and "DllImports". I'm way better off with Win32, which I'm using here.
The main problem with that code, is that it does not perform correct error handling. You need to check the return value of GetNamedPipeClientProcessId to detect an error.
[DllImport("kernel32.dll", SetLastError = true)]
internal static extern bool GetNamedPipeClientProcessId(IntPtr Pipe, out uint ClientProcessId);
public static uint getNamedPipeClientProcID(NamedPipeServerStream pipeServer)
{
UInt32 nProcID;
IntPtr hPipe = pipeServer.SafePipeHandle.DangerousGetHandle();
if (GetNamedPipeClientProcessId(hPipe, out nProcID))
return nProcID;
return 0;
}

If a server is locked - is it posible to send keys to sub client window?

My program, finds any subwindows, the case if an 3-part app shows an Error box, then i want to close it.. and it works fine, when the server not is locked.
Code:
[DllImport("user32", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private extern static bool PostMessage(IntPtr hwnd, uint msg, IntPtr WParam, IntPtr lParam);
[DllImport("user32", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private extern static bool BringWindowToTop(IntPtr hwnd);
public static bool FocusWindowAndSendEnter(IntPtr hWnd)
{
try
{ // hWnd = pointer to subwindow, like messagebox.
uint WM_KEYDOWN = 0x0100;
//Set focus
var res1 = BringWindowToTop(hWnd);
//Send enter_Key
var res2 = PostMessage(hWnd, WM_KEYDOWN, (IntPtr)Keys.Enter, IntPtr.Zero);
return (res1 == res2 == true);
}
catch (Exception ex)
{
Logger.LogException(MethodInfo.GetCurrentMethod().Name, ex);
}
return false;
}
Can this be done if the server is locked, but running?
When a computer is locked, you are very limited in what you can do - for security purposes. I doubt there is a way around this unless you either stop the computer being locked, or stop the message box from showing up in the first place.
You're attempting to solve a problem in the wrong methods.
Find out what you can about that error message box and do what you can to prevent that happening. Don't expect to have much you can do when the PC is locked.

PostMessage to Current Active Process doesn't work for all process?

I have this code:
const UInt32 WM_KEYDOWN = 0x0100;
const int VK_DOWN = 0x28;
const int VK_UP = 0x26;
[DllImport("user32.dll")]
static extern bool PostMessage(IntPtr hWnd, UInt32 Msg, int wParam, int lParam);
[DllImport("user32.dll")]
private static extern IntPtr GetForegroundWindow();
[DllImport("user32.dll")]
private static extern Int32 GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);
private static Process GetProcessByHandle(IntPtr hwnd)
{
try
{
uint processID;
GetWindowThreadProcessId(hwnd, out processID);
return Process.GetProcessById((int)processID);
}
catch { return null; }
}
public static Process GetActiveProcess()
{
IntPtr hwnd = GetForegroundWindow();
return hwnd != null ? GetProcessByHandle(hwnd) : null;
}
public static void KeyUp()
{
PostMessage(GetActiveProcess().MainWindowHandle, WM_KEYDOWN, VK_UP, 0);
}
public static void KeyDown()
{
PostMessage(GetActiveProcess().MainWindowHandle, WM_KEYDOWN, VK_DOWN, 0);
}
When i call the KeyUp/KeyDown it works only on some process, proccess like text editos, visual studio.
But doesn't work on Explorer.exe, iTunes.exe, Chrome.exe, Outlook.exe, FileZilla.exe and more..
I ran debug on console:
while (true)
{
Process currentProcess = GetActiveProcess();
if (currentProcess != null)
Console.WriteLine(currentProcess.MainWindowTitle);
Thread.Sleep(1000);
}
Here what I get from some applications:
ProjName - Microsoft Visual Studio (Administrator)
?PostMessage to Current Active Proccess doesn't work for all proccess ? - StackOverFlow - Google Chrome?
FileZilla
Inbox - Outlook Data File - Microsoft Outlook
And on Explorer.exe i get empty line..
There are multiple ways to read keyboard state in a Windows application, and responding to WM_KEYDOWN and WM_KEYUP is just one of them. Applications can also use GetKeyState or GetAsyncKeyState. Applications can also respond to the WM_CHAR, WM_SYSKEYDOWN and WM_SYSKEYUP messages. Different applications will use different methods and if you are not simulating the one the application is looking for, it won't respond.
The problem you are having is slightly different than the one posed in the question that Raymond linked to, but the solution may be the same. Namely using SendInput instead of PostMessage

Modifying keyboard-hook code to fit my own purposes... where to begin?

I'm writing a program that sits in the systray. It will have a keyboard hook into all typed input, in any open application. I want it to intercept any typed input, run code on that input, and then send the new 'correct' character to be typed. This new character will be what shows up in the app that has focus.
I found this code via another question on StackOverflow, and it looks good.
http://blogs.msdn.com/toub/archive/2006/05/03/589423.aspx
I added it as a class in my solution, created a new instance of it in the Form1 constructor, and it compiles. Any typed input into any app shows up in the Visual Studio output pane, one character at a time.
The problem is that this code is way over my head. That's the drawback of using this great concise code for my keyboard hooks: I haven't had the trial and error to teach me how to use it.
I envisioned this program working something like this:
key is pressed, triggers an event
get key information from the event
do computation on the key information, pick the character to be typed
send that key to the relevant program
my character is typed rather than the original keypress character
How does this code fit in this chain of events? I need to read the input characters before they are inputed. Then, where would the code to analyse the input and decide the correct input live? Finally, what's the correct 'sendInput()' type command to invoke to send a character to whatever app has focus?
Here's the full code for reference:
using System;
using System.Diagnostics;
using System.Windows.Forms;
using System.Runtime.InteropServices;
class InterceptKeys
{
private const int WH_KEYBOARD_LL = 13;
private const int WM_KEYDOWN = 0x0100;
private static LowLevelKeyboardProc _proc = HookCallback;
private static IntPtr _hookID = IntPtr.Zero;
public static void Main()
{
_hookID = SetHook(_proc);
Application.Run();
UnhookWindowsHookEx(_hookID);
}
private static IntPtr SetHook(LowLevelKeyboardProc proc)
{
using (Process curProcess = Process.GetCurrentProcess())
using (ProcessModule curModule = curProcess.MainModule)
{
return SetWindowsHookEx(WH_KEYBOARD_LL, proc,
GetModuleHandle(curModule.ModuleName), 0);
}
}
private delegate IntPtr LowLevelKeyboardProc(
int nCode, IntPtr wParam, IntPtr lParam);
private static IntPtr HookCallback(
int nCode, IntPtr wParam, IntPtr lParam)
{
if (nCode >= 0 && wParam == (IntPtr)WM_KEYDOWN)
{
int vkCode = Marshal.ReadInt32(lParam);
Console.WriteLine((Keys)vkCode);
}
return CallNextHookEx(_hookID, nCode, wParam, lParam);
}
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr SetWindowsHookEx(int idHook,
LowLevelKeyboardProc lpfn, IntPtr hMod, uint dwThreadId);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool UnhookWindowsHookEx(IntPtr hhk);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode,
IntPtr wParam, IntPtr lParam);
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr GetModuleHandle(string lpModuleName);
}
Thanks for any advice you have! Or, is there a better way to go about this?
Thanks!
UPDATE
My HookCallback method now looks like this:
private static IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam)
{
if (nCode >= 0 && wParam == (IntPtr)WM_KEYDOWN)
{
//Console.WriteLine((Keys)vkCode);
KBDLLHOOKSTRUCT replacementKey = new KBDLLHOOKSTRUCT();
Marshal.PtrToStructure(lParam, replacementKey);
replacementKey.vkCode = 90; // char 'Z'
Marshal.StructureToPtr(replacementKey, lParam, true);
}
return CallNextHookEx(_hookID, nCode, wParam, lParam);
}
Shoot... adding Marshal.StructureToPtr is close, but results in a A first chance exception of type 'System.ArgumentException' occurred in foobar.exe error.
VERSION WITH UNSAFE CODE, NO MARSHALLING, etc. (still doesn't output 'Z'!)
unsafe private static IntPtr HookCallback(int nCode, IntPtr wParam, void* lParam)
{
if (nCode >= 0 && wParam == (IntPtr)WM_KEYDOWN)
{
KBDLLHOOKSTRUCT* replacementKey = (KBDLLHOOKSTRUCT*)lParam;
replacementKey->vkCode = 90;
}
return CallNextHookEx(_hookID, nCode, wParam, (IntPtr) lParam);
}
At the moment, this code just writes to the console. This happens in line 4 of the HookCallback method. So you need to replace that line with your own code.
However, the info you're given isn't in a very C# friendly format. You need to look at the SDK docs for LowLevelKeyboardProc to figure out how to unpack it. It turns out all the good stuff is in lParam, which is a pointer to a KBDLLHOOKSTRUCT structure.
So your code needs to marshal that to a C# equivalent. You need to declare a KBDLLHOOKSTRUCT structure, or see if there's one on pinvoke.net, and use Marshal.PtrToStructure to unpack it. You can then party on this structure as much as Windows will allow -- I think modifying the event data is a better bet than trying to kill the keyboard event and then simulate a new one (for a start, I think the simulated "send keys" would run straight into the hook itself!) -- however I haven't tried this to see what it possible. The SDK struct does include a virtual key code and scan code, so you may be able to replace them to achieve the effect you want, but this will probably take some trial and error, and will be very specific to your app.
How does this code fit in this chain of events? I need to read the input characters before they are inputed. Then, where would the code to analyse the input and decide the correct input live?
The HookCallback method is the method which you're installing to intercept keystrokes.
Finally, what's the correct 'sendInput()' type command to invoke to send a character to whatever app has focus?
To modify the character which is passed to other processes, modify the parameters (nCode, wParam, and/or lParam) before you pass them to the CallNextHookEx method.

Categories

Resources