sichinumi
sichinumi

Reputation: 1875

SendMessage disappears into the ether

I'm attempting to pass messages between two applications - one of them is a plugin, and the other is a standalone configuration utility. When my plugin detects an event, I want to send a message to my utility and prompt the user to reconfigure.

The code I'm using is as follows:

[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr SendMessage(IntPtr hwnd, uint Msg, IntPtr wParam, IntPtr lParam);
private const int MESSAGE_UNAUTH = 0x401;

[... misc logic here, function def, etc]

Process[] processes = Process.GetProcessesByName("MyConfigurationApplication");

if (processes.Length > 0)
{
    foreach (Process p in processes)
    {
        SendMessage(p.MainWindowHandle, MESSAGE_UNAUTH, IntPtr.Zero, IntPtr.Zero);
    }
}

And then in my receiving process, I have the following code (I also defined MESSAGE_UNAUTH in this class):

protected override void WndProc(ref Message message)
{
    if (message.Msg == MESSAGE_UNAUTH)
    {
        MessageBox.Show("Message received");
    }
    base.WndProc(ref message);
}

Things I have already verified with the debugger:

  1. The message is getting sent. All the code in the Sender, including the SendMessage call, is executing.
  2. The message is not getting received (obviously).
  3. The WndProc() function is not getting called at all when the message is sent. It is, however, getting called a whole bunch of times when the configuration utility is launched (I'm assuming this is Windows' behavior).

I've gone through enough online tutorials to need eyedrops, and as far as I know, everything here is syntax-correct and "proper," but for some reason, between when I send the message and when the receiver's WndProc() should be called, black magic is happening.

Any ideas would be greatly appreciated.


Update: Using Marshal.GetLastWin32Error(), I am getting an error #1400, which appears to correspond to an invalid window handle. However, I don't see why that would be the case, since the process was found and we entered the for each loop successfully. The one caveat I can think of is that my configuration utility is presented as a taskbar icon, and doesn't necessarily have a visible window at all times - would this prevent p.MainWindowHandle from being valid? If so, how can I work around this to pass a message to the process instead of the window?


Update: Process.MainWindowHandle is 0, so it looks like that is indeed the problem - when the form in my configuration utility is not visible, no valid window handler is returned, even though my utility icon is visible in the notification bar. Is there any way I can send a message to the process, or even to the taskbar icon?

Upvotes: 2

Views: 683

Answers (5)

sichinumi
sichinumi

Reputation: 1875

Problem was that the process I was sending the message to only existed as a tooltip icon and not as an active, open window. Turns out the windows message functionality is designed for window-to-window messages, not process-to-process messages.

Solution was aforementioned kludgy system of file IO handlers.

Upvotes: 0

senthilkumar
senthilkumar

Reputation: 1

Use Windows Registermessage in bothe sender and receiver end will resolve the problem

Upvotes: 0

GETah
GETah

Reputation: 21459

Depending on the .NET framework you are using, this will help resolve your issues. There was a bug in the old .NET frameworks (2.0 I think) where calling to Process.MainWindowHandle when the process starts up returns 0. Any subsequent call will also result in a 0. This is due to caching the main window handle, which should have been fixed in .NET 3.0 and later.

You might also try giving full trust to your WndProc which might help. Something like:

[System.Security.Permissions.PermissionSet( System.Security.Permissions.SecurityAction.Demand, Name="FullTrust")]
protected override void WndProc(ref Message m) 
{
    //...
}

On a side note, if you can change your implementation then I strongly suggest you go for better inter process communication means such as sockets, TCPChannel (which I think is replaced by WCF), named pipes...

Upvotes: 1

Jacob Seleznev
Jacob Seleznev

Reputation: 8151

You can try to enumerate all windows associated with the process. See How to enumerate all windows belonging to a particular process using .NET?

Upvotes: 1

zmbq
zmbq

Reputation: 39069

The message might not be sent, it might be blocked. See here: When a message is blocked by UIPI the last error, retrieved with GetLastError, is set to 5 (access denied).

Upvotes: 0

Related Questions