Visualize Code Dependencies on Dependency Graphs

To see and understand the organization of your code and its dependencies, you can create dependency graphs in Visual Studio Ultimate. What are dependency graphs and how are they useful?

Supported projects:

  • Visual C# .NET and Visual Basic .NET projects, including Windows Store apps, and assembly files (.dll or .exe).

  • Visual C++ projects, including Windows Store apps, that have C or C++ code (managed or native), header files (.h or #include), and binary files.

Videos:

In this topic

  • How do I get started?

  • Visualizing dependencies in your code

  • Sharing dependency graphs

  • Generate graphs for batch processing

  • Troubleshooting

How do I get started?

  • Get an overview of your solution: On the Architecture menu, choose Generate Dependency Graph, For Solution.

    You get a graph that shows the top-level assemblies. You can now explore these assemblies by expanding them. Move the mouse pointer on top of an assembly, and then choose the chevron (^) button when it appears. Do the same for namespaces, types, and members to continue exploring your code.

    Top-level dependency graph of assemblies

    To see dependencies across groups, choose an item on the graph.

    Graph with selected items and expanded groups

    For more information, see Get an overview of your solution. You can also run analyzers to find potential problems in your code. See Find Potential Problems in Code on Dependency Graphs.

  • Visualize specific dependencies in your solution: In Solution Explorer, select items that interest you. You can select projects, assembly references, folders, files, types, and their members. To find a specific item, use the Solution Explorer search box.

    On the Solution Explorer toolbar, choose Create a new graph documentCreate New Graph From Selected Nodes Button.

    - or -

    Drag the items from Solution Explorer to an existing graph.

    Tip

    To create a blank graph, on the File menu, choose New, File, Directed Graph Document. To include the parent hierarchy for your items, press and hold the CTRL key while you drag items.

    You get a graph that shows your selected items. You can now explore these items by expanding them. Move the mouse pointer on top of an item, and then choose the chevron (^) button when it appears.

    For more information, see Visualize specific dependencies in your solution. You can also run analyzers to find potential problems in your code. See Find Potential Problems in Code on Dependency Graphs.

What are dependency graphs and how are they useful?

Dependency graphs provide a visual way for you to examine code and understand its dependencies without having to look through files and lines of code. You can see items and relationships as just nodes and links, or arrows. For example, suppose you have a code review to perform. You have a set of files that contain pending changes. You can visualize the code and dependencies for those changes by creating a dependency graph from those files. See Visualize specific dependencies in your solution.

By default, container relationships are represented as groups, which you can expand and collapse.

Dependency graph with grouped nodes

Tip

The Refetch Children button Refetch Children Icon lets you retrieve group members that exist in code but don't appear on the graph. We've also applied a different style to the Calls links so you can see it more easily. See Edit and Customize Dependency Graphs.

You can also view container relationships as links. Open the shortcut menu for the graph, choose Group, Turn Off Grouping:

Dependency graph with nodes and links

You can also run analyzers to find potential problems in your code. See Find Potential Problems in Code on Dependency Graphs.

When you generate a dependency graph the first time, Visual Studio indexes all the dependencies it finds. This process might take some time, especially for large solutions or graphs with many links. However, the index improves the performance of later operations. If the code changes, Visual Studio reindexes only the updated code.

If you don't want to wait for the graph to finish generating, you can cancel this step at any time and try the following suggestions:

  • Graph only the dependencies that interest you.

  • Before you generate the graph for an entire solution, reduce the solution scope.

Although Visual Studio can run with 1 GB of memory, we recommended that your computer have at least 2 GB of memory to avoid long delays while Visual Studio creates the code index and generates the graph.

Note

Visual Studio generates a graph if at least one project builds successfully. It shows only the dependencies for code that builds successfully. If build errors occur for certain components, then errors for those components appear on the graph. Make sure that a component actually builds and has dependencies on it before you make architectural decisions based on the graph.

It might take more time to create graphs or add items to a graph from Solution Explorer when a project item's Copy to Output Directory property is set to Copy Always. This might cause issues with incremental builds and Visual Studio to rebuild the project each time. To increase performance, change this property to Copy if newer or PreserveNewest. See Incremental Builds.

Visualizing dependencies in your code

  • Get an overview of your code

  • Visualize specific dependencies in your code

  • Visualize dependencies between C or C++ source files and header files

  • Generate graphs for batch processing by using GraphCmd.exe

Tip

To generate more complete graphs for C++ projects, the browse information compiler option (/FR) must be set on those projects. Otherwise, a message appears and prompts you to set this option. If the message appears, you can set the option for only the current graph by choosing OK, or you can set the option and hide the message for all later graphs. To make the message appear for later graphs, set the following registry key to 0 or delete the key:

HKEY_CURRENT_USER\Software\Microsoft\VisualStudio\11.0\NativeProvider : AutoEnableSbr

See /FR, /Fr (Create .Sbr File).

Get an overview of your code

You can create a dependency graph for your entire solution or for assemblies or binaries.

Get an overview of your solution

  1. On the Architecture menu, choose Generate Dependency Graph, For Solution.

    You get a graph that shows the top-level assemblies and aggregated links between them. The thickness of an aggregate link indicates how many individual dependencies the link represents. The Externals group contains anything outside your solution, including platform dependencies. External assemblies show only those items that are used.

    Top-level dependency graph of assemblies

  2. You can now explore these assemblies by expanding them. Move the mouse pointer on top of an assembly, and then choose the chevron (^) button when it appears. (Keyboard: Choose the item, then choose the PLUS key (+).) Do the same for namespaces, classes, and members to continue exploring your code.

  3. To get more information about an item or link, move the pointer on top of the item until a tooltip appears.

  4. To examine items and dependencies represented by an aggregate link, select the link first, and then open its shortcut menu. Choose Show, Contributing links in current diagram or Contributing links in a new diagram.

    Visual Studio expands the groups at both ends of the link and shows only those items and dependencies that participate in the link. To see items that exist in code but are missing from a group, choose Refetch ChildrenRefetch Children Icon.

See:

Get an overview of assemblies or binaries

  • Create a blank graph, or open an existing graph (.dgml file). From outside Visual Studio, drag the assemblies or binaries to the graph.

    Note

    You can drag assemblies or binaries from Windows Explorer only if you are running Windows Explorer and Visual Studio at the same User Access Control (UAC) permissions level. For example, if UAC is turned on, and you are running Visual Studio as Administrator, then Windows Explorer will block the dragging operation. To work around this, make sure that Visual Studio is running as Administrator, or turn UAC off. Note that in Windows 8, Windows Explorer is File Explorer.

    -or-

    1. On the Architecture menu, choose Windows, Architecture Explorer.

    2. In the first column, under File System, choose Select Files.

    3. In the Open box, find and select the assemblies or the binaries. Choose Open to add them to the next column in Architecture Explorer.

    4. In Architecture Explorer, select the assemblies or binaries.

    5. To the right of the column that contains the selected assemblies or binaries, choose the collapsed action column to expand it.

      Tip

      The collapsed action column appears highlighted when you move the pointer on top of it.

    6. In the action column, under Commands, choose Open to generate a dependency graph.

      See Find Code with Architecture Explorer.

To create a blank graph

  1. To open a new blank graph without adding it to your solution, on the File menu, choose New, File.

    -or-

    To add a blank graph to the Solution Items folder in your solution, open the shortcut menu for the top-level solution node. Choose Add, New Item.

  2. Under Installed, choose General.

  3. In the right pane, choose Directed Graph Document.

    You can also add a blank graph to a modeling project from the Architecture menu by choosing New Diagram.

Visualize specific dependencies in code

You can create a dependency graph for specific items in your solution or in assemblies and binaries.

Visualize specific dependencies in your solution

How to visualize specific code

How to visualize specific code and parents

  1. In Solution Explorer, select items that interest you. You can select projects, assembly references, folders, files, types, and their members. To find a specific item, use the Solution Explorer search box.

    Tip

    To find items with dependencies on types or members, open the shortcut menu for the type or member in Solution Explorer. Choose the dependency type. Solution Explorer shows items that have the dependency you specified. Select the results.

  2. To graph your items and their members, on the Solution Explorer toolbar, choose Create a new graph documentCreate New Graph From Selected Nodes Button.

    -or-

    To include the parent hierarchy on the graph, open the Create a new graph document… list on the Solution Explorer toolbar, then choose New Dependency Graph with Ancestors.

    Tip

    You can also drag items to the graph. First, create a blank graph or open an existing graph (.dgml file). To include the parent container hierarchy, press and hold the CTRL key while you drag the items.

    You get a graph that shows your selected items.

  3. To explore items, you can expand them. Move the mouse pointer on top of an item, then choose the chevron (^) button when it appears. To expand all items, open the shortcut menu for the graph. Choose Group, Expand All.

    Note

    This command is not available if expanding all groups generates an unusable graph or memory issues.

  4. To retrieve items missing from a group, choose Refetch ChildrenRefetch Children Icon inside the group.

  5. To see more items related to the ones on the graph, open the shortcut menu for the item. Choose Show and the relationship of the items that interest you.

    For an assembly, choose:

    Referenced Assemblies

    Add assemblies that this assembly references. External assemblies appear in the Externals group.

    Referencing Assemblies

    Add assemblies in the solution that reference this assembly.

    For a class, choose:

    Base Types

    For a class, add the base class and the implemented interfaces.

    For an interface, add the base interfaces.

    Derived Types

    For a class, add the derived classes.

    For an interface, add the derived interfaces and the implementing classes or structs.

    All Base Types

    Add the base class or interface hierarchy recursively.

    All Derived Types

    For a class, add all the derived classes recursively.

    For an interface, add all the derived interfaces and implementing classes or structs recursively.

    Containment Hierarchy

    Add the parent container hierarchy.

    Used Types

    Add all classes and their members that this class uses.

    Used-By Types

    Add all classes and their members that use this class.

    For a method, choose:

    Containment Hierarchy

    Add the parent container hierarchy.

    Called Methods

    Add methods that this method calls.

    Called-By Methods

    Add methods that call this method.

    Overridden Methods in Base Types

    For a method that overrides other methods or implements an interface's method, add all the abstract or virtual methods in base classes that are overridden and, if any, the interface's method that is implemented.

    Referenced Fields

    Add fields that this method references.

    For a field, choose:

    Containment Hierarchy

    Add the parent container hierarchy.

    Referencing Methods

    Add methods that reference this field.

See:

Visualize specific dependencies in assemblies or binaries

  1. On the Architecture menu, choose Windows, Architecture Explorer.

  2. In the first column, under File System, choose Select Files.

  3. In the Open box, find and select the assemblies or binaries. Choose Open to add them to the next column in Architecture Explorer.

  4. In the next column, select the assemblies or the binaries.

    By default, the next column shows items contained by the selected items.

    Tip

    To select other related items, expand the collapsed column to the right of the column with your selections. Under Node Navigation, select the kinds of items that interest you. Under Outbound Navigation or Inbound Navigation, select the kinds of relationships that interest you. See Find Code with Architecture Explorer.

  5. Find and select all the items that you want to put on the graph.

  6. To create a new graph, on the Architecture Explorer toolbar, choose Create a new graph document from all the selected nodesCreate New Graph From Selected Nodes Button.

    Visual Studio creates the graph and opens it.

    -or-

    To add your selection to a graph, follow these steps:

    1. Open the graph's .dgml file, or create a blank graph.

    2. On the Architecture Explorer tool bar, choose Add all the selected nodes to the currently visible graph documentAdd All Selected Nodes to Graph Button.

      -or-

      Drag items from Architecture Explorer to the graph.

Visualize dependencies between C and C++ source files and header files

To see dependencies between

Do this

All source files and header files in the solution

On the Architecture menu, choose Generate Dependency Graph, For Include File.

Dependency graph for native code

The currently open file and related source files and header files

  1. Open either a source file or header file.

  2. Open the shortcut menu anywhere inside the file. Choose Generate Graph of Include Files.

First-level dependency graph for .h file

Note

When you open a solution that contains Visual C++ projects, it might take some time to update the IntelliSense database. During this time, you might not be able to create dependency graphs for header (.h or #include) files until the IntelliSense database finishes updating. You can monitor the update progress in the Visual Studio status bar. To resolve issues or messages that appear because certain IntelliSense settings are disabled, see Troubleshooting.

Sharing dependency graphs

Save and share the graph with other users of Visual Studio

  • Use the File menu to save the graph.

    -or-

    To save the graph as part of specific project, open the shortcut menu for the graph surface. Choose Move <DependencyGraphName.dgml> into and the project where you want to save the graph.

    Visual Studio saves the graph as a .dgml file that you can share with other users of Visual Studio Ultimate, Visual Studio Premium, and Visual Studio Professional.

    Note

    Before you share a graph with those who use Visual Studio Premium and Visual Studio Professional, make sure to expand any groups, show hidden nodes and cross-group links, and retrieve any deleted nodes that you want others to see on your graph. Otherwise, other users won't be able to see these items.

    The following error might occur when you save a graph that is in a modeling project or was copied from a modeling project to another location:

    "Cannot save fileName outside the project directory. Linked items are not supported."

    Visual Studio shows the error, but creates the saved version anyway. To avoid the error, create the graph outside the modeling project. You can then save it to the location that you want. Just copying the file to another location in the solution, and then trying to save it will not work.

Export the graph as an image so you can copy it into other applications, such as Microsoft Word or PowerPoint

  1. Open the shortcut menu for the graph surface. Choose Edit, Copy Image.

  2. Paste the image into another application.

Export the graph as an XPS file so you can see it in XML or XAML viewers like Internet Explorer

  1. Open the shortcut menu from the graph surface. Choose Save As XPS.

  2. In the Save As dialog box, browse to where you want to save the file.

  3. Name the graph. Make sure that the Save as type box is set to XPS files (*.xps). Choose Save.

Generate graphs for batch processing

You can generate graph documents (.dgml files) in batch mode by using the GraphCmd.exe command-line tool. For example, you can run the tool after each build to find dependencies that have changed between builds. To find this tool, look in the following folder: C:\Program Files\Microsoft Visual Studio 11.0\Common7\IDE.

Note

GraphCmd.exe supports only .NET code and generates dependency information only for assemblies or .dgml files, not source code in Visual Studio solution or project files. GraphCmd.exe runs outside Visual Studio, so support for actions in DGQL queries is limited.

Use the following syntax for GraphCmd.exe:

GraphCmd -? -all -exceptions -input File_Name -query File_Name -exec "DGQL_Statement" -output File_Name -path alias=path

Tip

You can specify the following options multiple times: -input, -query, -exec, and -path.

The following table describes the options for GraphCmd.exe:

-?

Display the help for GraphCmd.exe.

-all

Include all intermediate query results, not just for the last node set.

-exceptions

Report the query exceptions as a graph document (.dgml) file.

-input File_Name

Process the specified .dgml file.

This is useful for post-processing a large .dgml file and filtering it so that you can visualize it more easily in Visual Studio.

-query File_Name

Run the specified Directed Graph Query Language (DGQL or .dgql) file.

See:

-exec "DGQL_Statement"

Run the specified DGQL statement.

See Understanding Directed Graph Query Language (DGQL).

-output File_Name

Output the specified .dgml file.

-path alias=path

Specify a new alias to use in the input and output of DGML documents.

For example:

GraphCmd -output MyGeneratedGraph.dgml -path "MyPathAlias=C:\Program Files\..."

See Aliases for Commonly-Used Paths.

Aliases for commonly-used paths

Aliases for commonly-used paths reduce the size of the .dgml file and the time required to load or save the file. To create an alias, add a <Paths></Paths> section at the end of the .dgml file. In this section, add a <Path/> element to define an alias for the path:

<Paths>
   <Path Id="MyPathAlias" Value="C:\...\..." />
</Paths>

To reference the alias from an element in the .dgml file, enclose the Id of the <Path/> element with a dollar sign ($) and parentheses (()):

<Nodes>
   <Node Id="MyNode" Reference="$(MyPathAlias)MyDocument.txt" />
</Nodes>
<Properties>
   <Property Id="Reference" Label="My Document" DataType="System.String" IsReference="True" />
</Properties>

To edit .dgml files, see Edit and Customize Dependency Graphs.

Understanding Directed Graph Query Language (DGQL)

DGQL is a lightweight query language that you can use to build DGML. A DGQL statement follows an alternating pattern of node selection and actions such that each node selection creates input for the next action, whose output becomes input for the next node selection, and so on.

The format of a DGQL statement is:

<node selection> / <action> / <node selection> / <action> / ...

The following table describes the DGQL syntax used to select nodes:

*

Select all nodes.

+ "text"

Select all nodes that contain "text".

+ Id.Equals("text")

Select all nodes whose Id is equal to "text".

+ Background.Contains("text")

Select all nodes whose Background attribute has a value that contains the string "text".

+ "text1" + "text2" + ...

Select all nodes that match "text1" or "text2".

+ MyProperty="True"

Select all nodes that have a property named MyProperty whose value is "True".

- Label.Contains("text")

Select all nodes except those that have a Label attribute that Contains the string "text".

+ Category.Is("MyCategory")

Select all nodes that have a category named MyCategory or that inherits from MyCategory.

The following table describes examples of direct actions that can be performed on selected nodes:

Example action

Description

Microsoft.Contains

Return all nodes that are contained by the input nodes. You can replace Contains with a different link category.

Microsoft.Open

Open the source code for the input nodes.

Note

Works only within Visual Studio.

Microsoft.AllOutBoundLinks

Return all nodes that are the target of an outgoing link from the input nodes.

Microsoft.AllInboundLinks

Return all nodes that are the source end of a link to the input nodes.

Microsoft.Core.CreateGroupsByProperties

Invoke the GroupByProperties action.

Microsoft.AllNodes

Return all nodes in the entire graph thus far.

Data-driven actions select items based only on the data in the input nodes and links. When matching categories using data-driven actions, inherited categories are included. The following table describes examples of data-driven actions:

Type

Description

Node:Both:Category

Return all nodes that have the category Category and are connected with the input nodes by a link that points in either direction.

Link:Both:Category

Return all nodes that are connected with the input nodes by a link that points in either direction and has the category Category.

Link:Backward:Category

Return all nodes that point to the input nodes with a link that has the category Category.

Link:Forward:Category

Return all nodes that point from the input nodes with a link that has the category Category.

Tips

  • Typically, there is a "default" action for a given set of input nodes, which is selected automatically by Architecture Explorer. To get the same behavior, use an empty action: //

  • Whitespace is not significant in DGQL, so you can format your query to fit on one line if necessary. This is useful when you use the –exec option with GraphCmd.

  • When debugging DGQL, use the action "Execute Expanded" in Architecture Explorer to help you see each step of the query and find the step that is not producing the expected results.

Example

The following DGQL statement performs a query as described in the following steps:

+ Id.Equals("Microsoft.Solution.ClassView") / "Microsoft.Solution.ClassView" / * / "Node:Both:CodeSchema_Class" / + CodeSchemaProperty_IsPublic.Equals("True")
  1. Choose the Class View node in the first column of Architecture Explorer.

  2. Perform the action "Microsoft.Solution.ClassView", returning all the namespaces in the solution. 

  3. Use * to select all the namespaces.

  4. Select all nodes that have the category CodeSchema_Class and are related to those namespaces by a link in either direction. These will usually be containment links.

  5. Filter the resulting classes to only those that have the property CodeSchemaProperty_IsPublic="True".

Technically, the action "Microsoft.Solution.ClassView" is unnecessary because it is the "default" action for the Class View node. Therefore, you can replace that action with // to simplify the query and format it on a single line as follows:

+Id.Equals("Microsoft.Solution.ClassView")//*/"Node:Both:CodeSchema_Class"/+CodeSchemaProperty_IsPublic.Equals("True")

Troubleshooting

The following items aren't supported for C and C++ code:

  • Base types don't appear on graphs that include the parent hierarchy.

  • Most Show menu items aren't available for C and C++ code.

The following issues might occur when creating dependency graphs for C and C++ code:

Issue

Possible cause

Resolution

The dependency graph failed to generate.

No projects in the solution were built successfully.

Fix the build errors that occurred and then regenerate the graph.

Visual Studio becomes unresponsive when you try to generate a dependency graph from the Architecture menu.

The program database (.pdb) file might be corrupted.

A .pdb file stores debugging information, such as type, method, and source file information.

Rebuild the solution and then try again.

Certain settings for the IntelliSense browsing database are disabled.

Certain IntelliSense settings might be disabled in the Visual Studio Options dialog box.

Turn on the settings to enable them.

See Options, Text Editor, C/C++, Advanced.

The message Unknown Methods appears on a method node.

This issue occurs because the name of the method cannot be resolved.

The binary file might not have a base relocation table.

Turn on the /FIXED:NO option in the linker.

See /FIXED (Fixed Base Address).

The program database (.pdb) file might not be built.

A .pdb file stores debugging information, such as type, method, and source file information.

Turn on the /DEBUG option in the linker.

See /DEBUG (Generate Debug Info).

Cannot open or find the .pdb file in the expected locations.

Make sure that the .pdb file exists in the expected locations.

Debug information has been stripped from the .pdb file.

If the /PDBSTRIPED option was used in the linker, include the complete .pdb file instead.

See /PDBSTRIPPED (Strip Private Symbols).

The caller is not a function and is either a thunk in the binary file or a pointer in the data section.

When the caller is a thunk, try using _declspec(dllimport) to avoid the thunk.

See:

What else can I do?

Where can I get more information?

Category

Links

Forums

Blogs