我正在开发一个
WPF应用程序,其中包含一个加载silverlight应用程序的webbrowser控件.我希望能够从visual studio(F5)启动应用程序,并将调试器附加到silverlight代码.但是,我没有运气.
我现在能做的最好的事情就是在没有附加的情况下启动应用程序,然后一旦启动并运行,就可以使用silverlight作为指定类型的代码手动附加到流程,这样就可以了. (当我使Web浏览器控件加载silverlight应用程序时,它将在我的silverlight代码中命中断点).我已经写了一些宏来自动化这个启动/附加,但它仍然不是最好的.
我已经尝试将WPF应用程序指定为在启动/调试silverlight应用程序时运行的外部程序,但Visual Studio会附加到想要调试托管.NET代码的进程.
有任何想法吗?理想情况下,我真的想附加到进程并调试托管的.NET和Silverlight代码,但我不认为这是可能的.我真的很想在启动时自动附加到silverlight代码,以便我可以轻松调试silverlight应用程序的所有问题,包括那些在加载时发生的问题.
解决方法
感谢您的想法Brandorf和脂肪. Brandorf几乎让我到了我想去的地方,但确实要求我的SL应用程序能够独立运行.我真的希望只有一个应用程序,即wpf和silverlight,SL端正在调试.
很久以后我问了这个问题(我忘了我曾经在这里问过),我实际上拼凑了一个我非常满意的解决方案.我在我的应用程序的WPF / .NET端使用visual studio自动化,找到visual studio的所有正在运行的实例,找出哪个生成了我的exe(因为它通常位于vcproj / sln文件夹下面的文件夹中),然后使用visual studio自动化将VS附加到应用程序,调试silverlight代码.完成后,我然后加载我的silverlight内容.
它工作得很好.你最终得到一个应用程序,并找到一个调试器,以便每次运行时附加到自身(所以你可能只希望这个代码在调试版本中,或者某种程度上可以关闭).因此,只要您想调试silverlight端,就可以从visual studio中使用ctrl-F5(无需调试启动)启动应用程序.
这是我的代码:
#if DEBUG using System; using System.Collections.Generic; using System.Collections; using System.Runtime.InteropServices; using System.IO; namespace Launcher { //The core methods in this class to find all running instances of VS are //taken/inspired from //http://www.codeproject.com/KB/cs/automatingvisualstudio.aspx class DebuggingAutomation { [DllImport("ole32.dll")] private static extern int GetRunningObjectTable(int reserved,out UCOMIRunningObjectTable prot); [DllImport("ole32.dll")] private static extern int CreateBindCtx(int reserved,out UCOMIBindCtx ppbc); ///<summary> ///Get a snapshot of the running object table (ROT). ///</summary> ///<returns> ///A hashtable mapping the name of the object ///in the ROT to the corresponding object ///</returns> private static Hashtable GetRunningObjectTable() { Hashtable result = new Hashtable(); int numFetched; UCOMIRunningObjectTable runningObjectTable; UCOMIEnumMoniker monikerEnumerator; UCOMIMoniker[] monikers = new UCOMIMoniker[1]; GetRunningObjectTable(0,out runningObjectTable); runningObjectTable.EnumRunning(out monikerEnumerator); monikerEnumerator.Reset(); while (monikerEnumerator.Next(1,monikers,out numFetched) == 0) { UCOMIBindCtx ctx; CreateBindCtx(0,out ctx); string runningObjectName; monikers[0].GetDisplayName(ctx,null,out runningObjectName); object runningObjectVal; runningObjectTable.GetObject(monikers[0],out runningObjectVal); result[runningObjectName] = runningObjectVal; } return result; } /// <summary> /// Get a table of the currently running instances of the Visual Studio .NET IDE. /// </summary> /// <param name="openSolutionsOnly"> /// Only return instances that have opened a solution /// </param> /// <returns> /// A list of the ides (as DTE objects) present in /// in the running object table to the corresponding DTE object /// </returns> private static List<EnvDTE.DTE> GetIDEInstances(bool openSolutionsOnly) { var runningIDEInstances = new List<EnvDTE.DTE>(); Hashtable runningObjects = GetRunningObjectTable(); IDictionaryEnumerator rotEnumerator = runningObjects.GetEnumerator(); while (rotEnumerator.MoveNext()) { string candidateName = (string)rotEnumerator.Key; if (!candidateName.StartsWith("!VisualStudio.DTE")) continue; EnvDTE.DTE ide = rotEnumerator.Value as EnvDTE.DTE; if (ide == null) continue; if (openSolutionsOnly) { try { string solutionFile = ide.Solution.FullName; if (!String.IsNullOrEmpty(solutionFile)) { runningIDEInstances.Add(ide); } } catch { } } else { runningIDEInstances.Add(ide); } } return runningIDEInstances; } internal static void AttachDebuggerIfPossible() { if (System.Diagnostics.Debugger.IsAttached) { //Probably debugging host (Desktop .NET side),so don't try to attach to silverlight side return; } var ides = GetIDEInstances(true); var fullPathToAssembly = System.Reflection.Assembly.GetExecutingAssembly().Location; var potentials = new List<EnvDTE.DTE>(); foreach (var ide in ides) { var solutionPath = ide.Solution.FullName; var topLevelSolutionDir = Path.GetDirectoryName(solutionPath); var assemblyName = fullPathToAssembly; if (assemblyName.StartsWith(topLevelSolutionDir,StringComparison.OrdinalIgnoreCase)) { potentials.Add(ide); } } EnvDTE.DTE chosenIde = null; //If you have multiple ides open that can match your exe,you can come up with a scheme to pick a particular one //(eg,put a file like solution.sln.pickme next to the solution whose ide you want to debug). If this is not a //concern,just pick the first match. if (potentials.Count > 0) { chosenIde = potentials[0]; } var dbg = chosenIde != null ? (EnvDTE80.Debugger2)chosenIde.Debugger : null; if (dbg != null) { var trans = dbg.Transports.Item("Default"); var proc = (EnvDTE80.Process2)dbg.GetProcesses(trans,System.Environment.MachineName).Item(Path.GetFileName(fullPathToAssembly)); var engines = new EnvDTE80.Engine[1]; engines[0] = trans.Engines.Item("Silverlight"); proc.Attach2(engines); } } } } #endif