Sunday, October 14, 2007

I hate drawing Visio diagrams. I’m no Picasso and, for me, drawing a network diagram is one of these necessary evils that I avoid doing as long as humanly possible.

Not anymore, the good people at Microsoft have released the Microsoft Active Directory Topology Diagrammer which dynamically creates Visio diagrams for your Windows infrastructure. The topology tool reads your AD configuration, including domains, sites, servers, administrative groups, routing groups and connectors (for those with Exchange) and outputs a detailed library of diagram for you to manipulate as required.

Impressed with this release I spent some time google’ing other Visio automation tools, chasing that illusive magic bullet to cure all my Visio pains, I found an abundance of information and samples on MSDN. One such sample, How to use OLE automation in Visio, is a VBA macro that did most of the grunt work, loading and created a new Visio diagram, drawing a shape with a label, saving the changes and closing Visio. Apart from being a macro it performed the key functionality that would be required for any tool. To obtain the flexibility I was looking for I have transposed the macro code to a Powershell script which we can expand on later.

# ' Create an instance of Visio and create a document based on the
# ' Basic Diagram template. It doesn't matter if an instance of
# ' Visio is already running, CreateObject will run a new one.
# Set AppVisio = CreateObject("visio.application")
$AppVisio = New-Object -ComObject Visio.Application

# Set docsObj = AppVisio.Documents
$docsObj = $AppVisio.Documents

# ' Create a document based on the Basic Diagram template that
# ' automatically opens the Basic Shapes stencil.
# Set DocObj = docsObj.Add("Basic Diagram.vst")
$DocObj = $docsObj.Add("Basic Diagram.vst")

# Set pagsObj = AppVisio.ActiveDocument.Pages
$pagsObj = $AppVisio.ActiveDocument.Pages

# ' A new document always has at least one page, whose index in the
# ' Pages collection is 1.
# Set pagObj = pagsObj.Item(1)
$pagObj = $pagsObj.Item(1)

# Set stnObj = AppVisio.Documents("Basic Shapes.vss")
$stnObj = $AppVisio.Documents.Add("Basic Shapes.vss")

# Set mastObj = stnObj.Masters("Rectangle")
$mastObj = $stnObj.Masters.Item("Rectangle")

# ' Drop the rectangle in the approximate middle of the page.
# ' Coordinates passed with the Drop method are always inches.
# Set shpObj = pagObj.Drop(mastObj, 4.25, 5.5)
$shpObj = $pagObj.Drop($mastObj, 4.25, 5.5)

# ' Set the text of the rectangle.
# shpObj.Text = "This is some text."
$shpObj.Text = "This is some text."

# ' Save the drawing and quit Visio. The message pauses the program
# ' so you can see the Visio drawing before the instance closes.
# DocObj.SaveAs "MyDrawing.vsd"
$DocObj.SaveAs("C:\MyDrawing.vsd")
# MsgBox "Drawing finished!", , "AutoVisio (OLE) Example"

# ' Quit Visio.
# AppVisio.Quit

$AppVisio.Quit()

# ' Clear the variable from memory.
# Set AppVisio = Nothing

In an effort to make it that little bit easier to understand I have commented all the sample code and incorporated the Powershell equivalents. Remember that Powershell, unlike VB 6, doesn’t support default properties. So when we are calling a method (e.g. $stnObj.Masters) we have to define the property we are setting (e.g. Item).

So great I have a rectangle with some text in the middle of a blank Visio, not very useful, but after a few changes we have something that will dynamically generate stencils for all computers in a domain.

# Zero initial drop coordinates
$x = 0
$y = 1.20

# Create an instance of Visio and create a document based on the Basic Diagram template.
$AppVisio = New-Object -ComObject Visio.Application
$docsObj = $AppVisio.Documents
$DocObj = $docsObj.Add("Basic Diagram.vst")

# Set the active page of the document to page 1
$pagsObj = $AppVisio.ActiveDocument.Pages
$pagObj = $pagsObj.Item(1)

# Load a set of stencils and select one to drop
$stnObj = $AppVisio.Documents.Add("SERVER_M.vss")
$mastObj = $stnObj.Masters.Item("Server")

# Retrieve a list of computer accounts from Active Directory
#
http://www.microsoft.com/technet/scriptcenter/resources/qanda/nov06/hey1109.mspx

$strCategory = "computer"

$objDomain = New-Object System.DirectoryServices.DirectoryEntry

$objSearcher = New-Object System.DirectoryServices.DirectorySearcher
$objSearcher.SearchRoot = $objDomain
$objSearcher.Filter = ("(objectCategory=$strCategory)")

$colProplist = "name"
foreach ($i in $colPropList){$objSearcher.PropertiesToLoad.Add($i)}

$colResults = $objSearcher.FindAll()

foreach ($objResult in $colResults)
{
  $objComputer = $objResult.Properties; $objComputer.name
  
  # Set coordinates for drop
  $x = $x + 1.30
  
  # Loop to the next line
  if($x -ge 8)
  {
   $x = 1.30
   $y = $y + 1.20
  }
  
  # Drop the selected stencil on the active page, with the coordinates x, y
  $shpObj = $pagObj.Drop($mastObj, $x, $y)
  
  # Enter text for the object
  $shpObj.Text = $objComputer.name
 }

# Save the diagram
$DocObj.SaveAs("C:\CMDBREAK_MyDrawing.vsd")

# Quit Visio
$AppVisio.Quit()

Lost?

Highlighted above in each of the colours is the following:
Yellow – What we started with, only modified to select and drop the Server stencil.
Red – Controls where we drop each stencil, so as they are not on top of each other.
Blue - Enumerates all computer accounts in the local domain. Detailed explanation is available at Hey, Scripting Guy! How Can I Use Windows PowerShell to Get a List of All My Computers?

Now we have a script that will retrieve all the computer accounts in an AD domain and draw shapes for each, one of the monotonous tasks required for any network diagram.

To recap we have converted a VBA macro to a Powershell script and after a few additions we can generate a set of Server stencils labelled with the hostnames of all computers connected to an AD domain. This is just a start, with some more modifications it would be easy to select a different stencil based on the services running or have the script modify existing shapes in a drawing to create a dynamic network diagram.

Happy Visio Automagic.

Sunday, October 14, 2007 9:59:08 PM (E. Australia Standard Time, UTC+10:00)
 Wednesday, October 10, 2007

Welcome to CommandBreak.com and thank you for visiting.

This blog is dedicated to the ramblings of myself, Ben Parker, on various IT topics.

I hope you find something worthwhile in my posts, and feel free to contact me via comments or email.

Wednesday, October 10, 2007 9:36:59 AM (E. Australia Standard Time, UTC+10:00)
Navigation
Search
On this page....
Archives
<October 2007>
SunMonTueWedThuFriSat
30123456
78910111213
14151617181920
21222324252627
28293031123
45678910
Categories
Blogroll
Contact me
Send mail to the author(s) E-mail
Powered by

newtelligence dasBlog 2.0.7226.0.