3 min read

Fun with PowerShell: Let's Get Started!

I've been having a lot of fun playing around with PowerShell recently. Let's see what it can do in Part 1 of a series on learning PowerShell with real-world examples!
Fun with PowerShell: Let's Get Started!

I've been having a lot of fun playing around with PowerShell recently, and wanted to write up some of my learnings.

If you're thinking: "I don't use Windows, so this post isn't for me", good news! Microsoft has released versions of PowerShell for OSX and Linux with easy installers, and I've tested the examples in this series on both Windows and Linux. I document the installation instructions in a separate post.

Let's get started. We'll interact with a REST API called the Open Movie Database. All of the APIs in OMDB require a (free) API key, so if you want to follow along, start by grabbing one.

Let's create a new directory called powershell-explore and create a new file in that directory called omdb.ps1. The ps stands for "PowerShell" and the 1 stands for "maybe we'll want a version 2 someday" (also .ps is taken by PostScript).

$key = "<PUT KEY HERE>"

Invoke-RestMethod "http://www.omdbapi.com/?apikey=$key&s=Avengers"

$key = ... is how you define a variable in Powershell. By default, Powershell variables are scoped to the script they were defined in.

Invoke-RestMethod is called a cmdlet, which is basically a function written in native code. PowerShell functions are invoked by referencing them, and arguments are space-separated. This matches the behavior of command invocation in other shells like Bash.

We're making an API call to ask for a list of all of the movies with the word "Avengers" in it. This dumps out:

Search
------
{@{Title=The Avengers; Year=2012; imdbID=tt0848228; Type=movie; Poster=https://m.media-amazon.com/images/M/MV5BNDYxNjQyMjAtNTdiOS00NGYwLWFmNTAtNThmYjU5ZGI2YTI1XkEyXkFqcGd…

This output is structured, which is one of the main points of Powershell. Unfortunately, it's not very readable.

Let's try again:

Invoke-RestMethod "http://www.omdbapi.com/?apikey=$key&s=Avengers" | Format-List

The | character means that we're passing the result of the previous command into a new function. The Format-List function takes an object as pipeline input and formats it like a list.

This time, we get slightly nicer output:

Search       : {@{Title=The Avengers; Year=2012; imdbID=tt0848228; Type=movie;
               Poster=https://m.media-amazon.com/images/M/MV5BNDYxNjQyMjAtNTdiOS00NGYwLWFmNTAtNThmYjU5ZGI2YTI1XkEyXkFqcGdeQXVyMTMxODk2OTU@._V1_SX300.jpg},
               @{Title=Avengers: Age of Ultron; Year=2015; imdbID=tt2395427; Type=movie;
               Poster=https://m.media-amazon.com/images/M/MV5BMTM4OGJmNWMtOTM4Ni00NTE3LTg3MDItZmQxYjc4N2JhNmUxXkEyXkFqcGdeQXVyNTgzMDMzMTg@._V1_SX300.jpg},
               @{Title=Avengers: Infinity War; Year=2018; imdbID=tt4154756; Type=movie;
               Poster=https://m.media-amazon.com/images/M/MV5BMjMxNjY2MDU1OV5BMl5BanBnXkFtZTgwNzY1MTUwNTM@._V1_SX300.jpg}, @{Title=The Avengers; Year=1998;
               imdbID=tt0118661; Type=movie;
               Poster=https://m.media-amazon.com/images/M/MV5BYWE1NTdjOWQtYTQ2Ny00Nzc5LWExYzMtNmRlOThmOTE2N2I4XkEyXkFqcGdeQXVyNjUwNzk3NDc@._V1_SX300.jpg}…}
totalResults : 92
Response     : True

Better, but still pretty hard to read.

Let's pull the response apart a little.

$movies = Invoke-RestMethod "http://www.omdbapi.com/?apikey=$key&s=Avengers"

$movies.totalResults
$movies.search | Format-List

And we get:

92

Title  : The Avengers
Year   : 2012
imdbID : tt0848228
Type   : movie
Poster : https://m.media-amazon.com/images/M/MV5BNDYxNjQyMjAtNTdiOS00NGYwLWFmNTAtNThmYjU5ZGI2YTI1XkEyXkFqcGdeQXVyMTMxODk2OTU@._V1_SX300.jpg

Title  : Avengers: Age of Ultron
Year   : 2015
imdbID : tt2395427
Type   : movie
Poster : https://m.media-amazon.com/images/M/MV5BMTM4OGJmNWMtOTM4Ni00NTE3LTg3MDItZmQxYjc4N2JhNmUxXkEyXkFqcGdeQXVyNTgzMDMzMTg@._V1_SX300.jpg

Title  : Avengers: Infinity War
Year   : 2018
imdbID : tt4154756
Type   : movie
Poster : https://m.media-amazon.com/images/M/MV5BMjMxNjY2MDU1OV5BMl5BanBnXkFtZTgwNzY1MTUwNTM@._V1_SX300.jpg

Title  : The Avengers
Year   : 1998
imdbID : tt0118661
Type   : movie
Poster : https://m.media-amazon.com/images/M/MV5BYWE1NTdjOWQtYTQ2Ny00Nzc5LWExYzMtNmRlOThmOTE2N2I4XkEyXkFqcGdeQXVyNjUwNzk3NDc@._V1_SX300.jpg

Title  : The Avengers: Earth's Mightiest Heroes
Year   : 2010–2012
imdbID : tt1626038
Type   : series
Poster : https://m.media-amazon.com/images/M/MV5BYzA4ZjVhYzctZmI0NC00ZmIxLWFmYTgtOGIxMDYxODhmMGQ2XkEyXkFqcGdeQXVyNjExODE1MDc@._V1_SX300.jpg

Title  : Ultimate Avengers
Year   : 2006
imdbID : tt0491703
Type   : movie
Poster : https://m.media-amazon.com/images/M/MV5BNDFmZTkxMjktMzRiYS00YzMwLWFhZDctOTQ2N2NlOTAyZDJhXkEyXkFqcGdeQXVyNjgzNDU2ODI@._V1_SX300.jpg

Title  : Ultimate Avengers II
Year   : 2006
imdbID : tt0803093
Type   : movie
Poster : https://m.media-amazon.com/images/M/MV5BZjI3MTI5ZTYtZmNmNy00OGZmLTlhNWMtNjZiYmYzNDhlOGRkL2ltYWdlL2ltYWdlXkEyXkFqcGdeQXVyNTAyODkwOQ@@._V1_SX300.jpg

Title  : The Avengers
Year   : 1961–1969
imdbID : tt0054518
Type   : series
Poster : https://m.media-amazon.com/images/M/MV5BZWI4ZWM4ZWQtODk1ZC00MzMxLThlZmMtOGFmMTYxZTAwYjc5XkEyXkFqcGdeQXVyMTk0MjQ3Nzk@._V1_SX300.jpg

Title  : Avengers Assemble
Year   : 2013–
imdbID : tt2455546
Type   : series
Poster : https://m.media-amazon.com/images/M/MV5BMTY0NTUyMDQwOV5BMl5BanBnXkFtZTgwNjAwMTA0MDE@._V1_SX300.jpg

Title  : Avengers Assemble
Year   : 2013–
imdbID : tt2455546
Type   : series
Poster : https://m.media-amazon.com/images/M/MV5BMTY0NTUyMDQwOV5BMl5BanBnXkFtZTgwNjAwMTA0MDE@._V1_SX300.jpg

Much nicer.

One thing you might have caught: anything that we type in a script that isn't piped into another command or assigned to a variable is printed out.

If we want to suppress that behavior, we can redirect things into $null, a special built-in variable that corresponds to "nothing". If you're familiar with Bash, $null is similar to /dev/null when used this way.

Let's try it:

$movies = Invoke-RestMethod "http://www.omdbapi.com/?apikey=$key&s=Avengers"

$movies.totalResults
$movies.search | Format-List > $null

Output:

92

To be continued.