27

マネージ コードの実行が開始されたアセンブリを見つける必要があります。

// using System.Reflection;
Assembly entryAssembly = Assembly.GetEntryAssembly();

これは進むべき道のように思えますが、MSDN のリファレンス ページにAssembly.GetEntryAssemblyは、このメソッドは「[c]アンマネージ コードから呼び出されたときに null を返す」と記載されています。

その場合、どのアセンブリがアンマネージ コードによって呼び出されたかを知りたいです。

これを行う信頼できる方法はありますか?つまり、null 以外のAssembly参照を常に返す方法はありますか?

4

3 に答える 3

23

これまでのところ、私が考えることができる最高のものは次のとおりです。これは、シングルスレッドのシナリオで機能するはずです。

// using System.Diagnostics;
// using System.Linq; 
Assembly entryAssembly = new StackTrace().GetFrames().Last().GetMethod().Module.Assembly;

(上記のスニペットは、実行速度やメモリ効率ではなく、理解しやすいように最適化されています。)

于 2013-01-04T22:08:34.300 に答える
11

stakxの両方の方法を試しました。

MainModule に基づくメソッドは、一部の特殊なケース (動的アセンブリなど) では機能しません。

StackTrace に基づくメソッドは、mscorlib のように、階層内で高すぎる (または低すぎる) アセンブリを返す可能性があります。

私のユースケースでうまく機能する小さなバリアントを作成しました:

// using System.Diagnostics;
// using System.Linq;
var methodFrames = new StackTrace().GetFrames().Select(t => t?.GetMethod()).ToArray();
MethodBase entryMethod = null;
int firstInvokeMethod = 0;
for (int i = 0; i < methodFrames.Length; i++)
{
    var method = methodFrames[i] as MethodInfo;
    if (method == null)
        continue;
    if (method.IsStatic &&
        method.Name == "Main" &&
        (
            method.ReturnType == typeof(void) || 
            method.ReturnType == typeof(int) ||
            method.ReturnType == typeof(Task) ||
            method.ReturnType == typeof(Task<int>)
        ))
    {
        entryMethod = method;
    }
    else if (firstInvokeMethod == 0 &&
        method.IsStatic &&
        method.Name == "InvokeMethod" &&
        method.DeclaringType == typeof(RuntimeMethodHandle))
    {
        firstInvokeMethod = i;
    }
}

if (entryMethod == null)
    entryMethod = firstInvokeMethod != 0 ? methodFrames[firstInvokeMethod - 1] : methodFrames.LastOrDefault();

Assembly entryAssembly = entryMethod?.Module?.Assembly;

基本的に、または戻り型を持つ「Main」という名前の従来のメソッドが見つかるまで、スタックを上に移動します。そのようなメソッドが見つからない場合は、リフレクションを介して呼び出されるメソッドを探します。たとえば、NUnit はその呼び出しを使用して単体テストをロードします。voidint

もちろん、 がAssembly.GetEntryAssembly()返された場合にのみ行いますnull

于 2015-07-17T11:35:43.590 に答える