My, browsers come and go so quickly these days. Microsoft’s replacement for Internet Explorer is already shuttered now that they’ve joined the Chromium open-source project to produce Edge using that codebase. And as much as I’m all here for that, it can still be handy to have Internet Explorer–especially when you can control it programatically from PowerShell.

Today’s script is one I’ve been using for a few years now in my day job, although its gone through at least 4 iterations of improvements. We recently went through a massive project to move literally tens of thousands of websites to a new modern hosting platform, and in the course of this work is was helpful to have screenshots of each finished website. We used these somewhat for QA purposes, scrolling through thumbnails to see anything that was obviously out of place. But primarily it was used for a mail-merge where each client received a personalized email letting them know their site transfer was finished, along with a screenshot of what the website looked like at the time.

A look at the script grabbing screenshots of 5 sites. Poor IE doesn’t even have its “globe e” icon on the taskbar anymore.

There are some tools for gathering website screenshots in bulk, but most associated with paid services. However this one can be run on any Windows system using PowerShell.

This script loads in a CSV file that has two columns of data: a filename for the captured screenshot picture file, and the URL address to visit to take the screenshot. Using carefully determined window placement and image bounds, the resultant screenshot has no trace of browser UI, although in my case I decided not to crop the vertical scroll bar out of view.

I’m editing it in Excel, but just make sure you save it as a .csv file type.

After loading in the CSV for data, the script launches the IE browser fresh for each row of the data file, instructs it to visit the given URL, and then waits for the browser to become idle before taking a screenshot, closing the browser, and repeating for the next row.

Room for improvement, but it works.

And finally, here’s the code:

# Author: Shawn Keene
# Date: 09/12/2019
# Powershell script to automate Internet Explorer and grab screenshots

$ScriptPath = Split-Path $MyInvocation.MyCommand.Path
cd $ScriptPath

[Reflection.Assembly]::LoadWithPartialName("System.Drawing")

function screenshot([Drawing.Rectangle]$bounds, $path) {
   $bmp = New-Object Drawing.Bitmap $bounds.width, $bounds.height
   $graphics = [Drawing.Graphics]::FromImage($bmp)

   $graphics.CopyFromScreen($bounds.Location, [Drawing.Point]::Empty, $bounds.size)

   $bmp.Save($path)

   $graphics.Dispose()
   $bmp.Dispose()
}

$bounds = [Drawing.Rectangle]::FromLTRB(4, 110, 1580, 1584)      #area for screenshot

cls
Write-Host -ForegroundColor Yellow "Starting... Move or minimize this window."
sleep 3                                                          #give the user 3 seconds to minimize or move the powershell window out of the way

$iterator = 1;
$OutputFile = "screenshot-log.log"                               #just in case we need to debug something later
 
$products = import-csv "urls.csv" | foreach {                    #load a 2-column CSV with headers of "filename" (for picture file) and "url" to visit

    $ie = New-Object -com internetexplorer.application;          #initialize a fresh browser window for each row of the CSV
    $ie.top = 0;
    $ie.left = -8;	                                             #because windows 10 has an invisible grab borders unless you use AeroLite theme
    $ie.height = 1600;
    $ie.width = 1600;
    $ie.visible = $true;

    $ie.navigate("about:blank");
    while ($ie.Busy -eq $true) { Start-Sleep -Seconds 1};

    $startTime = Get-Date                                       #start the stopwatch and log it
    write-host $iterator.ToString() `t $_.url
    
    $ie.navigate($_.url);                                       #go to the website and wait for browser to become idle
    
    while ($ie.Busy -eq $true) { Start-Sleep -Seconds 1};
    sleep 3                                                     #wait at least 3 seconds and then check for idle one more time to be sure
    while ($ie.Busy -eq $true) { Start-Sleep -Seconds 1};

    $endTime = get-date                                         #end timer

    $filepath = "Results\" + $_.filename + ".png"               #place screenshots into the Results subfolder of the current working directory

    screenshot $bounds $scriptpath\$filepath                    #say cheese
    
    #log the result to the log file
    $iterator.ToString() + "`t" + $_.filename + "`t" + $_.url + "`t" + $startTime.DateTime + "`t" + ($endTime - $startTime).TotalSeconds + " seconds" >> $outputFile

    $ie.quit();                                                 #close the browser process

    $iterator = $iterator+1;
}

Write-Host -ForegroundColor Green "All Done!";