运行时动态链接Responder类遇System.IO.FileNotFoundException错误求助
解决AppDomain动态加载程序集的FileNotFoundException问题(Autodesk Inventor iLogic环境)
核心原因
你创建的新AppDomain默认程序集搜索路径与当前运行域不一致——即使Responder.dll和Caller程序集在同一目录,新域的默认搜索路径是系统预设目录(如Inventor安装目录、GAC),而非你的DLL所在目录,因此找不到目标程序集。
解决方案
方案1:配置AppDomain的私有搜索路径
通过AppDomainSetup指定新域的PrivateBinPath为当前程序集所在目录,让新域在该目录下搜索程序集:
Public NotInheritable Class Caller Shared Sub Testing() ' 获取当前Caller程序集所在目录 Dim currentDir As String = IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location) ' 配置新AppDomain的搜索路径 Dim setup As New AppDomainSetup With { .PrivateBinPath = currentDir } ' 创建带配置的AppDomain Dim oDomain As AppDomain = AppDomain.CreateDomain("TestDomain", Nothing, setup) Try ' 创建实例并调用方法(使用后期绑定) Dim objHandle As ObjectHandle = oDomain.CreateInstance( "Responder, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", "Responder.Responder" ) Dim responderObj As Object = objHandle.Unwrap() responderObj.GetType().InvokeMember( "Testing", Reflection.BindingFlags.InvokeMethod, Nothing, responderObj, Nothing ) Finally ' 确保卸载AppDomain以释放程序集 AppDomain.Unload(oDomain) End Try End Sub Private Sub New() End Sub End Class
方案2:直接从文件路径加载程序集
使用CreateInstanceFrom方法直接指定Responder.dll的物理路径,跳过程序集名称解析步骤,更可靠:
Public NotInheritable Class Caller Shared Sub Testing() ' 拼接Responder.dll的完整路径 Dim currentDir As String = IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location) Dim responderDllPath As String = IO.Path.Combine(currentDir, "Responder.dll") Dim oDomain As AppDomain = AppDomain.CreateDomain("TestDomain") Try ' 从文件路径创建实例 Dim objHandle As ObjectHandle = oDomain.CreateInstanceFrom(responderDllPath, "Responder.Responder") Dim responderObj As Object = objHandle.Unwrap() responderObj.GetType().InvokeMember( "Testing", Reflection.BindingFlags.InvokeMethod, Nothing, responderObj, Nothing ) Finally AppDomain.Unload(oDomain) End Try End Sub Private Sub New() End Sub End Class
优化建议(强类型调用)
为避免后期绑定的反射调用,可定义一个公共接口程序集(如Common.dll),让Caller和Responder共同引用:
公共接口代码
Public Interface IResponder Sub Testing() End Interface
Responder类实现接口
Public Class Responder Implements IResponder Public Sub Testing() Implements IResponder.Testing MsgBox("hello") End Sub End Class
Caller类强类型调用
Public NotInheritable Class Caller Shared Sub Testing() Dim currentDir As String = IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location) Dim setup As New AppDomainSetup With {.PrivateBinPath = currentDir} Dim oDomain As AppDomain = AppDomain.CreateDomain("TestDomain", Nothing, setup) Try Dim objHandle As ObjectHandle = oDomain.CreateInstance( "Responder, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", "Responder.Responder" ) ' 直接转换为接口类型,强类型调用方法 Dim responder As IResponder = CType(objHandle.Unwrap(), IResponder) responder.Testing() Finally AppDomain.Unload(oDomain) End Try End Sub Private Sub New() End Sub End Class
iLogic环境特殊注意事项
- 确保DLL所在目录对Inventor进程有读写权限,避免权限导致的文件访问问题
- 每次更新
Responder.dll后,必须确保旧的AppDomain已被卸载,再创建新域加载更新后的DLL - 若遇到AppDomain创建限制,可尝试使用iLogic内置的规则重载功能,但动态加载+AppDomain仍是实现程序集卸载的唯一可靠方式
内容的提问来源于stack exchange,提问作者davidfjdkslfs
相关产品推荐
相关产品推荐

