本文介绍了从另一个AppDomain中的程序集复制方式,并从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:


  1. ,我fetching\invoking的方法是公开静态无效的run();

  2. 的AppDomain ,试图调用方法和的AppDomain 加载该dll\assembly具有相同的引用。

  1. The method that I am fetching\invoking is public static void Run();.
  2. The AppDomain that trying to invoke the method and the AppDomain 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.

推荐答案

您的实现有一个很大的错误,从的的是不可移植

Your implementation has a big fault, the byte array from MethodBase.GetMethodBody is not portable.

使用的或的结果在几个字节,1表示呼叫类型(呼叫/ callvirt),随后表示一个元数据标记四个字节。此令牌可在这种情况下,使用解析为一个Int32,决心一MethodBase

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执行它的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-30 01:17