Replacing .dll files while the application is running?

I have several game servers that use a certain .dll file to run. Sometimes I need to update the game servers but I don't wanna interrupt the games that are already running.

Is there a way to replace the .dll file (it's locked by Windows) so the next instances of the game servers that use that file open the new version, and the old ones keep using the old version of that .dll until they are restarted?

Is it safe to just unlock the file using one of those tools that do that and replace it?


Solution 1:

Actually, you can and it usually works without any issue (although not always)

What you do is rename the file without moving it (i.e. without changing the file location in the folder structure) and move the new file to the containing folder.

That will keep the handles to the file valid and working so that pre-existing instances still will be able to access the file properly and new instances (or new handles) wil go to the new file.

Obviously, if a program re-opens the same dll file and expects it to stay exactly the same (for instance, if there is resources to be loaded from the dll and that references to these resources is extracted from code running when the dll is loaded), this will cause issue but this is definitely not the norm.

Solution 2:

No. Even though a DLL may be entirely mapped into physical memory while the application runs, there is definitely no guarantee of that. Portions of DLLs (and even executables) can be mapped into RAM while other bits of it stay on disk, and may be read in at a later time.

Changing the file on disk while Windows has bits of it mapped in RAM would not end well. Windows locks it for a good reason.

Edit: I need to clarify something since some people seem intent on blaming Windows for what is actually an application design issue, not an OS design issue.

You can update DLLs that applications use in Windows without terminating the process, but the application must have been written in such a way that it can be signaled to unload the assembly, wait for the update to finish, then reload the DLL. This has nothing to do with the OS you're running. It's an application design issue.

Edit: Also see Stephane's answer for a possible solution that might work, depending on how your specific application responds to its DLL changing. I think he deserves an upvote.

Solution 3:

No, you should not tinker with the existing file handles.

If you can take control of the loading of the assembly, and specify it is opened with FileShare.Delete, then it should be possible to rename it. Existing processes will continue to reference the renamed assembly.

https://stackoverflow.com/questions/7147577/programmatically-rename-open-file-on-windows.

Solution 4:

You could look at how the asp.net hosted process works and develop something similar.

It takes the whole web application and moves it to a temporary location from which the application is actually loaded. Then it leaves a process to monitor for changes in the original folder, when detected, it spins up a new instance of the application in a new temporary location and starts redirecting new requests to that app. The old app is then torn down once pending requests are finished.

(Nitpicking, yes, it's a simplified view of things, in most cases IIS queues the requests until the new app is able to take over)

Solution 5:

No, unfortunately it is not possible.

Sorry, to be exact unless there is late binding, meaning the app uses that dll when runs some part of code in that dll, but it is still not reliable.