You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.NET 8 COM互操作WPF类库加载依赖程序集的UserControl时触发System.IO.FileNotFoundException异常

.NET 8 COM互操作WPF类库加载依赖程序集的UserControl时触发System.IO.FileNotFoundException异常

我完全懂你碰到的这个糟心问题——明明依赖的Wpf.Tools.CSharp程序集能被正常调用(比如实例化里面的类能弹出MessageBox),但一在WPF窗口里用它的UserControl,VB6调用COM组件时就触发找不到文件的异常,换用WPF测试程序却一切正常,这反差真的让人摸不着头脑。

先帮你梳理下核心的现象:

  • 主程序集是启用了COM托管的.NET 8 WPF类库,引用了另一个WPF类库Wpf.Tools.CSharp
  • 直接通过主程序集实例化依赖库的普通类,完全没问题,说明依赖集确实存在且能被加载
  • 但只要主程序集的窗口XAML里引用了ToolsUserControl,VB6调用时就会抛出System.IO.FileNotFoundException,提示找不到Wpf.Tools.CSharp
  • WPF测试程序调用COM组件全程正常,问题仅出在VB6的COM调用场景

问题根源:COM宿主的程序集加载上下文差异

这本质是普通WPF应用和COM宿主环境的程序集加载逻辑不一样导致的:

  1. 普通WPF应用启动时,会自动在应用目录、GAC等常规路径查找依赖程序集;但VB6作为COM宿主调用comhost.dll时,.NET运行时的加载上下文更受限,它会优先从VB6进程的当前工作目录或者GAC找依赖,而不是主COM组件的输出目录。
  2. 当你实例化依赖库的普通类时,是通过主程序集的代码直接触发加载,这时候.NET能利用Assembly.Load的上下文找到依赖;但WPF解析XAML中的csharp:ToolsUserControl时,XAML解析器的加载逻辑是独立的,它用默认加载上下文查找程序集,这时候如果依赖集不在VB6的工作目录或GAC里,就会找不到。

具体解决方案

下面给你三个可行的解决办法,按需选择:

方案1:把依赖程序集复制到VB6的运行目录

这是最直接的验证方法:

  • 找到VB6项目的运行目录(默认是VB6的安装目录,或者你编译生成的EXE所在目录)
  • 把Wpf.Tools.CSharp.dll及其依赖文件(如果有的话)复制到这个目录
  • 重新运行VB6测试程序,XAML解析器就能找到依赖集了

方案2:将依赖程序集安装到GAC

如果不想复制文件到多个目录,可以把依赖集注册到全局程序集缓存:

  • 注意你的目标平台是x86,要使用x86版本的gacutil.exe(通常在C:\Program Files (x86)\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.8 Tools\x86,如果是.NET 8,找对应SDK的x86工具)
  • 打开x86的命令提示符,执行命令:
    gacutil /i Wpf.Tools.CSharp.dll
    
  • 安装到GAC后,不管COM宿主的工作目录在哪,.NET运行时都能从GAC找到这个程序集

方案3:在主COM组件中添加程序集解析事件

这个方法不需要复制文件或安装GAC,让主组件主动告诉运行时去哪找依赖:

  • 在主程序集的SimpleComInteropClass构造函数中,注册AssemblyResolve事件,手动指定依赖集的路径:
    using System.Reflection;
    using System.IO;
    
    namespace Wpf.ComInterop
    {
        [ComVisible(true)]
        [Guid("C3634287-1BFA-410A-BEE7-634F080E9682")]
        [ClassInterface(ClassInterfaceType.None)]
        public class SimpleComInteropClass : ISimpleHost
        {
            public SimpleComInteropClass()
            {
                AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve;
            }
    
            private Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
            {
                // 检查是否是找不到目标依赖程序集
                if (args.Name.StartsWith("Wpf.Tools.CSharp,"))
                {
                    // 获取主程序集的所在目录
                    string mainAssemblyPath = Assembly.GetExecutingAssembly().Location;
                    string mainDir = Path.GetDirectoryName(mainAssemblyPath);
                    // 拼接依赖程序集的路径
                    string toolsAssemblyPath = Path.Combine(mainDir, "Wpf.Tools.CSharp.dll");
                    // 加载并返回程序集
                    return Assembly.LoadFrom(toolsAssemblyPath);
                }
                return null;
            }
    
            // 其他原有代码...
        }
    }
    
  • 这样当XAML解析器找不到依赖集时,会触发这个事件,主组件会指引运行时到自己的目录下去找依赖

额外验证提示

  • 先试试方案1快速确认是不是路径问题,没问题的话再根据需求选方案2或3
  • 确保主程序集和依赖程序集的平台目标一致(都是x86),避免因为平台不兼容导致的加载失败

内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.07 07:04:30