none
Using DTE.Find in macro

    Question

  •     
    I'm using the DTE.Find functionality in a macro to search through my solution and report back which stored procedures in our database are not being called by the app.  However, it doesn't find procedure names that it does find if I use the Find and Replace box.  To resolve, I recorded the act of opening Find and Replace and searching for one procedure, then I used the generated macro code in my macro.  Finds 2 occurrences with Find and Replace box, none with macro code.  I've tried debugging and checking the FindResult of DTE.Find.Execute() and it does return NotFound.  It doesn't do this for all of the stored procedures, only about half of them.  Does anyone see anything wrong with my code?  Note that I've stripped out the error handling and no errors occur when it runs.

    Public Sub Main()
        ProcessDatabaseProcedures()  'When this gets to "GetDialog" it returns Not Found as the result
       'FindProcedure("GetDialog")       'This works and finds 2 occurences of "GetDialog"
    End Sub

     Private Function FindProcedure(ByVal proc As String) As Boolean
            On Error Resume Next

            FindProcedure = False

            'Going through the Find and Replace window from the macro doesn't change the results.
          'DTE.ExecuteCommand("Edit.FindinFiles")
          'DTE.Windows.Item(
    "{CF2DDC32-8CAD-11D2-9302-005345000000}").Activate()

            'Setup find
            DTE.Find.FindWhat = proc
            DTE.Find.Target = vsFindTarget.vsFindTargetFiles
            DTE.Find.MatchInHiddenText = True
            DTE.Find.MatchCase = False
            DTE.Find.MatchWholeWord = True
            DTE.Find.PatternSyntax = vsFindPatternSyntax.vsFindPatternSyntaxLiteral
            DTE.Find.SearchPath = "Entire Solution"
            DTE.Find.SearchSubfolders = True
            DTE.Find.FilesOfType = "*.aspx;*.ascx;*.asax;*.cs;*.Master;"
            DTE.Find.ResultsLocation = vsFindResultsLocation.vsFindResults1
            DTE.Find.Action = vsFindAction.vsFindActionFindAll

            If (DTE.Find.Execute() = vsFindResult.vsFindResultNotFound) Then
               FindProcedure = False
            Else
                FindProcedure = True
            End If
        End Function

        Private Function ProcessDatabaseProcedures() As Boolean
            On Error Resume Next

            Dim cn As SqlConnection = New SqlConnection(CONN)
            Dim cmd As New SqlCommand()
            Dim reader As SqlDataReader
            Dim proc As String
            Dim fproc As String
            Dim findResult As EnvDTE.vsFindResult
            Dim ret As Boolean
            Dim id As Long

            ret = False
            ProcessDatabaseProcedures = False

            cn.Open()

            cmd.CommandType = CommandType.StoredProcedure
            proc = ""
            cmd.Connection = cn
            cmd.CommandText = "[admin].[GetProcedures]"

            reader = cmd.ExecuteReader()

            If (reader.HasRows()) Then
                While (reader.Read())
                    id = reader("ProcID")
                    proc = reader("ProcName").ToString()
                    fproc = reader("FullProcName").ToString()

                    If (FindProcedure(proc) = False) Then
                        Debug.Print(fproc & vbCrLf)
                        ret = True
                    End If
                End While
            End If

            'clean up
            reader.Close()
            cmd.Dispose()
            cn.Close()
            cn = Nothing
            cmd = Nothing
            reader = Nothing

            ProcessDatabaseProcedures = ret
        End Function


    Thursday, November 06, 2008 8:51 PM

Answers


  • Hi,

    As indicated by document, the search operation is asynchronous, when the search is set to Find All. Then the FindDone event occurs when the operation completes. It does not occur with any other Find or Replace operation as Find All is the only asynchronous Find operation.

    If you want to find the SQL Procedures that are not used by your project, one possible way would be you search through all the file in your project and list the Procedures that were not used.

    For more information, please check:
    http://msdn.microsoft.com/en-us/library/envdte.find.execute.aspx

    Thanks,
    Rong-Chun Zhang

    Please mark the replies as answers if they help and unmark if they don't.
    Wednesday, November 12, 2008 10:56 AM

All replies


  • Hi,

    As indicated by document, the search operation is asynchronous, when the search is set to Find All. Then the FindDone event occurs when the operation completes. It does not occur with any other Find or Replace operation as Find All is the only asynchronous Find operation.

    If you want to find the SQL Procedures that are not used by your project, one possible way would be you search through all the file in your project and list the Procedures that were not used.

    For more information, please check:
    http://msdn.microsoft.com/en-us/library/envdte.find.execute.aspx

    Thanks,
    Rong-Chun Zhang

    Please mark the replies as answers if they help and unmark if they don't.
    Wednesday, November 12, 2008 10:56 AM
  • Thanks for your help!  I had missed that in the documentation.  I was thinking that it might be a timing issue so that makes sense.

    However, I have changed it to use Find instead of FindAll and I'm still getting false results.  I get better results but still some Not Founds that should be Founds.  If I step through in debug, it works better but not 100%.   That suggests to me another timing issues. 

    The only line that I changed was DTE.Find.Action=vsFindAction.vsFindActionFind. Do I need to change something else?

    Oh!  Do I need to Search Up and Down for each item? 
    • Edited by HorseFly Wednesday, November 12, 2008 3:30 PM
    Wednesday, November 12, 2008 3:17 PM
  • Hi,

    If you just want list that procedures that are not used in your code, you don't need to search for each file. Not sure why your code doesn't work, but I have the following macro and it worked well for me.

    Public Module test

        Sub Main()

            'AddHandler DTE.Events.FindEvents.FindDone, AddressOf FindEvents_FindDone

            ProcessDatabaseProcedures()

        End Sub

     

     

        Private Function FindProcedure(ByVal proc As String)

            DTE.Find.FilesOfType = "*.cs;*.resx;*.xsd;*.wsdl;*.xaml;*.xml;*.htm;*.html;*.css"

            DTE.Find.FindWhat = proc

            DTE.Find.Target = vsFindTarget.vsFindTargetFiles

            DTE.Find.MatchCase = False

            DTE.Find.MatchWholeWord = False

            DTE.Find.MatchInHiddenText = True

            DTE.Find.PatternSyntax = vsFindPatternSyntax.vsFindPatternSyntaxLiteral

            DTE.Find.SearchPath = "Entire Solution"

            DTE.Find.SearchSubfolders = True

            DTE.Find.FilesOfType = "*.cs;*.resx;*.xsd;*.wsdl;*.xaml;*.xml;*.htm;*.html;*.css"

            DTE.Find.ResultsLocation = vsFindResultsLocation.vsFindResults1

            DTE.Find.Action = vsFindAction.vsFindActionFind

     

            Dim result As vsFindResult = DTE.Find.Execute()

            If (result = vsFindResult.vsFindResultNotFound) Then

                Dim myout As NamedOutputPane = New NamedOutputPane("NonUsed")

                myout.OutputTextLine(proc)

                myout.Pane().Activate()

                MsgBox(proc)

            End If

        End Function

     

        Private Function ProcessDatabaseProcedures() As Boolean

            On Error Resume Next

            Dim strs() As String = New String() {"Form", "some other value", "this", "not found"}

            For Each str As String In strs

                FindProcedure(str)

            Next

        End Function

    End Module

     

    Public Class NamedOutputPane

        Private win As OutputWindowPane

        Public ReadOnly Property Pane() As OutputWindowPane

            Get

                Return win

            End Get

        End Property

        Sub New(ByRef WindowName As String)

            win = Nothing

     

            ' Get an instance of the currently running Visual Studio .NET IDE.

     

            'The next two lines are required for AddIns but not for macros

     

            Dim DTE As EnvDTE.DTE

            DTE = System.Runtime.InteropServices.Marshal. _

                GetActiveObject("VisualStudio.DTE")

     

            ' Create a tool window handle for the Output window.

     

            Dim mwin As Window = DTE.Windows.Item(EnvDTE.Constants _

                            .vsWindowKindOutput)

            ' Create handles to the Output window and its panes.

     

            Dim OW As OutputWindow = mwin.Object

            Dim tmpOWp As OutputWindowPane

     

            'Look for the pane specified in "WindowPane"

     

            For Each tmpOWp In OW.OutputWindowPanes

                If tmpOWp.Name = WindowName Then

                    win = tmpOWp

                    Exit For

                End If

            Next

            If win Is Nothing Then

                ' Didn't find it - create a new pane

     

                win = OW.OutputWindowPanes.Add(WindowName)

            End If

        End Sub

        Sub OutputTextLine(ByRef txt As String)

            ' Add a line of text to the new pane.

     

            win.OutputString(txt)

            win.OutputString(vbCr)

        End Sub

    End Class

    For how to write to the Output Window in Visual Studio, please refer:
    http://www.codeproject.com/KB/macros/VSReadFileOutWin.aspx

    Thanks,
    Rong-Chun Zhang

    Please mark the replies as answers if they help and unmark if they don't.
    Thursday, November 13, 2008 2:32 AM