Generating Active Directory Diagrams with Visio 2003 and Visual Studio .NET 2003

 

Erika Ehrli
Saul Candib
Microsoft Corporation

December 2005

Applies to:
    Microsoft Office Visio 2003
    Microsoft Office 2003 Editions
    Microsoft Visual Studio .NET 2003

Summary: Create an Active Directory user diagram using a Microsoft Office Visio 2003 add-in, the Visio 2003 Primary Interop Assemblies, and Microsoft .NET Directory Services. The code provided in this article is written in C#. (29 printed pages).

Download OfficeTalkActiveDirectoryVisioDiagrams.exe.

Contents

Introduction
Working with the Visio Primary Interop Assemblies
Working with Active Directory
Building Visio Add-ins that Generate Active Directory Diagrams
Conclusion
Additional Resources
Acknowledgments

Introduction

Microsoft Office Visio 2003 is an application that allows you to model the real world graphically and generate all sorts of custom visual solutions. Visio provides a set of built-in features that allow you to create different kinds of diagrams. However, your organization might need a custom, automatically generated diagram to model a specific scenario.

A great example of a custom diagram that many organizations find valuable is a diagram based on Microsoft Active Directory directory services. You can create a managed Visio add-in that connects to Active Directory, searches for the objects you need, and places representations of them in a Visio diagram. For example, you can build diagrams that display all the users in a particular department, all the computers in your organization that run a given operating system, all the domain controllers in a country or region, and more.

In this article, we explain in detail how you can create a managed Visio add-in that uses .NET Directory Services to connect to Active Directory, and then use the Visio Primary Interop Assemblies to generate a Visio diagram that lays out all the necessary shapes. To keep the scope simple, we generate a diagram that displays all users that belong to a particular department and that share the same job title.

Working with the Visio Primary Interop Assemblies

If you are a developer of Microsoft .NET connection software, you can extend Office applications using Primary Interop Assemblies. A Primary Interop Assembly is a managed code assembly that lets you use managed code (for example, Microsoft Visual C# 2005 Express Edition) to control COM applications such as Visio programmatically. The Visio 2003 Primary Interop Assemblies allow you to integrate and extend Visio functionality into managed applications.

If you already have the .NET Framework installed on your computer, when you subsequently install Visio, the installer adds the Visio Primary Interop Assemblies to the Global Assembly Cache (GAC) on your computer. You can add a reference to the Visio Primary Interop Assemblies from your managed applications by following these steps:

  1. Open a managed project in Microsoft Visual Studio .NET 2003.

  2. On the Project menu, click Add Reference.

  3. On the COM tab, locate Microsoft Visio 11.0 Type Library, and then click Select (Figure 1).

    Add a reference to the Visio Primary Interop Assemblies from your managed applications

    Figure 1. Add a reference to the Visio Primary Interop Assemblies from your managed applications

  4. Click OK.

After adding the reference to the project, you can start working with Visio objects from your managed application. Visio has an extensive object model that provides a set of classes, interfaces, and enumerations that allow you to create diagrams programmatically. To create Active Directory user diagrams that we described in the previous section, you use the following classes:

  • Microsoft.Office.Interop.Visio.Application. Represents an instance of Visio.
  • Microsoft.Office.Interop.Visio.Document. Represents a drawing file (.vsd or .vdx), stencil file (.vss or .vsx), or template file (.vst or .vtx) that is open in an instance of Visio.
  • Microsoft.Office.Interop.Visio.Documents. Represents the collection that includes a Document object for each open document in a Visio instance.
  • Microsoft.Office.Interop.Visio.Window. Represents an open window in a Visio instance.
  • Microsoft.Office.Interop.Visio.Page. Represents a drawing page, which can be either a foreground page or a background page.
  • Microsoft.Office.Interop.Visio.Master. Represents a Master object from the Masters collection of a Document object whose Document stencil contains that master. Masters become Shapes once they are dropped on a page.
  • Microsoft.Office.Interop.Visio.Shape. Represents anything you can select in a drawing window: a basic shape, a group, a guide, or an object from another application embedded in or linked to in Visio.
  • Microsoft.Office.Interop.Visio.Shapes. Represents a collection that includes a Shape object for each basic shape, group, guide, or object from another application (linked to or embedded in Visio) on a drawing page, master, or group.
  • Microsoft.Office.Interop.Visio.Cell. Represents a cell in the Visio ShapeSheet spreadsheet, and can hold a formula that evaluates to some value. Under each Shape there is a ShapeSheet consisting of cells. These cells taken together describe the look and behavior of a Shape. Cells can also refer to other cells when defining behavior.

The following figure shows a partial object model diagram of the Visio classes that you need to generate the Active Directory user diagram.

Partial Visio 2003 object model (click picture to view larger image)

Figure 2. Partial Visio 2003 object model (Click picture to view larger image)

To make it easier to develop a Visio managed add-in, download and install the Visio 2003 Software Development Kit (SDK). The SDK installs a new Visio add-in or add-on project template to Visual Studio .NET 2003 and copies to your hard disk documentation and a set of sample applications in Microsoft Visual Basic .NET and Visual C# that provide guidance on how to generate Visio diagrams from your managed applications.

Working with Active Directory

Active Directory is a central component of the Windows platform that provides the means to share and manage identities and relationships that make up network environments. Active Directory uses a set of objects that represent network resources such as users, groups, domains, organizational units, subnets, sites, computers, devices, and applications. Each one of these objects has a set of attributes that describe specific characteristics of an object, allowing companies to store relevant information. Active Directory uses a schema to define the information that is stored for each object. For example, a user object schema specifies that a user has a name, e-mail, phone, title, and other attributes.

The following diagram represents some Active Directory objects and attributes.

Sample Active Directory objects and attributes

Figure 3. Sample Active Directory objects and attributes

For more information related to Active Directory objects and attributes, see the Microsoft Windows Server System documentation for Windows Server 2003 Active Directory.

Active Directory supports programming interfaces that provide access to Active Directory objects and attributes. The Lightweight Directory Access Protocol (LDAP) is an open-standard protocol that runs over TCP/IP. It allows you to build search queries to retrieve Active Directory objects and attributes. Active Directory Services Interfaces (ADSI) is a COM-based programming interface that also allows you to extract data programmatically from Active Directory. Although ADSI is not a standard protocol, it allows you to access all the features of an Active Directory. Using ADSI, you can create scripts to manage and query Active Directory. You can find sample ADSI scripts at the Microsoft TechNet Script Repository.

If you have a managed application and need to support access to Active Directory, you can use System.DirectoryServices Namespace to encapsulate ADSI providers and expose two classes:

  • DirectoryEntry Class. Encapsulates a node or object in Active Directory hierarchy. You use this class to connect to an LDAP path and return a reference to the node or object in Active Directory hierarchy that you want to work with.
  • DirectorySearcher Class. Performs queries against Active Directory.

In this article, we show how you can build custom Active Directory diagrams. However, if you are looking for a product that allows you to generate a complete set of Active Directory diagrams in Visio, consider evaluating NetDoc AD, a DataAssist product.

Building Visio Add-ins that Generate Active Directory Diagrams

Now that we know that you can generate Visio diagrams programmatically from managed applications, and the type of information that we can extract from Active Directory, we can start building a Visio add-in. This add-in will connect to Active Directory and generate a diagram that displays all the users that belong to a department and share the same job title.

Prerequisites

To build this solution, you must first install the following applications.

  • Microsoft Office Visio Professional 2003

  • Microsoft Visual Studio 2003

  • Microsoft Office Visio 2003 Software Development Kit (SDK)

    **Note   **The Visio 2003 SDK does not work with Microsoft Visual Studio 2005 or Beta versions of Microsoft Office "12."

You also must have access to Microsoft Windows Server 2003 Active Directory containing an existing set of users.

The general steps we take to build this solution are as follows:

  1. Create a Visio 2003 add-in project.
  2. Create an Active Directory helper class that connects to Active Directory and retrieves a list of users filtered by department and job title.
  3. Using the Visio Primary Interop Assemblies, create a Visio helper class to create the diagram.
  4. Create a Windows Form that defines connectivity settings for Active Directory and the department and job titles, to filter users.
  5. Modify the Connect.cs class and create a CommmandBarButton object that adds a button ("Create Users Diagram") to the Visio user interface.
  6. Build and install the Visio add-in setup project.
  7. Run and test the application.

Creating Visual Studio Projects

First, you create a Visio add-in project in Visual Studio.

To create a Visio add-in project

  1. Start Microsoft Visual Studio .NET 2003.

  2. On the Start page, click New Project.

  3. Under Project Types, select Visual C# Projects, and then, under Templates, select Visio add-in or add-on.

    Select the Visio add-in or add-on project template

    Figure 4. Select the Visio add-in or add-on project template

  4. Name your project VisioUserDiagrams, and click OK.

  5. On the Welcome screen of the Microsoft Visio Add-in or Add-on Wizard, click Next.

  6. Select Create a Visio COM add-in and click Next.

    Choose Visio COM add-in

    Figure 5. Choose the Visio COM add-in

  7. Name the add-in Visio ADUser add-in and type Active Directory user diagram filtered by department and title for the description. Click Next.

    Visio add-in name and description

    Figure 6. Visio add-in name and description

  8. Check both Add-in options check boxes. Click Next.

    Visio add-in options

    Figure 7. Visio add-in options

  9. Click Finish.

The wizard generates a new solution that contains two projects:

  • A Visio add-in project that contains references to the Visio Primary Interop Assemblies and a Connect.cs file that implements the IDTExtensibility2 interface to connect to Visio as a COM add-in. You work with this project to build all the logic to generate the diagrams.
  • A setup project that installs the Visio add-in to your computer. When you finish coding the solution, you must compile the setup project and run it to install the new Visio add-in.

The following figure shows both projects displayed in the Solution Explorer.

Visio add-in project and setup project

Figure 8. Visio add-in project and setup project

Now we can create a helper class that connects to and extracts data from Active Directory.

To create an Active Directory helper class

  1. In Solution Explorer, right-click the VisioUserDiagrams project, point to Add, and then click Add Class.

  2. Rename the file ADSIHelper.cs, and click Open.

    Adding a new file

    Figure 9. Adding a new file

  3. In Solution Explorer, right-click the VisioUserDiagrams project, right-click the References node and then click Add Reference.

  4. In the Add Reference dialog box, select System.DirectoryServices.dll.

    Adding a reference to System.DirectoryServices.dll

    Figure 10. Adding a reference to System.DirectoryServices.dll

  5. Click Select, and then click OK to add the reference.

Next, you must add the following namespaces that are referred to in the code. First, add a reference to System.Collections to work with collection objects. Open the ADSIHelper.cs file, and at the very top, add the following using statements:

using System.Collections;
// The System.DirectoryServices assembly provides access to Active Directory objects
using System.DirectoryServices;

The ADSIHelper class implements the IDisposable interface to allow the class to close and dispose of the connection object that is used to connect to Active Directory. Modify the class declaration to read as follows:

public sealed class ADSIHelper: IDisposable

With these declarations in place, you can add code that connects to Active Directory and queries for Active Directory objects. Active Directory uses LDAP connection strings to define the node or object to which we are connecting. To connect to an LDAP root, you also need to pass a user name and password so that Active Directory can validate the credentials and grant access to the user.

You first begin by creating fields, a constructor, and properties that store a user name, a password, and the LDAP path. You overload the class constructor to allow the user to select Windows Authentication instead of sending a user name and password.

Replace the empty constructor of the class ADSIHelper.cs file with the following code:

private DirectoryEntry _connection;
private string _password;
private string _path;
private string _userName;
private bool _windowsAuthentication;

// Constructor that uses Windows Authentication to connect to 
// Active Directory.
public ADSIHelper(string path) {
   _password = "";
   _userName = "";
   _path = path;
   _windowsAuthentication = true;
   _connection = CreateDirectoryEntry(_path);
}
      
// Constructor that uses a user name and password to connect to 
// Active Directory.
public ADSIHelper(string path, string username, string password) {
   _password = password;
   _userName = username;
   _path = path;
   _windowsAuthentication = false;
   _connection = CreateDirectoryEntry(_path);
}

You can use the DirectoryEntry class to connect to Active Directory and obtain a reference to a given node or object entry. The CreateDirectoryEntry method takes a string specifying the path to Active Directory and returns an instance of a DirectoryEntry.

Create the following method inside the ADSIHelper class:

private DirectoryEntry CreateDirectoryEntry(string path) {
   DirectoryEntry de = new DirectoryEntry();
   de.Path = path;
   if (_windowsAuthentication) {
      de.AuthenticationType = AuthenticationTypes.Secure;
   }
   else {
      de.Username = _userName;
      de.Password = _password;
   }
   return de;
}

To query Active Directory, you create the GetUsers method, which creates an instance of the DirectorySearcher class. You pass the method two strings that represent the job title and department for which you are searching. The method returns an instance of the ICollection class that contains all Active Directory users that satisfy the search criteria.

Create the following method inside the ADSIHelper class:

public ICollection GetUsers(string jobtitle, string department) {
   DirectorySearcher ds = new DirectorySearcher(_connection);
   ArrayList users = new ArrayList();

   // Transform the next three lines of code to a single line of code.
   ds.Filter = String.Format(
      "(&(objectCategory=Person)(objectClass=User)(title={0})
      (department={1}))", jobtitle, department);
   
   ds.SearchScope = SearchScope.Subtree;
   ds.ServerTimeLimit = TimeSpan.FromSeconds(60);
   SearchResultCollection results = ds.FindAll();

   foreach (SearchResult result in results) {
      DirectoryEntry userEntry = CreateDirectoryEntry(result.Path);
      users.Add(userEntry.Properties["name"].Value);
      userEntry.Close();
   }

   return users;
}

Finally, create two destructor methods inside the ADSIHelper class that dispose the connection to Active Directory:

~ADSIHelper() {
         Dispose(false);
}
      
private void Dispose(bool disposing) {
   if (_connection != null) {
      _connection.Close();
      _connection = null;
   }
}

public void Dispose() {
   Dispose(true);
   GC.SuppressFinalize(this);
}

Build the project to make sure that there are no compilation errors.

Creating Visio Helper Classes

Next, we create a class that uses the Visio Primary Interop Assemblies to generate a Visio diagram.

To create a Visio diagram generator class

  1. In Solution Explorer, right-click the VisioUserDiagrams project, point to Add, and then click Add Class.

  2. Rename the file DiagramGenerator.cs, and click Open.

  3. Open the DiagramGenerator.cs file and, at the very top of the file, add the following using statements for namespaces that are referred to in the code.

    using System.Collections;
    using Visio = Microsoft.Office.Interop.Visio; 
    

    Because we access the DiagramGenerator class only from the Visio add-in, we need to declare the class as internal. Modify the class declaration to:

    internal class DiagramGenerator
    
  4. With these declarations in place, we are ready to add code that uses the Visio Primary Interop Assemblies objects to create an Active Directory user diagram. We start by declaring a Visio Application object and replacing the empty constructor with a constructor that takes that object:

    private Visio.Application _vsoApplication;
    public DiagramGenerator(Visio.Application vsoApplication) {
       _vsoApplication = vsoApplication;
    }
    
  5. Next, we create a method that takes the department name we specified and the collection of users our query returns to generate the diagram in Visio. Create the following method inside the DiagramGenerator class:

    public void CreateDiagram(string departmentName, ICollection users) {
       // Add this line to provide Undo functionality in Visio.
       int undoScope = _vsoApplication.BeginUndoScope("Users Diagram");
    
       // Add the stencil shapes using a template for LDAP diagrams
       // (ldapdr_u.vst). You can modify the units of the diagram to the
       // metric system by changing the template to ldapdr_m.vst
       _vsoApplication.Documents.AddEx(
       "ldapdr_u.vst", Visio.VisMeasurementSystem.visMSUS, 0, 0);
    
       // Get a reference to the vsoWindow and the vsoPage.
       Visio.Window vsoWindow = _vsoApplication.ActiveWindow;
       Visio.Page vsoPage = vsoWindow.PageAsObj;
    
       // Transform the next two lines of code to a single line of code.
       // We split the code into two lines for readability, but it will not 
       // compile as is.
       Visio.Master departmentMaster =    _vsoApplication.Documents["LDAPOB_U.VSS"].Masters.get_ItemU("Locality");
    
       // Drop a department shape.
       Visio.Shape vsoDepartmentShape = vsoPage.Drop(departmentMaster,0, 0);
       vsoDepartmentShape.Text  = departmentName;
    
       // Define the user shape.
       Visio.Shapes shapes = vsoPage.Shapes;
    
       // Transform the next two lines of code to a single line of code.
       // We splitted the code in two lines for readability, but it will not 
       // compile as is.
       Visio.Master personMaster =    _vsoApplication.Documents["LDAPOB_U.VSS"].Masters.get_ItemU("Person");
    
       // Drop a Person shape for every user in the Users collection using
       // the Drop method.
       // You can improve performance if you use DropMany instead of Drop.
       foreach(string user in users) {
          Visio.Shape vsoPersonShape = vsoPage.Drop(personMaster, 0, 0);
          vsoPersonShape.Text = user;
    
          // Connect all the objects.
          Visio.Shape connector = vsoPage.Drop(
          _vsoApplication.ConnectorToolDataObject, 0, 0);
    
          Visio.Cell vsoCell1 = connector.get_CellsU("BeginX");
          Visio.Cell vsoCell2 = vsoDepartmentShape.get_CellsSRC(7, 3, 0);
          vsoCell1.GlueTo(vsoCell2);
    
          vsoCell1 = connector.get_CellsU("EndX");
          vsoCell2 = vsoPersonShape.get_CellsSRC(7, 0, 0);
          vsoCell1.GlueTo(vsoCell2);
       }
    
       //   Lay out shapes in the diagram as Flowchart/Tree.
       Visio.Cell layoutCell;
    
       layoutCell = vsoPage.PageSheet.get_CellsSRC(
    (short)Visio.VisSectionIndices.visSectionObject, 
    (short)Visio.VisRowIndices.visRowPageLayout,
    (short)Visio.VisCellIndices.visPLOResizePage);
    
       layoutCell.FormulaU = "TRUE";
    
       layoutCell = vsoPage.PageSheet.get_CellsSRC(
    (short)Visio.VisSectionIndices.visSectionObject, 
    (short)Visio.VisRowIndices.visRowPageLayout,
    (short)Visio.VisCellIndices.visPLOResizePage);
    
       layoutCell.FormulaU = "TRUE";
    
       layoutCell = vsoPage.PageSheet.get_CellsSRC(
    (short)Visio.VisSectionIndices.visSectionObject, 
    (short)Visio.VisRowIndices.visRowPageLayout,
    (short)Visio.VisCellIndices.visPLOPlaceStyle);
    
       layoutCell.set_Result (Visio.VisUnitCodes.visPageUnits,
          (double)Visio.VisCellVals.visPLOPlaceTopToBottom);
    
       layoutCell = vsoPage.PageSheet.get_CellsSRC(
    (short)Visio.VisSectionIndices.visSectionObject, 
    (short)Visio.VisRowIndices.visRowPageLayout,
    (short)Visio.VisCellIndices.visPLORouteStyle);
    
       layoutCell.set_Result (Visio.VisUnitCodes.visPageUnits,
          (double)Visio.VisCellVals.visLOBRouteFlowNS);
    
       vsoPage.Layout();
    
       _vsoApplication.EndUndoScope(undoScope, true);
    }
    
  6. Build the project to make sure that there are no compilation errors.

    **Note   **For more information about the Visio Primary Interop Assemblies objects used in the previous code, see the Visio 2003 SDK.

Creating Windows Forms to Request Connection Settings

Next, we need to create a Windows Form to display in Visio as a dialog box. The form allows users to provide connection settings for Active Directory and to specify the department and job title to use to search for users.

To create a Windows Form

  1. In Solution Explorer, right-click the VisioUserDiagrams project, point to Add, and then click Add Windows Form.

  2. Name the form ConnectionDialog.cs and click OK.

  3. Create text boxes, labels, and buttons in the ConnectionDialog form as shown in Figure 11.

    The ConnectionDialog form allows users to define connection parameters and the department and job title for search

    Figure 11. The ConnectionDialog form allows users to define connection parameters and the department and job title for search

  4. Define the text boxes, check box, and button names as shown in the following table:

    Table 1. Control values for the ConnectionDialog form

    Control type Name Default value
    TextBox tbLDAP LDAP://cn=myerken,ou=management,dc=fabrikam,dc=com
    TextBox tbUserName myDomain\myUserAccount
    TextBox tbPassword myPassword

    * Make this text box a password box

    CheckBox cbWinAuth Windows Authentication
    TextBox tbDepartment Finance
    TexBox tbJobTitle Accountant
    Button btnOK OK
    Button btnCancel Cancel
  5. Replace the text box strings shown in this table with a real LDAP connection string, user name from your domain, password, and an existing department and job title in your company. You can verify this information with a system administrator.

    **Important   **To simplify the code, we do not validate the input sent at the LDAP connection string, user name, password, department, and job title text boxes. However, for real world applications, you should always validate any input sent to an Active Directory helper class to avoid security risks.

  6. Select the ConnectionDialog form and set the form's properties as shown in the following table:

    Table 2. Property values for the ConnectionDialog form

    Property name Value
    Name ConnectionDialog
    AcceptButton btnOK
    CancelButton btnCancel
    FormBorderStyle FixedDialog
    MaximizeBox False
    MinimizeBox False
    Text Connection Properties. . .
  7. Double-click the ConnectionDialog form to open the ConnectionDialog.cs file to modify the code. After the code generated by the Windows Form Designer, add properties to allow the Visio add-in to get the department name and the ICollection of users defined in the form.

    private ICollection _users;
    
    public string DepartmentName {
       get {
          return tbDepartment.Text;
       }
    }
    public ICollection Users {
       get {
          return _users;
       }
    } 
    
  8. Double-click the Windows Authentication check box (cbWinAuth) and add the following code in the cbWinAuth_CheckedChanged event handler. The code disables the user name and password text boxes if the user selects Windows Authentication:

    private void cbWinAuth_CheckedChanged(object sender, System.EventArgs e) {
       if (cbWinAuth.Checked) {
          tbUserName.Enabled = false;
          tbPassword.Enabled = false;
       }
       else {
          tbUserName.Enabled = true;
          tbPassword.Enabled = true;
       }
    }
    
  9. Double-click the OK button and add the following code to the btnOK_Click event handler. The code uses the ADSIHelper class we defined previously to retrieve the users from Active Directory and generate the diagram in Visio:

    private void btnOK_Click(object sender, System.EventArgs e) {
       this.Cursor = Cursors.WaitCursor;ADSIHelper adhelper;
       if (!cbWinAuth.Checked) {
          adhelper = new ADSIHelper(
    tbLDAP.Text, tbUserName.Text, tbPassword.Text);
       }
       else {
          adhelper = new ADSIHelper(tbLDAP.Text);
       }
       try {
          _users = adhelper.GetUsers(tbJobTitle.Text, tbDepartment.Text);
       }
       catch (Exception ex) {
          this.Cursor = Cursors.Arrow;
          MessageBox.Show("Error while reading the users:" + ex.Message);
          return;
       }
    
       this.Cursor = Cursors.Arrow;
       this.DialogResult = DialogResult.OK;
       this.Close();
    }
    
  10. Double-click the Cancel button and add the following code to the btnCancel_Click event handler. The code closes the ConnectionDialog form when the user clicks Cancel:

    private void btnCancel_Click(object sender, System.EventArgs e) {
       this.Close();
    }
    
  11. Build the project to make sure that there are no compilation errors.

Modifying the Connect.cs Class

Next, you need to modify the Connect.cs file that the wizard automatically generated to add a CommandBarButton object that loads when Visio starts. The CommandBarButton object allows users to launch the ConnectionDialog form and create the diagram in Visio.

To modify the Connect.cs class

  1. Open the Connect.cs file and make sure that you have all the following using statements:

    using System;
    using System.Collections;
    using System.Windows.Forms;
    using System.Runtime.InteropServices;
    using System.Reflection;
    using Extensibility;
    using Microsoft.Office.Core;
    using Visio = Microsoft.Office.Interop.Visio;
    
  2. Replace the OnStartupComplete method with the following code:

    public void   OnStartupComplete(ref System.Array custom) {
       CreateButton();
    }
    
  3. Add a method to add a CommandBarButton object to Visio:

    private void CreateButton() {
       try {
          CommandBars cmdBars = (CommandBars)vsoApplication.CommandBars;
          CommandBar cmdBar = null;
          try {
             cmdBar = cmdBars.Add(
                      "UserDiagram", MsoBarPosition.msoBarTop, 
                      Missing.Value, true);
    
             // Transform the next three lines of code to a single line of code.
             CommandBarButton button = (CommandBarButton)cmdBar.Controls.Add(
             MsoControlType.msoControlButton, Missing.Value, Missing.Value
                Missing.Value, true);
    
             button.Caption = "Create Users Diagram";
             button.Style = MsoButtonStyle.msoButtonCaption;
    
             // Transform the next three lines of code to a single line of code.
             button.Click += new    
             _CommandBarButtonEvents_ClickEventHandler(button_Click);
    
             cmdBar.Visible = true;
          }
          catch {
             cmdBar = cmdBars["UserDiagram"];
          }
       }
       catch(Exception ex) {
          MessageBox.Show(
             "Error while creating the toolbar:" + ex.ToString());
       }
    }
    
  4. Add an event handler for the button click event of the CommandBarButton object that displays the ConnectionDialog form and creates the diagram:

    private void button_Click(CommandBarButton Ctrl, ref bool CancelDefault) {
       using(ConnectionDialog dialog = new ConnectionDialog()) {
          if (dialog.ShowDialog() == DialogResult.OK) {
             DiagramGenerator dg = new DiagramGenerator(vsoApplication);
             dg.CreateDiagram(dialog.DepartmentName, dialog.Users);
          }
       }
    }
    
  5. Build the project to make sure that there are no compilation errors.

Building and Installing the Visio Add-in Setup

Now you are ready to build and install the setup project created by the wizard. The setup project publishes our add-in so that Visio recognizes it.

To build and install the setup project

  1. In Solution Explorer, right-click the VisioUserDiagramSetup project and click Build.

  2. In Solution Explorer, right-click the VisioUserDiagramSetup project and click Install.

    **Note   **The project compiles a build into a Microsoft Installer (MSI) package that you can distribute for installation. Look for the VisioUserDiagramsSetup.msi package at the setup project's Debug or Release directories.

  3. The MSI starts and launches the project Setup Wizard.

    Visio add-in project setup wizard

    Figure 12. Visio add-in project setup wizard

  4. Complete the wizard to install the Visio add-in.

    **Note   **When you deploy managed COM add-ins, you should incorporate into your project a small, unmanaged proxy called a shim. For more information, see Deployment of Managed COM Add-Ins in Office XP and Using the COM Add-in Shim Solution to Deploy Managed COM Add-ins in Office XP.

Testing Visio Add-ins

Finally, open Visio to determine whether the add-in works properly.

To test the add-in

  1. Open Visio.

  2. Visio displays the CommandBarButton object at the top left corner.

    Visio displays a CommandBarButton object that launches the Visio add-in

    Figure 13. Visio displays a CommandBarButton object that launches the Visio add-in

  3. Click Create Users Diagram button.

  4. Visio displays the Connection Properties dialog box.

    Connection Properties dialog box

    Figure 14. Connection Properties dialog box

  5. Specify the values for LDAP paths, user name, password, department, and job title.

  6. Click OK.

  7. Visio generates a diagram like the one shown in the following figure.

    Sample Active Directory user diagram generated in Visio

    Figure 15. Sample Active Directory user diagram generated in Visio

Conclusion

The Visio Primary Interop Assemblies help you build different custom visual solutions from your managed applications. In this article, we showed how to create a managed Visio add-in that generates a custom Active Directory diagram. You can customize this solution to create different drawings that represent objects in Active Directory.

Additional Resources

For more information about the listed tools, see these resources:

Acknowledgments

We want to thank Mai-lan Tomsen Bukovec, Doug Groncki, Bill Morein, Chris Castillo, Abraham Mathew, Philippe-Joseph Arida, and Carlos Aguilar for their contributions to this article.