Click here to Skip to main content
15,883,864 members
Articles / Programming Languages / C#

Visual Studio Add-in that produces compact HTML code documentation

Rate me:
Please Sign up or sign in to vote.
3.00/5 (2 votes)
5 Aug 2005CPOL4 min read 35.4K   235   16   2
A Visual Studio add-in that produces compact HTML code documentation from embedded XML.

Image 1

Introduction

After many many years away from software development I decided to take the leap and rekindle my interest. Wow and have things changed! Having purchased a copy of Visual Studio and electing to go with C# my simple application grew and grew which screamed for a level of documentation due to my "put down pick up" approach. I initially used the bundled "Build Comment Web Pages" add-in which I liked but found it very verbose generating a multitude of pages and hence the presented lean and mean code documentation program.

Background

In developing this application I was exposed to many new aspects of the Visual Studio .NET development environment some were relatively easy to address either through MSDN or web sites such as CodeProject. Areas which were either picked up by chance or required a suck and see it approach included debugging Visual Studio add-in code, access to the DTE environment and TreeNode tags. I have captured some of my experiences related to these areas in the following section.

Using the code

To add the VShtmlhelp add-in to the Tools menu install VShtmlhelpSetup either using the Install function from the Solution Explorer or running directly the VShtmlhelpSetup.msi file. To complete registration double click the ReCreateCommands.reg file. The smiley icon VShtmlhelp will now be displayed in the Tools menu. Selecting this for the VShtmlhelp project will produce the above dialog while selecting the build button will produce the following HTML file output.

Image 2

Debugging Visual Studio add-in code is possible be it a bit tedious. After several hours of searching and experimenting the approach I used was as follows:

  1. Open Visual Studio and in the start page select New Project to create the add-in.
  2. Select Extensibility Projects under project type and then Visual Studio .NET Add-in under templates.
  3. Enter a name for your add-in then select OK button whereupon the add-in wizard dialog will be displayed.
  4. Step through the wizard recommended actions, beyond defaults deselect VSMacros tick box and select tick box for ‘Tools’ menu item.
  5. After creating your add-in project open the connect.cs file within the Solution Explorer.
  6. While developing and before your run your add-in for the first time - within the connect.cs file comment out the if ConnectMode = … statement within the OnConnection method, within the connect.cs file add the following to the OnDisconnection method (C# code shown, remember to enter the name of your Add-in on line 6):
C#
// Dev/Debug code, get the commands collection.
Commands commands = applicationObject.Commands ;
try
    {
        // Delete the required command.
        Command command =
          commands.Item("YourAddin.Connect.YourAddin", -1);
        command.Delete();
    }
catch(System.Exception)
    {
        MessageBox.Show ("Add-in OnDisconnection failure");
    }

As this code uses MessageBox add System.Windows.Forms to References in the Solution Explorer and as a Using statement within the connect.cs file, now build your code. When debugging, on the toolbar select Tools Add-in Manager.. identify your add-in and tick the startup box, prior to closing Visual Studio reverse this action. You are now able to develop and debug your add-in remember to reverse the above code changes once you are ready to release your code.

Visual Studio .NET provides tools for extending and automating the integrated development environment (IDE). DTE stands for Development Tools Extensibility and the DTE Object model presents a structured set components for the Visual Studio .NET runtime environment. This object model enables access and modification of different components which includes Solution, Projects and Project Items. The following sample code writes the Solution name into a label solutionNameLbl:

C#
using EnvDTE;
public _DTE dteApplication;

private void HelpDialog_Load(object sender,
                            System.EventArgs e)
{
    EnvDTE.Solution dteSolution =
                       dteApplication.Solution;

    solutionNameLbl.Text = dteSolution.FullName;
}

Through the use of a foreach statement you are able to iterate through each Project within the Solution. The following sample loads each Project name into a ListBox projectsLst:

C#
foreach (Project project in dteSolution.Projects)
{
    // if project does not contain valid code
    // then ignore the project entry
    if (project.ProjectItems != null)
    {
        projectsLst.Items.Add(project.Name);
        if (!projSelected)
        {
            // generates projectsLst_SelectedIndexChanged event
            projectsLst.SetSelected(0, true);
            projSelected = true;
        }
    }
}

Once you have the Project you are able to get a count of the ProjectItems within the Project. The following code is an extract from the function ProjectItems which iterates through each projectItems thereby obtaining the FileCodeModel and then calling iterateFileCodeModel:

C#
// For the selected Project Cycle each project item.
for (int r = 1; r< project.ProjectItems.Count +1; r++)
{
    projectItem = project.ProjectItems.Item(r);
    // Get the file code model
    fileCode = projectItem.FileCodeModel;
    // valid file if not a null
    if (fileCode != null)
    {
        // Cycle through the file code model
        iterateFileCodeModel(fileCode, filesTrv);
    }
}

The FileCodeModel object enables the user to find any code element within the Project given a fully qualified name. By using the Kind function and enumerator vsCMElement 39 elements can be identified including namespace, class, property, variable and function. The following extract from iterateFileCodeModel demonstrates this, it also shows the construction of the TreeView filesTrv. This construction consists of the namespace followed by the classes associated with the namespace, it uses the Tag function allowing namespace or class element data to be assigned to the associated TreeNode. This has the benefit that when the user selects the relevant Project and subsequently the Build button the HTML pages can be derived directly from the TreeView filesTrv.

C#
if (codeElement.Kind == vsCMElement.vsCMElementNamespace)
{
    // Generate new namespace node if index 0
    // otherwise use existing node
    nameSpaceNodeIndex =
        NameSpaceNode(codeElement.FullName, filesTrv);
    if (nameSpaceNodeIndex == -1)
    {
        nameSpaceNode =
          filesTrv.Nodes.Add(codeElement.FullName);
        //Tag the code element to the node,
        //to be used by HTML page generation.
        nameSpaceNode.Tag = codeElement;
    }
    else
        nameSpaceNode =
            filesTrv.Nodes[nameSpaceNodeIndex];
    foreach (CodeElement cdClassElmnt in
                 ((CodeNamespace)codeElement).Members)
    {
          if(cdClassElmnt.Kind ==
                         vsCMElement.vsCMElementClass)
          {
             TreeNode classNode =
               nameSpaceNode.Nodes.Add(cdClassElmnt.Name);
             //Tag the class element to the node, to be
             //used by HTML page generation.
             classNode.Tag = cdClassElmnt;
          }
    }
}

The HTML page consists of three frames - left, main and top pages. The top page is static whereas the left and main pages are dynamic depending on the built project. Once the build is activated the TreeView filesTrv is used to generate the index left page and as each class is added a main page (ClassXX.htm) is created by calling the function WriteClassDetail. This function is passed the classes TreeNode and using the Tag function the codeElement is recovered. The codeElement's codeType count is used to iterate through each function whereby the necessary data is extracted to construct the HTML class main page, as shown below:

C#
// Iterate through each of the classes functions
for (int i = 0; i < codeType.Members.Count; i++)
{
    codeElement = codeType.Members.Item(i+1);
    if (codeElement.Kind == vsCMElement.vsCMElementFunction)
    {
        CodeFunction codeFunction = (CodeFunction)codeElement;
        // Move edit point to function definition
        editPoint.MoveToPoint(codeFunction.GetStartPoint(
                                    vsCMPart.vsCMPartHeader));
        // Get function method statement
        functionStr = editPoint.GetLines(editPoint.Line,
                                            editPoint.Line+1);
        // Get summary statement
        summaryStr = SearchAndCut(codeFunction.DocComment,
                        "<SUMMARY>", "</SUMMARY>");
        Console.SetOut(swc);
        swc.Write(TABLEROW);
        swc.Write(TABLEWIDTH);
        swc.Write(TABLEINPUTSPACE);
        swc.Write(TABLEINPUTTOP, codeFunction.Name);
        swc.Write(TABLEINPUTFUN, functionStr, summaryStr);
        swc.Write(TABLEWIDTH);
        swc.Write(TAGTR);
    }
}

History

  • 6th August, 2005 - Initial version.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Web Developer
United Kingdom United Kingdom
Mike Knuckey is a software consultant for Barnecourt Solutions, operating from Dartmoor, Devon, UK.

Comments and Discussions

 
GeneralHelp me:this code is not working in .net 2005 Pin
arunprakash8328-Nov-05 21:35
arunprakash8328-Nov-05 21:35 
GeneralRe: Help me:this code is not working in .net 2005 Pin
Mike Knuckey9-Dec-05 4:52
Mike Knuckey9-Dec-05 4:52 
Arun
Could you be more specific on the problem you have experienced?
Regards

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.