从另一个AppDomain中的程序集复制方式,并从CurrentDomain执行它 [英] Copy method from another AppDomain's assembly and execute it from CurrentDomain
问题描述
在大画面,我试图从DLL主域,但之后执行的方法,卸载该DLL。到目前为止,我已经创造了新的的AppDomain
加载大会
\dll那里, MarshalByRefObject的
我拿来的身体和 MaxStackSize
该方法的主要领域,创造了 DynamicMethod的
有,重新在身体里面并调用它。
但是,当我调用它,我得到异常:
System.BadImageFormatException:签名是不是IMAGE_CEE_CS_CALLCONV_LOCAL_SIG
In the big picture I am trying to execute method from dll in the main domain but after that, unload that dll. So far I've created new AppDomain
loaded the Assembly
\dll there, with MarshalByRefObject
I fetched the body and MaxStackSize
of the method to the main domain, created DynamicMethod
there, recreated the body inside it and invoked it.
But when I invoke it I get exception:
System.BadImageFormatException: Signature is not IMAGE_CEE_CS_CALLCONV_LOCAL_SIG
.
这是获取并调用它的代码:
The code that fetches and invokes it:
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
is an object of type Proxy.
Some notes that might be necessary:
- ,我fetching\invoking的方法是
公开静态无效的run();
- 的
的AppDomain
,试图调用方法和的AppDomain
加载该dll\assembly具有相同的引用。
- The method that I am fetching\invoking is
public static void Run();
. - The
AppDomain
that trying to invoke the method and theAppDomain
that loads the dll\assembly have the same references.
修改
我的第一个字节从<$ C $更改为 0×07
固定签名C> GetSignature 方法。
但是有新的问题 System.InvalidProgramException:公共语言运行时检测到一个无效的程序
I fixed the signature with changing the first byte to 0x07
from the GetSignature
method.
But there's new problem System.InvalidProgramException: Common Language Runtime detected an invalid program.
推荐答案
您的实现有一个很大的错误,从的 MethodBase.GetMethodBody 的是不可移植的
Your implementation has a big fault, the byte array from MethodBase.GetMethodBody is not portable.
使用的 OpCodes.Call 或的 OpCodes.Callvirt 结果在几个字节,1表示呼叫类型(呼叫/ callvirt),随后表示一个元数据标记四个字节。此令牌可在这种情况下,使用解析为一个Int32,决心一MethodBase 。Module.ResolveMethod
A method invocation using OpCodes.Call or OpCodes.Callvirt results in several bytes, one indicating the type of call (call/callvirt) followed by four bytes that represents a metadata token. This token can, in this case, be parsed as an Int32 and resolved to a MethodBase using Module.ResolveMethod.
请注意,这些元数据标记在编译时产生的;它们可编译间有所不同。 (虽然这是编译器的实现细节,我相信他们是基于编译期间看到的方法的顺序只是自动递增的数字)。
Note that these metadata tokens are generated at compile time; they may differ between compilations. (While it's an implementation detail of the compiler, I believe they are just auto-incremented numbers based on the order of the methods seen during compilation.)
这意味着,你试图用实际字节包含元数据标记是动态模块中无效。他们可能指向现有的方法,不同的签名比你期待的,或者可能不会出现在模块中的。
This means that the actual bytes you're trying to use contains metadata tokens that are invalid in your dynamic module. They may point to an existing method with a different signature than you're expecting, or may not be present at all in your module.
您将需要分析你的IL -code并再次放出了一切,从而产生新的,有效的元数据标记。
You would need to parse your il-code and emit everything again, thus generating new and valid metadata tokens.
这篇关于从另一个AppDomain中的程序集复制方式,并从CurrentDomain执行它的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!