总的来说,我试图从主域中的 dll 执行方法,但之后,卸载该 dll。到目前为止,我已经创建了新的 AppDomain
并在那里加载了 Assembly
\dll,使用 MarshalByRefObject
我获取了主体和 MaxStackSize
到主域的方法,在那里创建了 DynamicMethod
,在其中重新创建了主体并调用了它。
但是当我调用它时出现异常:
System.BadImageFormatException:签名不是 IMAGE_CEE_CS_CALLCONV_LOCAL_SIG
。
获取和调用它的代码:
DynamicMethod method = new DynamicMethod( "func", typeof( void ), new Type[ 0 ] );
var info = method.GetDynamicILInfo( );
info.SetCode( marshal.GetILCode( ), marshal.GetMaxStackSize());
info.SetLocalSignature(
SignatureHelper.GetMethodSigHelper( CallingConventions.Standard, typeof( void ) ).GetSignature( ) );
method.Invoke( null, new object[ 0 ] ); //<-- exception here
marshal
是 Proxy 类型的对象.
可能需要的一些注意事项:
- 我正在获取\调用的方法是
public static void Run();
。 - 尝试调用该方法的
AppDomain
和加载 dll\assembly 的AppDomain
具有相同的引用。
编辑
我通过将 GetSignature
方法的第一个字节更改为 0x07
来修复签名。
但是出现了新问题 System.InvalidProgramException: Common Language Runtime detected an invalid program.
最佳答案
你的实现有一个很大的错误,字节数组来自MethodBase.GetMethodBody 不可移植。
使用 OpCodes.Call 的方法调用或 OpCodes.Callvirt产生几个字节,一个指示调用类型 (call/callvirt),后跟四个字节表示元数据标记。在这种情况下,此标记可以解析为 Int32 并使用 Module.ResolveMethod 解析为 MethodBase。 .
请注意,这些元数据标记是在编译时生成的;它们可能因编译而异。 (虽然这是编译器的实现细节,但我相信它们只是根据编译期间看到的方法顺序自动递增的数字。)
这意味着您尝试使用的实际字节包含在您的动态模块中无效的元数据标记。它们可能指向与您预期的签名不同的现有方法,或者可能根本不存在于您的模块中。
您需要解析您的 il 代码并再次发出所有内容,从而生成新的有效元数据 token 。
关于c# - 从另一个 AppDomain 的程序集中复制方法并从 CurrentDomain 执行它,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24350769/