{"id":51563,"date":"2010-01-14T00:01:00","date_gmt":"2010-01-14T00:01:00","guid":{"rendered":"https:\/\/blogs.technet.microsoft.com\/heyscriptingguy\/2010\/01\/14\/hey-scripting-guy-how-can-i-create-a-windows-visio-drawing-of-my-workstations-disk-subsystem\/"},"modified":"2010-01-14T00:01:00","modified_gmt":"2010-01-14T00:01:00","slug":"hey-scripting-guy-how-can-i-create-a-windows-visio-drawing-of-my-workstations-disk-subsystem","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/scripting\/hey-scripting-guy-how-can-i-create-a-windows-visio-drawing-of-my-workstations-disk-subsystem\/","title":{"rendered":"Hey, Scripting Guy! How Can I Create a Windows Visio Drawing of My Workstations&#039; Disk Subsystem?"},"content":{"rendered":"<p class=\"MsoNormal\"><a class=\"addthis_button\" href=\"http:\/\/www.addthis.com\/bookmark.php?v=250&amp;pub=scriptingguys\"><img decoding=\"async\" alt=\"Bookmark and Share\" src=\"http:\/\/s7.addthis.com\/static\/btn\/v2\/lg-share-en.gif\" width=\"125\" height=\"16\"><\/a><\/p>\n<p class=\"MsoNormal\">&nbsp;<\/p>\n<p><font size=\"2\"><img decoding=\"async\" title=\"Hey, Scripting Guy! Question\" border=\"0\" alt=\"Hey, Scripting Guy! Question\" align=\"left\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/q-for-powertip.jpg\" width=\"34\" height=\"34\"><\/font><\/p>\n<p class=\"MsoNormal\">Hey, Scripting Guy! I would like to do a drawing of the disk subsystem on my workstations. We are getting ready to upgrade to Windows 7, and I want to find out which computers have drives that are more than 50 percent full. In addition, I need to know the size of the drives. If I could make a Microsoft Visio drawing using Windows PowerShell, it would be awesome. Is this something that is possible?<\/p>\n<p class=\"MsoNormal\">&#8212; JB<\/p>\n<p class=\"MsoNormal\">\n<p>&nbsp;<\/p>\n<p class=\"MsoNormal\"><img decoding=\"async\" title=\"Hey, Scripting Guy! Answer\" border=\"0\" alt=\"Hey, Scripting Guy! Answer\" align=\"left\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/a-for-powertip.jpg\" width=\"34\" height=\"34\">Hello JB, <\/p>\n<p class=\"MsoNormal\">Microsoft Scripting Guy Ed Wilson here. I have been slowly catching up on e-mail that was sent to the <a href=\"http:\/\/blogs.technet.commailto:scripter@microsoft.com\"><font face=\"Segoe\">scripter@microsoft.com<\/font><\/a> alias, and when I ran across your letter, I thought the idea was pretty cool. I spent most of the day writing the ComputerDiskDrawing.ps1 script seen here. <\/p>\n<p class=\"MsoNormal\"><b>ComputerDiskDrawing.ps1<\/p>\n<p><\/b><\/p>\n<p class=\"CodeBlockScreened\"><font><font face=\"Lucida Sans Typewriter\">Param($computer = &#8220;LocalHost&#8221;)<\/p>\n<p># *** Functions ***<br \/>Function Get-ComputerSystem ($computer)<br \/>{<br \/><span>&nbsp;<\/span>Get-WmiObject -Class win32_computersystem -ComputerName $computer <br \/>} #end Get-ComputerSystem<\/p>\n<p>Function Get-Volumes($computer)<br \/>{<br \/><span>&nbsp;<\/span>Get-WmiObject -class win32_Volume -filter &#8220;DriveType = 3&#8221; `<br \/><span>&nbsp;&nbsp;&nbsp; <\/span>-computername $computer<br \/>} #end Get-Volumes<\/p>\n<p>Function Get-OptimalSize<br \/>{<br \/><span>&nbsp;<\/span>&lt;#<br \/><span>&nbsp; <\/span>.Synopsis<br \/><span>&nbsp;&nbsp;&nbsp; <\/span>Converts Bytes into the appropriate unit of measure. <br \/><span>&nbsp;&nbsp; <\/span>.Description<br \/><span>&nbsp;&nbsp;&nbsp; <\/span>The Get-OptimalSize function converts bytes into the appropriate unit of <br \/><span>&nbsp;&nbsp;&nbsp; <\/span>measure. It returns a string representation of the number.<br \/><span>&nbsp;&nbsp; <\/span>.Example<br \/><span>&nbsp;&nbsp;&nbsp; <\/span>Get-OptimalSize 1025<br \/><span>&nbsp;&nbsp;&nbsp; <\/span>Converts 1025 bytes to 1.00 KiloBytes<br \/><span>&nbsp;&nbsp;&nbsp; <\/span>.Example<br \/><span>&nbsp;&nbsp;&nbsp; <\/span>Get-OptimalSize -sizeInBytes 10099999 <br \/><span>&nbsp;&nbsp;&nbsp; <\/span>Converts 10099999 bytes to 9.63 MegaBytes<br \/><span>&nbsp;&nbsp; <\/span>.Parameter SizeInBytes<br \/><span>&nbsp;&nbsp;&nbsp; <\/span>The size in bytes to be converted<br \/><span>&nbsp;&nbsp; <\/span>.Inputs<br \/><span>&nbsp;&nbsp;&nbsp; <\/span>[int64]<br \/><span>&nbsp;&nbsp; <\/span>.OutPuts<br \/><span>&nbsp;&nbsp;&nbsp; <\/span>[string]<br \/><span>&nbsp;&nbsp; <\/span>.Notes<br \/><span>&nbsp;&nbsp;&nbsp; <\/span>NAME:<span>&nbsp; <\/span>Get-OptimalSize<br \/><span>&nbsp;&nbsp;&nbsp; <\/span>AUTHOR: Ed Wilson<br \/><span>&nbsp;&nbsp;&nbsp; <\/span>LASTEDIT: 1\/4\/2010<br \/><span>&nbsp;&nbsp;&nbsp; <\/span>KEYWORDS:<br \/><span>&nbsp;&nbsp; <\/span>.Link<br \/><span>&nbsp;&nbsp;&nbsp;&nbsp; <\/span>Http:\/\/www.ScriptingGuys.com<br \/><span>&nbsp;<\/span>#Requires -Version 2.0<br \/><span>&nbsp;<\/span>#&gt;<br \/><span>&nbsp;<\/span>Param([int64]$sizeInBytes)<br \/><span>&nbsp;<\/span>Switch ($sizeInBytes) <br \/><span>&nbsp; <\/span>{<br \/><span>&nbsp;&nbsp; <\/span>{$sizeInBytes -ge 1TB} {&#8220;{0:n2}&#8221; -f<span>&nbsp; <\/span>($sizeInBytes\/1TB) + &#8221; TeraBytes&#8221;;break}<br \/><span>&nbsp;&nbsp; <\/span>{$sizeInBytes -ge 1GB} {&#8220;{0:n2}&#8221; -f<span>&nbsp; <\/span>($sizeInBytes\/1GB) + &#8221; GigaBytes&#8221;;break}<br \/><span>&nbsp;&nbsp; <\/span>{$sizeInBytes -ge 1MB} {&#8220;{0:n2}&#8221; -f<span>&nbsp; <\/span>($sizeInBytes\/1MB) + &#8221; MegaBytes&#8221;;break}<br \/><span>&nbsp;&nbsp; <\/span>{$sizeInBytes -ge 1KB} {&#8220;{0:n2}&#8221; -f<span>&nbsp; <\/span>($sizeInBytes\/1KB) + &#8221; KiloBytes&#8221;;break}<br \/><span>&nbsp;&nbsp; <\/span>Default { &#8220;{0:n2}&#8221; -f $sizeInBytes + &#8221; Bytes&#8221; }<br \/><span>&nbsp; <\/span>} #end switch<br \/>} #end Function Get-OptimalSize <\/p>\n<p># *** Entry to Script ***<\/p>\n<p>$application = New-Object -ComObject Visio.Application<br \/>$application.visible = $false<br \/>$documents = $application.Documents<br \/>$document = $documents.Add(&#8220;Basic Network Diagram.vst&#8221;)<br \/>$pages = $application.ActiveDocument.Pages<br \/>$page = $pages.Item(1)<\/p>\n<p>$ComputerStencil = $application.Documents.Add(&#8220;Computers and Monitors.vss&#8221;)<br \/>$BasicStencil = $application.Documents.Add(&#8220;Basic Shapes.vss&#8221;)<\/p>\n<p>$pcinfo = Get-ComputerSystem -computer $computer<br \/>$pc = $ComputerStencil.Masters.Item(&#8220;PC&#8221;)<br \/>$shape1 = $page.Drop($pc, 2.2, 6.8) <br \/>$shape1.Text = &#8220;$($pcinfo.DNSHostName)`r`n$($pcinfo.Domain)&#8221;<\/p>\n<p>$Volumes = Get-Volumes -computer $computer<br \/>$x = 3.0 #establishes left column<br \/>$xx = 6.0<br \/>$y = 6.0 #establishes right column<br \/>$yy = 7.0<br \/>$visSectionObject = 1<br \/>$visRowFill = 3<br \/>$visFillForegnd = 0<br \/>ForEach($volume in $Volumes)<br \/>{<br \/><span>&nbsp;<\/span>$inuse = $volume.capacity &#8211; $volume.freeSpace<br \/><span>&nbsp;<\/span>$percentInUse = ($inuse \/ $volume.Capacity) * 100<br \/><span>&nbsp;<\/span>$shape2 = $page.DrawRectangle($x,$xx,$y,$yy)<br \/><span>&nbsp;<\/span>$shape2.text = &#8220;DRIVE: $($Volume.name)<br \/><span>&nbsp; <\/span>Capacity: $(Get-OptimalSize -sizeinbytes $($Volume.Capacity))<br \/><span>&nbsp; <\/span>In Use: $(Get-OptimalSize -sizeinbytes $inuse)&#8221;<br \/><span>&nbsp; <\/span>if($percentInUse -gt 50) <br \/><span>&nbsp;&nbsp;&nbsp; <\/span>{ <br \/><span>&nbsp;&nbsp;&nbsp;&nbsp; <\/span>$shape2.CellsSRC($visSectionObject,$visRowFill, `<br \/><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>$visFillForegnd).FormulaU=&#8221;THEMEGUARD(RGB(255,0,0))&#8221; <br \/><span>&nbsp;&nbsp;&nbsp; <\/span>}<br \/><span>&nbsp; <\/span>else<br \/><span>&nbsp;&nbsp;&nbsp; <\/span>{ <br \/><span>&nbsp;&nbsp;&nbsp;&nbsp; <\/span>$shape2.CellsSRC($visSectionObject,\n$visRowFill, `<br \/><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>$visFillForegnd).FormulaU=&#8221;THEMEGUARD(RGB(0,255,0))&#8221; <br \/><span>&nbsp;&nbsp;&nbsp; <\/span>}<br \/><span>&nbsp;<\/span>$xx -= 1.2<br \/><span>&nbsp;<\/span>$yy-= 1.2<br \/>}<br \/>$visCharacterStyle = 2<br \/>$visRowCharacter = 0<br \/>$visSectionCharacter = 3 <\/p>\n<p>$ColumnHead = $page.DrawRectangle(3.54,7.08,5.51,7.48)<br \/>$ColumnHead.TextStyle = &#8220;Normal&#8221;<br \/>$ColumnHead.LineStyle = &#8220;Text Only&#8221;<br \/>$columnHead.FillSTyle = &#8220;Text Only&#8221;<br \/>$ColumnHead.Text = &#8220;DISK DRIVES&#8221;<br \/>$ColumnHead.CellsSRC($visSectionCharacter,$visRowCharacter, `<br \/><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>$visCharacterStyle).FormulaU = 1<\/p>\n<p>$page.CenterDrawing()<br \/>$document.SaveAs(&#8220;C:fsoComputerDisks.vsd&#8221;)<br \/>$application.Quit()<\/p>\n<p><\/font><\/font><\/p>\n<p class=\"MsoNormal\">The first thing the ComputerDiskDrawing.ps1 script does is create a command-line parameter for the name of the target computer and a couple of functions that are used to retrieve WMI information. The <b>Get-ComputerSystem<\/b> function uses the <b>Win32_ComputerSystem<\/b> WMI class to retrieve basic computer information and the <b>Get-Volumes<\/b> function uses the <b>Win32_Volume<\/b> WMI class, which is available&nbsp;beginning with Windows Server 2003,&nbsp;to return information about fixed local disks on the computer. This section of the script is shown here: <\/p>\n<p class=\"CodeBlockScreened\"><font><font face=\"Lucida Sans Typewriter\">Param($computer = &#8220;LocalHost&#8221;)<br \/>Function Get-ComputerSystem ($computer)<br \/>{<br \/>Get-WmiObject -Class win32_computersystem -ComputerName $computer <br \/>} #end Get-ComputerSystem<br \/>Function Get-Volumes($computer)<br \/>{<br \/>Get-WmiObject -class win32_Volume -filter &#8220;DriveType = 3&#8221; `<br \/><span>&nbsp;&nbsp;&nbsp; <\/span>-computername $computer<br \/>} #end Get-Volumes<\/p>\n<p><\/font><\/font><\/p>\n<p class=\"MsoNormal\">It is time to create a function that will translate the disk sizes (returned in bytes) to a more easily understood size. Windows PowerShell has several built in constants that can be used to translate numeric values from bytes to kilobytes (KB), megabytes (MB), gigabytes (GB), or even terabytes (TB). To translate 1,024 bytes into kilobytes, you can use the KB constant, as seen here:<\/p>\n<p class=\"CodeBlockScreened\"><font><font face=\"Lucida Sans Typewriter\">PS C:&gt; 1024 \/ 1KB<br \/>1<br \/>PS C:&gt;<\/p>\n<p><\/font><\/font><\/p>\n<p class=\"MsoNormal\">Inside the <b>Get-OptimalSize<\/b> function, the <b>Switch<\/b> statement is used to evaluate the value of the <b>&ndash;sizeinbytes<\/b> parameter and to determine the correct unit to display the value. One interesting thing that is done inside the <b>Switch<\/b> statement is the use of a script block for each condition to evaluate. This technique is not documented in the help files. The reason a script block is required is to perform an evaluation of the size of the number stored in the <b>sizeinbytes<\/b> parameter. If the value is greater than or equal to 1 terabyte, the number is translated into terabytes. The <b>&ldquo;{0:n2}&rdquo; &ndash;f<\/b> construction is a format specifier to limit the number that is returned to two decimal places. The complete switch statement is seen here:<\/p>\n<p class=\"CodeBlockScreened\"><font><font face=\"Lucida Sans Typewriter\">Switch ($sizeInBytes) <br \/><span>&nbsp; <\/span>{<br \/><span>&nbsp;&nbsp; <\/span>{$sizeInBytes -ge 1TB} {&#8220;{0:n2}&#8221; -f<span>&nbsp; <\/span>($sizeInBytes\/1TB) + &#8221; TeraBytes&#8221;;break}<br \/><span>&nbsp;&nbsp; <\/span>{$sizeInBytes -ge 1GB} {&#8220;{0:n2}&#8221; -f<span>&nbsp; <\/span>($sizeInBytes\/1GB) + &#8221; GigaBytes&#8221;;break}<br \/><span>&nbsp;&nbsp; <\/span>{$sizeInBytes -ge 1MB} {&#8220;{0:n2}&#8221; -f<span>&nbsp; <\/span>($sizeInBytes\/1MB) + &#8221; MegaBytes&#8221;;break}<br \/><span>&nbsp;&nbsp; <\/span>{$sizeInBytes -ge 1KB} {&#8220;{0:n2}&#8221; -f<span>&nbsp; <\/span>($sizeInBytes\/1KB) + &#8221; KiloBytes&#8221;;break}<br \/><span>&nbsp;&nbsp; <\/span>Default { &#8220;{0:n2}&#8221; -f $sizeInBytes + &#8221; Bytes&#8221; }<br \/><span>&nbsp; <\/span>} #end switch<\/p>\n<p><\/font><\/font><\/p>\n<p class=\"MsoNormal\">The complete <b>Get-OptimalSize<\/b> function is shown here:<\/p>\n<p class=\"CodeBlockScreened\"><font><font face=\"Lucida Sans Typewriter\">Function Get-OptimalSize<br \/>{<br \/>&lt;#<br \/><span>&nbsp; <\/span>.Synopsis<br \/><span>&nbsp;&nbsp;&nbsp; <\/span>Converts Bytes into the appropriate unit of measure. <br \/><span>&nbsp;&nbsp; <\/span>.Description<br \/><span>&nbsp;&nbsp;&nbsp; <\/span>The Get-OptimalSize function converts bytes into the appropriate unit of <br \/><span>&nbsp;&nbsp;&nbsp; <\/span>measure. It returns a string representation of the number.<br \/><span>&nbsp;&nbsp; <\/span>.Example<br \/><span>&nbsp;&nbsp;&nbsp; <\/span>Get-OptimalSize 1025<br \/><span>&nbsp;&nbsp;&nbsp; <\/span>Converts 1025 bytes to 1.00 KiloBytes<br \/><span>&nbsp;&nbsp;&nbsp; <\/span>.Example<br \/><span>&nbsp;&nbsp;&nbsp; <\/span>Get-OptimalSize -sizeInBytes 10099999 <br \/><span>&nbsp;&nbsp;&nbsp; <\/span>Converts 10099999 bytes to 9.63 MegaBytes<br \/><span>&nbsp;&nbsp; <\/span>.Parameter SizeInBytes<br \/><span>&nbsp;&nbsp;&nbsp; <\/span>The size in bytes to be converted<br \/><span>&nbsp;&nbsp; <\/span>.Inputs<br \/><span>&nbsp;&nbsp;&nbsp; <\/span>[int64]<br \/><span>&nbsp;&nbsp; <\/span>.OutPuts<br \/><span>&nbsp;&nbsp;&nbsp; <\/span>[string]<br \/><span>&nbsp;&nbsp; <\/span>.Notes<br \/><span>&nbsp;&nbsp;&nbsp; <\/span>NAME:<span>&nbsp; <\/span>Get-OptimalSize<br \/><span>&nbsp;&nbsp;&nbsp; <\/span>AUTHOR: Ed Wilson<br \/><span>&nbsp;&nbsp;&nbsp; <\/span>LASTEDIT: 1\/4\/2010<br \/><span>&nbsp;&nbsp;&nbsp; <\/span>KEYWORDS:<br \/><span>&nbsp;&nbsp; <\/span>.Link<br \/><span>&nbsp;&nbsp;&nbsp;&nbsp; <\/span>Http:\/\/www.ScriptingGuys.com<br \/>#Requires -Version 2.0<br \/>#&gt;<br \/>Param([int64]$sizeInBytes)<br \/>Switch ($sizeInBytes) <br \/><span>&nbsp; <\/span>{<br \/><span>&nbsp;&nbsp; <\/span>{$sizeInBytes -ge 1TB} {&#8220;{0:n2}&#8221; -f<span>&nbsp; <\/span>($sizeInBytes\/1TB) + &#8221; TeraBytes&#8221;;break}<br \/><span>&nbsp;&nbsp; <\/span>{$sizeInBytes -ge 1GB} {&#8220;{0:n2}&#8221; -f<span>&nbsp; <\/span>($sizeInBytes\/1GB) + &#8221; GigaBytes&#8221;;break}<br \/><span>&nbsp;&nbsp; <\/span>{$sizeInBytes -ge 1MB} {&#8220;{0:n2}&#8221; -f<span>&nbsp; <\/span>($sizeInBytes\/1MB) + &#8221; MegaBytes&#8221;;break}<br \/><span>&nbsp;&nbsp; <\/span>{$sizeInBytes -ge 1KB} {&#8220;{0:n2}&#8221; -f<span>&nbsp; <\/span>($sizeInBytes\/1KB) + &#8221; KiloBytes&#8221;;break}<br \/><span>&nbsp;&nbsp; <\/span>Default { &#8220;{0:n2}&#8221; -f $sizeInBytes + &#8221; Bytes&#8221; }<br \/><span>&nbsp; <\/span>} #end switch<br \/>} #end Function Get-OptimalSize <\/p>\n<p><\/font><\/font><\/p>\n<p class=\"MsoNormal\">The next section of the script is the same as <a href=\"http:\/\/blogs.technet.com\/heyscriptingguy\/archive\/2010\/01\/13\/hey-scripting-guy-january-13-2010.aspx\">Wednesday&rsquo;s Hey, Scripting Guy! post<\/a>:<\/p>\n<p class=\"CodeBlockScreened\"><font><font face=\"Lucida Sans Typewriter\">$application = New-Object -ComObject Visio.Application<br \/>$application.visible = $false<br \/>$documents = $application.Documents<br \/>$document = $documents.Add(&#8220;Basic Network Diagram.vst&#8221;)<br \/>$pages = $application.ActiveDocument.Pages<br \/>$page = $pages.Item(1)<br \/>$ComputerStencil = $application.Documents.Add(&#8220;Computers and Monitors.vss&#8221;)<br \/>$BasicStencil = $application.Documents.Add(&#8220;Basic Shapes.vss&#8221;)<br \/>$pcinfo = Get-ComputerSystem -computer $computer<br \/>$pc = $ComputerStencil.Masters.Item(&#8220;PC&#8221;)<br \/>$shape1 = $page.Drop($pc, 2.2, 6.8) <br \/>$shape1.Text = &#8220;$($pcinfo.DNSHostName)`r`n$($pcinfo.Domain)&#8221;<\/p>\n<p><\/font><\/font><\/p>\n<p class=\"MsoNormal\">Store the management objects that are returned by the <b>Get-Volumes<\/b> function in the <b>$volumes<\/b> variable, as seen here:<\/p>\n<p class=\"CodeBlockScreened\"><font><font face=\"Lucida Sans Typewriter\">$Volumes = Get-Volumes -computer $computer<\/p>\n<p><\/font><\/font><\/p>\n<p class=\"MsoNormal\">Several variables are created to establish the initial coordinates for drawing the rectangle. These are seen here:<\/p>\n<p class=\"CodeBlockScreened\"><font><font face=\"Lucida Sans Typewriter\">$x = 3.0 #establishes left column<br \/>$xx = 6.0<br \/>$y = 6.0 #establishes right column<br \/>$yy = 7.0<\/p>\n<p><\/font><\/font><\/p>\n<p class=\"MsoNormal\">Three additional variables are created that hold enumeration values for the <b>CellsSRC<\/b> method that will be used to add color to the rectangle. The first variable, <b>$visSectionObject<\/b>, holds the <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/ms428277.aspx\"><font face=\"Segoe\">VisSectionIndices enumeration value<\/font><\/a>; the second variable, <b>$visRowFill<\/b>, holds the <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/ms428269.aspx\"><font face=\"Segoe\">VisRowIndices enumeration value<\/font><\/a>; and the third variable, <b>$visFillForegnd<\/b>, holds the <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/aa342128.aspx\"><font face=\"Segoe\">VisCellIndices enumeration value<\/font><\/a>. The value assignments are seen here: <\/p>\n<p class=\"CodeBlockScreened\"><font><font face=\"Lucida Sans Typewriter\">$visSectionObject = 1<br \/>$visRowFill = 3<br \/>$visFillForegnd = 0<\/p>\n<p><\/font><\/font><\/p>\n<p class=\"MsoNormal\">When all of the appropriate variables have been created and assigned values, it is time to loop through the collection of <b>Win32_Volume<\/b> objects that are stored in the <b>$volumes<\/b> variable. The <b>$volume<\/b> variable holds a complete object that represents one of the fixed local disks on the computer. The amount of occupied disk space is computed by subtracting the <b>freeSpace<\/b> from the capacity of the drive. The result is stored in the <b>$inuse<\/b> variable. Next, the percentage of disk utilization is computed by using the value stored in the <b>$inuse<\/b> variable and the capacity. The result is stored in the <b>$percentInUse<\/b> variable. This is seen here:<\/p>\n<p class=\"CodeBlockScreened\"><font><font face=\"Lucida Sans Typewriter\">ForEach($volume in $Volumes)<br \/>{<br \/>$inuse = $volume.capacity &#8211; $volume.freeSpace<br \/>$percentInUse = ($inuse \/ $volume.Capacity) * 100<\/p>\n<p><\/font><\/font><\/p>\n<p class=\"MsoNormal\">The <b>DrawRectangle<\/b> method is used to draw a rectangle on the Microsoft Visio document. The first two arguments to the <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/ms195968.aspx\"><font face=\"Segoe\">DrawRectangle method<\/font><\/a> of the <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/ms408981.aspx\">page object<\/a> represent the lower left corner of the rectangle, and the last two arguments to the method represent the upper right corner of the rectangle. The returned shape object is stored in the <b>$shape2<\/b> variable seen here:<\/p>\n<p class=\"CodeBlockScreened\"><font><font face=\"Lucida Sans Typewriter\"><span>&nbsp;<\/span>$shape2 = $page.DrawRectangle($x,$xx,$y,$yy)<\/p>\n<p><\/font><\/font><\/p>\n<p class=\"MsoNormal\">The <b>text<\/b> property of the <b>shape<\/b> object is used to display the drive name, capacity, and amount of space that is in use. The <b>Get-OptimalSize<\/b> function is used to choose the appropriate units of measure for each drive:<\/p>\n<p class=\"CodeBlockScreened\"><font><font face=\"Lucida Sans Typewriter\"><span>&nbsp;<\/span>$shape2.text = &#8220;DRIVE: $($Volume.name)<br \/><span>&nbsp;<\/span>Capacity: $(Get-OptimalSize -sizeinbytes $($Volume.Capacity))<br \/><span>&nbsp;<\/span>In Use: $(Get-OptimalSize -sizeinbytes $inuse)&#8221;<\/p>\n<p><\/font><\/font><\/p>\n<p class=\"MsoNormal\">If the drive is more than 50 percent full, the rectangle representing the drive is displayed in red. To do this, the <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/ms425971.aspx\"><font face=\"Segoe\">CellsSRC property<\/font><\/a> is used to apply a red-green-blue (RGB) value. When the RGB value is 255,0,0, it is all red. If the drive is less than 50 percent full, the rectangle representing the drive is displayed in green. Green is 0,255,0 in RGB nomenclature. This section of the script is seen here:<\/p>\n<p class=\"CodeBlockScreened\"><font><font face=\"Lucida Sans Typewriter\">if($percentInUse -gt 50) <br \/><span>&nbsp;&nbsp;&nbsp; <\/span>{ <br \/><span>&nbsp;&nbsp;&nbsp;&nbsp; <\/span>$shape2.CellsSRC($visSectionObject,$visRowFill, `<br \/><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>$visFillForegnd).FormulaU=&#8221;THEMEGUARD(RGB(255,0,0))&#8221; <br \/><span>&nbsp;&nbsp;&nbsp; <\/span>}<br \/><span>&nbsp; <\/span>else<br \/><span>&nbsp;&nbsp;&nbsp; <\/span>{ <br \/><span>&nbsp;&nbsp;&nbsp;&nbsp; <\/span>$shape2.CellsSRC($visSectionObject,$visRowFill, `<br><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>$visFillForegnd).FormulaU=&#8221;THEMEGUARD(RGB(0,255,0))&#8221; <br \/><span>&nbsp;&nbsp;&nbsp; <\/span>}<\/p>\n<p><\/font><\/font><\/p>\n<p class=\"MsoNormal\">Because the script loops around creating rectangles for each volume on the computer system, the value of the <b>$xx<\/b> and <b>$yy<\/b> variables is decremented by 1.2. This will lower the position of the next rectangle to be created by 1.2. The <b>-=<\/b> operator is used to subtract and assign a new value to the existing value of the <b>$xx<\/b> and <b>$yy<\/b> variables respectively. Using the <b>-=<\/b> operator is illustrated here:<\/p>\n<p class=\"CodeBlockScreened\"><font><font face=\"Lucida Sans Typewriter\">PS C:&gt; $a = 5<br \/>PS C:&gt; $a -= 3<br \/>PS C:&gt; $a<br \/>2<br \/>PS C:&gt;<\/p>\n<p><\/font><\/font><\/p>\n<p class=\"MsoNormal\">The code to decrement the value of the two variables is seen here:<\/p>\n<p class=\"CodeBlockScreened\"><font><font face=\"Lucida Sans Typewriter\"><span>&nbsp;<\/span>$xx -= 1.2<br \/>$yy-= 1.2<br \/>}<\/p>\n<p><\/font><\/font><\/p>\n<p class=\"MsoNormal\">Now three more variable assignments need to be made. These variables will be used with the b property. The first variable, <b>$visCharacterStyle<\/b>, holds the <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/ms428277.aspx\"><font face=\"Segoe\">VisSectionIndices enumeration value<\/font><\/a>. The second variable, <b>$visRowCharacter<\/b>, holds the <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/ms428269.aspx\"><font face=\"Segoe\">VisRowIndices enumeration value<\/font><\/a>. And the third variable, <b>$visSectionCharacter<\/b>, holds the <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/aa342128.aspx\"><font face=\"Segoe\">VisCellIndices enumeration value<\/font><\/a>. This is seen here:<\/p>\n<p class=\"CodeBlockScreened\"><font><font face=\"Lucida Sans Typewriter\">$visCharacterStyle = 2<br \/>$visRowCharacter = 0<br \/>$visSectionCharacter = 3 <\/p>\n<p><\/font><\/font><\/p>\n<p class=\"MsoNormal\">The <b>DrawRectangle<\/b> method from the <b>page<\/b> object is used to create a text box that will be used for the column head. The resulting shape is stored in the <b>$ColumnHead<\/b> variable:<\/p>\n<p class=\"CodeBlockScreened\"><font><font face=\"Lucida Sans Typewriter\">$ColumnHead = $page.DrawRectangle(3.54,7.08,5.51,7.48)<\/p>\n<p><\/font><\/font><\/p>\n<p class=\"MsoNormal\">After creating the shape, the <b>TextStyle<\/b> property is set to <b>normal<\/b>, and the <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/ms426141.aspx\"><font face=\"Segoe\">LineStyle<\/font><\/a> and <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/ms426030.aspx\"><font face=\"Segoe\">FillStyle<\/font><\/a> properties are set to <b>Text Only<\/b>. The resulting shape will only display the value that is assigned to the <b>Text<\/b> property of the shape. This section of the script is seen here:<\/p>\n<p class=\"CodeBlockScreened\"><font><font face=\"Lucida Sans Typewriter\">$ColumnHead.TextStyle = &#8220;Normal&#8221;<br \/>$ColumnHead.LineStyle = &#8220;Text Only&#8221;<br \/>$columnHead.FillStyle = &#8220;Text Only&#8221;<br \/>$ColumnHead.Text = &#8220;DISK DRIVES&#8221;<\/p>\n<p><\/font><\/font><\/p>\n<p class=\"MsoNormal\">It is time to use the <b>CellsSRC<\/b> property to assign the <b>FormulaU<\/b> the value of 1. This will cause the text to appear in bold:<\/p>\n<p class=\"CodeBlockScreened\"><font><font face=\"Lucida Sans Typewriter\">$ColumnHead.CellsSRC($visSectionCharacter,$visRowCharacter, `<br \/><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/span>$visCharacterStyle).FormulaU = 1<\/p>\n<p><\/font><\/font><\/p>\n<p class=\"MsoNormal\">After adding the column heading, all that remains is to center the drawing, save the drawing, and exit Microsoft Visio. The code to do this is the same we have used all week:<\/p>\n<p class=\"CodeBlockScreened\"><font><font face=\"Lucida Sans Typewriter\">$page.CenterDrawing()<br \/>$document.SaveAs(&#8220;C:fsoComputerDisks.vsd&#8221;)<br \/>$application.Quit()<\/p>\n<p><\/font><\/font><\/p>\n<p class=\"MsoNormal\">When the script runs, the following drawing is saved to the destination supplied to the <b>SaveAs<\/b> method of the <b>document<\/b> object. <\/p>\n<p class=\"Fig-Graphic\"><img decoding=\"async\" title=\"Image of drawing created when script is run\" alt=\"Image of drawing created when script is run\" src=\"http:\/\/img.microsoft.com\/library\/media\/1033\/technet\/images\/scriptcenter\/qanda\/hsg\/2010\/january\/hey0114\/hsg-01-14-10-01.jpg\" width=\"600\" height=\"431\"><\/p>\n<p class=\"Fig-Graphic\">\n<p>&nbsp;<\/p>\n<\/p>\n<p class=\"MsoNormal\">JB, that is all there is to using Microsoft Visio to create a diagram of your disk drives.&nbsp;The script for today can also be found at the <a href=\"http:\/\/bit.ly\/8wIJa1\">Script Repository<\/a>. &nbsp;This concludes the Microsoft Visio Week articles. Join us tomorrow for Quick-Hits Friday. <\/p>\n<p class=\"MsoNormal\">If you want to know exactly what we will be discussing tomorrow, follow us on <a href=\"http:\/\/bit.ly\/scriptingguystwitter\" target=\"_blank\">Twitter<\/a> or <a href=\"http:\/\/bit.ly\/scriptingguysfacebook\" target=\"_blank\"><font face=\"Segoe\">Facebook<\/font><\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>&nbsp; Hey, Scripting Guy! I would like to do a drawing of the disk subsystem on my workstations. We are getting ready to upgrade to Windows 7, and I want to find out which computers have drives that are more than 50 percent full. In addition, I need to know the size of the drives. [&hellip;]<\/p>\n","protected":false},"author":595,"featured_media":87096,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[53,49,3,45],"class_list":["post-51563","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-scripting","tag-microsoft-visio","tag-office","tag-scripting-guy","tag-windows-powershell"],"acf":[],"blog_post_summary":"<p>&nbsp; Hey, Scripting Guy! I would like to do a drawing of the disk subsystem on my workstations. We are getting ready to upgrade to Windows 7, and I want to find out which computers have drives that are more than 50 percent full. In addition, I need to know the size of the drives. [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/51563","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/users\/595"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/comments?post=51563"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/51563\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/media\/87096"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/media?parent=51563"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/categories?post=51563"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/tags?post=51563"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}