Skip to content

Latest commit

 

History

History
266 lines (178 loc) · 9.25 KB

File metadata and controls

266 lines (178 loc) · 9.25 KB

PowerShell

GitHub star list

See here.

Tracing commands

Use trace-command

Trace-Command -expression {"g*","s*" | Get-Alias } -name parameterbinding -pshost
#to see all options for -name above
Get-TraceSource

AND IF YOU FORGOT to run that before starting, use (H/T redog)

Get-Content (Get-PSReadLineOption | select -ExpandProperty HistorySavePath) | out-gridview

Updating Microsoft Store apps

From here:

Get-CimInstance -Namespace "Root\cimv2\mdm\dmmap" -ClassName "MDM_EnterpriseModernAppManagement_AppManagement01" |
Invoke-CimMethod -MethodName UpdateScanMethod

Simple things I forget

Converting to int and string

Examples from here making use of Convert class:

# Convert accepts bases 2, 8, 10, and 16
PS >[Convert]::ToInt32("10011010010", 2)
1234
PS >[Convert]::ToString(1234, 16)
4d2
# or use the formatting operator
PS >"{0:X4}" -f 1234
04D2

pre-sized arrays

from here

PS> [int[]]::new(4)
0
0
0
0
#We can use the multiplying trick to do this too.
PS> $data = @(0) * 4
PS> $data
0
0
0
0

Use Where() to split one collection into two

Where() accepts multiple params.

@(1,2,3).Where({$_ -gt 0}, 'first')
#1
@(1,2,3).Where({$_ -gt 0}, 'first', 2)
#1
#2
@(1,2,3).Where({$_ -gt 10}, 'first')
@(1,2,3).Where({$_ -gt 10}, 'first', 2)
$Running,$Stopped = (Get-Service).Where({$_.Status -eq 'Running'},'Split') 
#use $Running and $Stopped

Here-strings

See here

@"
For help, type "get-help"
"@

Prefer generic List over ArrayList

Comment to prefer $NewList = [System.Collections.Generic.List[PSObject]]::new() over New-Object System.Collections.ArrayList to avoid silencing Add() returning true/false.

Regex

Always going back to the docs

Gotchas

Various items that have bitten me.

Pipelined input to my advanced function isn't processing

Verify your code is in a process block. To quote:

If a function parameter is set to accept pipeline input, and a process block isn't defined, record-by-record processing will fail. In this case, your function will only execute once, regardless of the input.

Using -split with "|"

Be sure to escape the pipe as it's a special character, or substitute Split() instead.

# does not match expectations
PS >"foo|bar" -split "|"

f
o
o
|
b
a
r

# escaping the pipe parses as expected
PS >"foo|bar" -split "\|"
foo
bar

# you can also opt for Split() to ignore special chars
PS >"foo|bar".Split("|")
foo
bar

New in PS v7

Ternary

$IsWindows ? "ok" : "not ok"

Chain operators

1 && 2
1/0 || Write-Warning "What are you trying to do?"

Null-Coalescing Assignment

$foo = $null
$foo ?? "bar"
#Related to this is the Null-Coalescing assignment operator, ??=.
#<left-side> ??= <right-side>
$computername ??= ([system.environment]::MachineName)

Null Conditional Operators

$p = Get-Process -id $pid
${p}?.startTime

ForEach-Object Parallel

Measure-Command {1..1000 | ForEach-Object -parallel {$_*10}}

SSH for remoting

Clean block (v7.3+)

Acts like a finally block, see here.

Nuggets from "The PowerShell Scripting and Toolmaking Book"

Transcripts

Use Start-Transcript and Stop-Transcript to write all actions taken (along with their output) to a file.

Write-Information

From two sections in the book, use this to add tags to its output which can then be filtered.

$r = "thinkp1","srv1","srv3","bovine320" |
Get-Bits -InformationVariable iv -Verbose
#All of the information records generated by Write-Information are stored in $iv.
#These are objects with their own set of properties.

Make Powershell ISE 'aware' of v7

Enter-PSSession -computername $env:COMPUTERNAME -Configuration PowerShell.7
#This hack will open a remoting session to yourself using the PowerShell 7
#endpoint. Now, the scripting panel will be PowerShell 7 “aware”.

Solutions I've needed but came up empty

  • Can I select XML's #text() in a SelectNode()?
  • Can I create a cycled iterator that repeats a list? there's no 'yield' equivalent. I want ('red','green','blue') to cycle forever.
  • Can I iterate with an index like other languages -- for (index, value) in list.something(). There's a language request ticket for $PSIndex that was closed.
  • I need a PS script to run as admin on a fresh Win10 box to keep the system updated. How to configure the script to allow user to click .ps1 file to run, and have it prompt for creds? Adding #Requires -RunAsAdministrator did not work, plus the default PS v5.1 running it failed to parse simple lines correctly, e.g. "& control update" to open the Windows update panel.
  • Running a scheduled PS script without a popup. There are ways to wrap with VBS.

Range operator

See here.

Predictive IntelliSense

Install PSReadLine and you can get a list view of selections based on your history by pressing F2 - details.

Helpful links

Practice and Style Guide

Local book PowerShell Notes for Professionals from here

Powershell cheat sheet

Big Book of Powershell Gotchas

Unit testing vs integration testing

Info on system testing and another

Local cheatsheat from here

Gist cheatsheet

Common Cmdlets with examples

Best Practies

Azure has a module best practices as other bests.

PoshCode has a best practices

MS strongly encouraged development guidelines. Using WriteObject for -PassThru caught my eye.

MS Standard Cmdlet Parameter Names and Types

Unsorted

https://learn-powershell.net/2012/11/09/powershell-and-wpf-textbox/

https://old.reddit.com/r/PowerShell/comments/17lah5l/what_have_you_done_with_powershell_this_month/k7cxp54/

Review one liners

Pull anything of value from here.

Review operators

Read over the full page. The subexpressions were interesting.