Variables in PowerShell are going to be a bit different than they are for you in most languages.
#easy and best practice way to create most variables $foo = 5 $bar = get-service alg
- Accessing variables requires a pre-pended dollar sign, so instead of “foo” you type “$foo” to grab the value
#This will throw an error trying to run the cmdlet named "foo" foo #this will go get the value in a variable named "foo" $foo
- Variables, like the rest of PowerShell, are case-insensitive. This means $Foo and $foo are the same variable, so you need two unique names for two unique values. Tab complete and intellisense will use whatever capitalization you specify on creation for readability.
- Variables allow numbers in the name, so “$Foo1” is totally fine.
- Variables are weakly typed, so no specifying what will go in them.
#Powershell does not care what you put in your variables $foo = 5 $foo $foo = get-service alg $foo $foo = Get-Process $foo
- Variables utilize the “output stream”, you can learn more about streams in this Hey, Scripting Guy post, but all you really need to know is that your variable will only pick up valid data coming back from a cmdlet and will ignore non-terminating errors (just letting them do their thing). This means you can write error logs, but also keep running your script on the successful results you got.
#This cmdlet returns results on the output stream and errors on the error stream get-process powershell_ise, OUTLOOK, System, FAKE #our variables just see output by default $procs = get-process powershell_ise, OUTLOOK, System, FAKE $procs #we can hide the error eaily, and we can touch on that more in a post about error handling $procs = get-process powershell_ise, OUTLOOK, System, FAKE -ErrorAction SilentlyContinue $procs
Objects are going to work how they do most places. Dot notation lets us dig into their properties and methods.
#Accessing the properties and methods $service = get-service alg $service.DisplayName $service.GetType() #you don't need them in variables for quick one-offs (get-service Winmgmt).DependentServices
If you want to see your object’s members, we have several options:
1. Get-Member: you’ll notice the definitions look a lot like you’re used to in C-based languages because we are pulling from .NET, COM, etc.
#for whatever reason they didn't make -inputobject a positional parameter $service = get-service alg Get-Member -InputObject $service #We can utilize the pipe though, and get member has a GM alias. $service | Get-Member get-process powershell_ise | GM
2. Intellisense: in the ISE, when typing a “.” or forcing it with ctrl+space you get wonderful auto-complete like visual studio
3. Quick and dirty trick for properties
#This will force all the properties to come out in a list with their names and values $service | Format-List -Property * get-process powershell_ise | FL * #Nice shortcuts
4. Documentation: PowerShell is built on .NET so that’s where many of the objects come from
Data types come from .NET, COM and other places.
You can always access data types by typing [TYPE]
[System.ServiceProcess.ServiceController] [system.int32] #sometimes friendly names work, expecially with basic types [int] [string]
“Okay, but why does this matter?”
We can do some different tricks with data types.
1. Static members exist on these objects, just like they do in .NET. Unfortunately, trying to find them can be a little frustrating if you’re just diving in:
#notice this returns a System.RuntimeType outline #Its actually showing us the members that exist on objects we use to hold type data (inception-y) [string] | GM #We need to add a switch param to Get-Member to tell it what we really want: [string] | GM -Static
We access these using a “::” instead of a “.”
#math is a really useful place to pull static members from [math]::Round(57575 / 1kb) [math]::Max(5,2)
2. Strong typing: we can override PowerShell’s default weak typing if we want to. This is great for things involving user input, or on our function parameter (which I’ll show off when we talk a bit more about them later). To strongly type, we just pre-pend the data type we want to the variable name on creation.
[int]$foo = 5 $foo #notice PowerShell will add an auto-convertion step before erroring $foo = 5.5 #turning a double into an int is easy $foo $foo = "hello world" #take a look at the error
Cannot convert value "hello world" to type "System.Int32". Error: "Input string was not in a correct format."
3. Type casting: If you just want to force a value to convert to another type, we can do the same thing just: just pre-pend the value with [TYPE]
#its a string $foo = "5" $foo.GetType().Name #its an int $foo = [int]"5" $foo.GetType().Name #user input explicit convertion without strong typing $input = [int](read-host "give me a number:")
4. New-Object can be used to generate anything you know about:
$stack = new-object -TypeName System.Collections.Stack $stack.push(1) $stack.push(2) $stack.push(3) $stack.pop()
5. Comparisons using the –is operator
$service = get-service alg $service -is [system.serviceprocess.servicecontroller]
Well that’s all for now, hopefully this helps you on your PowerShell journey and shows you that there is a lot of convenient data access in the language. I’ll be adding to the series to cover other quirks as well so let me know in the comments if there is any particular topics confusing you!
If you find this helpful don't forget to rate, comment and share 🙂
For the main series post, check back here.