我正在使用一对未签名的第三方程序集库,其中包含我创建派生类的窗口控件和基本类型。 dll驻留在我的应用程序安装的子文件夹中。除了我的控制之外,具有相同名称但针对更高版本的.Net运行时构建的库的较新版本安装在与我的可执行文件相同的目录中。
这导致我的应用程序抛出BadImageFormatException:
无法加载文件或程序集'sharedlibA'[...]此程序集是 由比当前加载的运行时更新的运行时构建而不能 加载。
这是我正在使用的文件系统结构:
[MyappFolder]
|--Myapp.exe
|--sharedlibA.dll (wrong version)
|--sharedlibB.dll (wrong version)
|--bin
|--sharedlibA.dll (need to use this)
|--sharedlibB.dll (need to use this)
我一直在阅读不同的程序集加载上下文并创建一个单独的AppDomain,但这些似乎都不起作用。
修改
我已经从配置文件中删除了探测信息,正如Hans在下面建议并订阅了AssemblyResolve事件,所以现在所有其他依赖程序集都会触发sharedEibA和sharedlibB的事件EXCEPT。它们仍会导致BadImageFormatException。尽管发生了变化,看起来AppBase文件夹仍在探测中。
这是融合日志:
=== Pre-bind state information ===
LOG: User = ...
LOG: DisplayName = sharedlibA, Version=1.0.0.0, Culture=neutral, PublicKeyToken=643d95c7ce242296
(Fully-specified)
LOG: Appbase = file:///C:/[MyappFolder]
LOG: Initial PrivatePath = NULL
Calling assembly : (Unknown).
===
LOG: This bind starts in default load context.
LOG: Using application configuration file: C:\[MyappFolder]\Myapp.exe.Config
LOG: Using machine configuration file from C:\Windows\Microsoft.NET\Framework\v2.0.50727\config\machine.config.
LOG: Post-policy reference: sharedlibA, Version=1.0.0.0, Culture=neutral, PublicKeyToken=643d95c7ce242296
LOG: Attempting download of new URL file:///C:/[MyappFolder]/sharedlibA.DLL.
ERR: Failed to complete setup of assembly (hr = 0x8013101b). Probing terminated.
编辑#2
我已经解决了我的具体问题。回答如下。
答案 0 :(得分:1)
我通过向应用程序配置文件添加<codeBase>
元素来解决此问题,以指定每个dll的确切位置。显然这是有效的,因为在每次需要加载程序集时,在探测启发式搜索之前检查<codebase>
。
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="sharedlibA" culture="neutral" publicKeyToken="..." />
<codeBase version="1.0.0.0" href="bin\sharedlibA.dll" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="sharedlibB" culture="neutral" publicKeyToken="..." />
<codeBase version="1.0.0.0" href="bin\sharedlibB.dll" />
</dependentAssembly>
</assemblyBinding>
</runtime>
答案 1 :(得分:0)
这真的应该用“停止这样做!”来解决。一个非常具体的解决方法是删除.exe.config文件中的<probing>
元素,以便CLR无法再找到DLL。并实现AppDomain.CurrentDomain.AssemblyResolve事件以返回受祝福的事件。