簡體   English   中英

卸載使用DllImport加載的DLL

[英]Unload a DLL loaded using DllImport

如何卸載在C#中使用DllImport加載的DLL?

從[DllImport] pinvoke聲明加載的進程中卸載非托管DLL的最可靠方法是通過pinvoking LoadLibrary()再次自己加載它。 這為DLL提供了可靠的DLL處理,即使DLL的模塊名稱不明確也能正常工作。 它在運行時沒有任何影響,除了Windows加載器將DLL的內部引用計數從1增加到2。

然后,您可以將FreeLibrary() 兩次旋轉以將引用計數減少為0,並將其從LoadLibrary()傳遞給IntPtr。 卸載DLL,以及任何加載的依賴DLL。

要注意的是,當你嘗試這樣做后,再次的PInvoke的DLL 任何導出函數, 任何時候你會得到非常討厭失敗。 pinvoke marshaller不知道DLL不再存在,並且會在它認為仍然有效的地址處調用該函數。 如果幸運的話,哪些程序會使用AccessViolation異常對您的程序進行轟炸。 或者運行一個完全隨機的代碼,如果你不是那么幸運,以前DLL占用的地址空間被另一個DLL重用。 任何事情都可能發生,沒有一件好事。

這應該釋放先前在您調用P / Invoke函數時加載的模塊。

[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);
        }
    }
}

根據彼得斯的建議,這對我有用:

    [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);
            }
        }
    }

晚了,但我已經做了一個工具來做到這一點。 它應該在Unity中運行,但我認為它可以被其他C#解決方案采用。 它可以在這里找到: https//github.com/mcpiroman/UnityNativeTool

請注意,它本質上是一個黑客(但經常使用hack,請參閱Harmony ),所以我不建議在生產代碼中使用它。

由於我在瀏覽信息時遇到了這些信息,因此我想我會回過頭來解決OSX IN UNITY上的Sixense SDK問題。 您將在那里看到在OSX上動態加載/卸載dylib的實現:

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

如果您是函數式編程的粉絲,那么您可以使用LINQ來實現@IllidanS4建議的內容:

[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);
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM