Category Archives: PowerShell

Fun With PowerShell Hash Tables

Introduction

Hash tables are powerful, flexible items. In some languages, hash tables are also called dictionaries. In this post we’ll start with a few basics, then get into some fun things you can do with hash tables.

A quick note, some documentation calls them a hash table, others read hashtable, one word. For this post I’ll use the two word hash table, but it’s the same thing no matter what documentation or blog you read.

For all of the examples, we’ll display the code, then under it the result of our code. In this article I’ll be using PowerShell Core, 7.1.3, and VSCode. The examples should work in PowerShell 5.1 in the PowerShell IDE, although they’ve not been tested there.

To run a snippet of code highlight the lines you want to execute, then in VSCode press F8 or in the IDE F5. You can display the contents of an array variable (or any variable) by highlighting it and using F8/F5.

Hash Table Basics

To create a hash table you will need to use the @{} syntax to create a set of key / value pairs.

$hash = @{'Key'                 = 'Value'
          'PowerShell'          = 'PowerShell.com'
          'Arcane Code'         = 'arcanecode.com'
          'Pluralsight'         = 'pluralsight.com'
          'GitHub - ArcaneCode' = 'github.com/arcanecode'
         }
$hash                  # Display all values

Result:
Name                           Value
----                           -----
Arcane Code                    arcanecode.com
Key                            Value
Pluralsight                    pluralsight.com
PowerShell                     PowerShell.com
GitHub - ArcaneCode            github.com/arcanecode

In this example I lined up the equal signs because, in my humble opinion, it’s easier to read. But it’s not required.

Similar to an array, you can use positional notation to retrieve a value, only instead of a numeric value you pass in the key.

$hash['PowerShell']

Result:
PowerShell.com

The hash table manifests each key as a property. This means instead of positional notation you can instead use . (dot) notation.

$hash.PowerShell

Result:
PowerShell.com

But Arcane, you may ask, some of those keys have spaces in them. How does that work?

Well all you have to do is put the key in quotes.

$hash.'Arcane Code'

Result:
arcanecode.com

Well that was fun, but what about updating a value for a key? All you have to do is assign the new value.

$hash.'Arcane Code' = 'ArcaneCode.me'
$hash

Result:
Name                           Value
----                           -----
GitHub - ArcaneCode            github.com/arcanecode
Key                            Value
PowerShell                     PowerShell.com
Pluralsight                    pluralsight.com
Arcane Code                    arcanecode.me

As you can see the value for the 'Arcane Code' key has changed from arcanecode.com to arcanecode.me.

In addition to updating, you will have times you want to add a new item to an array. Doing so isn’t intuitive, but it’s easy. Just use the hash table, provide the new key and assign the value to it.

$hash.Ubuntu = 'Ubuntu.com'
$hash

Result:
Name                           Value
----                           -----
GitHub - ArcaneCode            github.com/arcanecode
Key                            Value
Ubuntu                         Ubuntu.com
PowerShell                     PowerShell.com
Pluralsight                    pluralsight.com
Arcane Code                    arcanecode.me

Fun Properties and Methods of Hash Tables

Hash tables have a variety of useful properties and methods you can call. The first, Keys, will return a list of all the keys.

$hash.Keys

Result:
GitHub - ArcaneCode
Key
PowerShell
Pluralsight
Arcane Code
Ubuntu

As you might guess, there’s a corresponding property to return all the values.

$hash.Values

Result:
github.com/arcanecode
Value
PowerShell.com
pluralsight.com
arcanecode.me
Ubuntu.com

Just like the array data type, hash tables also have a Count property to let you know how many key/value pairs are in the table.

$hash.Count

Result:
6

Earlier in this post I showed how to add a new key/value pair. Before adding, it would probably be a good idea to check and see if it is already there. There is a ContainsKey method that will do that.

$hash.ContainsKey('Arcane Code')

Result:
True

This method will return either True or False depending on the presence of the key.

Likewise, there is a method to check to see if a value is present.

$hash.ContainsValue('pluralsight.com')

Result:
True

What if we’d wanted to use ContainsKey to see if a key was present, and if so we wanted to remove it? There is a Remove method that will delete a key/value pair from our hash table.

$hash.Remove('Ubuntu')
$hash

Result:
Name                           Value
----                           -----
GitHub - ArcaneCode            github.com/arcanecode
Key                            Value
PowerShell                     PowerShell.com
Pluralsight                    pluralsight.com
Arcane Code                    arcanecode.me

As you can see in the results, the key / value pair for the Ubuntu entry is now gone.

The final method we’ll look at in this section will allow us to remove all key / value pairs from the hash table.

$hash.Clear()
$hash

Result:
(Nothing is displayed because the hash table is empty)

Creating an Empty Hash Table

Much as with arrays, there are times you will want to create an empty hash table. You could then enter a loop that added new key / value pairs to the hash table.

To declare an empty hash table, you simply assign @{} to a variable.

$empty = @{}

Now you can assign values to it. Here we’ll do it in individual lines, but as I indicated this technique is most useful in a loop.

$empty['Pluralsight'] = 'pluralsight.com'
$empty['DataFabricator'] = 'datafabricator.com'
$empty

Result:
Name                           Value
----                           -----
Pluralsight                    pluralsight.com
DataFabricator                 datafabricator.com

Ordered Hash Tables

Let’s reset our hash table, then look at the output.

$hash = @{'Key'                 = 'Value'
          'PowerShell'          = 'PowerShell.com'
          'Arcane Code'         = 'arcanecode.com'
          'Pluralsight'         = 'pluralsight.com'
          'GitHub - ArcaneCode' = 'github.com/arcanecode'
         }
$hash

Result:
Name                           Value
----                           -----
Arcane Code                    arcanecode.com
Key                            Value
Pluralsight                    pluralsight.com
PowerShell                     PowerShell.com
GitHub - ArcaneCode            github.com/arcanecode

Look at the output carefully. The returned list is not in the same order we added them to the hash table. Most of the time you are referencing the hash table via a specific key, so the ordering isn’t a concern.

What if you needed them to be returned in the same order they were added in? Fortunately PowerShell has an [ordered] instruction you can place before declaring the hash table.

$hash = [ordered]@{
  'Key'                 = 'Value'
  'PowerShell'          = 'PowerShell.com'
  'Arcane Code'         = 'arcanecode.com'
  'Pluralsight'         = 'pluralsight.com'
  'GitHub - ArcaneCode' = 'github.com/arcanecode'
}
$hash

Result:
Name                           Value
----                           -----
Key                            Value
PowerShell                     PowerShell.com
Arcane Code                    arcanecode.com
Pluralsight                    pluralsight.com
GitHub - ArcaneCode            github.com/arcanecode

As you can see, the results are returned in the exact same order they were added to the hash table. This example also demonstrates you can begin the list of key / value pairs on the next line after the single squiggly bracket {.

Iterating (Looping) Over a Hash Table

It is possible to loop over the contents of a hash table. But it isn’t quite as intuitive as it is with arrays. If you were to use foreach($item in $hash) you’d get an error, because PowerShell isn’t sure if you want to loop over the keys, values, or something else.

Instead, the hash table has a special method called GetEnumerator which will allow you to iterate over the table, returning one key / value pair each time through the loop.

foreach($item in $hash.GetEnumerator())
{
  "$($item.Name) has a value of $($item.Value)"
}

Result:
Key has a value of Value
PowerShell has a value of PowerShell.com
Arcane Code has a value of arcanecode.com
Pluralsight has a value of pluralsight.com
GitHub - ArcaneCode has a value of github.com/arcanecode

This is the way I prefer to iterate over a hash table. Just my personal opinion, but I think the code is cleaner and easier to read. That said, there is a second method you may like better.

In it you loop over the Key values, then reference the value from the hash table, using the key as the position. Do notice that instead of using the key[] notation, you have to reference the Item method then pass the key into it.

foreach($key in $hash.Keys)
{
  "$key value is $($hash.Item($key))"
}

Result:
Key value is Value
PowerShell value is PowerShell.com
Arcane Code value is arcanecode.com
Pluralsight value is pluralsight.com
GitHub - ArcaneCode value is github.com/arcanecode

As you can see, the result is the same either way. Use which ever method makes the most sense for you.

Splatting

Right now you are probably asking yourself “Splatting? Hey Arcane, are you trying to confuse us with silly names?”

Fear not, splatting is a real thing. First, let’s start with an example. Here, we are going to take the output of GetChildItem and pipe it to a cmdlet called Join-String. If you aren’t familiar with it, Join-String will take a list of objects and join them to a single string.

Get-ChildItem -Directory D:\ |
  Join-String -Property Name -Separator ', '

Result:
Backups_Temp, CamtasiaWorkspace, Hyper-V, ISOs, Mobile Report Publisher

With splatting, we create a hash table, Each key is the name of a parameter that needs to be passed in, and the value is what we want to use for that parameter.

$splat = @{Property = 'Name'
           Separator = ', '
          }

Here you can see the Property and Separator parameter names were passed in as keys, and the values are what we want to pass in.

Now we can call our cmdlet, passing in the name of our hash table. Only, and this is important, instead of a $ we use an @ at the front of the name of our hash table.

Get-ChildItem -Directory D:\ | Join-String @splat

Result:
Backups_Temp, CamtasiaWorkspace, Hyper-V, ISOs, Mobile Report Publisher

Whenever PowerShell sees a @ in front of a name that corresponds to a hash table, it understand you are using a splat and expands each key / value pair into parameters. As you can see, it shortens the call to Join-String significantly.

What if we want to change the value of one of our parameters? That’s easy, we just assign a new value. The rest of the hash table remains the same.

$splat.Separator = ' - '
Get-ChildItem -Directory D:\ | Join-String @splat

Result:
"Backups_Temp" - "CamtasiaWorkspace" - "Hyper-V" - "ISOs" - "Mobile Report Publisher"

All of the parameters don’t have to be included in the splat. For example, Join-String has a switch that, when included, will wrap each item in single quotes.

$splat = @{Property = 'Name'
           Separator = ', '
          }

Get-ChildItem -Directory D:\ |
  Join-String @splat -SingleQuote

Result:
'Backups_Temp', 'CamtasiaWorkspace', 'Hyper-V', 'ISOs', 'Mobile Report Publisher'

Here I used a switch, but it could be another parameter with a value added after the splat.

What if you wanted to include the switch in the hash table though? Switches don’t have a value that is passed in.

That turns out to be a simple answer, just include the switch as a key, and for the value use either $True or $False.

$splat = @{Property = 'Name'
           Separator = ', '
           SingleQuote = $True
          }
Get-ChildItem -Directory D:\ | Join-String @splat

Result:
'Backups_Temp', 'CamtasiaWorkspace', 'Hyper-V', 'ISOs', 'Mobile Report Publisher'

You could also include the switch in the splat, but set the value to $False if you didn’t want to use single quoted every time.

While this example only had a few parameters, I’ve worked with some cmdlets that had a dozen or more parameters that were required to pass in. SQL Server’s cmdlets come to mind.

I often had scripts that had a dozen parameters, but the only one that changed with each call was the actual SQL command I was sending to the server. Using a splat let me reduce the amount of code significantly.

Conclusion

In this post, we saw a lot of fun things you can do with hash tables. A few were creating, updating, adding and removing values. We also covered iterating over a hash table, and even the very useful concept of splatting.

Now you can use these features in your own scripts where a hash table comes into play.

The demos in this course came from my Pluralsight course PowerShell 7 Quick Start for Developers on Linux, macOS and Windows, one of many PowerShell courses I have on Pluralsight. All of my courses are linked on my About Me page.

If you don’t have a Pluralsight subscription, just go to my list of courses on Pluralsight. At the top is a Try For Free button you can use to get a free 10 day subscription to Pluralsight, with which you can watch my courses, or any other course on the site.

Fun With PowerShell Arrays

Introduction

In this article, we’ll look at the different ways to use Arrays in PowerShell. We’ll cover the basics, then move onto more advanced topics.

For all of the examples, we’ll display the code, then under it the result of our code. In this article I’ll be using PowerShell Core, 7.1.3, and VSCode. The examples should work in PowerShell 5.1 in the PowerShell IDE, although they’ve not been tested there.

To run a snippet of code highlight the lines you want to execute, then in VSCode press F8 or in the IDE F5. You can display the contents of an array variable (or any variable) by highlighting it and using F8/F5.

A quick note for my non-native English speaking friends, I use the term aka a few times. AKA is shortcut for “also known as“, it’s just a quick way to say “a is another word for b”.

Array Basics

The formal array to declare an array is to use @() around the contents, assigning it to a variable.

$array = @('Robert', 'Cain')
$array

Result:
Robert
Cain

Note that in the output, each item (aka element) in the array is displayed on a single line.

There is a little easier way to create an array, you can omit the @() . If you are passing in more than one item, separated by a comma, PowerShell converts it to an array.

$array = 'Robert', 'Cain'

If you have a long list of items, you can break the list over multiple lines. As long as a comma is the last thing on the line PowerShell will assume the rest of the array contents continue on the next line.

$array = 'Robert',
         'Cain'

You can access individual items in the array by using what is called positional notation. After the name of the array, use square brackets [] and inside put a number that indicates the position in the array.

Numbering begins at zero and goes to the maximum number of elements. (Well, technically the max number of elements minus one, but more on that in a moment.) If you try to use a number greater than the maximum number of elements, you will get an error.

$array = 'Robert', 'Cain'
$array[0]

Result:
Robert

$array[1]

Result:
Cain

Of course you can use variables in place of the numeric values for positional notation.

$x = 1
$array[$x]

Result:
Cain

So how do you know how many items are in an array? The array variable type has a Count property that can tell you that.

$array.Count

Result:
2

There is also a property called Length, which returns the same thing. They can be used interchangeably, most people however use the Count property.

One thing to be careful of with Count, is that it returns the number of items in the array. But arrays start with position 0 (zero), so the last item in an array will be Count - 1, not Count.

$array[$array.Count - 1]

Result:
Cain

PowerShell does provide a shortcut to get the last element. You can pass in a -1 (negative one) into the position, and it will get the last item.

$array[ -1 ]

Result:
Cain

Fun Tricks with Positional Notation

There are a few fun tricks you can do with positional notation. So far, we’ve only used a single value in the square brackets to get a single value from the array.

Did you know you can pass in multiple numbers and get back multiple elements from the array in one command?

$array = 'Zero', 'One', 'Two', 'Three',
         'Four', 'Five', 'Six', 'Seven'
$array[2, 4, 6]

Result:
Two
Four
Six

If you pass in the same number twice, you’ll get that array item back twice in the results.



$array = 'Zero', 'One', 'Two', 'Three',
         'Four', 'Five', 'Six', 'Seven'
$array[2, 4, 2]

Result:
Two
Four
Two

Finally, you can use PowerShell’s range operator to return a series of values.



$array = 'Zero', 'One', 'Two', 'Three',
         'Four', 'Five', 'Six', 'Seven'
$array[1..4]

Result:
'One'
'Two'
'Three'
'Four'

Adding Items to an Array

Adding items is pretty easy, you can use the += (plus equal) to add a new item into the array. In this example, we’ll add two new items, then display the new array, and finally the count of items.

$array = 'Robert', 'Cain'

$array += 'Arcane'
$array += 'Code'
$array

$array.Count

Result:
Robert
Cain
Arcane
Code
4

Here you can see are my original two items, followed by the new ones we just added. Finally the count, 4, is displayed.

Updating an Array Element

What if we want to update a value in the array? Turns out that is as easy as adding a new one. Simply address the item to replace with positional notation, then assign a new value.

$array[0] = 'Mr.'
$array

Result:
Mr.
Cain
Arcane
Code

Empty Arrays

When you need to create an empty array, you use the formal array declaration syntax we saw in the first example, only you put nothing in it.

$empty = @()
$empty

Result:
(Nothing is displayed because the array is empty)

So why would you need an empty array?

Let’s say you were looping over a collection of some type, and were building a new array to output. It might be a collection (aka array) of files, or records return from a SQL Server query.

You would create the empty array, enter the loop, extract and format the information you want then add it to the empty array using the += syntax.

Iterating Over Arrays

There are a few methods we can use to iterate, or loop over the contents of our arrays. The most common, and one I use the most, is a foreach loop.

foreach($item in $array)
{
  "The current item is $item"
}

Result:
The current item is Mr.
The current item is Cain
The current item is Arcane
The current item is Code

The next option is to pipe our array into the ForEach-Object cmdlet, passing a script block to the cmdlet with our instructions.

$array | ForEach-Object { "Current Value: $PSItem"}

Result:
Current Value: Mr.
Current Value: Cain
Current Value: Arcane
Current Value: Code

The variable $PSItem is a built in PowerShell variable, meant to represent the current item in a loop.

Finally, an Array datatype has a ForEach method built right in. You call the method, then as you did with the ForEach-Object cmdlet pass in a script block with the instructions.

$array.ForEach({ "Current Value: $_"})

Result:
Current Value: Mr.
Current Value: Cain
Current Value: Arcane
Current Value: Code

In this example we used the variable $_ to represent the current item. The $_ was the original way to create a placeholder, later PowerShell added the $PSItem variable. $PSItem was introduced way back in version 3, so unless you are on a really really REALLY old version of PowerShell, you can use $_ and $PSItem interchangeably.

Erasing the Contents of an Array

Clearing out the contents of an array is easy, just call the array’s Clear method.

$array.Clear()
$array

Result:
(Nothing is displayed because the array is empty)

Mixed Data Types

Unlike a lot of other languages, the values going into an array can be a mix of data types. In the example below I’m going to load an array with some strings, integers, and a floating point type.

$array = 'Arcane', 'Code', 33, 42,
         'Alabama', 3.14, 'In the Morning'
$array

Result:
Arcane
Code
33
42
Alabama
3.14
In the Morning

Removing Items From Arrays

We now move to a topic that doesn’t have a happy answer. You cannot remove an item from an array. That said, you could create a brand new array, filtering out the unwanted elements.

In this example, we pipe our array into the Where-Object cmdlet. We pass in a script block, in which we say only pass out items where the value of the current item is not equal ( -ne ) to the state of Alabama. After that we display the results.

Note too we are using another built in line continuation feature of PowerShell. If the pipe symbol, a | , is the last thing on the line PowerShell assumes what is on the next line is a continuation of the line above. (I like to indent the second line to the right of my equal sign, but it’s not required.)



$array = 'Arcane', 'Code', 33, 42,
         'Alabama', 3.14, 'In the Morning'
$newArray = $array |
            Where-Object { $PSItem -ne 'Alabama' }
$newArray

Result:
Arcane
Code
33
42
3.14
In the Morning

As you can see, the state of Alabama is no longer in our list.

Fun Operators – In and Compare

There are other operators in PowerShell that can let us do fun things with arrays.

First, what if we need to know if an item is already in the array? There’s actually two methods to handle that. In the first, we’ll see if the item is in the array.

$array = 'Arcane', 'Code', 33, 42,
         'Alabama', 3.14, 'In the Morning'
'Arcane' -in $array

Result:
True

In the second method we’ll use the contains operator.

$array -contains 'Code'

Result:
True

More Fun Operators – Join

What if you wanted to convert all of the elements in the array into a single string? To handle that we have the join operator.

After the join, you pass in a character to use to separate each element. You also have the option to pass in an empty string if you don’t want anything separating your results.

In the last example, you’ll see that you can pass in more than one character to separate the results.

$array = 1, 3, 5, 7, 9
$result = $array -join ' '
$result

Result: 1 3 5 7 9

$array = 1, 3, 5, 7, 9
$result = $array -join '-'
$result

Result: 1-3-5-7-9

$array = 1, 3, 5, 7, 9
$result = $array -join ','
$result

Result: 1,3,5,7,9

$array = 1, 3, 5, 7, 9
$result = $array -join ''
$result

Result: 13579

$result = $array -join ', '
$result

Result: 1, 3, 5, 7, 9

Even More Fun Operators – Replace, Match, Split

There are three more operators we’ll cover here. The first is Replace, which will search through the array and replace one string with another.

$servers = 'HOLD-001', 'HOLD-002', 'SQL-001', 'SQL-002'
$newServers = $servers -replace 'HOLD', 'TEST'
$newServers

Result:
TEST-001
TEST-002
SQL-001
SQL-002

You might use this to develop a script to run against your servers. When designing the script you might use a string like HOLD-001, HOLD-002, etc where HOLD is just a place holder.

At runtime you pass a parameter into your script such as DVLP (development), TEST, or PROD (production) so you can use the same script in multiple environments.

The next operator we’ll look at is match. Match can be used as a filter. Let’s take a look at this example:

$servers = 'SRV-001', 'SRV-002', 'SQL-001', 'SQL-002'
$newServers = $servers -match 'SQL'
$newServers

Result:
SQL-001
SQL-002

As you can see, only servers with SQL in the name were returned. This might be useful if you had a full list of all servers you wanted to iterate over, but in certain sections of your script you only wanted to do things to your SQL Servers.

The final operator to look at is split. You can use split to further divide the elements in your array into smaller parts.

In this example we’ll reuse our list of servers, but split the items based on a dash (or hyphen).

$servers = 'SRV-001', 'SRV-002', 'SQL-001', 'SQL-002'
$newServers = $servers -split '-'
$newServers

Result:
SRV
001
SRV
002
SQL
001
SQL
002

Here you can see each server name was split into two parts, each part becoming a new element in our output array. Also note that the character we split on, the dash, is discarded from the result set.

Iterating Over an Array of Objects

Just like arrays of simple items like strings and integers, you can also loop over an array of objects.

Here, we’ll get a list of files in my temp directory using the Get-ChildItem cmdlet. We’ll also use the empty array technique you saw earlier. A foreach loop will be used to go over each file object in the array and format a string with some of its properties, then add that string to our empty $newFiles array.

Set-Location "C:\Temp"
$files = Get-ChildItem
$newFiles = @()
foreach($file in $files)
{
  $newFiles += "$($file.Name) is $($file.Length) in size"
}
$newFiles

Result:
2019-ARRL-FieldDay-Rules-RevA.pdf is 111434 in size
ARRL-FIELD-DAY.adi is 76110 in size
azuredatastudio-windows-user-setup-1.13.1.exe is 91789368 in size
curl-7.74.0.zip is 6068670 in size
standard-notes-3.6.14-win.exe is 105761936 in size
SysinternalsSuite.zip is 41889407 in size

Within my loop $file represents the current item in my $files array. Inside I access the properties of my file object. I could, for example, have used if ($file.Length -gt 1) and done something useful.

In this case I’m using string interpolation to display the value of a property. Note that because I want it to access the property, within the string I have to wrap it in $(), such as $($file.Name).

This forces PowerShell to first evaluate what is inside the $(), then return that into the string.

Conclusion

This post turned out longer than I’d intended, but there are so many fun things you can do with a PowerShell Array it was hard to stop at just a few.

With luck you’ll have found some new techniques you can employ with arrays in your own PowerShell scripts.

The demos in this course came from my Pluralsight course PowerShell 7 Quick Start for Developers on Linux, macOS and Windows, one of many PowerShell courses I have on Pluralsight. All of my courses are linked on my About Me page.

If you don’t have a Pluralsight subscription, just go to my list of courses on Pluralsight. At the top is a Try For Free button you can use to get a free 10 day subscription to Pluralsight, with which you can watch my courses, or any other course on the site.

Fun With PowerShell String Formatting

Introduction

In last Monday’s blog post, Fun With PowerShell Strings, I covered a lot of the basics around PowerShell Strings. One thing we didn’t get into though was some of the special formatting commands you can use with PowerShell.

Specifically, this can control the output when we embed a numeric value inside a string. Passing in special formatting instructions will make it easy to display values with commas, as currency, or even as hexidecimal.

For all of the examples, we’ll display the code, then under it the result of our code. In this article I’ll be using PowerShell Core, 7.1.3, and VSCode. The examples should work in PowerShell 5.1 in the PowerShell IDE, although they’ve not been tested there.

To run a snippet of code highlight the lines you want to execute, then in VSCode press F8 or in the IDE F5. You can display the contents of an array variable (or any variable) by highlighting it and using F8/F5.

How it Works

PowerShell supports the C# / C / C++ style of string formatting. Let’s take a look at this example.

[string]::Format("There are {0} items.", $items)

Inside our string we have {0}. This is a placeholder, when a C style language sees this it will look for the first variable after the string and put that into placeholder 0.

PowerShell of course always wants to make life easier on us, so we can use this much simpler format.

"There are {0} items." -f $items

In PowerShell we have our string, including the placeholder. After it we have a -f to let PowerShell know the following items will be copied into the placeholders. In this case, the value in $items will be inserted into the {0} placeholder.

It’s not necessary to use a variable, we could have just hardcoded a value.

"There are {0} items." -f 33

What if we had multiple items? Well we’d just use multiple placeholders (all on one line).

"There are {0} items in the location {1}." -f $items, $loc

In this example, $items will go into the {0} and the value in $loc will get inserted into placeholder {1}.

You can even repeat a placeholder.

"There's {0} items in {1}. {0} is a lot of items!" -f $items, $loc

Now, if you’ve read my previous post you’re probably thinking “wait, wouldn’t string interpolation make all these unnecessary?”

And in these examples you are correct, with string interpolation you could have used the much easier to read syntax.

"There are $items items."

So why use the placeholder style? Well it turns out the placeholder syntax includes some extra syntax which will allow you to format values passed in. Let’s take a look at some examples.

Number

In the placeholder, after the placeholder position ( 0 in these examples ) you can put a colon : , then a letter that indicates the formatting style. Then another number which indicates the decimal places to retain.

"N0 {0:N0} formatted" -f 12345678.119    

Result:
N0 12,345,678 formatted

In this example, after the colon we have the letter N. This lets PowerShell know we want this to be formatted as a numeric value, and to include commas to separate the numbers.

In this example after the letter N we have another number, a 0. This indicates how many decimal places to retain in the output.

Here’s another example where we’ll include two decimal places.

"N2 {0:N2} formatted" -f 12345678.119

Result:
N2 12,345,678.12 formatted

As you can see, it follows the normal rules for rounding up the output. The next to the last last number, 1, was rounded up to 2 since the number after it was a 9.

Often we want to display numbers as right aligned, so the last digit will line up in our output. This means we want to display a number of spaces in front of it. PowerShell includes a feature for this too.

"N0 {0,8:N0} formatted" -f 123.119

Result:
N0      123 formatted

After the place holder we have a comma then a number ( here 0,8 ). This tells PowerShell we want the value for this placeholder to be eight characters in width.

In the output, PowerShell saw the final value, 123, was three characters wide. So it subtracted three from eight and put five spaces in front of the 123 so the entire output became eight characters in width.

A common question is “what if the output is longer than the width passed in?”. For example, you used 0,3 but your input to the placeholder was a value of 123456? In that case PowerShell will still format it as 123,456 but will not add any spaces before the number. This could result in some misaligned output in your display, but at least the accurate value will still be shown.

Currency

Using the C format instruction, PowerShell can display the results in currency format. It will use the default currency symbol for your computer’s language / location. Since I’m in the United States it will use a dollar sign.

"C0 {0:C0} formatted" -f 12345678.1234
"C2 {0:C2} formatted" -f 12345678.1234
"C2 {0,20:C2} formatted" -f 12345678.1234

Result:
C0 $12,345,678 formatted
C2 $12,345,678.12 formatted
C2       $12,345,678.12 formatted

Currency acts very similar to the Number format, the only real difference is the addition of your location’s currency symbol in the formatted output.

Percentage

PowerShell also has the ability to display values in a percentage format.

"P0 {0:P0} formatted" -f 0.1234
"P2 {0:P2} formatted" -f 0.1234
"P2 {0,8:P2} formatted" -f 0.1234

Result:
P0 12% formatted
P2 12.34% formatted
P2   12.34% formatted

Make sure to notice that PowerShell will take the decimal amount and automatically convert the percentage for you. Thus, if you want to display 12%, you have to pass in 0.12.

Hex

Next up on the list is Hexadecimal notation. PowerShell supports two methods for doing Hex values. In the first, it will take a standard number (base 10) and convert it to hexadecimal then display it.

"X0 0x{0:X0} formatted" -f 1234

Result:
X0 0x4D2 formatted

In this case we passed in the number 1234. PowerShell converted it to hex then displayed it.

What if the value were already in hex format though, and we just wanted to display it? In PowerShell, we indicate a number is in hex by placing a 0x in front of it. So we just pass in our number with 0x in front to the string.

"X0 0x{0:X0} formatted" -f 0x4D2

Result:
X0 0x4D2 formatted

When PowerShell saw the 0x on the front of 0x4D2, it knew this value was already in hex format and didn’t try to convert it, it simply displayed our value.

Decimal

The name of the next formatter we’ll look at is Decimal. It’s a bit misnamed though, because it’s really just for formatting integer based numbers. As a matter of fact, if you try use with a non integer value, such as 33.42, it will error out.

Let’s look at the most basic form of Decimal.

"D0 {0:D0} formatted"   -f 123

Result:
D0 123 formatted

Pretty simple, it just displays the value. So you can guess D is the formatter for decimal, but what is D0? The number after the D indicates how many spaces we want to zero pad to.

In other words, we want the string to be a certain number of characters long, so the number indicates that length. It will then put zeros to the left to pad it out. Let’s look at this example to make it clear.

"D8 {0:D8} formatted"   -f 123

Result:
D8 00000123 formatted

In this case, the D8 indicated we wanted eight characters in decimal formatting. PowerShell converted 123 to a string that was three characters long, so it put five zero’s in front to make the total length eight.

You can also add the placeholder comma value formatting to make a value a certain width wide. In these two examples, the first will act like a Number format. The second though will let you use leading zeros, but still set the total space.

"D0 {0,9:D0} formatted" -f 123
"D0 {0,9:D6} formatted" -f 123

Result:
D0       123 formatted
D0   0000123 formatted

In the first example, it made the output nine characters wide by placing six spaces in front of the 123. In the second example, it first made the 123 six characters by placing 000 on front, resulting in 000123.

It then took the resulting 000123 and made that nine wide by placing three spaces in front. As you can see, PowerShell is very flexible when formatting this way.

A reminder, as stated earlier Decimal is only for integers. If I were to try using -f 123.1 as an input it would error out.

Custom Date Formatting

In addition to the other formats, PowerShell provides the ability to create custom date outputs. You do so using these characters, note they are case sensitive.

M / MMOne or Two character month number
d / ddOne or two character day of the month number.
yy / yyyyTwo or four digit year number.
h / hhOne or two digit hour of the day in 12 hour format
H / HHOne or two digit hour of the day in 24 hour format
m / mmOne or two digit minute of the hour
s / ssOne or two digit second of the minute

Let’s see these used in a series of examples.

"Today is {0:M/d/yy}."                 -f $(Get-Date)
"Today is {0,10:MM/dd/yyyy}."          -f $(Get-Date)
"Today is {0,10:dd/MM/yyyy}."          -f $(Get-Date)
"Today is {0,10:yyyyMMdd}."            -f $(Get-Date)
"Today is {0,10:MM/dd/yyyy hh:mm:ss}." -f $(Get-Date)
"Today is {0,10:MM/dd/yyyy HH:mm:ss}." -f $(Get-Date)

Result:
Today is 7/18/21.
Today is 07/18/2021.
Today is 18/07/2021.
Today is   20210718.
Today is 07/18/2021 04:59:56.
Today is 07/18/2021 16:59:56.

In all of these, I passed in the current date (as I’m writing this) using Get-Date, but any date based variable would have worked.

In the output I’ve arranged the date parts in a variety of common manners. You can use these or create your own custom formats. For example you may wish to use a dash instead of a slash to separate the date parts.

Custom Number Formatting

Let’s say you lived in London, where the pound was your default currency. But you are part of a multinational company and need to produce output to send to your coworkers in the United States. You don’t want to have to change your computer to a US language just to get the $ symbol.

You can fix this by using custom formatting. In these examples, when it sees a character such as the $ it will just keep it in the output. When it sees #, (a pound sign followed by a comma) it will know to use commas in the output.

When it sees just a # sign it will put a number there if it has one, otherwise a space, and when it sees 0 it will put a number from the passed in data, or a zero if there is no number there. These examples will clarify it.

Note each one is on it’s own line, WordPress is wrapping the -f part to the next line for space reasons. Additionally, in this and other examples I’ve chosen to add spaces to line up the demos for readability, this isn’t a requirement and you can format however you need.

"Custom 0, 25 $ #,##0.0000  = {0,25:$ #,##0.0000} " -f 123456789.012000005
"Custom 0, 25 $ #,##0.0000  = {0,25:$ #,##0.00} "   -f 123456789.012000005
"Custom 0, 25 $ ##0.0000    = {0,25:$ ##0.00} "     -f 123456789.012000005

Result:
Custom 0, 25 $ #,##0.0000  =        $ 123,456,789.0120
Custom 0, 25 $ #,##0.0000  =          $ 123,456,789.01
Custom 0, 25 $ ##0.0000    =            $ 123456789.01

Using Formatting with Variables

It’s possible to create a formatted value, then assign that to a variable. Let’s take a look at this slightly more complex example.

$vTday = "{0,8:N0}" -f 134567
$vYest = "{0,8:N0}" -f 23546

$tday = "{0:MM/dd/yyyy}" -f $(Get-Date)
$yest = "{0:MM/dd/yyyy}" -f $((Get-Date).AddDays(-1))

$output = "Visitors to ArcaneCode.com`r`n"
$output += "$tday had $vTday visitors`r`n"
$output += "$yest had $vYest visitors"
$output

Result:
Visitors to ArcaneCode.com
07/18/2021 had  134,567 visitors
07/17/2021 had   23,546 visitors

The first two lines you’ve seen a few times by now. I’m simply taking a number, formatting it with commas and making it eight spaces wide.

The next line you’ve seen as well, I take the current date, format to MM/dd/yyyy format and assign to $tday.

The $yest line is slightly more complex, but only because I’m doing some date math. The (Get-Date) will get the current date, but create a date object from it. Essentially I have a date variable type but without a variable name.

Because I have a date datatype I can employ a method of the date datatype, AddDays. This will let me add a number of days to the date, or if you pass in a negative value subtract days. Thus AddDays(-1) will give me yesterday’s date. I then have to wrap it all in $() so PowerShell will evaluate the entire expression before passing it back to the placeholder.

Finally I’m using the += operand to concatenate several strings together for a nice output. Note the formatted dates, and how the visitors number right aligns nicely.

Conclusion

While string interpolation makes creating output strings easy, knowing how to use placeholders can make creating formatted output even easier, allowing you to create output with numeric values that align neatly, or creating custom date formatting.

The demos in this course came from my Pluralsight course PowerShell 7 Quick Start for Developers on Linux, macOS and Windows, one of many PowerShell courses I have on Pluralsight. All of my courses are linked on my About Me page.

If you don’t have a Pluralsight subscription, just go to https://pluralsight.com. At the top is a Try For Free button you can use to get a free 10 day subscription to Pluralsight, with which you can watch my courses, or any other course on the site. Once there just search for my name, Robert Cain, to see all the courses I have.

Fun With PowerShell Strings

Introduction

PowerShell has some of the best, most flexible string handling of any language I’ve used. In this post we’ll look at some string basics, then some of the features that make it special.

Note in these demos I’m using PowerShell Core 7.1.3 and VSCode. Everything here should also work in the PowerShell 5.1 and the PowerShell IDE.

Basic Strings in PowerShell

Strings in PowerShell can be denoted with either single quote marks or double quote marks.

"This is a string"
'This is a string too!'

If you want to see the result, simply highlight the strings and press either F8 in VSCode, or F5 in the PowerShell IDE.

This is a string
This is a string too!

Multiline Strings, aka Here Strings

PowerShell has the ability to create a multiline string, also known as a “here” string. To create a here string, use an @ sign, followed by a quotation mark (either single or double) then hit Enter.

On the next lines, enter the value for your string. Finally hit Enter, then on the next line put the closing quotation mark then another @ sign.

This is important, the closing quotation mark and @ sign must be the first two characters on the line. If you attempt to indent them in any way the technique will not work!

$heretext = @"
Some text here
Some more here
     a bit more

a blank line above
"@

$heretext

Some text here
Some more here
     a bit more

a blank line above

Again, this works with single or double quotes. So what’s a common use?

One common thing I use it for is SQL queries. Here’s an example in a traditional language.

$sql = 'SELECT col1' `
     + '     , col2' `
     + '     , col3' `
     + '  FROM someTable ' `
     + ' WHERE col1 = ''a value'' '

Note the single ` (back tick) mark at the end of each line. This is the line continuation character in PowerShell.

As you can see, each line has to be connected with + signs. Now let’s contrast it with a here string version.

$sql = @'
SELECT col1
     , col2
     , col3
  FROM someTable
 WHERE col1 = 'a value'
'@

This is not only much more readable, but easier to work with. You can develop your SQL query in SQL Server Management Studio, or Azure Data Studio, then simply cut and paste it into PowerShell.

Another thing to notice, you can embed single or double quotes within a here string, and PowerShell will ignore them as denoting another string.

Embedded Quote Marks

If you need to embed a quotation mark in a string, you can simply double them up.

"ArcaneCode said ""PowerShell is awesome!"" and the crowd applauded."

ArcaneCode said "PowerShell is awesome!" and the crowd applauded.

This technique works with single quote marks as well. For example one’s used in common words such as shouldn’t.

'You shouldn''t miss the blog posts at arcanecode.com'

You shouldn't miss the blog posts at arcanecode.com

String Interpolation

You may be wondering what the difference between single and double quotes is. Double quotes allow you to use something called string interpolation. String interpolation will take any variables embedded in the string and expand them before returning the string.

Here’s a simple example. First we get the number of items in the current folder. Then we copy the current folder location into another variable. Finally we create a string with these variables in it, surrounding the string in double quote marks.

$items = (Get-ChildItem).Count 

$loc = Get-Location

"There are $items items are in the folder $loc."

There are 3 items are in the folder C:\PSCore-QuickStart.

As you can see in the result (the bottom line) it has taken the value in $items, a 3, and expanded it in the return result.

Likewise, it has taken the value in $loc and expanded it to the name of the current folder.

Now see the result if single quote marks had been used.

$items = (Get-ChildItem).Count 

$loc = Get-Location

'There are $items items are in the folder $loc.'

There are $items items are in the folder $loc.

With single quotes, the string interpolation engine does not kick in.

As a rule of thumb then, only use double quotes if you have to have interpolation. Otherwise use single quotes so you don’t incur the (admittedly minimal) amount of time for the string interpolation engine to needlessly process the string.

Escape Characters

PowerShell also has the concept of escape characters. These are special characters you can embed in the string that provide additional formatting instructions.

Note that escape characters only work inside double quote marked strings. If you use single quotes for your strings, it will just display the escape character.

There are four that are the most commonly used. Tab, Carriage Return, Line Feed, and escaping the $ (dollar sign) so it may be used.

Escape characters are preceded by a back tick ` then the character. Let’s look at the tab, which is a `t.

"`tThis is tabbed in"

        This is tabbed in

The next is the carriage return line feed sequence, which is `r`n.

"Here is some text`r`nAnd some more text`r`n`r`nA blank line before this"

Here is some text
And some more text

A blank line before this

You would most commonly use this when looping over data and building a new output string.

The final escape character we’ll look at allows you to embed a $ character in an double quoted string. Simply use a back tick followed by the dollar sign.

"The `$items variable is $items"

The $items variable is 3

We’ve only covered four here, but note there are many more escape sequences you can use in PowerShell.

Conclusion

In this post you saw all kinds of cool things you can do with PowerShell strings. With this knowledge you can take your PowerShell scripts to the next level, and be able to generate some creative output with your own PowerShell strings.

The demos in this course came from my Pluralsight course PowerShell 7 Quick Start for Developers on Linux, macOS and Windows, one of many PowerShell courses I have on Pluralsight. All of my courses are linked on my About Me page.

If you don’t have a Pluralsight subscription, just go to https://pluralsight.com. At the top is a Try For Free button you can use to get a free 10 day subscription to Pluralsight, with which you can watch my courses, or any other course on the site. Once there just search for my name, Robert Cain, to see all the courses I have.

Fun with PowerShell Get-Random

Introduction

Many people know about PowerShell’s Get-Random cmdlet. Using it you can generate a random value. For example:

Get-Random

Will output a value such as:

64031951

But did you know there’s other features of Get-Random?

Numeric Ranges

With Get-Random you can lock down the return result to a specific range. You can specify a minimum value as well as a maximum.

Get-Random -Minimum 100 -Maximum 200

122

You can run it numerous times and the return value will always be between 100 and 200.

You don’t have to use both the minimum and maximum values, you can just use one or the other.

While be default it returns an unsigned 32 bit integer, you can also use it to return a random floating point value.

Get-Random -Minimum 10.5 -Maximum 20.9

11.9004625960255

Get-Random and Arrays

You can also use Get-Random with Arrays. Let’s say you have an array of integer values. You can pipe it through Get-Random and it will pick one value from the array for you.

$array = 1, 3, 5, 7, 9
$array | Get-Random

7

The cool thing about this is it works with any array. Let’s say you have an array of states, and want to pick a state at random.

$array = (
  'Alabama', 'Alaska', 'Arizona',
  'Arkansas', 'California', 'Colorado',
  'Connecticut', 'Delaware', 'Florida',
  'Georgia', 'Hawaii', 'Idaho',
  'Illinois', 'Indiana', 'Iowa'
)
$array | Get-Random

Florida

This also works with arrays that hold a collection of objects. Let’s get a collection of file objects from our C:\Temp folder and let it pick one for us.

$files = Get-ChildItem -Path "C:\Temp"
$files | Get-Random

    Directory: C:\Temp

Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
d----           1/14/2021  2:31 PM                curl-7.74.0

Getting More Than One Random Item

Get-Random also has a -Count parameter which you can use to get multiple values back. Let’s use our state example, and let it return five states.

$array = (
  'Alabama', 'Alaska', 'Arizona',
  'Arkansas', 'California', 'Colorado',
  'Connecticut', 'Delaware', 'Florida',
  'Georgia', 'Hawaii', 'Idaho',
  'Illinois', 'Indiana', 'Iowa'
)
$array | Get-Random -Count 5

Idaho
Alaska
California
Delaware
Colorado

This works with any type of array, or just random integers.

Get-Random -Count 3

1981714362
1664558041
1474367023

SetSeed

Get-Random has one more parameter, -SetSeed. You can pass in a value, and when you do Get-Random will always return the same result for that seed.

Get-Random -SetSeed 100

1881691673

No matter how many times you run Get-Random, as long as you use the same seed value, it will always return a result of 1881691673. This also works with other types of arrays such as the array of states we used earlier.

$array = (
  'Alabama', 'Alaska', 'Arizona',
  'Arkansas', 'California', 'Colorado',
  'Connecticut', 'Delaware', 'Florida',
  'Georgia', 'Hawaii', 'Idaho',
  'Illinois', 'Indiana', 'Iowa'
)
$array | Get-Random -SetSeed 33

Illinois

Again, run this as much as you want and with the same SetSeed value it will always return the same state, in this case Illinois.

So why use SetSeed? One main use it testing. You want to create a set of reusable tests, for example using Pester, and want to validate you always get the same value back from your array.

Conclusion

In this post we saw how to use Get-Random for a variety of purposes. Hopefully you’ll find it as useful as I do!

I have many PowerShell related courses on Pluralsight. All of my courses are linked on my About Me page.

If you don’t have a Pluralsight subscription, just go to https://pluralsight.com. At the top is a Try For Free button you can use to get a free 10 day subscription to Pluralsight, with which you can watch my courses, or any other course on the site. Once there just search for my name, Robert Cain, to see all the courses I have.

Exclude A File From Git Source Code Control in VSCode

Like many developers, I use VSCode for my projects. Primarily PowerShell, but also other things like the PHP code used for my ham radio club website or markdown projects.

It can be useful to have extra files, that I don’t need or want to have saved in Git. One example, I often have a “scratchpad.ps1” file. It’s a place I can prototype code, test out ideas, before I copy them into my main project. If this file gets lost, or damaged, I don’t really care as it’s just temporary.

Another example stems from my need to demonstrate code on video, for my Pluralsight courses, or live at SQL Saturdays and code camps. I often need to login to a website or database, and don’t want to have my credentials hard coded in my script for everyone to see.

To solve this, I simply place my needed information in a text file, then use Get-Content (with the -Raw switch) to read it into a variable. I don’t want this text file though to be placed in my public github repositories.

Excluding a file is simple. In the root folder of your source controlled project is a folder named .git. (Note the period on the front, also note that on some operating systems it may be hidden by default.) Under it is another folder called info.

In .git/info is a file called exclude (with no extension). To it, simply add the names of the files you want to exclude from source control. Here’s an example:

# git ls-files --others --exclude-from=.git/info/exclude
# Lines that start with '#' are comments.
# For a project mostly in C, the following would be a good set of
# exclude patterns (uncomment them if you want to use them):
# *.[oa]
# *~
uid.txt

The lines that begin with a pound sign (#) are comments, and are included by git.

Under it is the file I added, uid.txt. This file is will now be excluded from any git commits, and will not be uploaded to github or whatever tool you use for git. You can see this in the VSCode file tree, the file will appear in an off color font. In a dark mode theme, this will be a gray.

The arrow points to the uid.txt file that was excluded from the project.

That’s all there is to it. Now you can include extra files, such as scratch pads, notes, or even passwords that you don’t need (or want) to have as part of your git repository. Just keep in mind it’s your responsibility to back these files up.

Suppress Write-Verbose When Calling A function in PowerShell

In a project for one of my recent Pluralsight courses, “Everyday PowerShell for Developers on Linux, macOS, and Windows“, I had created some functions in my DataFabricator module. Some of these called many child functions.

I wanted to be able to call the parent function using Verbose in order to track progress. As you may be aware though, when you call a parent function using Verbose, it carries down to all of the functions it calls. This caused a large volume of verbose messages making it difficult to find the information I wanted. Hence I needed to suppress verbose in the called functions.

Let’s see how. First let’s create two simple functions that don’t suppress verbose messages.

function Parent1()
{
  [CmdletBinding()]
  param()

  Write-Verbose "Verbose: Parent1"
  Write-Host "Parent1"
  Child1
}

function Child1()
{
  [CmdletBinding()]
  param()

  Write-Verbose "Verbose: Child1"
  Write-Host "Child1"
}

When we call the parent function with the verbose switch, we get the expected output.

Parent1 -Verbose

VERBOSE: Verbose: Parent1
Parent1
VERBOSE: Verbose: Child1
Child1

Now let’s create an alternate version of the parent function. To suppress verbose on a called child function, all that is needed is to add the verbose switch, but followed by a colon and a $false.

function Parent2()
{
  [CmdletBinding()]
  param()

  Write-Verbose "Verbose: Parent2"
  Write-Host "Parent2"
  Child1 -Verbose:$false
}

Here is the output when we call the new Parent2.

Parent2 -Verbose

VERBOSE: Verbose: Parent2
Parent2
Child1

As you can see, the verbose statements in the Child1 function do not trigger. All that was needed was to add “-Verbose:$false” as a switch when calling Child2.

And that’s all there is to it, using this simple technique you can suppress verbose messages when calling a child function, whether verbose was used to call the parent or not.

Fixing the Failed To Acquire Token Error When Logging Into Azure from PowerShell

When I haven’t used Azure from PowerShell in some time, I’ll get an error “failed to acquire token” when using cmdlets such as Get-AzSubscription or Get-AzContext.

To add to the confusion, sometimes Connect-AzAccount appears to work and log me in, but I’ll still get the error.

Under the hood, the Azure cmdlets are caching some connection tokens. Fixing this issue is pretty simple, although not intuitive or easy to find the solution. All you have to do is issue the following cmdlet:

Clear-AzContext

This will remove old tokens from your system.

After issuing the clear command, just end your current PowerShell session, then login again using Connect-AzAccount and you should be good to go.

Iterate Over A Hashtable in PowerShell

Iterating over an array in PowerShell using a foreach loop is pretty simple. You might think you can do the same thing with a hash table using the same syntax, but if you do you’ll get nothing back.

It is possible to loop over a hash table though, using one of two methods.

First, let’s create a simple hashtable.

$hash = @{
'About Arcane Code' = 'http://arcanecode.me'
'ArcaneCode Blog' = 'https://arcanecode.com'
'ArcaneCode RedGate Articles' = 'http://arcanecode.red'
'ArcaneCode Github Repository' = 'http://arcanerepo.com'
}

In the first method, the one that I prefer, you can use the GetEnumerator method of the hash table object.

foreach ($h in $hash.GetEnumerator() )
{
  Write-Host "$($h.Name) : $($h.Value)"
}

Within the loop, you can use the Name property to get the key part of the hash, and the Value property to retrieve the value. Here is the output:

ArcaneCode Blog : https://arcanecode.com 
ArcaneCode Github Repository : http://arcanerepo.com 
About Arcane Code : http://arcanecode.me 
ArcaneCode RedGate Articles : http://arcanecode.red

In the second method, instead of iterating over the hash table itself, we loop over the Keys of the hash table.

foreach ($h in $hash.Keys) 
{
  Write-Host "$h: $($hash.Item($h))"
}

For each key, we retrieve it’s value from the hash table using the key to indicate the item we want. We could have shortened this slightly, but skipping the Item and just referencing the value by the key, using this syntax:

foreach ($h in $hash.Keys) 
{
  Write-Host "$h: $($hash.$h)"
}

Both of these methods produce the same output as our original version.

ArcaneCode Blog : https://arcanecode.com 
ArcaneCode Github Repository : http://arcanerepo.com 
About Arcane Code : http://arcanecode.me 
ArcaneCode RedGate Articles : http://arcanecode.red

There you go, two simple ways in which you can iterate over a hash table in PowerShell. As I indicated, I prefer GetEnumerator because I have access to both the key and the value in a single variable within my loop. But feel free to use the method that works best for your situation.

Two New PowerShell Courses for Developers on Pluralsight

I’m proud to announce I have not one but two, yes TWO new PowerShell courses available on Pluralsight, targeted for developers. These two courses are designed to work in harmony, to show developers how they can leverage PowerShell to automate and assist in their daily work.

The first is “PowerShell 7 Quick Start for Developers on Linux, macOS, and Windows”. It leverages your knowledge as a developer to bring you up to speed on the PowerShell language. It doesn’t waste time explaining concepts you already know, like variables and loops. It simply shows you how to do things in PowerShell.

The second course is “Everyday PowerShell for Developers on Linux, macOS, and Windows”. It begins showing how to combine PowerShell with Docker to create a PHP container and test a simple website. It then proceeds to create an Azure SQL database and load data in it.

In the second you are taught how to code your own classes and modules by creating a simple module that leverages a USPS website API to lookup a zip code and return the city and state it belongs to.

In the final part of the course you are shown how to use the new DataFabricator module to generate realistic looking, but fake data for use in testing your applications.

While originally developed with PowerShell 7.0.3, all code in the course was tested and videoed using PowerShell 7.1.0.

Additionally, the code was tested on a variety of platforms, including Ubuntu 20.04, 20.10, Windows 10, H1 and H2, macOS Catalina and even macOS Big Sur.

If you don’t have a Pluralsight subscription, just go to the Pluralsight page and click the Try for Free link to get a free 10 day trial.

VSCode User Snippets for PowerShell and MarkDown

I’ve been working a lot on a new course for Pluralsight, Everyday PowerShell 7 for Developers. I’ve been cranking out a lot of code as a result, PowerShell, obviously, as well as Markdown for documentation.

I’m finding the use of VSCode’s User Snippets to be extremely useful for developing this course. Snippets have allowed me to store my most often used code as templates, quickly manifesting new sections of code.

In PowerShell I’m finding these especially useful for writing Pester tests. Most tests fall into a few simple patterns, using a snippet I can quickly create the bulk of my test, leaving me to fill in the few remaining pieces.

If you know Markdown, you know some of the syntax can be a bit arcane. Using snippets makes it easy to insert commonly used ones, such as being able to type in a snippet name of mdlink and get the correct syntax to appear for a hyperlink.

It also helps with consistency. A small example, for doing italics in Markdown, you can use a singe underscore or a single asterisk. For bold, two underscores or asterisks.

I decided (for no particular reason) to use underscores for italics and asterisks for bold. If it’s been a while since I wrote Markdown though, I may not always remember. So I setup mditalic and mdbold to insert the correct formatting for me.

I’ve placed my snippets in a repository on my github site:

https://github.com/arcanecode/VSCode_User_Snippets

If you aren’t familiar with how to use User Snippets, I have a quick overview in a Markdown file in the repository.

Speaking of Markdown, there is one issue with VSCode. By default, intellisense is not enabled in VSCode for Markdown. While snippets can be used without intellisense, it’s much easier to use them with intellisense turned on.

In the repository I have a Markdown  file with information on how to turn intellisense on in VSCode for Markdown files.

Be aware there are also user snippets available through the Extensions Marketplace in VSCode. Just go into the Extensions, and enter Snippet into the search bar.  I just didn’t happen to find any that quite suited my needs, hence I created my own.

You’re welcome to copy and use the user snippets, just some or all of them, as you need. Do be aware some of them have my name and websites, such as the author info snippet I use for the bottom of all my Markdown files, or the header snippet for the top of my PowerShell files.

I hope you find user snippets as helpful as I do.

Getting Started with PowerShell Core on Linux and macOS

My newest course, Getting Started with PowerShell Core on Linux and macOS, is now live on Pluralsight! This course is my eighteenth in a long line of Pluralsight courses.

I begin the course explaining the difference between PowerShell for Windows (version 5.1) and the all-new PowerShell Core (version 6.2 was used for this course), which works not only on Windows but on Linux and macOS as well. I then show how to install PowerShell Core, along with a few other key components such as Visual Studio Code, on both Linux and macOS.

Not familiar with PowerShell? No problem! I quickly cover the basics of PowerShell including cmdlets, the use of the pipeline, how to write functions, and how to put those functions in reusable scripts.

As if that weren’t enough, I show how to do some “cool things” with PowerShell Core, including working with Docker containers, SQL Server, and Azure.

For the course, I primarily used Ubuntu 19.04 and macOS Mojave. The code was also tested on Ubuntu 18.04 LTS and 18.10, as well as macOS High Sierra. In addition, I tested the Linux installs on a variety of distributions including CentOS, Manjaro, and more. The samples include markdown files with information on how to install on these other distributions.

All of the samples are included in the downloadable components of the course on Pluralsight. New with this course I have the samples also available on my GitHub site. As I move into the future the GitHub codebase will be updated with new samples and information.

Also included in the samples are several markdown files that have additional information not included in the course, such as setting VSCode on Windows to use PowerShell Core instead of Windows PowerShell 5.1 as the default terminal.

While you are up on my GitHub site be sure to check out the full list of repositories, I have a lot of examples on it, including some from previous courses such as my recent Reporting Services course. (For a full list of my courses just check out the About ArcaneCode page on this site.)

Note the sample file on Pluralsight will remain static, so if someone watches the course their samples will reflect what is in the course. For the latest updated samples see the GitHub site referenced above.

What? You don’t have a Pluralsight subscription yet? Well, no worries dear reader, just email me, free @ arcanetc.com and I can send you a code good for 30 days with which you can watch all 18 of my courses, plus anyone else’s course at Pluralsight.

Downloading Files with PowerShell and Invoke-WebRequest

Last weekend I was at the Atlanta Code Camp, giving a presentation on PowerShell for Developers. One of the attendees emailed me, asking for a good example of being able to download multiple files from a website.

To do so, we’ll use the Invoke-WebRequest cmdlet. But first, we’ll setup a directory to hold our output. For all my demos I have a root folder, C:\PowerShell. For this article I’ve created a subfolder called Invoke-WebRequest-Demo. The first thing my code does is sets a variable to point to this folder, then changes the current location to it.

$dir = 'C:\PowerShell\Invoke-WebRequest-Demo'
Set-Location $dir

Next, we’ll need a variable to point to the root URL of the website we wish to download from. This will be everything except for the actual file name.  For this demo I will use files from the No Agenda Show podcast. Not only is it a cool podcast, but they have an unrestricted license for their material meaning I can freely reuse it for demo purposes. Each episode of the podcast has it’s own image, so we’ll download images from a few recent episodes.

After I place the base URL into a variable, I create an array, each item in the array having the name of a file to download.

$baseUrl = 'http://adam.curry.com/enc/'
$files = '1537127586.656_na-1069-art-feed.png',
          '1536868338.385_na-1068-art-feed.png',
          '1536264075.484_na-1066-art-feed.png'

Now that everything is setup, we use a simple foreach loop to iterate over the array and download each file via Invoke-WebRequest.

foreach ($file in $files)
{
   Write-Host "Downloading $file"
   $dlUrl = "$($baseUrl)$file"
   $dlPath = "$($dir)$file"
   Invoke-WebRequest $dlUrl -OutFile $dlPath
}

And that’s all there is to it. If you want to learn more about downloading files via the web, this code was extracted from my Testing PowerShell with Pester course on Pluralsight. In it I test a module which gets the RSS feed, then downloads images and audio files for the No Agenda show. Just go to the About Me link at the top and you’ll find a complete list of all my Pluralsight courses.

Speaking of Pester, you might also appreciate the introduction to Pester series of articles I’m currently authoring for Red Gate’s Simple Talk website. You can find a link via the same About Me page, or just jump directly there by going to http://arcanecode.red to see my articles.

Get Notified When Your Home Router IP Address Changes–With PowerShell!

Readers of my blog over may recall I’m an amateur (ham) radio operator (N4IXT that’s me!). One of my ham radio buddies has a cool radio that can be remotely controlled over the internet. With their software he just enters the IP address of his home (his home router that is, after we setup some port forwarding), and he can connect to and operate his radio remotely, make contacts around the world and more.

The tricky part of all this came in the sentence enters the IP address of his home…. His home router tends to change its address on the whim of his service provider. If the router reboots, it will definitely have a new address when it comes up. You may be thinking “well just get a static IP address”. Unfortunately, his internet service provider can’t give him this, something about him using a bonded pair of 10 mb lines to get 20 mb prevents it.

So how could he get notified when his IP address changes? Well I was fairly certain I could solve his problem with some simple PowerShell scripting!

I’ve now published the solution on my GitHub site:

https://github.com/arcanecode/PowerShell/tree/master/IPAddressMailer

Rather than going more in-depth here, the ReadMe has the full details describing the scripts that were created. In addition the code is heavily commented.

In addition to solving this particular problem, the code could be used as a template for:

  • Getting the IP Address of your home router
  • Sending emails via GMail
  • Setting up tasks in the Windows Task Scheduler

Hopefully other people with similar issues will find this little project as useful as my ham radio buddy has!

Azure PowerShell PlaybooK: Azure SQL–Now on Pluralsight!

My latest course is now available on Pluralsight! It’s the Azure PowerShell Playbook: Azure SQL. If you aren’t familiar with Pluralsight’s Playbook format, they are fast past courses that are almost 100% demo driven. They are meant to be consumed quickly, my course is just one hour and four minutes long. Great lunchtime viewing!

This course shows you how to use PowerShell to manage and migrate your on premises database up to Azure SQL. In brief, you’ll learn how to:

  • Create resource groups
  • Create and work with Storage Accounts
  • Create a SQL Server in Azure SQL
  • Package up your local database into a bacpac file
  • Import your bacpac file into a new Azure SQL database
  • Execute commands against your new Azure SQL database
  • Cleanup! I even show how to remove everything you’ve created, individually or as a whole

And all of this with PowerShell!

Additionally, I’ve included functions for just about everything listed, so (assuming your subscription gives you access to the samples) you’ll have a great starting point for your own library of cmdlets. (All the code for the functions appears on screen, so if you have to you could always pause and type it in.)

You can find my new course at:

https://www.pluralsight.com/courses/azure-powershell-sql-playbook

I also wrote an article for RedGate’s SimpleTalk website that aligns well with this course. I dive deeper into the restartability aspect of the way the functions were coded, something I couldn’t get deep into with the video course due to time constraints.

https://www.red-gate.com/simple-talk/sysadmin/powershell/powershell-functions-reusability-restartability-azure/

What’s that? Yes you in the back row, you say you don’t have a Pluralsight subscription? Well no worries, just email me, free@arcanetc.com and I’ll be glad to send you a code that will be good for 30 days at Pluralsight. During that time you can watch my courses, indeed you can watch any course at Pluralsight.