我需要找到开始执行托管代码的程序集。
// using System.Reflection;
Assembly entryAssembly = Assembly.GetEntryAssembly();
这似乎是要走的路,但是Assembly.GetEntryAssembly
声明这个方法“当从非托管代码调用时可以返回null”。
在这种情况下,我想知道非托管代码调用了哪个程序集。
是否有一种可靠的方法来做到这一点,即总是返回一个非空Assembly
引用?
发布于 2013-01-04 22:08:34
到目前为止,我能想到的最好的方法是以下几点,它应该可以在单线程的情况下工作:
// using System.Diagnostics;
// using System.Linq;
Assembly entryAssembly = new StackTrace().GetFrames().Last().GetMethod().Module.Assembly;
(上面的片段是为便于理解而优化的,而不是为了执行速度或内存效率。)
发布于 2015-07-17 11:35:43
两种方法我都试过了。
基于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;
基本上,我沿着堆栈向上走,直到找到一个名为“常规方法”的void
或int
返回类型。如果找不到这样的方法,我将查找通过反射调用的方法。例如,NUnit使用该调用来加载单元测试。
当然,只有当Assembly.GetEntryAssembly()
返回null
时,我才会这样做。
发布于 2013-01-04 23:08:17
另一个(主要是未经测试的)工作解决方案的起点可能是这样的:
// 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
保证总是返回一个非空引用吗?https://stackoverflow.com/questions/14165785
复制相似问题