如何修改使用中的dll? [英] How can you modify an in-use dll?

查看:82
本文介绍了如何修改使用中的dll?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如果同一进程的多个实例正在访问某个dll,这些进程之一是否有办法获取对其的锁定,删除,替换并继续?

If I have multiple instances of the same process accessing some dll, is there a way for one of these processes to obtain the lock on it, delete it, replace it, and continue?

推荐答案

要能够替换正在使用的dll,正在使用它们的程序必须在"

To be able to replace dll's that are in use the programs using them must have their app domain in "Shadow Copy" mode. What this does is instead of using the file directly the assembly makes a copy of the file and loads that copy in to memory. This allows you to replace or delete a DLL of a currently running application, when the application is next restarted it will grab a new copy of the current version. This is how IIS makes it possible for you to update a website that is in use, it shadow copies its assemblies and when it detects a change to the directory it restarts the website loading the new versions of your assembiles.

卷影复制设置是 AppDomain级别设置,但是一旦启动AppDomain,就无法更改设置.

The Shadow Copy setting is a AppDomain level setting, however once a AppDomain is started you can not change the setting.

启用卷影复制的两种方法是使用一个小的加载程序"应用程序域,该域在您的程序之前启动,此加载程序启动一个启用了卷影复制的新AppDomain,然后启动您的程序集.

The two ways to enable Shadow Copy is either use a small "Loader" app domain that starts before your program, this loader starts a new AppDomain with Shadow Copy enabled then starts your assembly.

private static void Main(string[] args)
{
    if (AppDomain.CurrentDomain.ShadowCopyFiles == false)
    {

        var assembly = Assembly.GetEntryAssembly();
        var currentAppDomain = AppDomain.CurrentDomain;
        AppDomain newDomain = AppDomain.CreateDomain("ShadowedDomain", 
            null,
            currentAppDomain.BaseDirectory,
            currentAppDomain.RelativeSearchPath, 
            true); //<-- This true is what enables Shadow Copy on the AppDomain.

        //This calls Main again in the new AppDomain and blocks till the call to Main exits.
        newDomain.ExecuteAssembly(assembly.Location, args);
     }
    else
    {
        RealMain(args);
    }
}

private static void RealMain(string[] args)
{
    //Your code here.
}

一个缺点是您的主EXE仍将被锁定,但您的EXE加载的所有DLL都将使用卷影复制进行加载.

One drawback is your main EXE will still be locked but any DLL's your EXE loads will be loaded using Shadow Copy.

另一个选项与第一个类似,但是您可以告诉自己的程序集使用自定义加载程序来启用Shadow Copy,而不是手动运行该加载程序并将其指向您的程序集.为此,首先要制作一个单独的dll作为加载程序,并包含一个从AppDomainManager派生的类,此文件将不会被影子复制.

The other option is similar to the first, but you can tell your own assembly to use a custom loader to enable Shadow Copy instead of manually running the loader and pointing it to your assembly. To do this first make a separate dll that will act as the loader and have it contain a class derived from AppDomainManager, this file will not be shadow copied.

using System;

namespace DomainManager
{
    public class ShadowDomainManager : AppDomainManager
    {
        public override void InitializeNewDomain(AppDomainSetup appDomainInfo)
        {
            base.InitializeNewDomain(appDomainInfo);
            appDomainInfo.ShadowCopyFiles = "true";
        }
    }
}

然后在程序集的app.config中,可以告诉它使用加载程序dll.

Then in the app.config of your assembly you can tell it to use your loader dll.

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <startup>
    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/>
  </startup>
    <runtime>
      <appDomainManagerType value="DomainManager.ShadowDomainManager" />
      <appDomainManagerAssembly
         value="DomainManager, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
    </runtime>
</configuration>

现在,您的exe及其加载的所有DLL(存储在应用程序目录或其子目录中)将被加载到Shadow Copied App Domain中,并且在使用时可以删除/替换.

Now your exe and any DLL's it loads (that are stored in the application directory or its subdirectories) will be loaded in to a Shadow Copied App Domain and can be deleted/replaced while in use.

这篇关于如何修改使用中的dll?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆