windows 在不停止服务的情况下更新 dll

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/226581/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-15 11:30:32  来源:igfitidea点击:

Update a dll without stopping the service

.netwindowsdllwindows-services

提问by Matt

I would like to update a dll for a server process without stopping the service. How do I do that? A bit like how asp.net automatically picks up new dlls placed in the bin folder.

我想在不停止服务的情况下更新服务器进程的 dll。我怎么做?有点像 asp.net 如何自动选择放置在 bin 文件夹中的新 dll。

回答by Gulzar Nazim

Asp.Net uses a technique called shadow copy

Asp.Net 使用一种称为卷影复制的技术

If you copy an updated dll into an application's bin subdirectory, the ASP.NET runtime recognizes there is new code to execute. Since ASP.NET cannot swap the dll into the existing AppDomain , it starts a new AppDomain. The old application domain is “drain stopped”, that is, existing requests are allowed to finish executing, and once they are all finished the AppDomain can unload. The new AppDomain starts with the new code and begins taking all new requests.

如果将更新的 dll 复制到应用程序的 bin 子目录中,则 ASP.NET 运行时会识别出要执行的新代码。由于 ASP.NET 无法将 dll 交换到现有的 AppDomain 中,因此它会启动一个新的 AppDomain。旧的应用程序域是“耗尽停止”的,即允许现有请求完成执行,一旦它们都完成,AppDomain 可以卸载。新的 AppDomain 以新代码开始,并开始接受所有新请求。

Typically, when a dll loads into a process, the process locks the dll and you cannot overwrite the file on disk. However, AppDomains have a feature known as Shadow Copy that allows assemblies to remain unlocked and replaceable on disk.

通常,当 dll 加载到进程中时,进程会锁定 dll,并且您无法覆盖磁盘上的文件。但是,AppDomains 具有称为 Shadow Copy 的功能,该功能允许程序集在磁盘上保持解锁和可替换状态。

The runtime initializes ASP.NET with Shadow Copy enabled for the bin directory. The AppDomain will copy any dll it needs from the bin directory to a temporary location before locking and loading the dll into memory. Shadow Copy allows us to overwrite any dll in the bin directory during an update without taking the web application offline.

运行时在为 bin 目录启用卷影复制的情况下初始化 ASP.NET。AppDomain 会将它需要的任何 dll 从 bin 目录复制到一个临时位置,然后再锁定 dll 并将其加载到内存中。Shadow Copy 允许我们在更新期间覆盖 bin 目录中的任何 dll,而无需使 Web 应用程序脱机。

回答by Kev

In addition to Gulzar's answer:

除了 Gulzar 的回答:

If your service is just directly referencing the DLL's you'll need to re-design the service a bit to utilise AppDomains and the ShadowCopy capabilities to take advantage of this feature.

如果您的服务只是直接引用 DLL,则您需要稍微重新设计服务以利用 AppDomains 和 ShadowCopy 功能来利用此功能。

We do something like this where the service is just a shell/host process. All functionality is loaded into separate app domains as an when required.

我们做这样的事情,其中​​服务只是一个外壳/主机进程。所有功能都在需要时加载到单独的应用程序域中。

http://blogs.msdn.com/junfeng/archive/2004/02/09/69919.aspx

http://blogs.msdn.com/junfeng/archive/2004/02/09/69919.aspx

回答by computinglife

When a process has loaded a dll it is not possible to change it.

当一个进程加载了一个 dll 时,就不可能更改它。

IIS does not keep a DLL loaded in memory when it is not being used (affected by the Cache property) and i assume the same is the case with ASP.NET. If you follow the same strategy you could update your dlls too.

IIS 在不使用时(受 Cache 属性的影响)不会将 DLL 加载到内存中,我认为 ASP.NET 也是如此。如果您遵循相同的策略,您也可以更新您的 dll。

However if your dlls are being used, you should have a way to tell your server process to unload all your dlls.

但是,如果您的 dll 正在被使用,您应该有办法告诉您的服务器进程卸载所有的 dll。

For this to happen the server process must load all the DLLS using the LoadLibrary calls such that it can unload them when it receives a communication asking it to do so.

为此,服务器进程必须使用 LoadLibrary 调用加载所有 DLLS,以便它可以在收到要求它这样做的通信时卸载它们。

Communicating with the server process can be done by creating a globally available named event that can be accessed by the new program and used to signal the running process that an update is about to happen. (You could also think of other variations of doing this).

与服务器进程的通信可以通过创建一个全局可用的命名事件来完成,该事件可由新程序访问并用于向正在运行的进程发出更新即将发生的信号。(您也可以考虑这样做的其他变体)。