下文引用自MSDN:
§ 提高的调试性能
宿主进程创建一个应用程序域并将调试器与应用程序关联起来。执行这些任务会导致在开始调试和开始运行应用程序之间有很明显的延迟。通过在后台创建应用程序域和关联调试器,并在运行应用程序之间保存应用程序域和调试器状态,宿主进程使性能得到提高。有关应用程序域的更多信息,请参见应用程序域。
§ 部分信任调试
在“项目设计器”的安全页中,可将应用程序指定为部分信任应用程序。调试部分信任应用程序需要对应用程序域进行特殊的初始化。此初始化由宿主进程处理。
§ 设计时表达式计算
设计时表达式计算使您可以从“即时”窗口进行代码测试,而不必运行应用程序。宿主进程在设计时表达式计算期间执行此代码。有关更多信息,请参见即时窗口。
然而VS 2005是如何使用.vshost.exe来做到上面说的这些功能(或者说改进)的呢?实际上你的托管程序是通过.vshost.exe启动的,而.vshost.exe是一个固定的程序,在每次启动调试过程前,VS会把.vshost.exe拷贝到被调试进程的同一目录里面,然后在后台帮你启动.vshost.exe以便节省调试时间,直到你关闭VS或者关闭当前的VS解决方案(.sln文件),VS才会终止.vshost.exe。
.vshost.exe负责创建应用程序域并将调试器和自身关联起来,因为在你调试你的.NET工程的时候,.vshost.exe只启动一次,因此避免了每一次调试.NET可执行文件时准备调试环境的过程,然后.vshost.exe使用AppDomain.ExecuteAssembly函数来执行我们的可执行文件。这里是我猜测的.vshost.exe所提供的三个功能的流程:
§ 提高的调试性能
§ 部分信任调试
§ 设计时表达式计算 ,这个只会影响到Class Library(类型库)工程,.vshost.exe将.dll可执行文件加载到应用程序域里面,然后跟Visual Studio交互,获取表达式的值。如果将.vshost.exe禁用,那么你不能在类型库项目中使用设计时表达式计算这个功能。但是你仍然可以使用可执行文件的设计时表达式功能,这是因为Visual Studio通过直接启动你的可执行.exe文件来完成的。
整个分析过程如下:
1. 首先将VS 2008运行起来,打开一个工程,这里我打开的是PersonalFinancy工程,这个时候VS 2008自动将PersonalFinancy.vshost.exe运行起来。
2. 启动可执行文件,PersonalFinancy.exe,因为这是一个窗体程序,所以我没有在工程里面设置断点。
3. 接着启动Windbg.exe,选择Attach to a Process,然后从打开的对话框里面选择PersonalFinancy.vshost.exe,勾选“NonInvasive”复选框。这是因为我们的PersonalFinancy.vshost.exe已经被一个调试器所调试,如果将两个调试器附加到同一个进程上面,会有很多不可预料的问题。
4. 打印堆栈,并且查看PersonalFinancy.vshost.exe里面的应用程序域信息。
0:000> !eestack --------------------------------------------- Thread 0 Current frame: ntdll!KiFastSystemCallRet ChildEBP RetAddr Caller,Callee 0012f490 7c957cfb ntdll!ZwWaitForMultipleObjects+0xc 0012f494 7c82202c KERNEL32!WaitForMultipleObjectsEx+0x11a, calling ntdll!ZwWaitForMultipleObjects 0012f4d4 7c822080 KERNEL32!WaitForMultipleObjectsEx+0x34, calling ntdll!RtlActivateActivationContextUnsafeFast # 此处省略了很多不相关的函数信息 … 0012feec 79f45dc0 mscorwks!GetMetaDataInternalInterfaceFromPublic+0xb31b, calling mscorwks!GetMetaDataInternalInterfaceFromPublic+0xb35f 0012fef0 79f45ddf mscorwks!GetMetaDataInternalInterfaceFromPublic+0xb33a, calling mscorwks+0x18bb # 虽然我没有使用正确的调试符号文件,但是CorExeMain函数还是告诉我这个是 # PersonalFinancy.vshost.exe的主线程 0012ff18 79fb9793 mscorwks!CorExeMain+0x14c, calling mscorwks!GetCLRFunction+0xcd27 0012ff68 79fb96df mscorwks!CorExeMain+0x98, calling mscorwks!CorExeMain+0x103 0012ffb0 7900b1b3 mscoree!_CorExeMain+0x2c 0012ffc0 7c82f23b KERNEL32!BaseProcessStart+0x23 --------------------------------------------- # 此处省略了很多不相关的线程堆栈信息 … --------------------------------------------- Thread 6 Current frame: ntdll!KiFastSystemCallRet ChildEBP RetAddr Caller,Callee 039ffe18 7c95783b ntdll!NtReplyWaitReceivePortEx+0xc # PersonalFinancy.vshost.exe通过这个线程与Visual studio 2008相互交流 039ffe1c 77c585ac RPCRT4!LRPC_ADDRESS::ReceiveLotsaCalls+0x198, calling ntdll!NtReplyWaitReceivePortEx 039fff30 77c584a6 RPCRT4!LRPC_ADDRESS::ReceiveLotsaCalls+0x3a, calling RPCRT4!FormatTimeOut 039fff38 77c584b6 RPCRT4!LRPC_ADDRESS::ReceiveLotsaCalls+0x4a, calling ntdll!alloca_probe 039fff84 77c58792 RPCRT4!RecvLotsaCallsWrapper+0xd, calling RPCRT4!LRPC_ADDRESS::ReceiveLotsaCalls 039fff8c 77c5872d RPCRT4!BaseCachedThreadRoutine+0x9d 039fffac 77c4b110 RPCRT4!ThreadStartRoutine+0x1b 039fffb8 7c824829 KERNEL32!BaseThreadStart+0x34 --------------------------------------------- # 此处省略了很多不相关的线程堆栈和函数信息 … 0494f574 7937dd77 (MethodDesc 0x79255938 +0x37 System.Reflection.Assembly.nLoad(System.Reflection.AssemblyName, System.String, System.Security.Policy.Evidence, System.Reflection.Assembly, System.Threading.StackCrawlMark ByRef, Boolean, Boolean)), calling mscorwks!GetCLRFunction+0x48c29 0494f59c 7937dbe8 (MethodDesc 0x7914b8b8 +0xd4 System.Reflection.Assembly.InternalLoad(System.Reflection.AssemblyName, System.Security.Policy.Evidence, System.Threading.StackCrawlMark ByRef, Boolean)), calling (MethodDesc 0x79255938 +0 System.Reflection.Assembly.nLoad(System.Reflection.AssemblyName, System.String, System.Security.Policy.Evidence, System.Reflection.Assembly, System.Threading.StackCrawlMark ByRef, Boolean, Boolean)) 0494f5ac 7937dbf6 (MethodDesc 0x7914b8b8 +0xe2 System.Reflection.Assembly.InternalLoad(System.Reflection.AssemblyName, System.Security.Policy.Evidence, System.Threading.StackCrawlMark ByRef, Boolean)), calling mscorwks!LogHelp_TerminateOnAssert 0494f5d0 79423431 (MethodDesc 0x79255690 +0x55 System.Reflection.Assembly.InternalLoadFrom(System.String, System.Security.Policy.Evidence, Byte[], System.Configuration.Assemblies.AssemblyHashAlgorithm, Boolean, System.Threading.StackCrawlMark ByRef)), calling (MethodDesc 0x7914b8b8 +0 System.Reflection.Assembly.InternalLoad(System.Reflection.AssemblyName, System.Security.Policy.Evidence, System.Threading.StackCrawlMark ByRef, Boolean)) # 启动实际需要被调试的进程—PersonalFinancy.exe 0494f5f8 793def29 (MethodDesc 0x79257218 +0x39 System.AppDomain.ExecuteAssembly(System.String, System.Security.Policy.Evidence, System.String[])), calling mscorwks!CreateHistoryReader+0x2f890 0494f60c 0120156b (MethodDesc 0x983d10 +0x2b Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()) 0494f61c 793b0d1f (MethodDesc 0x792713d0 +0x3b System.Threading.ThreadHelper.ThreadStart_Context(System.Object)) 0494f63c 793b0d1f (MethodDesc 0x792713d0 +0x3b System.Threading.ThreadHelper.ThreadStart_Context(System.Object)) 0494f644 79373ecd (MethodDesc 0x7914e0d8 +0x81 System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object)) 0494f658 793b0c68 (MethodDesc 0x791511d0 +0x40 System.Threading.ThreadHelper.ThreadStart()), calling (MethodDesc 0x7914e0d8 +0 System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object)) # 此处省略了很多不相关的线程堆栈和函数信息 … # 查看PersonalFinancy.vshost.exe应用程序域信息,以及每一个应用程序域所加载的Assembly 0:000> !dumpdomain -------------------------------------- # 此处省略了很多不相关的线程应用程序域信息 … -------------------------------------- Domain 1: 0015e560 LowFrequencyHeap: 0015e584 HighFrequencyHeap: 0015e5dc StubHeap: 0015e634 Stage: OPEN SecurityDescriptor: 00158f98 # PersonalFinancy.vshost.exe执行的应用程序域 Name: PersonalFinancy.vshost.exe Assembly: 001a3dc8 [C:\WINDOWS\assembly\GAC_32\mscorlib\2.0.0.0__b77a5c561934e089\mscorlib.dll] ClassLoader: 00173528 SecurityDescriptor: 00163938 Module Name 790c2000 C:\WINDOWS\assembly\GAC_32\mscorlib\2.0.0.0__b77a5c561934e089\mscorlib.dll # 此处省略了很多不相关的线程应用程序域信息 … Assembly: 0022ba88 [D:\Workspace\PersonalFinancy\PersonalFinancy\bin\Debug\PersonalFinancy.vshost.exe] ClassLoader: 00223f90 SecurityDescriptor: 00224018 Module Name 00987528 D:\Workspace\PersonalFinancy\PersonalFinancy\bin\Debug\PersonalFinancy.vshost.exe # PersonalFinancy.vshost.exe其实将被调试的可执行文件PersonalFinancy.exe放在与它相同的 # 应用程序域中执行 Assembly: 0421faa0 [D:\Workspace\PersonalFinancy\PersonalFinancy\bin\Debug\PersonalFinancy.exe] ClassLoader: 0024c690 SecurityDescriptor: 0024c2c0 Module Name 041025c0 D:\Workspace\PersonalFinancy\PersonalFinancy\bin\Debug\PersonalFinancy.exe |
原文出处:
http://blog.csdn.net/Donjuan/archive/2009/01/21/3849200.aspx
http://blog.csdn.net/Donjuan/archive/2009/01/22/3849508.aspx