none
VisualStudioのマクロから"シンボルの検索結果"の一覧を取得したい RRS feed

  • 質問

  • やりたいのはプロジェクト内の全てのメソッド呼び出し元を洗い出し、ファイルに保存したいのです。
    その呼び出しもとの洗い出しに"シンボルの検索"マクロを呼び出して結果Windowから取得させたいのですが…。
    VisualStudioのバージョンは2003~2010までのいずれかで可能であれば問題ないです。
    そもそも不可能ということでも結構ですのでお教えいただければと思います!

    2011年2月4日 13:06

回答

  • むりやり取ってみた

    Imports System
    Imports EnvDTE
    
    Public Module Test
      Public Sub Test()
        Dim sb As New System.Text.StringBuilder()
        For Each s As String In FindSymbol.GetSymbolsText("Stream", "/word")
          sb.AppendLine(s)
        Next
        System.Windows.Forms.MessageBox.Show(sb.ToString())
      End Sub
    End Module
    
    Friend Class FindSymbol
      ''' <summary>「シンボルの検索」の結果を取得してみる</summary>
      ''' <params name="symbol">検索したいシンボル</params>
      ''' <params name="findoption">http://msdn.microsoft.com/ja-jp/library/3k01sw92.aspx 参照</option>
      Shared Function GetSymbolsText(ByVal symbol As String _
      , Optional ByVal findoption As String = "") _
      As System.Collections.Specialized.StringCollection
        Dim retval As New System.Collections.Specialized.StringCollection()
    
        Dim windowBrowser As EnvDTE.Window = DTE.Windows.Item(EnvDTE.Constants.vsWindowKindObjectBrowser)
        windowBrowser.Close()
    
        Dim windowOutput As EnvDTE.Window = DTE.Windows.Item(EnvDTE.Constants.vsWindowKindOutput)
        Dim out As OutputWindow = windowOutput.Object
        Dim pane As EnvDTE.OutputWindowPane = out.ActivePane
    
        Dim commandoption As String = symbol + IIf(String.IsNullOrEmpty(findoption), String.Empty, " " + findoption)
        DTE.ExecuteCommand("Edit.FindSymbol", commandoption)
        DTE.ExecuteCommand("Edit.GoToNextLocation")
        DTE.ExecuteCommand("Edit.Copy")
        System.Windows.Forms.Application.DoEvents()
        Dim strStart As String = GetClipboard()
        Dim str As String
        Do
          DTE.ExecuteCommand("Edit.GoToNextLocation")
          DTE.ExecuteCommand("Edit.Copy")
          str = GetClipboard()
          retval.Add(str)
          If (pane IsNot Nothing) Then
            pane.OutputString(str)
            pane.OutputString(System.Environment.NewLine)
          End If
        Loop While strStart <> str
        Return retval
      End Function
    
      Private Shared Function GetClipboard() As String
        Dim start As New System.Threading.ParameterizedThreadStart(AddressOf GetClipboardText)
        Dim thread As New Threading.Thread(start)
        thread.ApartmentState = Threading.ApartmentState.STA
        Dim param(0) As String
        thread.Start(param)
        thread.Join()
        Return param(0)
      End Function
    
      Private Shared Sub GetClipboardText(ByVal param As Object)
        Dim s As String() = DirectCast(param, String())
        s(0) = System.Windows.Forms.Clipboard.GetText()
      End Sub
    End Class
    
    

     

    • 回答としてマーク 山本春海 2011年2月22日 8:15
    2011年2月5日 17:45
  • むりやり取ってみた

     

    Imports System
    Imports EnvDTE
    
    Public Module Test2
      Public Sub Test2()
        Dim sb As New System.Text.StringBuilder()
        For Each s As String In FindSymbol2.GetAllReferencesSymbolsText()
          sb.AppendLine(s)
        Next
        System.Windows.Forms.MessageBox.Show(sb.ToString())
      End Sub
    End Module
    
    Friend Class FindSymbol2
      ''' <summary>エディタの選択位置での「すべての参照の検索」の結果を取得してみる</summary>
      Shared Function GetAllReferencesSymbolsText() _
      As System.Collections.Specialized.StringCollection
    
        Dim retval As New System.Collections.Specialized.StringCollection()
    
        Dim activeWindow As EnvDTE.Window = DTE.ActiveWindow
        If DTE.ActiveDocument Is Nothing Then
          'Throw New Exception("実行するにはソースコードを表示して選択する必要があります。")
          System.Windows.Forms.MessageBox.Show("実行するにはソースコードを表示して選択する必要があります。")
    
        ElseIf Not TypeOf DTE.ActiveDocument.Selection Is TextSelection Then
          System.Windows.Forms.MessageBox.Show("実行するにはソースコードを選択する必要があります。")
    
        Else
          DTE.ActiveDocument.Activate()
    
          Dim sel As TextSelection = CType(DTE.ActiveDocument.Selection, TextSelection)
          Dim pointTop As Integer = sel.TopPoint.AbsoluteCharOffset
          Dim pointEnd As Integer = sel.BottomPoint.AbsoluteCharOffset
          Dim windowFindResult As EnvDTE.Window = DTE.Windows.Item(EnvDTE.Constants.vsWindowKindFindSymbolResults)
          Dim canCopy As Boolean = True
    
          DTE.ExecuteCommand("Edit.FindAllReferences", String.Empty)
          windowFindResult.Activate()
          Try
            DTE.ExecuteCommand("Edit.Copy") '結果がないとエラーをはく?
          Catch ex As System.Runtime.InteropServices.COMException
            canCopy = False
          End Try
          If (canCopy) Then
            Dim strStart As String = GetClipboard()
            Dim str As String = strStart
            Do
              retval.Add(str)
              DTE.ExecuteCommand("Edit.GoToNextLocation")
              windowFindResult.Activate()
              DTE.ExecuteCommand("Edit.Copy")
              str = GetClipboard()
            Loop While strStart <> str
          End If
    
          activeWindow.Activate()
          sel.MoveToAbsoluteOffset(pointTop)
          sel.MoveToAbsoluteOffset(pointEnd, True)
        End If
    
        Return retval
      End Function
    
      Private Shared Function GetClipboard() As String
        Dim start As New System.Threading.ParameterizedThreadStart(AddressOf GetClipboardText)
        Dim thread As New Threading.Thread(start)
        thread.ApartmentState = Threading.ApartmentState.STA
        Dim param(0) As String
        thread.Start(param)
        thread.Join()
        Return param(0)
      End Function
    
      Private Shared Sub GetClipboardText(ByVal param As Object)
        Dim s As String() = DirectCast(param, String())
        s(0) = System.Windows.Forms.Clipboard.GetText()
      End Sub
    
    End Class
    

     

    せめて『シンボルの検索』ウィンドウで下矢印キーを送信できればよいのですが。
    EnvDTE.Window.HWndでハンドルが取れるので、そこから結果ウィンドウのハンドルを見つけてやって、PostMessageキーを送信すればできました。
    試してみるなら、結果ウィンドウをSPY++で見つけて、最下層のウィンドウに送ってみてください。
    • 回答としてマーク 山本春海 2011年2月22日 8:15
    2011年2月7日 11:56
  • 目的の用途だけなら、IL 読んだほうが早いような気がします...

    • 回答としてマーク 山本春海 2011年2月22日 8:15
    2011年2月10日 3:20

すべての返信

  • むりやり取ってみた

    Imports System
    Imports EnvDTE
    
    Public Module Test
      Public Sub Test()
        Dim sb As New System.Text.StringBuilder()
        For Each s As String In FindSymbol.GetSymbolsText("Stream", "/word")
          sb.AppendLine(s)
        Next
        System.Windows.Forms.MessageBox.Show(sb.ToString())
      End Sub
    End Module
    
    Friend Class FindSymbol
      ''' <summary>「シンボルの検索」の結果を取得してみる</summary>
      ''' <params name="symbol">検索したいシンボル</params>
      ''' <params name="findoption">http://msdn.microsoft.com/ja-jp/library/3k01sw92.aspx 参照</option>
      Shared Function GetSymbolsText(ByVal symbol As String _
      , Optional ByVal findoption As String = "") _
      As System.Collections.Specialized.StringCollection
        Dim retval As New System.Collections.Specialized.StringCollection()
    
        Dim windowBrowser As EnvDTE.Window = DTE.Windows.Item(EnvDTE.Constants.vsWindowKindObjectBrowser)
        windowBrowser.Close()
    
        Dim windowOutput As EnvDTE.Window = DTE.Windows.Item(EnvDTE.Constants.vsWindowKindOutput)
        Dim out As OutputWindow = windowOutput.Object
        Dim pane As EnvDTE.OutputWindowPane = out.ActivePane
    
        Dim commandoption As String = symbol + IIf(String.IsNullOrEmpty(findoption), String.Empty, " " + findoption)
        DTE.ExecuteCommand("Edit.FindSymbol", commandoption)
        DTE.ExecuteCommand("Edit.GoToNextLocation")
        DTE.ExecuteCommand("Edit.Copy")
        System.Windows.Forms.Application.DoEvents()
        Dim strStart As String = GetClipboard()
        Dim str As String
        Do
          DTE.ExecuteCommand("Edit.GoToNextLocation")
          DTE.ExecuteCommand("Edit.Copy")
          str = GetClipboard()
          retval.Add(str)
          If (pane IsNot Nothing) Then
            pane.OutputString(str)
            pane.OutputString(System.Environment.NewLine)
          End If
        Loop While strStart <> str
        Return retval
      End Function
    
      Private Shared Function GetClipboard() As String
        Dim start As New System.Threading.ParameterizedThreadStart(AddressOf GetClipboardText)
        Dim thread As New Threading.Thread(start)
        thread.ApartmentState = Threading.ApartmentState.STA
        Dim param(0) As String
        thread.Start(param)
        thread.Join()
        Return param(0)
      End Function
    
      Private Shared Sub GetClipboardText(ByVal param As Object)
        Dim s As String() = DirectCast(param, String())
        s(0) = System.Windows.Forms.Clipboard.GetText()
      End Sub
    End Class
    
    

     

    • 回答としてマーク 山本春海 2011年2月22日 8:15
    2011年2月5日 17:45
  • gekkaさん

    ご返答有難うございます!
    #ご連絡が遅くなってすみません。アラート設定でメールアドレス設定していませんで
    気付きませんでした。

    シンボルの検索の取得は出来ました!
    が、説明が足りず申し訳ございません。
    「Edit.FindAllReferences」での検索結果Window「シンボルの検索結果」のファイルパス部分は取れますでしょうか。
    メソッドの呼び出し元一覧を取得したいのです。

    しかし、gekkaさんが無理やりやられている&ネットで探してみても見つからないので恐らく無理なんでしょうか・・・。
    せめて『シンボルの検索』ウィンドウで下矢印キーを送信できればよいのですが。

    2011年2月7日 8:24
  • むりやり取ってみた

     

    Imports System
    Imports EnvDTE
    
    Public Module Test2
      Public Sub Test2()
        Dim sb As New System.Text.StringBuilder()
        For Each s As String In FindSymbol2.GetAllReferencesSymbolsText()
          sb.AppendLine(s)
        Next
        System.Windows.Forms.MessageBox.Show(sb.ToString())
      End Sub
    End Module
    
    Friend Class FindSymbol2
      ''' <summary>エディタの選択位置での「すべての参照の検索」の結果を取得してみる</summary>
      Shared Function GetAllReferencesSymbolsText() _
      As System.Collections.Specialized.StringCollection
    
        Dim retval As New System.Collections.Specialized.StringCollection()
    
        Dim activeWindow As EnvDTE.Window = DTE.ActiveWindow
        If DTE.ActiveDocument Is Nothing Then
          'Throw New Exception("実行するにはソースコードを表示して選択する必要があります。")
          System.Windows.Forms.MessageBox.Show("実行するにはソースコードを表示して選択する必要があります。")
    
        ElseIf Not TypeOf DTE.ActiveDocument.Selection Is TextSelection Then
          System.Windows.Forms.MessageBox.Show("実行するにはソースコードを選択する必要があります。")
    
        Else
          DTE.ActiveDocument.Activate()
    
          Dim sel As TextSelection = CType(DTE.ActiveDocument.Selection, TextSelection)
          Dim pointTop As Integer = sel.TopPoint.AbsoluteCharOffset
          Dim pointEnd As Integer = sel.BottomPoint.AbsoluteCharOffset
          Dim windowFindResult As EnvDTE.Window = DTE.Windows.Item(EnvDTE.Constants.vsWindowKindFindSymbolResults)
          Dim canCopy As Boolean = True
    
          DTE.ExecuteCommand("Edit.FindAllReferences", String.Empty)
          windowFindResult.Activate()
          Try
            DTE.ExecuteCommand("Edit.Copy") '結果がないとエラーをはく?
          Catch ex As System.Runtime.InteropServices.COMException
            canCopy = False
          End Try
          If (canCopy) Then
            Dim strStart As String = GetClipboard()
            Dim str As String = strStart
            Do
              retval.Add(str)
              DTE.ExecuteCommand("Edit.GoToNextLocation")
              windowFindResult.Activate()
              DTE.ExecuteCommand("Edit.Copy")
              str = GetClipboard()
            Loop While strStart <> str
          End If
    
          activeWindow.Activate()
          sel.MoveToAbsoluteOffset(pointTop)
          sel.MoveToAbsoluteOffset(pointEnd, True)
        End If
    
        Return retval
      End Function
    
      Private Shared Function GetClipboard() As String
        Dim start As New System.Threading.ParameterizedThreadStart(AddressOf GetClipboardText)
        Dim thread As New Threading.Thread(start)
        thread.ApartmentState = Threading.ApartmentState.STA
        Dim param(0) As String
        thread.Start(param)
        thread.Join()
        Return param(0)
      End Function
    
      Private Shared Sub GetClipboardText(ByVal param As Object)
        Dim s As String() = DirectCast(param, String())
        s(0) = System.Windows.Forms.Clipboard.GetText()
      End Sub
    
    End Class
    

     

    せめて『シンボルの検索』ウィンドウで下矢印キーを送信できればよいのですが。
    EnvDTE.Window.HWndでハンドルが取れるので、そこから結果ウィンドウのハンドルを見つけてやって、PostMessageキーを送信すればできました。
    試してみるなら、結果ウィンドウをSPY++で見つけて、最下層のウィンドウに送ってみてください。
    • 回答としてマーク 山本春海 2011年2月22日 8:15
    2011年2月7日 11:56
  • 目的の用途だけなら、IL 読んだほうが早いような気がします...

    • 回答としてマーク 山本春海 2011年2月22日 8:15
    2011年2月10日 3:20