Backing up your Testlab with Altaro VM Backup

To be a good engineer, you need a Testlab. End of sentence.

You need it so you can peruse flights of fancy, like making some web services, trying out that new language and other endeavors perhaps not specifically related to your day to day work.

It HAS to be your own too!  You can’t just use the one at your work.  If things go awry between you and your company, you definitely don’t want to lose your livelihood AND your hard-earned testlab in the same stroke!  This is also why you don’t want to have your life insurance purchased through your work too (or if you do, make sure you don’t get fired and die in the same day).

In consulting, I would get assigned to a project and have a month or so to come up to speed on new technologies. I found that when I had a testlab, it was so much quicker to get working, just make a new VM, domain join it and have SQL installed and ready for a new SCCM, Scorch, Air-Watch, whatever. In fact, the periods when I did the best engineering work over my career closely line up to the times that I had a working testlab available to model my customer’s environments and make mistakes on my own time, not theirs.

If you have read this and are convinced that you too need a testlab, and don’t yet have one, you can click here to read my guide here on setting up a Domain Controller with one-click!

The one-click domain controller UI in action

And what should we do with things that are important? We protect them. In this post I’ll walk you through some of the options available to protect and backup your testlab.

Continue reading


Glorious PowerShell Dashboards

I’ve covered the topic of dashboards on this blog a few times before, from layering CSS on PowerShell’s built-in HTML capabilities, to hacking together HTML 5 templates with PowerShell, as the hunt continues for the next great thing in PowerShell reporting. Guys, the hunt is OVER!  Time to ascend to the next level in reporting…

It’s the motherlode!  Adam Driscoll’s AWESOME PowerShell Universal Dashboard, a gorgeous and dead-simple dashboard tool which makes it super easy to retrieve values from your environment and spin them into adaptive, animated dashboards full of sexy transitions and colors.   Click here to see it in action. Or just look at these sexy animations and tasteful colors.  Deploy this and then show your boss.  It’s guaranteed to impress, blow his pants off, and get you a huge raise or maybe a $5 Starbucks gift card.


In this post, we’ll learn what the PowerShell Universal Dashboard is, how to quickly get setup, and I’ll share my own TOTALLY PIMPED OUT CUSTOM Dashboard with you free, for you to modify to fit your environment, and get that free Pumpkin Spice, son!

What is it?

The PowerShell Universal Dashboard is an absolutely gorgeous module created by the great Adam Driscoll.  It seeks to make it dead-simple to create useful, interactive dashboards anywhere you can run PowerShell.  It’s built using .net Core Kestrel and ChartJS, and you can run it locally for folks to connect to see your dashboard, or deploy right to IIS or even Azure!

If you didn’t earlier, you really should click here to see it in action!!!

Getting Started

To begin, simply launch PowerShell and run the following command.

Install-Module UniversalDashboard

Next, copy the code for Adam’s sample Dashboard from here and run it.  You should see this screen appear

Now, PowerShell Pro Tools IS a paid piece of software.  But the trial license is super generous, so simply put in your e-mail and you’ll receive a license automatically in a few minutes. Continue reading

Ignite, decompressed

MSFTignite2017 (1)

Ignite Orlando WAS AWESOME! In this post, I’ll give you some of my fun memories and commentary about the event, and then end with a bunch of the best videos from Microsoft Ignite 2017.

My sessions

We had a HUGE turn out for the PowerShell Community Event, in fact, it was so big that we had an overflow room with 200 people in it!

2017-09-26 15.07.11

There were a lot of folks waiting outside who weren’t able to attend, and at this point Adam Bertram and Simon Whalin were the REAL MVPs.  They left the room and lead an impromptu session to get the discussion going in the overflow room. Continue reading

At Microsoft Ignite? Come find me!


I’m speaking at Microsoft Ignite again this year!  Come find me at the PowerShell Community Meetup and the Intro to PowerShell sessions to talk code, scripting, OSD, automation or beer!

Here are the links to my sessions

Tuesday, 3:15 PM, Microsoft Ignite PowerShell Meetup – BRK 1061 – OCCC West Hall, 204 AB.

Thursday, 1:40 PM, Microsoft Ignite Intro To PowerShell – OCCC South Hall, Expo, Theater 1

I’ve got a backpack full of PowerShell and DSC Girl stickers, and look forward to meeting you!

Use PowerShell to take automated screencaps

I saw a post on Reddit a few days ago, in which a poster took regular screenshots of weather radar and used that to make a gif tracking the spread of Hurricane Irma.  I thought it was neat, and then read a comment asking how this was done.

How did you do this? Did you somehow automate the saves? Surely you didn’t stay up all night?

/u/SevargmasComment Link

It brought to mind the time I used PowerShell four years ago to find the optimal route to work.

Solving my lifelong issues with being on-time

You ever notice how if you leave at 6:45, you’ll get to work twenty minutes early. But if you leave at 6:55, more often than not you’ll be late? Me too, and I hated missing out on sleep!  I had a conversation with my boss and was suddenly very motivated to begin arriving on time.

I knew if I could just launch Google Maps and see the traffic, I could time it to see the best to time to leave for work.  But if I got on the PC in the morning, I’d end up posting cat gifs and be late for work.

Of course, Google Maps now provides a built in option to allow you to set your Arrive By time, which removes the need for a tool like this, but at the time, this script was the bees-knees, and helped me find the ideal time to go to work.  It saved my literal bacon.

There are many interesting uses for such a tool, like tracking the progress of a poll, tracking satellite or other imagery, or to see how a page changes over time, in lieu of or building on the approach we covered previously in Extracting and monitoring for changes on websites using PowerShell, when we learned how to scrape a web page.

How this works

First, copy the code over and save it as a .PS1 file.  Next, edit the first few lines

$ie         = New-Object -ComObject InternetExplorer.Application
$shell      = New-object -comObject Shell.Application
$url        = ""
$sleepInt   = 5
$count      = 20
$outFolder  = 'C:\temp'

Provide the following values:

$url      = the page you want to load
$sleepInt = how many seconds you want to pause
$count    = how many times you'd like to run
$outFolder= which directory to save the files

From this point, the tool is fully automated. We leverage the awesome Get-ScreenShot function created by Joe Glessner of  Once we load the function, we simply use the $shell .Net instance we created earlier to minimze all apps, then display Internet Explorer using the $ie ComObject.  We navigate to the page, wait until it’s finished loading, and then take a screenshot.

Then we un-minimize all apps and we’re set.  Simple, and it works!

Hope you enjoy it!

$ie         = New-Object -ComObject InternetExplorer.Application
$shell      = New-object -comObject Shell.Application
$url        = ""
$sleepInt   = 45
$count      = 20
$outFolder  = 'C:\temp\WhenToGoToWork'

#region Get-Screenshot Function
    ##  FUNCTION.......:  Get-Screenshot
    ##  PURPOSE........:  Takes a screenshot and saves it to a file.
    ##  REQUIREMENTS...:  PowerShell 2.0
    ##  NOTES..........:
    Function Get-Screenshot {
         Takes a screenshot and writes it to a file.
         The Get-Screenshot Function uses the System.Drawing .NET assembly to
         take a screenshot, and then writes it to a file.
        .PARAMETER <Path>
         The path where the file will be stored. If a trailing backslash is used
         the operation will fail. See the examples for syntax.
        .PARAMETER <png>
         This optional switch will save the resulting screenshot as a PNG file.
         This is the default setting.
        .PARAMETER <jpeg>
         This optional switch will save the resulting screenshot as a JPEG file.
        .PARAMETER <bmp>
         This optional switch will save the resulting screenshot as a BMP file.
        .PARAMETER <gif>
         This optional switch will save the resulting screenshot as a GIF file.
         C:\PS>Get-Screenshot c:\screenshots

         This example will create a PNG screenshot in the directory

         C:\PS>Get-Screenshot c:\screenshot -jpeg

         This example will create a JPEG screenshot in the directory

         C:\PS>Get-Screenshot c:\screenshot -verbose

         This example will create a PNG screenshot in the directory
         "C:\screenshots". This usage will also write verbose output to the
         comsole (inlucding the full filepath and name of the resulting file).

         NAME......:  Get-Screenshot
         AUTHOR....:  Joe Glessner
         LAST EDIT.:  12MAY11
         CREATED...:  11APR11
            Param (
                )#End Param
        $asm0 = [System.Reflection.Assembly]::LoadWithPartialName(`
        Write-Verbose "Assembly loaded: $asm0"
        $asm1 = [System.Reflection.Assembly]::LoadWithPartialName(`
        Write-Verbose "Assembly Loaded: $asm1"
        $screen = [System.Windows.Forms.Screen]::PrimaryScreen.Bounds
        $Bitmap = new-object System.Drawing.Bitmap $screen.width,$screen.height
        $Size = New-object System.Drawing.Size $screen.width,$screen.height
        $FromImage = [System.Drawing.Graphics]::FromImage($Bitmap)
        $FromImage.copyfromscreen(0,0,0,0, $Size,
        $Timestamp = get-date -uformat "%Y_%m_%d_@_%H%M_%S"
        If ([IO.Directory]::Exists($Path)) {
            Write-Verbose "Directory $Path already exists."
        }#END: If ([IO.Directory]::Exists($Path))
        Else {
            [IO.Directory]::CreateDirectory($Path) | Out-Null
            Write-Verbose "Folder $Path does not exist, creating..."
        }#END: Else
        If ($jpeg) {
            $FileName = "\$($Timestamp)_screenshot.jpeg"
            $Target = $Path + $FileName
        }#END: If ($jpeg)
        ElseIf ($bmp) {
            $FileName = "\$($Timestamp)_screenshot.bmp"
            $Target = $Path + $FileName
        }#END: If ($bmp)
        ElseIf ($gif) {
            $FileName = "\$($Timestamp)_screenshot.gif"
            $Target = $Path + $FileName
        Else {
            $FileName = "\$($Timestamp)_screenshot.png"
            $Target = $Path + $FileName
        }#END: Else
        Write-Verbose "File saved to: $target"
    }#END: Function Get-Screenshot

for ($i=0;$i -le $count;$i++){

    $ie.Visible = $true
    start-sleep 15
    Get-Screenshot $outFolder -Verbose

    "Screenshot Saved, sleeping for $sleepInt seconds"
    start-sleep $sleepInt


When this runs, you’ll have a moment or two to rearrange the screen before the first screen capture is taken. While executing, should leave the computer unattended, as we’re simply automating taking a screencap. If you’re using the computer, it will attempt to minimize your windows, display IE, SNAP, then restore your programs. If you have other windows up, they could be mistakenly included in the screen shot.

Afterwards, you will find the files in whichever path you specified for $outFolder.

Pro-tip, you can exit this at any point by hitting CONTROL+C.

Photo credit: Nirzar Pangarkar