Click here to Skip to main content
15,881,172 members
Articles / Programming Languages / C#
Article

Visualizing Project Dependencies Automatically

Rate me:
Please Sign up or sign in to vote.
4.09/5 (11 votes)
4 Sep 2007CPOL3 min read 42.8K   428   32   8
Have a large code tree? Wondering which projects refer to which other ones? Manually run this console app, schedule it to run nightly or after each build.
Screenshot - AllCode.jpg

Introduction

Developer 1: Hey I want to make some changes to CommonLibrary1. Is that going to affect the 15 other projects people are working on?

Developer 2: I dunno, ask John.

Developer 1: He told me to ask you.

Sound familiar? I wanted a quick easy, foolproof way to visualize project dependencies without depending on human intervention, i.e. some poor sap typing stuff into a Word document which would probably be wrong before he saved the document.

This project attempts to solve that by taking a directory location and an output JPG location as parameters. It then scans the directories getting all the *.csproj files and determines their relationships. It then uses the graphviz package to visualize these dependencies quickly and easily with fancy schmancy arrows and circles.

Background

I thought for sure that someone would have done this already but I could only find something similar for C++ apps. Even if there was an existing thing that did this, chances are it wouldn't work for the code structure I like to use. Different companies like to do their references and what not differently, so it would be nice to own the code and modify it according to personal preference... hence this project was born.

I like to put in post build events for code that will copy the output DLLs to a directory called References. That way, whether it is a debug or release compile, the referencing projects all point to the same place and everyone has consistent references. This project assumes that structure so if you have something different then you will need to make code changes. Don't worry, I have included 3 sample projects and full unit tests so you can figure out how it's supposed to work first, then change it to suit your needs. You'll need Nunit to run the tests. It's free, get it.

Using the Code

In the DependencyTracker/Launch directory, there is a *.bat file which will generate two JPG files: one for the library code projects only and one that generates a JPG for all projects. By changing the search directory and output JPG locations, you can customize it to your scenario and then schedule it to run on whatever schedule works best. Output to a network drive which happens to be on a Web server and you have instant up to date documentation which is easily accessible.

Most of the magic happens in Project.cs when it is trying to find the references:

C#
/// <summary>
/// Load project file from disk and get list of project paths
/// </summary>
/// <returns></returns>
private string[] GetReferenceProjectPaths()
{
    XmlDocument project = new XmlDocument();
    project.Load(ProjectPath);
    XmlNamespaceManager namespaceManager = 
    new XmlNamespaceManager(project.NameTable);
    namespaceManager.AddNamespace(
    "ns", 
    "http://schemas.microsoft.com/developer/msbuild/2003");

Nothing earth shattering, just parsing the *.csproj file which is XML and looking for the references. The only complication is that the reference is stored as a relative file path, but by changing the current directory to where the project is and then just browsing to that path, we can get to the referenced DLL pretty easy. Then we just have to figure out where the source project is given the compiled DLL's location. As mentioned previously, I like to keep a consistent "References" folder so it isn't too difficult to find the referenced project file from there. If you have a different structure, you will need to make changes here.

After all of this is loaded in memory, we then call out to a command line program to launch the graphviz image generation based on a file that is output below. We must recursively parse all the various projects and dependencies that have been loaded and take care not to process the same one twice so we don't get phantom arrows on the graph. The basic format of the graphviz program is to take a *.dot file which has lines like "a -> b" which means a points to b.

C#
/// <summary>
/// This will output all dependencies since that is what we care about. 
/// Will need some additional work if we want to display 
/// straggler projects with no dependencies also.
/// </summary>
private void AppendProjectLinks(StringBuilder sb, ProjectList projects)
{
    //loop through every project and output its dependencies to the 
    //file in the format
    //parent -> child
    //order doesn't matter for dot files
    foreach (Project project in projects)
    foreach (Project reference in project.ReferencedProjects)
    {
        //if not processed output link and add to processed list
        if (!ProcessedLinks.Contains(
            project.Name + "-" + reference.Name)
        )
        {
            sb.Append(
            "\"" + project.Name + "\" -> \"" + 
            reference.Name + "\"" + Environment.NewLine
            );
            ProcessedLinks.Add(project.Name + "-" + reference.Name);
        }

        AppendProjectLinks(sb, project.ReferencedProjects);
    }
}

Points of Interest

All the tests use relative paths so it shouldn't matter where you unzip the files to, they should work as long as you don't move any of the folders around in the zip file.

History

  • 17-August-2007 - Initial version
  • 04-September-2007 - Changed dot.exe launch method to use registry key

License

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


Written By
United States United States
I've been a software developer since 1996 and have enjoyed C# since 2003. I have a Bachelor's degree in Computer Science and for some reason, a Master's degree in Business Administration. I currently do software development contracting/consulting.

Comments and Discussions

 
GeneralNice Job Pin
Ashutosh Phoujdar21-May-08 6:25
Ashutosh Phoujdar21-May-08 6:25 
GeneralFixed infinite loop problem Pin
Doug in NH12-Sep-07 2:55
Doug in NH12-Sep-07 2:55 
GeneralRe: Fixed infinite loop problem Pin
Paul B.12-Sep-07 4:04
Paul B.12-Sep-07 4:04 
GeneralTo add support for VB Projects... Pin
Doug in NH12-Sep-07 2:47
Doug in NH12-Sep-07 2:47 
GeneralToo much hard coded stuff Pin
Vagif Abilov4-Sep-07 2:13
professionalVagif Abilov4-Sep-07 2:13 
GeneralRe: Too much hard coded stuff Pin
Paul B.4-Sep-07 3:59
Paul B.4-Sep-07 3:59 
GeneralBug on non english OS Pin
Lukas Ith20-Aug-07 0:59
Lukas Ith20-Aug-07 0:59 
GeneralRe: Bug on non english OS Pin
Paul B.20-Aug-07 3:26
Paul B.20-Aug-07 3:26 

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.