Powershell for n00bz

Preface

inb4…

Yeah, yeah. Laugh it up. But the harsh truth is as much as we can all preach for Linux goodness, Windows isn’t going away any time soon. So we need to make the best of it.

Some time ago, I made the thread Powershell - Useful Commands just to share some of the things I was doing with Powershell. I often come across lots of cool things that people are creating with Powershell, but I haven’t found a whole lot of good starter guides. I’m hoping this post isn’t insulting to experienced programmers and command line gurus, but not lost to novices.

Most of the material so far is fairly generic, these concepts will work in Powershell Core across supported platforms… However not all of the commands will be available or behave exactly the same depending on your system.


Table o’ Contents

  1. Outside Resources
  2. Before starting
  3. Commands to get started
  4. Script Blocks
  5. Command output
  6. Variables
  7. Manipulating Command Output
  8. Conditions and Comparisons
  9. Splatting, Arrays, and Creating Objects

Outside Resources

TL;DR… I wanna watch videos!

Documentation


Before actually getting started

There are a few things to keep in mind when using WIndows in general. A lot of the general wonky-ness that comes with using Windows through the GUI often applies just the same as in Powershell.

  1. User Permissions - “Run as Administrator” and actually logging in with an Admin account are NOT always the same. Depending on the task at hand, there is added complexity while using Powershell for tasks that require escalated privileges.

  2. Version numbers matter (a LOT) - Like any Microsoft Product, it doesn’t matter whether it’s the version of Windows, .NET, or Powershell. The version you’re running makes a difference. Not all commands support the same arguments or use context, just because the command you’re running throws an error on one system doesn’t mean it will throw the same error on another running a different version.


Learn by doing …there’s nothing more insulting than a “Hello World” project.

The vernacular:

For the most part, Powershell commands follow a naming convention that is referred to as Verb-Noun. This is useful to keep in mind because the verbs that are used throughout different commands are typically a constant. Get, Remove, Start, Stop are fairly common for command names.

What commands are available on my system?

Get-Command will spit out a huge list of ALL of the different commands that are currently available for you to run… And there’s going to be a lot of them. Fortunately, this can be narrowed down though a basic filter and/or argument.

A great argument add is -Noun. This filter the output based on the second word of a command. Get-Command -Noun Help will output any commands where the noun is “Help”.

What about getting commands with a specific verb? This requires use of wildcards. Get-Command Get* will output any commands that begin with “Get”.

Additionally, any executable files available on a system can be run. For Windows, this is any .exe; for Linux (running Powershell Core) this can be anything from the /bin/ directory to a custom shell script.

Can I get some help here?

Some commands can be more straightforward than others, either way it’s not a great idea to blindly run commands. That’s where the Get-Help comes in. This command will show details and arguments for a given command.

Get-Help Get-Command is all it takes. Though the arguments lists can sometimes be a little vague. Which is what the -Examples argument is for. Get-Help Get-Command -Examples will show some examples for proper use of the command and its arguments.

Typically, the help pages will update automatically. But there is a chance this will need to be done manually from time to time. While there usually aren’t many changes for help pages, running Update-Help every now and then wouldn’t hurt.


Making sense of a command’s output

Unlike DOS or BASH, most Powershell commands’ output are in the form of objects. Notice how with Test-Connection each part of the output has a label and shown in a consistent table.

Each row in this table is an object, and each column is data (aka data member) in that object. Data members that are displayed can be changed by piping the output through Select-Object

To find what data that is available in an object, simply use the * wildcard. Keep in mind if the command you’re running will yield more than one object, it will show all of the data for each object without any apparent separation.


Variables

In Powershell, variables can be declared and defined as strictly or loosely as you could want; this leaves us free to create variables without defining them as strings, integers, ect… which is especially useful for creating variables that receive their data from a command.

A variable in Powershell is notated with a $ followed by its name, $PROFILE and $HOME are both examples of variables; these among others are also some of the predefined variables that are created when opening a new Powershell session (window).

Generic Variables

A new variable can be created by setting it = to a given set of data or a command. $numbers = 1234 and $folder = Get-Location will create new variables named “numbers” and “folder” respectively. To check the contents of existing variables, use the Get-Variable command or put the variable through the echo command.

Alternatively, a variable can be created using the New-Variable command. This method opens more options to be set when creating a variable, including using variables to create variables.

Keep in mind, a variable will store the OUTPUT of a command; not execute the command when the variable is used. For example:

image

Variables with Data Types

While Powershell is usually smart enough to manage these on its own, there are some instances where they need to be declared manually.

This technet page has a list of possible types that can be declared. Generally, a type would need to be declared when the stored data will be used in a comparison.

image

Both with and without the declaration of the variable’s type, most use cases will treat it the same. Generally there is no need to declare the type, and in some cases may cause problems. But when the behavior of a command or script is not what was expected declaring a type may solve the issue.


Script Blocks

While this is an over-simplified way of putting it, any commands or expressions inside { } are executed in a block. The best way to learn about these is to look at the examples in the next to sections.

Commands in succession behave the same way they do in the rest of Powershell. A new command can be defined by adding a new line or adding a ; before the next command.


Output Manipulation

There are a multitude of ways to go about making the output of a command or data in a variable useful for whatever it may be needed for. For this section I wrote a small function (command) to have some simple data to work with.

Here is a copy of it…
function Show-Example {$num = 0;while ($num -le 5) { $prop = [ordered]@{ ‘Id’ = $num; ‘Double’ = $num*2; ‘Triple’ = $num*3}; New-Object -TypeName psobject -Property $prop; $num++}}

If you’re inclined to try some of this out with the example data, just run the command above.

image

Getting a Single Data Member

Each object here has 3 data members in it. Before this can be used as a data source for other commands, this output will need to be narrowed down. The way this can be done is with the dot operator followed by the name of the member. Just be sure to put the original command in parentheses.

image

Now only the data for “Double” is being accessed. This output is perfect for commands that can accept multiple data entries.

image

I’m not sure if it’s convenient or unfortunate that the music client I was using became unresponsive while writing this part, but it was perfect for creating an example. I used Get-Process (a Powershell cmdlet) to get the PID numbers, which was fed to kill (a Linux utility).

Getting a Single Object

What about when a single object is needed/can be used? A single object can be obtained with the [ ] index operator.

image

Keep in mind the first object is always the 0th item… Because computers count from 0.

Getting a Single Object’s Data Member

Additionally, if only a specific data member of a specific object is needed, the dot operator and [ ] operator can be used in conjunction.

image

Usage with Variables

If a variable has a whole set of objects stored in it, the same rules apply, just drop the parentheses.

image

And yes, the inverse works as well.

image

ForEach-Object and Current Object

Making use of and manipulating the data of each object independently is an extremely important component to making output usable for any situation.

ForEach-Object will loop through each object and execute any specified commands for each one. In conjunction with the “current item” variable $_, the data in the current object ForEach is currently observing is specifically available without needing to access it through the index operator.

Out of habit, I use the predefined alias % for ForEach-Object. They do the same thing, but keep in mind it is technically an alias.

image

Where-Object

Whether its to not have to dig through useless nonsense or to get the appropriate output for a script, there are times when the output of a command needs to be narrowed down.

For example we have quite a number of entries in the Get-PSDrive command.

image

By piping this through Where-Object, we can exclude the drives that don’t have usable space.

Where-Object has a predefined alias for ?.

image


If and or… but…

Comparison Operators

Anyone that is familiar with comparison operations in a typical programming language will notice that some of the comparisons that Powershell can do generally don’t behave the same as what they’re use to. Anything beyond comparing numbers is generally trial and error.

Consult the link for this section for a list of the possible comparisons. Operators such as = < > =! do NOT work.

If statements

The simplest way to put this is probably: IF the statement is TRUE, THEN DO whatever. If statements will test a comparison to determine what will be executed next.

Unlike most programming languages, Powershell will test if the data equals true by default.

However the implicit -eq $TRUE is only so useful. Other comparison operators make if statements useful for comparing numbers, strings, and much more.

image

Anything following the if statement will be executed normally, but if there is anything that should be run if the statement is false, this is where an else statement would be needed.


SPL@TING, Arrays, and Creating Objects

Basic Arrays

Most of the time, Powershell will create an array without needing to define it. And in most cases it is completely unnecessary for creating one manually, or the same thing can be achieved with the Get-Content command against a text file with a line break for each item.

For those who are familiar with arrays, these are dynamic arrays, so there is no need to define a size for the array.

An array can be created with @( )
Note that parentheses are used here, splat objects are created very similarly.

image

image

Splatting - Command Parameters

When writing a script, passing many values to different parameters can become cumbersome to manage. This can be made easier by passing a splatted hash table to given commands.

Splats are created using @{ }
Note that curly brackets are used here.

image

Splatting and Creating Objects

In the example above, a splat was created with two objects with properties of “Name” and “Value”. These can be used by New-Object to convert these to properties for an object.

image

However, this becomes most useful when used in conjunction with variables and some sort of loop such as ForEach-Object or while.


{MORE TO COME… Sooner or later…}

If anything is wrong or needs clarification, please DM me or feel free to fix it yourself if your account has access to do so.
25 Likes