我创建了一个DLL,它将从AssemblyInfo.cs收集信息。在类构造函数中,我使用Reflection来获取正在运行的最顶层的应用程序。
public class AppInfo()
{
public AppInfo()
{
System.Reflection.Assembly assembly =
System.Reflection.Assembly.GetEntryAssembly();
if (assembly == null)
assembly = System.Reflection.Assembly.GetCallingAssembly();
//code to gather needed information
}
}
如果我从给定应用程序MyApp中的任何DLL调用此函数,那么这个名称将永远是“MyApp”。检索该信息不是问题,它在Windows服务和Windows应用程序中运行良好。我的问题是: 如何获得最顶级网站的大会?
我找到了一些文章,我可以通过将网站的AssemblyInfo.cs移出App_Code文件夹并进入网站的根目录来获取Global.asax.cs中的信息。然后通过将compilerOption添加到AssemblyInfo.cs的物理路径
<compiler
language="c#;cs;csharp"
extension=".cs"
compilerOptions="C:\Sandbox\MyWebSite\AssemblyInfo.cs"
type="Microsoft.CSharp.CSharpCodeProvider,System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" warningLevel="4">
使用它我可以通过System.Reflection.Assembly.GetExecutingAssembly()
在网站的AssemblyInfo.cs中检索信息。现在我可以重载我的AppInfo
类的构造函数以接受Assembly
并以这种方式检索信息,但如果MyWebSite
使用的另一个DLL创建new AppInfo()
我会获取该DLL的汇编信息而不是父网站。
我知道如果我使用的是Web Apps而不是Web站点,我就不会遇到这个问题,但由于我不会进入的原因,我无法使用Web Apps。关于如何从我运行的网站的AssemblyInfo.cs中读取信息的任何建议,无论我在哪个DLL中?
编辑:我需要这个才能用于网站,Windows应用和Windows服务
答案 0 :(得分:2)
如果我理解正确,问题是Assembly.GetEntryAssembly()
在网站中返回null并且Assembly.GetCallingAssembly()
返回错误的东西,因为你有一连串的调用导致网站不是直接来电者。如果是这种情况,您可以使用堆栈跟踪&amp;找到“Entry Assembly”。走回调用帧。堆栈将充满来自System.Web等的引用,因为调用将来自IIS内部的深处,但您应该能够通过抓住可以肯定识别的最低帧来挑选您感兴趣的程序集属于你。请注意,这非常hacky,但我认为它会让你得到你想要的......
var trace = new StackTrace();
Assembly entryAssembly = null;
foreach (var frame in trace.GetFrames())
{
var assembly = frame.GetMethod().DeclaringType.Assembly;
//check if the assembly is one you own & therefore could be your logical
//"entry assembly". You could do this by checking the prefix of the
//Assembly Name if you use some standardised naming convention, or perhaps
//looking at the AssemblyCompanyAttribute, etc
if ("assembly is one of mine")
{
entryAssembly = assembly;
}
}
希望其他人能够提出一种不那么讨厌的方法......但是如果你真的被困住了,这可能会有所帮助。
答案 1 :(得分:1)
每个网站都会创建AppDomains,然后将bin * .dll文件加载到该应用程序的AppDomain中。该网站没有“大师大会”,至少没有任何特殊含义。
这是一个过程。 System.Web.Hosting.ProcessHost通过System.Web.ApplicationHost和System.Web.Hosting.ApplicationManger的组合创建System.Web.Hosting.Environment,然后为应用程序创建System.AppDomain。
AppDomain非常安全,所以除非你知道如何进入AppDomain,否则你运气不好。
如果您可以更新您的问题,可能会有人提供更多帮助。
如果未正确设置安全性,可能能够执行此操作“
String binDir = Server.MapPath("/bin/");
Response.Write(String.Format("Bin dir:{0}<br/><br/>",binDir));
foreach (string file in Directory.GetFiles(binDir, "*.dll"))
{
Response.Write(String.Format("File:{0}<br/>", file));
try
{
Assembly assembly = Assembly.LoadFile(file);
object[] attrinutes = assembly.GetCustomAttributes(true);
foreach (var o in attrinutes)
{
//AssemblyCompanyAttribute is set in the AssemblyInfo.cs
if (o is AssemblyCompanyAttribute)
{
Response.Write(String.Format("Company Attribute: Company = {0}<br/>", ((AssemblyCompanyAttribute)o).Company));
continue;
}
Response.Write(String.Format("Attribute: {0}<br/>", o));
}
}
catch(Exception ex)
{
Response.Write(String.Format("Exception Reading File: {0} Exception: {1}",file,ex));
}
}
您在这里假设主站点未编译(具有App_Code目录)并且与您的子站点位于同一个应用程序池中。您是否需要访问权限?主站点是共享主机站点还是什么?
答案 2 :(得分:1)
Deviant是对的。但是如果可以,你应该使用Assembly.Load而不是Assembly.LoadFile。
这是一个很好的参考:
http://gisresearch.blogspot.com/2007/09/assembly-load-loadfrom-loadfile.html
答案 3 :(得分:0)
使用Alconja的建议我正在检查assembly.GlobalAssemblyCache,直到我发现第一个在那里。不存在的最后一个是我自己的第一个我认为是入口组件的dll。
如果只知道程序集名称和类型名称,则下面的类有助于获取Type对象。
public static class AssemblyHandler {
private static Dictionary<String, Assembly> Assemblies;
public static Assembly GetAssembly(String Name) {
if (Assemblies == null) {
Assemblies = new Dictionary<string, Assembly>();
var mainAsm = Assembly.GetEntryAssembly();
if (mainAsm == null) {
var trace = new StackTrace();
foreach (var frame in trace.GetFrames()) {
var assembly = frame.GetMethod().DeclaringType.Assembly;
if (assembly.GlobalAssemblyCache) {
break;
}
mainAsm = assembly;
}
}
Assemblies.Add(mainAsm.FullName, mainAsm);
ScanReferencedAssemblies(mainAsm);
}
if (!Assemblies.ContainsKey(Name)) {
return null;
}
return Assemblies[Name];
}
private static void ScanReferencedAssemblies(Assembly Asm) {
foreach (var refAsmName in Asm.GetReferencedAssemblies()) {
Assembly a = Assembly.Load(refAsmName);
if (a.GlobalAssemblyCache) {
continue;
}
if (!Assemblies.ContainsKey(a.FullName)) {
Assemblies.Add(a.FullName, a);
ScanReferencedAssemblies(a);
}
}
}
public static Type GetType(string AssemblyName, string TypeName) {
return GetAssembly(AssemblyName).GetType(TypeName);
}
}