Monthly Archives: May 2016

PScribo for the win!

Sup’ PSHomies,

Is it just me or are there way too many cool development in the community happening right now? You know you’re addicted to PowerShell if your idea of unwinding on a Sunday evening is scripting! 😛

How I discovered PScribo

I was busy creating a server documentation script based on WMI. I’ve used sydi-server in the past, but I wanted it to be PowerShell-based for obvious reasons… 😉

My first idea was to create a well-defined XML document and use CSS to generate the HTML file. HTML had my preference. My first attempt was using the specialized XmlTextWriter object. That was only the first part, I had to do the CSS as well. It was a lot of code. At that time I didn’t make use of snapshots.

My next attempt was to use ConvertTo-HTML -Fragment -As (list,Table). This worked out pretty well for what I wanted, still it’s no PScribo. I’ve probably done three versions of this script.

As luck would have it, while working on the third version, the PSConfEu 2015 was taking place in StockHolm. I didn’t attend that one. Luckily for me, the presentations were uploaded. One presentation immediately caught my eye Documenting xxIT.

This is exactly what I wanted! HTML reporting capabilities!!! Having a Word version was a bonus! I downloaded the module and tried every example. Took me 2 hours to master the syntax. After that I never looked back!

PowerShell documentation made easy

PScribo has been brought to us by Iain Brighton.  Iain gave me some background information on how PScribo came to be:

I was helping Carl sort out a few “performance” issues with the Word functions he was using. As Carl’s documentation framework uses COM, it is painful! Here are a list of some of the issues:

  1. It’s slow
  2. When MS release a new version (or update) Word things can break
  3. There are localisation issues
  4. There is a reliance on Word actually being installed
  5. PS v5 has actually broken quite a lot of his code (although sped it up too)
  6. The code wasn’t factored particularly well, it is somewhat “better” now!

I told Carl I’d get rid of the Word dependency, improve performance and try to enforce a separation of concerns to aid maintenance. PScribo is the result of this.

So fun fact, I recently saw that Mr. Carl Webster is the guardian of Jeff Wouter’s ADHealthCheck script. A few lines into the script and I’m seeing a lot of Word configuration going on. I thought to myself this needs PScribo! In all my enthusiasm I sent a tweet to Mr Webster not knowing he already knew about PScribo 😛

Iain Twitt

Don’t I feel silly! I wasn’t trying to be cheeky or anything like that, I just thought I’d share what the advantages are of PScribo. I apologize for my ignorance. If I could just take a moment to demonstrate the awesomeness of PScribo, I’m sure you’ll be hooked as well!

Creating the ADHC snapshot

My mantra these days is to gather now and process later. I already did most of the grunt work with the Active Directory configuration snapshot. I just needed to extend it with Users, Privileged groups and Computers. With the snapshot, there’s no limitation where you get your source from. For Forest information, I gathered data using the Get-ADForest cmdlet and also [System.DirectoryServices.ActiveDirectory.Forest]::GetCurrentForest(). The latter also has sites,sitelinks and subnets data, which comes in handy if the Get-ADReplication* cmdlets aren’t available… Gather now, process later… 😉

Here’s what I came up with:

The snapshot helps me concentrate on the task at hand. It’s also a great way to separate the documentation process from gathering all the Active Directory bits and pieces. This makes a huge difference in maintenance! If you need to add anything just update the snapshot.

Now for the fun part!

Creating the PScribo ADHC report

First I need to import the saved snapshot. Export-CliXml & Import-CliXml are growing on me!

#Get ADSnapshot
$ADHCSnapshot = Import-Clixml .\export\adds\ADHC-$($snapshotDate).xml

Next I need to initiate the Document. PScribo is DSL (Domain-specific Language) oriented. This makes the flow quite logical.

#region Create PScribo Document
$reportAD = Document "ADHC snapshot report - $($snapshotDate)" {
   GlobalOption -ForceUppercaseSection -EnableSectionNumbering -PageSize A4 -Margin 24
   BlankLine -Count 20
   Paragraph "Active Directory Health report - $($snapshotDate)"  -Style Title
   BlankLine -Count 20
   TOC -Name 'Table of Contents'

A “Document” is an object that contains one or more “sections”, TOC and Paragraphs just to name a few. Just have a look at the README.MD on github get an idea of what is possible and by all means try the examples!

To find the commands available in PScribo run

get-command -Module PScribo

Quick update: Iain just updated PScribo to include landscape page orientation!

Iain Twitt - Landscape

Now to break the document down into sections. Sections can be nested to create sub-sections much like you would do in Word with Header1, Header2, Header 3 etc. The TOC (Table of Content) will be generated according to how the sections are nested. You can also exclude a section from the TOC.

For ADHC, I started with the Forest Information

   Section -Style Heading1 'Forest Information' {
      $ADForest = [Ordered]@{
         Name = $($ADHCSnapshot.ADDS.Forest.Name)
         RootDomain = $($ADHCSnapshot.ADDS.Forest.RootDomain)
         ForestMode = $($ADHCSnapshot.ADDS.Forest.ForestMode.ToString())
         Domains = $($ADHCSnapshot.ADDS.Forest.Domains)

      Table -Name 'Forest Information' -List -Width 0 -Hashtable $ADForest

For this part I created an ordered hashtable to generate a list

My favorite part is the following: Selecting the properties I want to report!

      Section -Style Heading2 'FSMO Roles' {
         $ADHCSnapshot.ADDS.Forest |
         Select-Object DomainNamingMaster,SchemaMaster |
         Table -Name 'FSMO Roles Forest' -List -Width 0


         $ADHCSnapshot.ADDS.Domain |
         Select-Object PDCEmulator,InfrastructureMaster,RIDMaster |
         Table -Name 'FSMO Roles Domain' -List -Width 0

I demonstrated at the end of the ADHC snapshot how you can extract the information you want.

"`nDisabled users`n"
$snapshot.Users.Disabled | Select-Object Name

"`nExpired users`n"
$snapshot.Users.Expired  | Select-Object Name

"`nExpiring users`n"
$snapshot.Users.Expiring | Select-Object Name

To document, it’s as simple as selecting the properties and sending them down the pipeline.

Here’s where you do your formatting and filtering as well:

         Section -Style Heading3 'Privileged groups count'{

            #Create Style for Privileged Groups count greater than 5
            Style -Name PrivilegedGroupsGT5 -Color White -BackgroundColor Firebrick

            $PrivilegedGroupsGT5 = $ADHCSnapshot.Groups.Privileged.Groups |
            Foreach-object {
                  Name = $_.Name
                  MemberCount = @($_.Members).Count

            #Set Style for Privileged Groups count greater than 5
            $PrivilegedGroupsGT5 | Where-object{ $_.MemberCount -gt 5} | Set-Style -Style 'PrivilegedGroupsGT5'

            Table -InputObject $PrivilegedGroupsGT5 -Name 'Privileged groups count' -Width 0

For the privileged group member count I created a special style that would higlight any row where the count is greater than five.

Privileged Groups.PNG
How cool is that?!

Want a table with all the sites without a description?

         Section -Style Heading3 'Sites without a description' {
            $ADHCSnapshot.ADDS.Sites.Where{$_.Description -eq $null} |
            Select-Object Name |
            Table -Name 'Sites without a description' -Width 0

Here the reporting part:

Some cool tip & tricks courtesy of Iain

Well-defined XML File

Here’s something else you can do with PScribo: Generate a well-defined XML File!

Iain stated that there are bits of functionality missing. With a well-defined XML file you could do your own XML mapping as part of your Word document generation solution.

Export at a later time

You can export the “document” object with Export-CliXml if you wanted to generate a report later. That way you can recreate the “document” in any format, at any time! Gotta love Export-, Import-CliXml! 😉

Manipulate the object directly

It’s just a [PSCustomObject], but why mess with a good thing eh? Hehe…

Bonus: Excel reports for user, groups and computers

As a added bonus I also threw in some excel files for reporting Users, Groups and Computers using ImportExcel by  Doug Finke. Instead of exporting to csv just to cut/paste in Excel, why not just export directly to a xlsx file!

I hope this gives you an idea what the possibilities are when it comes to reporting. PScribo is awesome! Add ImportExcel to the mix and you’ve got all you need when it comes to documentation!

Hope it’s worth something to you