late binding to an unmanaged dll

Hello all,
      I am writing an application in C# that has a need to call DLLs whose file name, path, entry point and parameter signature will be passed into my application at run time.  I have found a few vague references to using Reflection.Emit, but after reading the articles, it seems that Reflection.Emit can not handle the criteria outlined above.  All the documentation I have read about P/Invoke requires early binding to a known file, entry point and parameter signature.  I have read one article that talks about writing an assembly language DLL as a bridge between .NET and unmanaged DLLs.  While an extraneous DLL is an option, I would prefer to find a more elegant solution to the problem.  The one criterion above that is flexible is the parameter signature, but again I would prefer to be able to allow flexibility in that as well.

So to sum up, the problem is allowing .NET to call an unamanged DLL whose details (file name, entry point and parameter signature) are not known at compile time.

Thanks all.
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Just write some C# that uses PInvoke (or your prefered .NET language) out to a .cs file, compile it, and load it using Reflection.

That said, doing PInvoke knowing the signatures and sometimes implementation details can be hard, not knowing can be REALLY hard. Note that even doing that in unmanaged code is still hard. DLL entrypoints have little to no information about param types and characteristics, so you'll have to trust your user's input, as well as all the "tips" on how to treat each param (that's what the PInvoke attributes are for)

Another option is to build a Managed CPP assembly that deals with calling the unmanaged call and does all the marshaling, etc... (essentially redoing what PInvoke does).

edcAuthor Commented:
Hi Vasco,

>>not knowing can be REALLY hard (Tell me about it :) )

The project is a workflow engine.  Entities in the workflow have to be able to call out to user specified DLLs.  I can write a spec that requires a function named "functionWhatever(string data)" in the DLL, but I have no way of knowing the dll name.  So, do you, per chance, have more info on how to implement this?

The user specified DLLs can be in managed code ? If you are still specing, make it so that they write MANAGED code. It will simplify your life (and your users) a lot.
Here are some examples:

If they could, that would be a lot easier. Then it could all be acomplished with reflection which would end up being a lot more flexible and robust
If they can't, and if you really have to use that mechanism, i advise you to just take a look at the PInvoke docs.

If you go down the managed cpp road, then you'll need to call LoadLibrary, then GetProcAddress, marshall the parameters, call the function, unmarshall the params, get back to managed code...
Here's an example of the Cpp part:

The generation of some C# stub that you would customize on each run is also a possibility (as is generating code on the fly with reflection.emit, but probably a lot more work...)
Personally, i would probably just use a C# file, save it, compile it and load it... (well, i wouldn't use a DLL entrypoint at all, but if i did...)

As a side note, note that you should encourage your users to use few DLLs. Loading a DLL into your address space takes disk/io, cpu, mem and address space.



Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
There is a way to do this... but it's a bit messy.

Let's say that you know in advance the "signatures" for the public methods and properties in the external DLL.  You could create a generic DLL class module that contained those empty methods and properties in managed code.   You would then add a reference to this generic DLL to your C# application.  Then during execution you'd load the *real* DLL file instead of the empty generic DLL file.

This works a bit better when you're writing both pieces... because you could set the real DLL class modules to inherit from the generic DLL class module.  (That means that you'd have to add a reference to the generic DLL file again).

It's a bit of smoke and mirrors...  you'll telling the application to expect a module of some "base" class,  yet you're faking it out... and providing it a module of some inherited class.   As long as the signatures for the public methods and properties are the same in the two, your application will never know that it's not running the generic DLL file (the only one of the two that it knows about).

Here is an example of the execution phase (in VB.Net, but hey.. you'll get the point)

        Dim Assmbly As Reflection.Assembly
        Dim PlugInType As Type
        Dim ProbePlugIn As PlugInBase.PlugInBase
        Dim PlugInName, temp As String

            ' If running under the IDE, then always get the development version of the
            ' plugin DLL from it's development directory (which is a subdirectory under
            ' this developement directory).
            If System.Diagnostics.Debugger.IsAttached Then
                Assmbly = Reflection.Assembly.LoadFrom(Application.StartupPath & "\..\" & PlugInName & "\bin\" & PlugInName & ".dll")
                Assmbly = Reflection.Assembly.LoadFrom(Application.StartupPath & "\" & PlugInName & ".dll")
            End If
            PlugInType = Assmbly.GetType(Assmbly.GetName.Name & "." & PlugInName, True, True)
            ProbePlugIn = CType(Activator.CreateInstance(PlugInType), PlugInBase.PlugInBase)
        Catch ex As Exception
            MsgBox("Yikes!, can't find the " & PlugInName & ".dll plug-in" & vbCr & ex.message, MsgBoxStyle.Exclamation, "Internal Program Error")
            Exit Sub
        End Try
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Web Components

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.