C# AppDomain load(byte[]) throws FileLoadException (HResult

本文关键字:throws FileLoadException HResult AppDomain load byte | 更新日期: 2023-09-27 18:05:01

我有一个单独的。net 4应用程序来远程升级主应用程序(功能)。由于最近的更改,它现在与主应用程序共享对同一文件的引用。这当然可以防止它复制在新的dll,将覆盖该文件(基本上dll,除其他事项外,处理设置-从我需要检索一些数据,防止只是不加载它)。通过浏览SO,我想我已经成功地取得了进一步的进展,但现在遇到了一个障碍。

我试图从资源中加载dll(由于应用程序从应用程序目录中找到较旧的common.dll而不工作,如果我从资源中加载,则同一dll的两个不同版本之间存在类型冲突)。因为似乎没有任何方法可以更改默认应用程序域的DisallowApplicationBaseProbing设置(以防止从目录加载旧的common.dll),所以我创建了启动程序应用程序,该应用程序将启动带有该选项集的升级程序到新创建的应用程序域。为了防止启动器通过对升级程序的引用来获取对设置文件的引用,我将两者都包含为资源(如果直接引用,它的子引用会导致文件从应用程序目录加载并阻止文件复制),您可以在下面看到-我对其他配置也有类似的块。

<When Condition=" '$(Configuration)' == 'Debug' ">
  <ItemGroup>
    <EmbeddedResource Include="..'..'Libraries'Common'bin'Debug'Common.dll">
      <Link>Common.dll</Link>
    </EmbeddedResource>
    <EmbeddedResource Include="..'..'Deployment'Upgrader'bin'Debug'Upgrader.dll">
      <Link>Upgrader.dll</Link>
    </EmbeddedResource>
  </ItemGroup>
</When>

据我所知,正确的dll将被选择到资源中。在启动器中,我有以下代码(它确实找到了数据,并且之前已经正确加载了文件-但现在已经崩溃了)。

        Console.WriteLine("Setting up AppDomain..");
        var setup = AppDomain.CurrentDomain.SetupInformation;
        setup.DisallowApplicationBaseProbing = true;
        createdDomain = AppDomain.CreateDomain("CorrectedCommonDomain", null, setup);
        using (Stream s = Assembly.GetEntryAssembly().GetManifestResourceStream("UpgraderLauncher.Common.dll"))
        {
            if (s == null)
            {
                Console.WriteLine("Could not load common.dll correctly!");
                throw new ArgumentNullException("Could not load internal common.dll resource.");
            }
            Console.WriteLine("Loading common.dll..");
            byte[] data = new byte[s.Length];
            s.Read(data, 0, data.Length);
            commonDllAssembly = createdDomain.Load(data);
            Console.WriteLine("Loading common.dll is done.");
        }

在"createdDomain.Load(data);"部分,抛出fileloadeexception (HResult 0x80131040 aka manifest error)。下面是完整的异常细节。

未处理的System.IO类型异常。

FileLoadException' occurred in UpgraderLauncher.exe

附加信息:无法加载文件或程序集'Common, Version=1.0.5256.21424, Culture=neutral, PublicKeyToken=86e85f643d1e5711'或其依赖项之一。定位的程序集的清单定义与程序集引用不匹配。(Exception from HRESULT: 0x80131040)

在重建common.dll(以及随后的启动器)时,异常消息中的dll版本被更新。我该如何继续,如何可以字节加载dll的清单是不同的?(所有的文件都是强签名的)

C# AppDomain load(byte[]) throws FileLoadException (HResult

好了,我解决了这个问题。问题是程序集被加载到两个域中(因为在启动程序中有对程序集的引用,它也被加载到默认的AppDomain,而不是加载它被要求的dll,而是继续从启动程序所在的目录中加载旧文件的清单,从而以旧文件和启动程序中包含的字节之间的清单冲突结束)。为了解决类似情况下的错误,不要让任何代码在默认的AppDomain中加载文件,而是将加载移动到创建的AppDomain中。为此,将字节[]保存到appdomain data:

createdDomain.SetData("CommonDllAssembly", data);

然后在创建的域上运行的代码中:

byte[] bytes = AppDomain.CurrentDomain.GetData("CommonDllAssembly") as byte[];
commonDllAssembly = Assembly.Load(bytes);

这可以防止弹出上述错误。