如何解决如何从外部DTE中检索IVsDebugger以在Visual Studio 2019中实现自动化
我正在尝试为Visual Studio 2019编写VSIX,以控制Visual Studio IDE的多个实例。我们正在进行一个联网项目,该项目需要一些自动化才能执行多个用户的测试。过去我会在外部工具中使用DTE,但我的理解是,从VS2017开始,COM guid不再全局注册,因此在IDE中进行操作是唯一的方法。
无论如何,我都试图获取IVsDebugger,以便可以跟踪调试器中的事件。但是,我没有运气。我可以获得IVsDebugger2、3、4、5,但没有IVSDebugger。这是我正在做的一般流程:
void CaptureDebugger()
{
DTE dte = GetDTE(GetRemoteProcessID());
ServiceProvider sp = new ServiceProvider((Microsoft.VisualStudio.OLE.Interop.IServiceProvider)dte);
IVsDebugger vsDebugger = sp.GetService(typeof(SVsShellDebugger)) as IVsDebugger;
// vsDebugger is null!
IVsDebugger2 vsDebugger2 = sp.GetService(typeof(SVsShellDebugger)) as IVsDebugger2;
// vsDebugger2 is not null!
}
/// <summary>
/// Gets the DTE object from any devenv process.
/// </summary>
private static EnvDTE.DTE GetDTE(int processId)
{
object runningObject = null;
IBindCtx bindCtx = null;
IRunningObjectTable rot = null;
IEnumMoniker enumMonikers = null;
try
{
Marshal.ThrowExceptionForHR(CreateBindCtx(reserved: 0,ppbc: out bindCtx));
bindCtx.GetRunningObjectTable(out rot);
rot.EnumRunning(out enumMonikers);
IMoniker[] moniker = new IMoniker[1];
IntPtr numberFetched = IntPtr.Zero;
while (enumMonikers.Next(1,moniker,numberFetched) == 0)
{
IMoniker runningObjectMoniker = moniker[0];
string name = null;
try
{
if (runningObjectMoniker != null)
{
runningObjectMoniker.GetDisplayName(bindCtx,null,out name);
}
}
catch (UnauthorizedAccessException)
{
// Do nothing,there is something in the ROT that we do not have access to.
}
Regex monikerRegex = new Regex(@"!VisualStudio.DTE\.\d+\.\d+\:" + processId,RegexOptions.IgnoreCase);
if (!string.IsNullOrEmpty(name) && monikerRegex.IsMatch(name))
{
Marshal.ThrowExceptionForHR(rot.GetObject(runningObjectMoniker,out runningObject));
}
}
}
finally
{
if (enumMonikers != null)
Marshal.ReleaseComObject(enumMonikers);
if (rot != null)
Marshal.ReleaseComObject(rot);
if (bindCtx != null)
Marshal.ReleaseComObject(bindCtx);
}
return runningObject as EnvDTE.DTE;
}
让我困惑的是我通过调用获得了本地IVsDebugger
var MYDEBUGGER = Package.GetGlobalService(typeof(SVsShellDebugger)) as IVsDebugger;
我看到的是使用GlobalService。我认为我检索到的DTE中没有类似的东西。
有见识吗?
解决方法
我也遇到了这个问题(但是就我而言,我实际上是在尝试检索 IVsDebugger
in proc 而不是听起来像 out of proc);在调试 vsdebug!CDebugger::QueryInterface
的工作原理后,我确定实际问题似乎是您的应用程序 the calling thread 中的 needs to be STA。
- 当您的应用程序中的调用线程是 MTA 时,而
vsdebug!CDebugger::QueryInterface
以HRESULT
0
返回 - 由于
0x80040155
未能找到此类型的代理 DLL,这很快就被 OLE 变成了REGDB_E_IIDNOTREG
(CStdWrapper::GetPSFactory
) - 此错误依次由
CRemoteUnknown::RemQueryInterface
转换为0x80004002
(E_NOINTERFACE
) - 如果您尝试在 C# 中使用
Marshal.QueryInterface
直接查看发生的情况,系统会向您报告哪些内容。
如果您的程序包含位于远程 Visual Studio 进程中的进程内组件(就像我的一样),您可以检索并执行针对 UI 线程上的 IVsDebugger
的操作。否则,您可能会创建一个新的 Thread
并在启动它之前对其调用 thread.SetApartmentState(ApartmentState.STA)
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。