Article

# Visualizing Project Dependencies Automatically

By , 4 Sep 2007
 Rate this:

## 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:

/// <span class="code-SummaryComment"><summary></span>
/// Load project file from disk and get list of project paths
/// <span class="code-SummaryComment"></summary></span>
/// <span class="code-SummaryComment"><returns></returns></span>
private string[] GetReferenceProjectPaths()
{
XmlDocument project = new XmlDocument();
XmlNamespaceManager namespaceManager =
new XmlNamespaceManager(project.NameTable);
"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.

/// <span class="code-SummaryComment"><summary></span>
/// 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.
/// <span class="code-SummaryComment"></summary></span>
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)
{
project.Name + "-" + reference.Name)
)
{
sb.Append(
"\"" + project.Name + "\" -> \"" +
reference.Name + "\"" + Environment.NewLine
);
}

}
}

## 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

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.

 First Prev Next
 Nice Job 3779886 21-May-08 6:25
 Fixed infinite loop problem Doug in NH 12-Sep-07 2:55
 Re: Fixed infinite loop problem Paul B. 12-Sep-07 4:04
 To add support for VB Projects... Doug in NH 12-Sep-07 2:47
 Too much hard coded stuff Vagif Abilov 4-Sep-07 2:13
 Re: Too much hard coded stuff Paul B. 4-Sep-07 3:59
 The example wasn't meant to be a perfect example of how to launch an external program, it was meant to demonstrate how to visualize the projects. There are unit tests and if this particular assumption was flawed, one of the tests would fail, so it would be fairly obvious what the problem was. At the time of writing, the time it would take to figure out where the registry entry was, etc. didn't seem to be worth the time given that it was an internal app run on a schedule automatically.   However, a few people have had problems with that so I went ahead and changed it to lookup the registry entry and updated the zip file. The code you posted in your comment was changed to the below:   //get a reference to the registry key used for graphviz Microsoft.Win32.RegistryKey GraphvizKey = Microsoft.Win32.Registry.LocalMachine.OpenSubKey("Software\\ATT\\Graphviz"); if (GraphvizKey == null) throw new ApplicationException("Unable to find Graphviz registry entry - is it installed?");   //get path to dot.exe, should be in bin directory in install path string DotExePath = System.IO.Path.Combine(GraphvizKey.GetValue("InstallPath").ToString(), "bin\\dot.exe");   //call out to graphviz to create JPG file System.Diagnostics.Process.Start( DotExePath, "-Tjpg \"" + DOTFile + "\" \"-o" + OutputJPGFilePath + "\"" );
 Bug on non english OS Lukas Ith 20-Aug-07 0:59
 Re: Bug on non english OS Paul B. 20-Aug-07 3:26
 Last Visit: 31-Dec-99 18:00     Last Update: 19-Apr-14 4:16 Refresh 1