我需要找到托管代码执行开始的程序集。
// using System.Reflection;
Assembly entryAssembly = Assembly.GetEntryAssembly();
这似乎是合适的方法,但Assembly.GetEntryAssembly的MSDN参考页面指出,当从非托管代码中调用此方法时,该方法可能返回null。
在这种情况下,我想知道是哪个程序集被非托管代码调用了。
是否有可靠的方法来做到这一点,即始终返回一个非空的Assembly
引用?
我需要找到托管代码执行开始的程序集。
// using System.Reflection;
Assembly entryAssembly = Assembly.GetEntryAssembly();
这似乎是合适的方法,但Assembly.GetEntryAssembly的MSDN参考页面指出,当从非托管代码中调用此方法时,该方法可能返回null。
在这种情况下,我想知道是哪个程序集被非托管代码调用了。
是否有可靠的方法来做到这一点,即始终返回一个非空的Assembly
引用?
到目前为止,我能想到的最好的方法是以下内容,适用于单线程情况:
// using System.Diagnostics;
// using System.Linq;
Assembly entryAssembly = new StackTrace().GetFrames().Last().GetMethod().Module.Assembly;
上述代码片段是为了易于理解而进行优化的,而不是为了执行速度或内存效率。
// 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;
void
或int
的常规方法,该方法名为“Main”。
如果找不到这样的方法,则我会寻找通过反射调用的方法。例如,NUnit使用该调用来加载单元测试。Assembly.GetEntryAssembly()
返回null
时,我才会执行上述操作。int
,而其他类中可能会有其他的主函数,但这是一个好的开始。 - Rob Prouse// using System;
// using System.Diagnostics;
// using System.Linq;
ProcessModule mainModule = Process.GetCurrentProcess().MainModule;
Assembly entryAssembly = AppDomain.CurrentDomain.GetAssemblies()
.Single(assembly => assembly.Location == mainModule.FileName);
仍有一些不确定性:
模块和程序集不是同一回事。ProcessModule
可能在概念上与 Module
有所不同。当存在多模块(即多文件)程序集且程序集的入口点不在清单模块中时,上述代码是否总是有效?
Process.MainModule
是否保证始终返回非空引用?
Assembly.GetEntryAssembly() ?? new StackTrace().GetFrames().Last().GetMethod().Module.Assembly
。 - Ohad Schneider