以下代码(打包在“控制台应用程序”Visual Studio项目中):
using System;
using System.Collections.Generic;
using System.Text;
using System.Reflection;
namespace TestReflection
{
class Program
{
static void Main(string[] args)
{
bool found = false;
foreach (Assembly assembly in AppDomain.CurrentDomain.GetAssemblies())
{
if (assembly.GetType("System.Diagnostics.Process") != null)
{
found = true;
break;
}
}
Console.WriteLine(found);
Console.ReadKey();
}
}
}
在调试模式(F5)下运行时打印'True',但在没有调试器(Ctrl-F5)的情况下启动时输出'False'。其他类显示类似的行为(System.Text.RegularExpressions.Regex
),其他类在两种情况下都可以找到(System.IO.File
)。
我可能错过了一些明显的东西 - 为什么会这样?
(在Visual Studio 2005和2008中都会发生同样的事情)。
找到的集合列表:
调试模式:
mscorlib
TestReflection
System
Microsoft.VisualStudio.HostingProcess.Utilities
System.Windows.Forms
运行模式:
mscorlib
TestReflection
正如答案所暗示的那样,在运行模式下,系统组件丢失(未加载)。我的问题是我假设GetAssemblies()也返回未加载的程序集。
虽然这解释了System.Diagnostics.Process
的行为,但为什么我的代码在运行和调试模式下都找到System.IO.File
?
谢谢!
我已经将代码更改为循环加载的程序集和当前程序集,收集这些程序集引用的程序集列表。如果在迭代加载的程序集后我找不到我正在寻找的类型,我开始加载并检查引用的程序集。
似乎即使我在项目中引用System.dll
(我正在查看Visual Studio中'System'引用的属性),我的可执行文件也仅引用mscorlib.dll
(根据Reflector)。
如何为System.dll
添加“真实”引用?放置虚线
new System.Diagnostics.ProcessStartInfo();
在Main
的开头做了诀窍(事情按预期工作,Reflector在检查可执行文件时显示mscorlib.dll
和System.dll
的引用),但它是一个hack。< / p>
再次感谢!
答案 0 :(得分:11)
AppDomain.GetAssemblies不会返回您引用的所有程序集,而是返回当前已加载到appdomain中的所有程序集。
显然,您的应用程序不直接使用Diagnostics.Process类,因此在调试器外部运行时不会加载。
那么为什么我们找到System.IO.File而不是System.Diagnostics.Process? 原因是这两个类虽然位于同一个顶级命名空间System中,但实际上存在于两个不同的程序集中。如果在Visual Studio对象浏览器中查找这两个类,则很容易看到这一点。 File类恰好位于 mscorlib dll中,而Process类位于系统 dll中。
由于没有mscorlib,没有.Net应用程序可以在没有加载程序集的情况下运行,因为你没有加载System.dll,因为你没有引用该dll中的任何类型。
答案 1 :(得分:4)
VS中的调试器尽力欺骗并欺骗您以为您在生产计算机上运行应用程序。然而,它正在做一大堆你不会想到的东西,例如急切地装载组件,在通常被收集之后长时间保持vars活着等等。
在发布版本中,CLR不会将程序集加载到appdomain中,直到需要类型或类型实例来执行代码。调试时无法保证此行为。
如果您的代码对这些更改很敏感,我建议您重新设计或检查System.Diagnostics.Debugger.IsAttached.
答案 2 :(得分:0)
我认为某些程序集不是由您的项目直接引用的,但是当调试被调试器本身映射到您的进程时。
确保您要查找的装配体位于项目的References
。
答案 3 :(得分:0)
通常在需要之前不会加载程序集。在调试模式下运行时,调试器会在启动时加载Microsoft.VisualStudio.HostingProcess.Utilities程序集。我的猜测是这个程序集调用了System程序集,因此系统在启动时以调试模式加载。
答案 4 :(得分:0)
您可能会发现使用和不使用调试器来尝试这一行很有意思:
Console.WriteLine(Process.GetCurrentProcess().ProcessName);
简而言之,as @Will notes,当您在VS中运行附加的调试器时,您根本不会运行'您的exe',而是VS调试器为您设置的整个框架。情况会有所不同。