跟踪C#交互窗口中的更改

时间:2017-12-14 06:47:56

标签: c# visual-studio vs-extensibility

VS现在提供了一个交互式窗口,但与运行原始CSI.EXE Roslyn进程不同,Visual Studio添加了IntelliSense和一些其他功能,例如能够加载当前项目。

我想编写一个VS插件来跟踪此窗口中所有文本编辑器的更改。这可能吗?我正在寻找的是类似于PreviewKeyDown/PreviewTextInput WPF事件的东西。我可以在C#交互式窗口中获取这些内容,如果是,那么如何?

到目前为止我已经走了多远:

var dte = Shell.Instance.GetComponent<DTE>();
foreach (Window window in dte.MainWindow.Collection)
{
  if (window.Kind.ToUpper().Contains("TOOL"))
  {
    if (window.Caption == "C# Interactive")
    {
      WpfWindow wpfWindow = (WpfWindow)HwndSource.FromHwnd((IntPtr) window.HWnd).RootVisual;
      for (int i = 0; i < VTH.GetChildrenCount(wpfWindow); ++i)
      {
        // now what?
      }
    }
  }
}

1 个答案:

答案 0 :(得分:10)

以下是一些代码,它将在C#交互式窗口中获得IWpfTextViewHost引用。从那里,您可以访问Visual Studio中的所有文本服务:文本行,文本缓冲区等(或者您可以直接挂钩WPF的控件,我不建议这样做)

// get global UI shell service from a service provider
var shell = (IVsUIShell)ServiceProvider.GetService(typeof(SVsUIShell));

// try to find the C# interactive Window frame from it's package Id
// with different Guids, it could also work for other interactive Windows (F#, VB, etc.)
var CSharpVsInteractiveWindowPackageId = new Guid("{ca8cc5c7-0231-406a-95cd-aa5ed6ac0190}");

// you can use a flag here to force open it
var flags = __VSFINDTOOLWIN.FTW_fFindFirst;
shell.FindToolWindow((uint)flags, ref CSharpVsInteractiveWindowPackageId, out IVsWindowFrame frame);

// available?
if (frame != null)
{
    // get its view (it's a WindowPane)
    frame.GetProperty((int)__VSFPROPID.VSFPROPID_DocView, out object dv);

    // this pane implements IVsInteractiveWindow (you need to add the Microsoft.VisualStudio.VsInteractiveWindow nuget package)
    var iw = (IVsInteractiveWindow)dv;

    // now get the wpf view host
    // using an extension method from Microsoft.VisualStudio.VsInteractiveWindowExtensions class
    IWpfTextViewHost host = iw.InteractiveWindow.GetTextViewHost();

    // you can get lines with this
    var lines = host.TextView.TextViewLines;

    // and subscribe to events in text with this
    host.TextView.TextBuffer.Changed += TextBuffer_Changed;
}

private void TextBuffer_Changed(object sender, TextContentChangedEventArgs e)
{
    // text has changed
}

注意“Microsoft.VisualStudio.VsInteractiveWindow”程序集未明确记录,但源已打开:http://source.roslyn.io/#Microsoft.VisualStudio.VsInteractiveWindow