12

I have a buggy third-party DLL files that, after some time of execution, starts throwing the access violation exceptions. When that happens I want to reload that DLL file. How do I do that?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Poma
  • 8,174
  • 18
  • 82
  • 144
  • 2
    How about loading the dll into a proxy process and terminate the whole process? Usually a process is considered broken after access violations. – CodesInChaos Jun 23 '11 at 11:03
  • How to do that? I heard very little about AppDomains. Can you please post some example? – Poma Jun 23 '11 at 11:15
  • 2
    Since it's a native dll AppDomains won't help you. You need to have a second process that loads the dll and then uses some form of inter process communication to transfer calls between processes. .net remoting might be one way. But I haven't done that myself. – CodesInChaos Jun 23 '11 at 11:17
  • Looks like Stecya's solution is much simpler. – Poma Jun 23 '11 at 11:36
  • 3
    Expecting a clean unload and reload from a dll that already has corrupted the memory so much that it throws access violation is not something I like. The dll lost track of which of its pointers are still valid. How should it free its memory cleanly on unload? – CodesInChaos Jun 23 '11 at 11:53
  • 2
    Access violation errors are fatal in nature. I doubt you can catch them using try catch handlers and then take some corrective measure. – RBT Feb 09 '17 at 03:37

3 Answers3

24

Try this

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

If you want to call functions first you must create delegate that matches this function and then use 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);
bluish
  • 26,356
  • 27
  • 122
  • 180
Stecya
  • 22,896
  • 10
  • 72
  • 102
  • And how to call my dll functions? When I declare them as `DllImport` this approach doesn't work – Poma Jun 23 '11 at 11:14
  • 1
    Did you resolve this? can you provide some code snippe of the native code? how should the native code be declared and how does the delegate look? Thanks – freshWoWer Aug 05 '11 at 18:16
  • @Poma Did you get this working ? Can you please tell me how to get the GetDelegateForFunctionPointer working ? – GuidoG Jan 26 '18 at 07:46
0

Load the dll, call it, and then unload it till it's gone.

I've adapted the following code from the VB.Net example here.

  [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;
  }
aboy021
  • 2,096
  • 2
  • 23
  • 23
0

Create a worker process that communicates via COM or another IPC mechanism. Then when the DLL dies, you can just restart the worker process.

Ben
  • 34,935
  • 6
  • 74
  • 113