views:

1626

answers:

3

Can someone post a Visual Studio macro which goes through all C# source files in a project and adds a file banner? Extra credit if it works for any type of source file (.cs, .xaml, etc).

+3  A: 

Visual Studio macro to add file headers

Pop Catalin
Wow--great answer. Too bad the OP doesn't seem to grok Google.
Onorio Catenacci
Thanks for the link. Onorio, I did try google but used the word "banner" instead of "header"... which returns entirely different results. Don't know why, I've always called them banners. Of course now because of this post, using the word "banner" returns this very post!
DSO
+1  A: 

Here is the jist of it. No, I have not debugged this, that is an excercise for the reader. And, this is done off the top of my head. (Except the File commenter...That's a real Macro that I use).

function CommentAllFiles
    option explicit

    Dim ActiveProjectFullName
    Dim dte80 As EnvDTE80.Solution2

    ActiveProjectFullName = dte80.Projects.Item(0).FullName
    If ActiveProjectFullName = "" Then
        MsgBox("No project loaded!")
        Exit Sub
    End If

    Err.Number = 0
    doc.Open(ActiveProjectFullName, "Text", True)
    If Err.Number <> 0 Then
        MsgBox("Open " + ActiveProjectFullName + " failed: " & Hex(Err.Number))
        Exit Sub
    End If

    ActiveDocument.Goto(1, 1, vsMovementOptions.vsMovementOptionsMove)

    ' Build search string
    Dim SearchString
    Dim vsFindOptionsValue As Integer
    SearchString = "^SOURCE=.*" + dn + "$"

    while ActiveDocument.Selection.FindText(SearchString, vsFindOptions.vsFindOptionsFromStart + vsFindOptions.vsFindOptionsRegularExpression)
        Dim TheFile
        TheFile = ActiveDocument.Selection.Text
        TheFile = Mid(TheFile, 8)
        doc.Open(TheFile)
    wend
    ActiveDocument.Close()
end function

Tried and true "Flower Box" adder:

    Function IsClassDef()
    Dim ColNum
    Dim LineNum
    Dim sText

    sText = ActiveDocument.Selection.ToString()
    If sText = "" Then
        'ActiveDocument.Selection.WordRight(dsExtend)
        'sText = ActiveDocument.Selection
        'sText = ucase(trim(sText))
    End If

    If (sText = "CLASS") Then
        IsClassDef = True
    Else
        IsClassDef = False
    End If
End Function

Sub AddCommentBlock()
    'DESCRIPTION: Add Commecnt block to header, CPP files and Class Defs
    AddCPPFileDesc()
End Sub

Sub AddCPPFileDesc()
    'DESCRIPTION: Add File desc block to the top of a CPP file
    Dim selection As EnvDTE.TextSelection
    ActiveDocument.Selection.StartOfLine()

    Dim editPoint As EnvDTE.EditPoint
    selection = DTE.ActiveDocument.Selection()
    editPoint = selection.TopPoint.CreateEditPoint()

    Dim bOk, sExt, IsCpp, IsHdr, sHeader, IsCSharp
    bOk = True
    IsCpp = False
    IsCSharp = False

    If ActiveDocument.Selection.CurrentLine > 10 Then
        If MsgBox("You are not at the top of the file. Are you sure you want to continue?", vbYesNo + vbDefaultButton2) = vbNo Then
            bOk = False
        End If
    End If

    If (bOk) Then
        sExt = ucase(right(ActiveDocument.Name, 4))
        IsCpp = sExt = ".CPP"
        IsHdr = Right(sExt, 2) = ".H"
        IsCSharp = sExt = ".CS"

        If (IsCpp) Then
            sHeader = left(ActiveDocument.Name, len(ActiveDocument.Name) - 3) + "h"
            FileDescTopBlock(1)
            editPoint.Insert("#include " + Chr(34) + "StdAfx.h" + Chr(34) + vbLf)
            editPoint.Insert("#include " + Chr(34) + sHeader + Chr(34) + vbLf)
        ElseIf (IsCSharp) Then
            FileDescTopBlock(1)
        Else
            If IsHdr Then
                'If IsCLassDef() Then
                'AddClassDef()
                'Else
                AddHeaderFileDesc()
                'End If
            Else
                FileDescTopBlock(1)
            End If
        End If
    End If
End Sub

Sub AddHeaderFileDesc()
    FileDescTopBlock(0)
    Dim selection As EnvDTE.TextSelection
    ActiveDocument.Selection.StartOfLine()

    Dim editPoint As EnvDTE.EditPoint
    selection = DTE.ActiveDocument.Selection()
    editPoint = selection.TopPoint.CreateEditPoint()
    editPoint.Insert("#pragma once" + vbLf)
End Sub


Sub FileDescTopBlock(ByVal HasRevHistory)
    'DESCRIPTION: Add File desc block to the top of a CPP file
    Dim selection As EnvDTE.TextSelection

    ActiveDocument.Selection.StartOfLine()
    ActiveDocument.Selection.EndOfLine()
    Dim sComment
    sComment = ActiveDocument.Selection.ToString()
    If Left(sComment, 2) = "//" Then
        ActiveDocument.Selection.Delete()
        sComment = LTrim(Mid(sComment, 3))
    Else
        sComment = ""
    End If

    Dim sLineBreak
    Dim sFileName
    Dim sBlock
    sLineBreak = "////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////"
    sFileName = ActiveDocument.Name

    ActiveDocument.Selection.StartOfDocument()
    sBlock = sLineBreak & vbLf & _
            "//  File   : " & sFileName & vbLf & _
           "//  Author : Larry Frieson" & vbLf & _
          "//  Desc   : " & sComment & vbLf & _
         "//  Date   : " & CStr(Now.Date()) & vbLf & _
        "//" & vbLf & _
       "//  Copyright © 20" + Right(CStr(Now.Year.ToString()), 2) + " MLinks Technologies. All rights reserved" + vbLf
    If (HasRevHistory > 0) Then
        sBlock = sBlock & _
                "//" & vbLf & _
               "//  Revision History: " & vbLf & _
              "//    " & CStr(Now) & " created." & vbLf & _
             "// " & vbLf
    End If
    sBlock = sBlock + sLineBreak + vbLf

    Dim editPoint As EnvDTE.EditPoint
    selection = DTE.ActiveDocument.Selection()
    editPoint = selection.TopPoint.CreateEditPoint()
    editPoint.Insert(sBlock)

End Sub

Hope this helps, or at least gives you some ideas. Again, I didn't test/debug the "source file looper", I figure you can handle that.

Larry

LarryF
+10  A: 

Here you go, I provide an example for .cs and .vb but shouldn't be hard for you to adjust it to your other file type needs: Edited to recursively add header to sub-folders

Sub IterateFiles()
    Dim solution As Solution = DTE.Solution
    For Each prj As Project In solution.Projects
        IterateProjectFiles(prj.ProjectItems)
    Next
End Sub

Private Sub IterateProjectFiles(ByVal prjItms As ProjectItems)
    For Each file As ProjectItem In prjItms
        If file.SubProject IsNot Nothing Then
            AddHeaderToItem(file)
            IterateProjectFiles(file.ProjectItems)
        ElseIf file.ProjectItems IsNot Nothing AndAlso file.ProjectItems.Count > 0 Then
            AddHeaderToItem(file)
            IterateProjectFiles(file.ProjectItems)
        Else
            AddHeaderToItem(file)
        End If
    Next
End Sub

Private Sub AddHeaderToItem(ByVal file As ProjectItem)
    DTE.ExecuteCommand("View.SolutionExplorer")
    If file.Name.EndsWith(".cs") OrElse file.Name.EndsWith(".vb") Then
        file.Open()
        file.Document.Activate()

        AddHeader()

        file.Document.Save()
        file.Document.Close()
    End If
End Sub

Private Sub AddHeader()
    Dim cmtHeader As String = "{0} First Line"
    Dim cmtCopyright As String = "{0} Copyright 2008"
    Dim cmtFooter As String = "{0} Footer Line"

    Dim cmt As String

    Select Case DTE.ActiveDocument.Language
        Case "CSharp"
            cmt = "//"
        Case "Basic"
            cmt = "'"
    End Select
    DTE.UndoContext.Open("Header Comment")
    Dim ts As TextSelection = CType(DTE.ActiveDocument.Selection, TextSelection)
    ts.StartOfDocument()
    ts.Text = String.Format(cmtHeader, cmt)
    ts.NewLine()
    ts.Text = String.Format(cmtCopyright, cmt)
    ts.NewLine()
    ts.Text = String.Format(cmtFooter, cmt)
    ts.NewLine()
    DTE.UndoContext.Close()
End Sub
Brian Schmitt
Thanks, I'm gonna vote for this one instead of the one that has the link to the blog, because this shows how to enumerate the projects.
DSO
How well does this work for files that have designers, like WinForms?
Scott A. Lawrence
Should add it to any CS or VB file in the solution. Which would include the designer file - however as with any 'generated' file, the file could change and your comment may no longer be there.
Brian Schmitt
Just what I was looking for! But the macro does not dive into sub folders and add headers to the files contained in them. Will post modified code if I find a solution.
SDX2000