如何动态加载和卸载本地 DLL 文件?

12

我有一个有缺陷的第三方 DLL 文件,执行一段时间后开始抛出访问冲突异常。当发生这种情况时,我想重新加载该 DLL 文件。我该如何做到这点?


2
把dll加载到代理进程中,然后终止整个进程怎么样?通常情况下,访问违规后进程被视为已崩溃。 - CodesInChaos
怎么做呢?我对AppDomains了解很少。你能否提供一些例子? - Poma
2
由于它是本地dll,AppDomains对你没有帮助。你需要有第二个进程来加载dll,然后使用某种形式的进程间通信在进程之间传递调用。.net remoting可能是一种方法。但我自己没有做过这样的事情。 - CodesInChaos
看起来Stecya的解决方案更简单。 - Poma
3
期望从一个已经损坏内存以至于抛出访问违规异常的dll中进行清洁卸载和重新加载并不是我喜欢的事情。这个dll迷失了哪些指针仍然有效的追踪。它应该如何在卸载时清理其内存? - CodesInChaos
2
访问冲突错误具有致命性质。我怀疑您无法使用try catch处理程序捕获它们,然后采取一些纠正措施。 - RBT
3个回答

24

试一下这个

[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr LoadLibrary(string libname);

[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
private static extern bool FreeLibrary(IntPtr hModule);

//Load
IntPtr Handle = LoadLibrary(fileName);
if (Handle == IntPtr.Zero)
{
     int errorCode = Marshal.GetLastWin32Error();
     throw new Exception(string.Format("Failed to load library (ErrorCode: {0})",errorCode));
}

//Free
if(Handle != IntPtr.Zero)
        FreeLibrary(Handle);

如果你想要调用函数,首先必须创建一个匹配该函数的委托,然后使用WinApi的GetProcAddress函数。

[DllImport("kernel32.dll", CharSet = CharSet.Ansi)]
private static extern IntPtr GetProcAddress(IntPtr hModule, string lpProcName); 


IntPtr funcaddr = GetProcAddress(Handle,functionName);
YourFunctionDelegate function = Marshal.GetDelegateForFunctionPointer(funcaddr,typeof(YourFunctionDelegate )) as YourFunctionDelegate ;
function.Invoke(pass here your parameters);

如何调用我的 DLL 函数?当我将它们声明为 DllImport 时,这种方法不起作用。 - Poma
1
你解决了吗? 你能提供一些本地代码片段吗?本地代码应该如何声明,委托又是什么样子的呢?谢谢。 - freshWoWer
@Poma,你解决了这个问题吗?你能告诉我如何让GetDelegateForFunctionPointer工作吗? - GuidoG

0
创建一个通过COM或其他IPC机制进行通信的工作进程。然后当DLL死亡时,您可以重新启动工作进程。

0

加载dll,调用它,然后卸载它直到它消失。

我从VB.Net示例这里中改编了以下代码。

  [DllImport("powrprof.dll")]
  static extern bool IsPwrHibernateAllowed();

  [DllImport("kernel32.dll")]
  static extern bool FreeLibrary(IntPtr hModule);

  [DllImport("kernel32.dll")]
  static extern bool LoadLibraryA(string hModule);

  [DllImport("kernel32.dll")]
  static extern bool GetModuleHandleExA(int dwFlags, string ModuleName, ref IntPtr phModule);

  static void Main(string[] args)
  {
        Console.WriteLine("Is Power Hibernate Allowed? " + DoIsPwrHibernateAllowed());
        Console.WriteLine("Press any key to continue...");
        Console.ReadKey();
  }

  private static bool DoIsPwrHibernateAllowed()
  {
        LoadLibraryA("powrprof.dll");
        var result = IsPwrHibernateAllowed();
        var hMod = IntPtr.Zero;
        if (GetModuleHandleExA(0, "powrprof", ref hMod))
        {
            while (FreeLibrary(hMod))
            { }
        }
        return result;
  }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接