views:

53

answers:

3

There's another question similar to mine, but I wanted to gather some specifics:

I want to create a DLL that is called from unmanaged code. When the unmanaged functions are called in the DLL, I want to collect information and show it in a kind of form.

What I'd like to do is, when DllMain() is called, and the reason is DLL_PROCESS_ATTACH, I would like to instantiate a form. This form should be run on a separate thread. When my function FOO() inside my DLL is called, I would like to take the information from FOO(), dispatch it to the form for rendering.

So, more specifically:

i) What is the proper way to create a DLL project and have the ability to have Windows forms created in the designer be available to the DLL?

ii) What is the correct way to give this form its own thread and message processing loop?

iii) How do I dispatch information from the unmanaged DLL functions to the form, or, alternatively a managed class that can update its own state and the form?

The form inside the DLL is sort of a "monitor" for data passing in and out of the DLL, so I can keep track of errors/bugs, but not change the core functionality of the DLL functions that are available.

A: 

You should be very careful when doing things in DllMain (You CANNOT call LoadLibrary or other functions that acquire the loader lock)

w0lo
A: 

An application can only have one message processing loop - all your UI must exist on a single thread. You can create a modeless form that sits on the application's UI thread, but if the UI thread is "busy" it won't dispatch messages to your form, so it won't be interactive.

IMHO the easiest way to avoid trouble would be to write a separate .exe to handle the form and have your dll simply launch it so that the whole form runs as a separate regular WinForms process. Then you could use Sockets, WM_USER messages, or even just shared files to send commands and data to the form's process from your dll. (A socket would have the advantage that you could run the monitoring form on a different PC, too)

Jason Williams
A: 

Here's what I do:

    
static HWND *callbackWindow;
struct Info instanceInfo;
DLLEXPORT void setCallbackWindow(HWND* newCallbackWindow) {
       callbackWindow = newCallbackWindow;
}
DLLEXPORT void checkForInformation() {
        /* gather some info ... */
        instanceInfo.computerOver = VERY_YES;
}
DLLEXPORT void retrieveInformation() {
        PostMessage(callbackWindow, ...);
}

First, set the callback to Form.Handle. Thenyou can either call checkForInformation() by overriding the WndProc in a .NET form OR you can set a timer to periodically call checkForInformation. Once your form is ready for the info call retrieveInformation() and check in the Form's window handler for a magic message (WM_USER + your offset).

MrAnonymous