Get in touch with us!

17 Powershell tips

We are constantly learning new things and I like to share a couple of things that I’ve learned that i think all sysadmins need to know.

So I have created a list of my first 17 Powershell tips and tricks.

#1 If you are scripting against an external data source like Azure AD och Exchange Online and want to do large batchjobs you need to cut down on the number of requests. Why?
Well, in exo there is a thing called “microdelay” which is an attack-preventions-thingy (goole it), and number two. This commands is time consuming.
My solution is to download all the things you need and then do all the filter stuff in the script.

$users = Get-MsolUser -All

#2 These huge scripts feeds on three things time, cpu and ram. To save som time you can user the built in index in your arrays to speed up filters like this.

#Old way
Measure-Command -Expression {
$users.where({$psitem.UserPrincipalName -eq "user1@contoso.net"}) #avg 86 ms
}

#My way!!
Measure-Command -Expression {
$users[$users.UserPrincipalName.IndexOf("user1@contoso.net")] #avg 13 ms
}

#3 This is also a speed tip, don’t use “like” to do binary decisions. It’s slow!!!

Measure-Command -Expression {
$users.where({$psitem.UserPrincipalName -eq "user1@contoso.net"}) #avg 86 ms
}

Measure-Command -Expression {
$users.where({$psitem.UserPrincipalName -like "user1@contoso.net"}) #avg 120 ms
}

#4 People is still using XP and PS 2.0 but if you live in the real world, you probably have WMF 4 or 5.
If you do, use the new cool .net where / foreach loops.

#New cool way
Measure-Command -Expression {
$users.where({$psitem.UserPrincipalName -eq "user1@contoso.net"}) #avg 86 ms
}

#Old boring way
Measure-Command -Expression {
$users | % {$_.UserPrincipalName -eq "user1@contoso.net"} #avg 200 ms
}

#5 Now you know that indexof() is super cool. But it can screw up, big time! If you don’t do error handling.

#if 0 or more than 1 records are found the indexof() returns -1
$index=$users.UserPrincipalName.IndexOf("user1@contoso.ns")
if ($index -eq -1) {throw "Error"}
$users[$index]
#or use ValidateRange
[ValidateRange(0,([int]::MaxValue))]$index=$users.UserPrincipalName.IndexOf("user1@contoso.ns")
#The variable cannot be validated because the value -1 is not a valid value for the index variable.

#6 Use “in” & “notin” to find differentials and matches in arrays. It’s there to help you, use it.

$findLicenses = "ENTERPRISEPACK"

#Find all users where ENTERPRISEPACK is in the licenses property
$HaveE3 = $users.Where({
$findLicenses -in ($PSItem.licenses.accountskuid -split ":")[1]
}).count

#Find all users where ENTERPRISEPACK is not in the licenses property
$HaveNotE3 = $users.Where({
$findLicenses -notin ($PSItem.licenses.accountskuid -split ":")[1]
}).count

#Find all users from 0 to 10 where UPN is in UPN from users 9 to 20
$users[0..10].where({$psitem.UserPrincipalName -in $users[9..20].UserPrincipalName}).count #2
#Find all users from 0 to 10 where UPN is not in UPN from users 9 to 20
$users[0..10].where({$psitem.UserPrincipalName -notin $users[9..20].UserPrincipalName}).count #9

#7 Use regex in “replace”, it’s like dark magic. If you don’t know regex, visit regexr.com it’s the best.

[string[]]$users2 = @(
"john.doe@thisnice.domain.se"
"john.doe@thisnice.domain.dk"
"john.doe@thisnice.domain.net"
"john.doe@internal.thisnice.domain.local"
"j.d@thisnice.net"
)

#Replace the . (dot) to .mig. where it matches in between thisnice and domain
$users2 -replace "(\.)(?=domain)(?<!thisnice)",".mig."

#8 Don’t forget that regex is default in -repace, -match, -split….. escape special charaters \ like . (dot)

#tip 8 dont forget that regex is default, escape special charaters \ like . (dot)
"Test.test2" -replace ".","," #,,,,,,,,,,

"Test.test2" -replace "\.","," #Test,test2

#9 Tab separation character this is super useful, when exporting to tsv-files.

"test,Test3" -replace ",","`t"
"test,Test3" -replace ",",[char]9

#10 int ranges is cool.

0..10

#11 Disable type information in csv export, this crap have hunted me for far to long now.

$users[0..10] | Export-Csv -NoTypeInformation -Path c:\test\test.csv -Delimiter "`t"
#this will remove the \/ bullshit from the csv file.
#TYPE System.String
#Length

#12 Split and join is extremely useful when dealing with external application that uses weird ways to send data. Or things like the old cmd commands 🙂

$splitRegex = "JonJanderIsMyName!!!" -split "(\w{4})" | ? {$_}
$splitRegex -join ","

$ping = Invoke-Expression -Command "cmd /C ping 1.1.1.1 /n 1"
($ping -split ",").Where({$PSItem -like '*Received*'})

#13 Hex values and bitwise operations exist in Powershell, don’t forget that. I love this one.

(0xFF -band 0xF0) -bxor 0xAA

$binaryString = "010111"
$int = [convert]::ToInt32($binaryString,2) #Binary to int
$shiftleft = $int -shl 1 #shift left
[convert]::ToString($shiftleft,2) #Int to binary
#010111
# 101110 <<

#14 Get unique values from arrays.

#Sort the values or the get-Unique will fail.
$users.licenses.accountskuid | sort | Get-Unique

#15 Group-object is super useful when doing things like usage statistics.

$GroupLicense = $users | group -Property {$_.licenses.accountskuid -join ","} #single property
$GroupLicenseCountry = $users | group -Property {$_.licenses.accountskuid -join ","},Country #Multiple properties

#16 One of the first this you learn when doing Powershell is select-object, this is the next level.

#tip 16 Use Select label expression to return calculated parameters
$Group | select Count,@{label="Name";expression={($_.Name -replace "(\w+\:)","")}}
$GroupLicenseCountry | select Count,@{l="Name";e={($_.Name -replace "(\w+\:)","")}}

#Count Name
#----- ----
# 528 ENTERPRISEPACK
# 406
# 40 DESKLESSPACK
# 12 EMS,ENTERPRISEPACK
# 6 INTUNE_A_VL,DESKLESSPACK
#...

#Count Name
#----- ----
# 73 ENTERPRISEPACK, Finland
# 145 , Sweden
# 274 ENTERPRISEPACK, Sweden
# 18 , Norway
# 47 ENTERPRISEPACK, Denmark
#...

#17 Last one is among the latest I’ve learned. I hate myself for not using regions as much as I do today.

#tip 17 use regions
#region Code
function test1 {
1..2
}
function test2 {
Write-Host "foobar"
}
#endregion

“Programming is a creative art form based in logic. Every programmer is different.” – id Software

Submit a Comment

Your email address will not be published. Required fields are marked *

Starkare tillsammans

Bolag inom både publik och offentlig sektor efterfrågar en alltmer kostnadseffektiv, platsoberoende och säker digital arbetsplats. Därför går nu Altitude 365 och Uclarity samman och bildar ett gemensamt specialistbolag.
Fortsätt på Altitude 365Kolla in Uclarity

Altitude 365 + Uclarity – Årets Modern Work Partner!

Vinnaren är ett bra exempel på hur en “Born in the Cloud” ständigt förbättrar sitt erbjudande, arbetar nära och proaktivt med Microsoft för att hjälpa kunderna på deras digitaliseringsresa. Plus att vi på Microsoft verkligen ser fram mot den nya bolags-konstellationen (Altitude 365 + Uclarity) för ett “Starkare Tillsammans”.

Uclarity och Altitude 365 - Starkare tillsammans

Uclarity är specialister på digitala möten, telefoni, kontaktcenter och digitalt arbetssätt. Altitude 365 är specialister på säkerhet, mobilitet och hur bolag kan optimera resan till Microsoft365. Nu gör vi gemensam sak och bildar bolag tillsammans.

– Pandemin har tydliggjort behoven av en modern digital arbetsplats och vi har diskuterat ett samgående med Altitude 365 under en längre tid. Våra kunder har behov av specialistkompetens och tillsammans blir vi en ledande specialist inom Digital Workplace-området, säger Niklas Olsson Hellström, VD Uclarity AB.

Tommy Clark, Partner, Altitude 365, kommenterar:
– Inget bolag köper det andra utan båda bolagen får lika stora delar i det nya bolaget. Vår ledstjärna är att vi blir starkare tillsammans och att vi kan hjälpa våra kunder under hela deras resa.
Målet med sammanslagningen är att kunna hjälpa kunder med både teknik och effektiva arbetssätt.

– Det är då våra kunder får önskad effekt av sin investering i den digitala arbetsplatsen, säger Niklas Olsson Hellström.

Båda bolagen har svenska och internationella kunder från både privat och offentlig sektor. Sammanslagningen resulterar i en organisation på 50+ anställda baserade i Stockholm, Örebro och Göteborg.

För frågor, vänligen kontakta;
Tommy Clarke, Partner, Altitude 365 AB, 0703-593854, tommy.clarke@altitude365.com
Niklas Olsson Hellström, VD, Uclarity AB, 0734-198016, niklas.olsson@uclarity.com

Fortsätt på Altitude 365Kolla in Uclarity