感谢Brandorf和fatty的想法。Brandorf的想法几乎让我达到了我想要的目标,但是需要我的SL应用程序能够独立运行。我真的只想有一个应用程序,它既是wpf又是silverlight,并且SL端可以进行调试。
在我提出这个问题很久之后(我忘记我在这里提出了这个问题),我实际上拼凑出了一个解决方案,我非常满意。我在我的应用程序的WPF/.NET端使用Visual Studio自动化来查找所有正在运行的Visual Studio实例,找出哪一个生成了我的exe文件(因为它通常位于vcproj/sln文件夹下面的文件夹中),然后使用Visual Studio自动化使该VS附加到应用程序上,调试Silverlight代码。完成这些操作后,我加载我的Silverlight内容。
它的效果非常好。每次运行时,您都会得到一个应用程序,它会去找一个调试器来附加到自己身上(所以您可能只想在调试版本中使用此代码,或者以某种方式将其关闭)。因此,您只需在Visual Studio中使用Ctrl-F5(不带调试启动)启动应用程序,以便在需要调试Silverlight端时进行调试。
以下是我的代码:
#if DEBUG
using System;
using System.Collections.Generic;
using System.Collections;
using System.Runtime.InteropServices;
using System.IO;
namespace Launcher
{
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);
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;
}
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)
{
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 (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