Messaging between a DLL and a C# app

Behrens
Behrens used Ask the Experts™
on
I have a DLL that monitors global events and when it finds the correct event I want to send a message to the C# app.  So far the DLL appears to be monitoring fine but when I try to send a message to the C# app it never makes it.  When I load the DLL in C# I pass it the handle to the C# window.  Then in the DLL I send a message like so:

SendMessage(g_hAppHandle,WM_COPYDATA,(WPARAM) somedata,(LPARAM) somedata);

Then in the C# app I register a message filter that monitors for 0x004A (WM_COPYDATA).  But even though the message is sent my C# app never receives it.  It appears that I have implemented the C# message filter correctly because I can see a bunch of messages going through it, but no WM_COPYDATA message.

Does anybody have any idea why the C# app wouldn’t see the message, and how to fix it?  Thanks in advance.
Comment
Watch Question

Do more with

Expert Office
EXPERT OFFICE® is a registered trademark of EXPERTS EXCHANGE®

Commented:
When you send a message to the C# window it is running in the CLR... There are security things now in place that weren't before. An educated guess would be that it knows the message is not comming from the system so it blocks it...but then again, I may be wrong.

Commented:
I am sorry, but you are taking the hard road on this one.  Try to remember that C# is not C++.

Instead of using this convoluted windows messaging, create a delegate for your message in your DLL.  If you spend a couple hours, you will notice a delegate is simply a method descriptor for an event (simply put).  Declare the delegate like so (you can specify the parameters that you wish to send however you like):

public delegate void StatusMessageHandler(object sender, String Message, String Source, StatusType MessageType, byte[] data); // or however you like the parameters to be

Then, in the class in your DLL that wants to throw the events, add this line:

public event StatusMessageHandler StatusMessage;

In the methods of the class where you want to fire the event, use this line:

StatusMessage(this,"The message goes here", "Source Info", StatusType.EventOccurred,myData);

In your CLIENT APP, create a function to capture the event call:
private void StatusMessage(object sender, String Message, String Source, ImportAction.StatusType Type,Byte [] data)
{
}

Use this line to subscribe to the event after creating the object (class instance) that defines it:
MyObject m_Object = new MyObject();
m_Object.StatusMessage += new MyObject.StatusMessageHandler(StatusMessage);

Once this is complete, your client apps will receive the events from your DLL.  If you want to call a MessageBox in your StatusMessage message handler, that is your perogative, but I do not recommend passing window handles around.

Hope this helps,

Bg

Author

Commented:
bgungor,

Thanks for the help.  

But I forgot to add that the DLL was written in C++.  I like the idea of having a callback function but I am not sure it will work with what I have.  In the DLL I create a global hook SetWindowsHookEx(WH_CALLWNDPROCRET,(HOOKPROC) CallWndProc,g_hinstDLL,0); and then in the CallWndProc I watch for the WM_COPYDATA message.  When it sees a WM_COPYDATA message directed at a particular window I want it to tell my C# app about it.  I believe that since the DLL is loaded in other processes it has to use some type of IPC to communicate back to my app.  So that is why I chose the SendMessage function with the WM_COPYDATA message.  Do you think if I pass it a function pointer (delegate) that it would work?

Sorry for the confusion.  If you have any other suggestions I would appreciate it.

Wayne
Become a CompTIA Certified Healthcare IT Tech

This course will help prep you to earn the CompTIA Healthcare IT Technician certification showing that you have the knowledge and skills needed to succeed in installing, managing, and troubleshooting IT systems in medical and clinical settings.

Commented:
Sending a delegate/function pointer will work. I have done that...

Author

Commented:
nuron,

I think I have heard about this security stuff.  Do you know how to get past it?  I started up Spy++ and the WM_COPYDATA messages are definitely making it to the C# app but it must not be processing them.

Wayne

Commented:
you could always send messages using tcp/ip :o)

Try this:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vjref98/html/com.ms.wfc.app.Application_addMessageFilter.asp

maybe it will give some ideas...

Author

Commented:
nuron,

That is what I have in my C# app right now (MessageFilter).  I can see a ton of messages going through the app but no WM_COPYDATA messages from my DLL.

Commented:
are you sure that you have the correct window handle you are posting to?

TCP/IP is simpler

Author

Commented:
nuron,

Yes I am sure.  I sent the window handle to the debugger and then in spy++ I confirmed that it is the handle.  So I attached to the window in spy++ and I can see the WM_COPYDATA message being sent to the app window.  But like I said, for some reason it is not making it to the messagefilter.

Commented:
Why not use TCP/IP?

Author

Commented:
nuron,

Well I guess I could use TCP/IP but it shouldn’t have to come to that.

So I have been doing some more digging and it looks like the messagefilter will not catch messages sent using the SendMessage function.  Since the messagefilter is just a hook into the internal message loop; it only sees messages posted to the message queue.  SendMessage bypasses this message queue and sends the message directly to the target window procedure.  So I overrode the WndProc in my C# app and now I can see the WM_COPYDATA messages, whew!

Thank you nuron for your help.

Wayne

Author

Commented:
nuron,

Well I guess I could use TCP/IP but it shouldn’t have to come to that.

So I have been doing some more digging and it looks like the messagefilter will not catch messages sent using the SendMessage function.  Since the messagefilter is just a hook into the internal message loop; it only sees messages posted to the message queue.  SendMessage bypasses this message queue and sends the message directly to the target window procedure.  So I overrode the WndProc in my C# app and now I can see the WM_COPYDATA messages, whew!

Thank you nuron for your help.

Wayne

Commented:
Another option may be to simply add .NET support to your DLL.  Then you could accept subscribers to a defined delegate.  I will keep chewing on it, unless you've found a solution already.

Bg

Author

Commented:
bgungor,

I appreciate the help but I already found the solution.  I just need to override the WndProc() in the C# app and now I can see the WM_COPYDATA messages.  So everything is working now.  Thanks again.

Wayne

Commented:
excellent, thanks for the info...
Commented:
PAQed, with points refunded (50)

modulo
Community Support Moderator

Do more with

Expert Office
Submit tech questions to Ask the Experts™ at any time to receive solutions, advice, and new ideas from leading industry professionals.

Start 7-Day Free Trial