C# 在IDE中打开模式对话框时,访问Visual Studio DTE成员将挂起

C# 在IDE中打开模式对话框时,访问Visual Studio DTE成员将挂起,c#,visual-studio,debugging,freeze,envdte,C#,Visual Studio,Debugging,Freeze,Envdte,在下面的代码中,我试图访问有效的DTE2对象的Debugger属性(通过类似的方法获得),以检查它是否正在调试当前进程(可能会打开多个Visual Studio实例) 它工作得很好,除了当其中一个Visual Studio(2015)实例显示模式对话框(例如,询问当前加载的项目的源代码是否应由于背景代码更改而重新加载)时,访问dte.Debugger将挂起,直到用户处理该对话框。试图访问dte对象的其他成员也将挂起 using System.Runtime.InteropServices; us

在下面的代码中,我试图访问有效的
DTE2
对象的
Debugger
属性(通过类似的方法获得),以检查它是否正在调试当前进程(可能会打开多个Visual Studio实例)

它工作得很好,除了当其中一个Visual Studio(2015)实例显示模式对话框(例如,询问当前加载的项目的源代码是否应由于背景代码更改而重新加载)时,访问
dte.Debugger将挂起,直到用户处理该对话框。试图访问
dte
对象的其他成员也将挂起

using System.Runtime.InteropServices;
using System.Runtime.InteropServices.ComTypes;
using System.Threading;
using EnvDTE;
using EnvDTE80;
using EnvDTE90a;

public static class VSAutomation {
  public static int? GetCurrentDebuggerPid() {
    var taskCompletion = new TaskCompletionSource<int?>();
    var staThread = new System.Threading.Thread(() => {
      try {
        int? debuggerPid = null;
        using (new MessageFilter()) {
          using (var currentProcess = System.Diagnostics.Process.GetCurrentProcess())
          using (var vsInstances = System.Diagnostics.Process.GetProcessesByName("devenv").AsDisposable()) {
            foreach (var p in vsInstances.Enumerable) {
              DTE2 dte;
              if (TryGetVSInstance(p.Id, out dte)) {
                Utils.Retry(() => {
                  var debugger = dte.Debugger; //MAY HANG HERE
                  if (debugger != null) {
                    foreach (Process2 process in debugger.DebuggedProcesses) {
                      if (process.ProcessID == currentProcess.Id) {
                        debuggerPid = p.Id;
                        break;
                      }
                    }
                  }
                  Marshal.ReleaseComObject(dte);
                }, nbRetries: int.MaxValue, msInterval: 1000, retryOnlyOnExceptionTypes: typeof(COMException).InArray());
                if (debuggerPid != null) break;
              }
            }
          }
        }
        taskCompletion.SetResult(debuggerPid);
      }
      catch (Exception ex) {
        taskCompletion.TrySetException(ex);
      }
    }) { IsBackground = true };
    staThread.SetApartmentState(ApartmentState.STA);
    staThread.Start();
    taskCompletion.Task.Wait();
    return taskCompletion.Task.Result;
  }
}
使用System.Runtime.InteropServices;
使用System.Runtime.InteropServices.ComTypes;
使用系统线程;
使用EnvDTE;
使用EnvDTE80;
使用EnvDTE90a;
公共静态类自动化{
公共静态int?GetCurrentDebuggerPid(){
var taskCompletion=new TaskCompletionSource();
var statthread=新系统.Threading.Thread(()=>{
试一试{
int?debuggerPid=null;
使用(new MessageFilter()){
使用(var currentProcess=System.Diagnostics.Process.GetCurrentProcess())
使用(var vsInstances=System.Diagnostics.Process.GetProcessesByName(“devenv”).AsDisposable()){
foreach(vsInstances.Enumerable中的var p){
DTE2-dte;
if(TryGetVSInstance(p.Id,out dte)){
Utils.Retry(()=>{
var debugger=dte.debugger;//可能挂在这里
if(调试器!=null){
foreach(调试器.DebuggedProcesses中的Process2进程){
if(process.ProcessID==currentProcess.Id){
debuggerPid=p.Id;
打破
}
}
}
元帅发布对象(dte);
},nbRetries:int.MaxValue,msInterval:1000,retryOnlyOnExceptionTypes:typeof(COMException.InArray());
如果(debuggerPid!=null)中断;
}
}
}
}
taskCompletion.SetResult(debuggerPid);
}
捕获(例外情况除外){
任务完成。TrySetException(ex);
}
}){IsBackground=true};
SetApartmentState(ApartmentState.STA);
statthread.Start();
taskCompletion.Task.Wait();
返回taskCompletion.Task.Result;
}
}
尽管模式对话框已打开,但是否有任何方法可以访问调试器对象


如果没有,除了在有超时的任务中启动赋值
var debugger=dte.debugger
之外,还有什么方法可以检测到需要用户操作吗?

嘿,你有没有解决过这个问题?我也有类似的问题@SyntaxError不,很遗憾我没有。@SyntaxError如果可能的话,你真的需要更新到VS 2019,他们确实做了很多改进。我同时有两个版本,但仍在处理一些不会(尚未)在VS2019中构建的旧项目