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        = "http://goo.gl/1bFh5W"
$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 http://joeit.wordpress.com/.  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        = "http://goo.gl/1bFh5W"
$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 {
        <#
        .SYNOPSIS
         Takes a screenshot and writes it to a file.
        .DESCRIPTION
         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.
         session.
        .EXAMPLE
         C:\PS>Get-Screenshot c:\screenshots

         This example will create a PNG screenshot in the directory
         "C:\screenshots".

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

         This example will create a JPEG screenshot in the directory
         "C:\screenshots".

        .EXAMPLE
         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).

        .NOTES
         NAME......:  Get-Screenshot
         AUTHOR....:  Joe Glessner
         LAST EDIT.:  12MAY11
         CREATED...:  11APR11
        .LINK
         http://joeit.wordpress.com/
        #>
        [CmdletBinding()]
            Param (
                    [Parameter(Mandatory=$True,
                        Position=0,
                        ValueFromPipeline=$false,
                        ValueFromPipelineByPropertyName=$false)]
                    [String]$Path,
                    [Switch]$jpeg,
                    [Switch]$bmp,
                    [Switch]$gif
                )#End Param
        $asm0 = [System.Reflection.Assembly]::LoadWithPartialName(`
            "System.Drawing")
        Write-Verbose "Assembly loaded: $asm0"
        $asm1 = [System.Reflection.Assembly]::LoadWithPartialName(`
            "System.Windows.Forms")
        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,
            ([System.Drawing.CopyPixelOperation]::SourceCopy))
        $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
            $Bitmap.Save("$Target",
                ([system.drawing.imaging.imageformat]::Jpeg));
        }#END: If ($jpeg)
        ElseIf ($bmp) {
            $FileName = "\$($Timestamp)_screenshot.bmp"
            $Target = $Path + $FileName
            $Bitmap.Save("$Target",
                ([system.drawing.imaging.imageformat]::Bmp));
        }#END: If ($bmp)
        ElseIf ($gif) {
            $FileName = "\$($Timestamp)_screenshot.gif"
            $Target = $Path + $FileName
            $Bitmap.Save("$Target",
                ([system.drawing.imaging.imageformat]::Gif));
        }
        Else {
            $FileName = "\$($Timestamp)_screenshot.png"
            $Target = $Path + $FileName
            $Bitmap.Save("$Target",
                ([system.drawing.imaging.imageformat]::Png));
        }#END: Else
        Write-Verbose "File saved to: $target"
    }#END: Function Get-Screenshot
#endregion 

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

    $ie.Navigate($url)
    $shell.MinimizeAll()
    $ie.Visible = $true
    start-sleep 15
    Get-Screenshot $outFolder -Verbose

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

    $shell.UndoMinimizeALL()
    }

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

Advertisements

QuickStart PowerShell on Red Hat

PowerShell On RedHat in five minutes (1)

Configuring PowerShell on RHEL 7

Hey y’all. There are a lot of guides out there to installing PowerShell on Linux, but I found that they expected a BIT more Linux experience than I had.

In this post, I’ll walk you through installing PowerShell on a RHEL 7 machine, assuming you are running a RHEL 7.4 VM on Hyper-V. There are a couple stumbling blocks you might run into, and I know, because I ran into ALL of them.

200
Real footage of my attempts

Downloading RHEL

Much like Microsoft’s approach to ISO access, Red Hat greedily hordes their installer dvd’s like a classic fantasy dragon. Continue reading

Windows 10 Must-have Customizations

I’ve performed a number of Windows 10 Deployment projects, and have compiled this handy list of must-have customizations that I deploy at build time using SCCM, or that I bake into the image when capturing it.

Hope it helps, and I’ll keep updating it as I find more good things to tweak.

Continue reading

MDM errors failures and how to fix them

Over the course of this many month Air-Watch MDM project I’ve been conducting, I have run into WAY more than my fair share of MDM enrollment related issues.

Troubleshooting MDM issues presents a whole new set of difficulties, because where SCCM provides glorious log files with tons of community engagement and answers, MDM gives you hard to locate Windows Event logs. Every SCCM error code is meticulously documented on the web, where MDM errors give you this result:

This is how you know you are WAY off the reservation!

Never fear though, for I have compiled the most common and frustating errors which I have painstakingly worked through into this, very originally named volume

Where to find enrollment errors

You can monitor the status of an enrollment in the Windows Event Viewer, under this area:

Microsoft-Windows-DeviceManagement-Enterprise-Diagnostics-Provider/Admin

It is routine to see some errors here, so not all errors need to be solved, however when you’re trying to troubleshoot why a machine won’t enroll in MDM, then you should be looking here first.   Continue reading

Wow, ONE MILLION HITS!

I hope you guys will tolerate a little bit of navel gazing for this post!

Today at the FoxDeploy Global Headquarters in Marietta, Georgia, we counted down to a very special milestone here!

1 MILLION HITS!

First and foremost, thank you very much for sticking with me through the years and through the awesome engagement, comments and corrections!  In this post, we’ll take a quick look back at some of the history of the site, what I’ve learned, some hard knocks and some of the fun to look forward too!

Looking back to my First post

Hard to believe that just under four years ago, on August 21st I made my first post here!  It was this helpful little post here, How to Reset your local admin password on Hyper-V.

This post has done well over the years, accruing a little more than 1,000 hits over the years.  I’m not why this might be, but this post on how to recover your password spikes every year after Cinco De Mayo.  What may have happened so that people accidentally locked themselves out?

The Monday after Cinco de Mayo had the greatest hits ever for this post. Looks like people all forgot their passwords for some reason…maybe Margaritas?

This post slowly gained some traffic and gave me confidence to focus on my writing in the evenings, but children would prove to make that a little bit difficult. Continue reading