Search code examples
c#pinvokeunmanageddllimport

Programmatically change the location of an unmanaged DLL to import


Possible Duplicate:
How to separate managed and unmanaged DLLs in another directory

I am using unmanaged code with my C# managed code. I have the unmanaged DLL embedded in the executable of the application. In order to make this work I extract the resource/DLL to a file before I make any calls to the DLLs methods.

public static class ResourceExtractor
{
    public static void ExtractResourceToFile(string resourceName, string filename)
    {
        if (!System.IO.File.Exists(filename))
            using (System.IO.Stream s = System.Reflection.Assembly.GetExecutingAssembly().GetManifestResourceStream(resourceName))
            using (System.IO.FileStream fs = new System.IO.FileStream(filename, System.IO.FileMode.Create))
            {
                byte[] b = new byte[s.Length];
                s.Read(b, 0, b.Length);
                fs.Write(b, 0, b.Length);
            }
    }
}

So that before I make calls to the DLL I make sure to do the following:

ResourceExtractor.ExtractResourceToFile("Namespace.dll_name.dll", "dll_name.dll");

And to wrap the methods of the unmanaged DLL I have...

public class DLLWrapper
{
    public const string dllPath = "dll_name.dll";

    [DllImport(dllPath)]
    public static extern uint functionA();

    [DllImport(dllPath)]
    public static extern uint functionB();

    [DllImport(dllPath)]
    public static extern uint functionC();
}

Now for the question...

This all works. What I DO NOT like is that it creates the DLL sitting next to the executable. I would much rather create the DLL in a temporary directory and load it from there. Something like...

string tempDLLname = Path.GetTempFileName();
ResourceExtractor.ExtractResourceToFile("Namespace.dll_name.dll", tempDLLname );
DLLWrapper.dllPath = tempDLLname;

...

public class DLLWrapper
{
    public static string dllPath;

    [DllImport(dllPath)]
    public static extern uint functionA();

    [DllImport(dllPath)]
    public static extern uint functionB();

    [DllImport(dllPath)]
    public static extern uint functionC();
}

However this does not work because [DllImport(path)] requires the path to be a const. So how do you change the location that you want to load the DLL from? I won't know until runtime.


Solution

  • Before you invoke any calls against the dll you can explicitly use LoadLibrary and pass in the full path that you extracted it to.

    http://msdn.microsoft.com/en-us/library/windows/desktop/ms684175(v=vs.85).aspx