VB.NET VS2019无法捕获缺失自定义DLL 启动前报FileNotFoundException问题
问题根因
.NET Framework的即时编译(JIT)机制会在执行某个方法前,提前加载该方法代码中直接引用的所有依赖程序集。你之前的DLL检测逻辑写在main_Load()方法中,而新增的自定义DLL已经被main_Load()或者更早执行的入口方法直接引用,因此CLR会在运行main_Load()内的检测逻辑前就尝试加载该DLL,找不到就直接抛出System.IO.FileNotFoundException,你的检测代码完全没有执行机会。
可行解决方案
方案1:调整入口逻辑,把依赖检测前移到无强引用的方法
新增一个完全不引用自定义DLL的启动入口方法,所有DLL检测、下载补全逻辑都放在这个入口中,检测通过后再调用包含自定义DLL引用的业务启动方法。参考代码示例:// 仅做依赖检测、补全,无任何自定义DLL的直接引用 static void Main() { // 执行所有DLL存在性校验 if (!CheckAllDllsExists()) { DownloadMissingDllsFromServer(); } // 校验完成后再启动主业务逻辑 RunBusinessApp(); } // 所有引用自定义DLL的代码都放在该方法中,执行时DLL已经完成补全 static void RunBusinessApp() { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); Application.Run(new MainForm()); }方案2:订阅
AppDomain.AssemblyResolve事件手动处理程序集加载
在程序最早的无强引用入口中订阅当前应用域的程序集解析事件,CLR找不到目标DLL时会触发该事件,你可以在回调中实时下载缺失的DLL并加载返回给CLR。参考代码示例:static void Main() { AppDomain.CurrentDomain.AssemblyResolve += OnAssemblyResolve; RunBusinessApp(); } private static Assembly OnAssemblyResolve(object sender, ResolveEventArgs args) { string assemblyName = new AssemblyName(args.Name).Name; string localDllPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, $"{assemblyName}.dll"); // 本地不存在则从自有服务器下载 if (!File.Exists(localDllPath)) { DownloadDllFromRemote(assemblyName, localDllPath); } return Assembly.LoadFrom(localDllPath); }方案3:改用反射调用自定义DLL
取消对自定义DLL的直接强引用,所有调用逻辑都通过反射实现,CLR不会在启动时提前加载该DLL,你可以在检测补全完成后再通过反射加载调用即可。
内容的提问来源于stack exchange,提问作者Lama
相关产品推荐
相关产品推荐

