如何加载网络共享DLL且不锁定文件并解决依赖加载失败问题
解决网络共享DLL加载时的锁定与依赖找不到问题
你不需要修改MyDll中对依赖DLL的引用方式,问题出在CLR加载程序集时的上下文差异:
Assembly.LoadFrom会记录程序集的原始加载路径,因此能自动找到同目录下的依赖,但会锁定源文件;Assembly.Load(byte[])是从内存加载程序集,CLR不知道它的原始位置,因此无法自动定位同目录的依赖。
下面是两种可行的解决方案:
方案1:复制到本地临时目录加载(推荐)
将网络DLL复制到本地临时文件夹,再用LoadFrom加载本地副本——既不会锁定网络文件,又能让CLR自动处理同目录依赖:
Dim srcPath As String = "\\NetworkLocation\MyDll.dll" Dim tempDir As String = Path.GetTempPath() Dim tempPath As String = Path.Combine(tempDir, Path.GetFileName(srcPath)) ' 将网络DLL复制到本地临时目录 File.WriteAllBytes(tempPath, File.ReadAllBytes(srcPath)) ' 加载本地副本,无网络文件锁定 Dim asm As Assembly = Assembly.LoadFrom(tempPath) Dim formType As Type = asm.GetType("MyDll.FrmMain") Dim mainForm As Form = DirectCast(Activator.CreateInstance(formType), Form) ' 窗体关闭后清理临时文件 AddHandler mainForm.FormClosed, Sub(sender, e) If File.Exists(tempPath) Then Try File.Delete(tempPath) Catch ex As Exception ' 忽略删除失败(比如程序集仍被占用) End Try End If End Sub Application.Run(mainForm)
方案2:通过AssemblyResolve事件手动加载依赖
订阅AppDomain.CurrentDomain.AssemblyResolve事件,当CLR找不到依赖时,手动从网络目录读取并加载对应的DLL:
' 先注册程序集解析事件 AddHandler AppDomain.CurrentDomain.AssemblyResolve, AddressOf ResolveNetworkAssembly ' 从内存加载主DLL Dim srcFile As String = "\\NetworkLocation\MyDll.dll" Dim asm As Assembly = Assembly.Load(File.ReadAllBytes(srcFile)) Dim formType As Type = asm.GetType("MyDll.FrmMain") Application.Run(DirectCast(Activator.CreateInstance(formType), Form)) ' 程序集解析方法 Private Function ResolveNetworkAssembly(sender As Object, e As ResolveEventArgs) As Assembly Dim assemblyName As New AssemblyName(e.Name) Dim dllPath As String = Path.Combine("\\NetworkLocation", $"{assemblyName.Name}.dll") ' 检查网络目录是否存在该依赖DLL If File.Exists(dllPath) Then Return Assembly.Load(File.ReadAllBytes(dllPath)) End If ' 返回null让CLR继续默认查找逻辑 Return Nothing End Function
注意事项
- 方案1需要处理临时文件的清理,若程序集未卸载(比如WinForm应用未关闭),可能无法立即删除临时文件,可以在应用退出时统一清理;
- 方案2要确保网络目录的权限足够,且依赖DLL的文件名与程序集名称一致(若有强命名或版本号,需调整路径拼接逻辑)。
内容的提问来源于stack exchange,提问作者Sphinx
相关产品推荐
相关产品推荐

