Unload a DLL loaded using DllImport

2019-01-10 15:13发布

How do I unload a DLL which has been loaded using DllImport in C#?

标签: c# dllimport
5条回答
Explosion°爆炸
2楼-- · 2019-01-10 15:20

Just in case if you are fan of functional programming then you can use LINQ to achieve what @IllidanS4 has suggested:

[DllImport("kernel32", SetLastError=true)]
static extern bool FreeLibrary(IntPtr hModule);

public static void UnloadModule(string moduleName)
{
   var loadedAssemblyModule =
            Process.GetCurrentProcess().Modules.OfType<ProcessModule>()
                .FirstOrDefault(x => x.ModuleName == moduleName);

   if (loadedAssemblyModule != null)
       FreeLibrary(loadedAssemblyModule.BaseAddress);
}
查看更多
在下西门庆
3楼-- · 2019-01-10 15:22

Since I came across the information here while I was looking around for information I figure I will contribute back what I ended up doing to fix an issue with the Sixense SDK on OSX IN UNITY. You'll see in there an implementation of dynamically loading/unloading a dylib on OSX:

https://gist.github.com/amirebrahimi/d7b02c01bcd3ca7da144

查看更多
够拽才男人
4楼-- · 2019-01-10 15:27

The most reliable way to unload an unmanaged DLL from a process that got loaded by a [DllImport] pinvoke declaration is to load it yourself, again, by pinvoking LoadLibrary(). That gives you a reliable handle to the DLL and works correctly even if the module name of the DLL is ambiguous. It doesn't have any affect at runtime, other than the Windows loader increasing the internal reference count on the DLL from 1 to 2.

You can then pinvoke FreeLibrary() twice to decrease the reference count to 0, passing it the IntPtr you got from LoadLibrary(). That unloads the DLL, as well as any dependent DLLs that got loaded.

Beware that you'll get very nasty failure when you try to pinvoke any exported function on the DLL again, any time after doing this. The pinvoke marshaller is unaware that the DLL isn't around anymore and will call the function at the address it thinks is still valid. Which bombs your program with an AccessViolation exception if you are lucky. Or runs a completely random bit of code if you are not so lucky and the address space formerly occupied by the DLL got re-used by another DLL. Anything can happen then, none of it good.

查看更多
放荡不羁爱自由
5楼-- · 2019-01-10 15:28

Based on Peters recommendation this works for me:

    [DllImport("kernel32", SetLastError = true)]
    private static extern bool FreeLibrary(IntPtr hModule);

    public static void UnloadImportedDll(string DllPath)
    {
        foreach (System.Diagnostics.ProcessModule mod in System.Diagnostics.Process.GetCurrentProcess().Modules)
        {
            if (mod.FileName == DllPath)
            {
                FreeLibrary(mod.BaseAddress);
            }
        }
    }
查看更多
兄弟一词,经得起流年.
6楼-- · 2019-01-10 15:32

This should free a module previously loaded when you called P/Invoke function.

[DllImport("kernel32", SetLastError=true)]
static extern bool FreeLibrary(IntPtr hModule);

public static void UnloadModule(string moduleName)
{
    foreach(ProcessModule mod in Process.GetCurrentProcess().Modules)
    {
        if(mod.ModuleName == moduleName)
        {
            FreeLibrary(mod.BaseAddress);
        }
    }
}
查看更多
登录 后发表回答