- Console
- vscode
- Variables
- Remoting
- AD
- Networking
- Error Handling
- Credential
- SecureString
- Parameter
- Pester
- Plaster
- Modules
- String
- Here String
- Lists
- Objects
- Hashtable
- Help
- Useful Cmdlets
- Useful Modules
- Statements
- CmdletBinding
- Formatting
- Regular expressions, regex
- Diverse
Changing Tab Completion (shows and lets choose parameter):
Set-PSReadLineKeyHandler -Key Tab -Function MenuComplete
Show help for Parameter
Set-PSReadlineOption -ShowToolTips
Deactivate beep on error:
Set-PSReadlineOption -BellStyle None
Bash style completion:
Set-PSReadlineOption -EditMode Emacs
Don't write certain phrases to history:
Set-PSReadLineOption -AddToHistoryHandler {
param([string]$line)
$sensitive = "password|asplaintext|token|key|secret|credential"
return ($line -notmatch $sensitive)
}
predictive IntelliSense
Set-PSReadLineOption -PredictionSource History
use correct casing:
powershell.codeFormatting.useCorrectCasing
get-item
Get-Item
format on save:
"[powershell]": {
"editor.formatOnSave": true
}
Search console history [CTRL]+[R]:
C:\>bck-i-search: <String>
'#' searcher:
C:\>#<optional String>
+[TAB]
Set dynamic Variablename
$ProcessName = 'explorer'
$PropertyName = 'Id'
Get-Process -Name $ProcessName |
Select-Object -Property $PropertyName |
Set-Variable ('{0}{1}' -f $ProcessName, $PropertyName)
$ExplorerId
Id
--
7936
$Null = Get-Service -OutVariable GetService |
Sort-Object -Property Status -Descending -OutVariable GetServiceByStatus |
Format-Table -AutoSize -OutVariable GetServiceByStatusAutosize
$GetService
$GetServiceByStatus
$GetServiceByStatusAutosize
Enabling with WinRM:
([wmiclass]"\\$ComputerName\root\cimv2:win32_process").Create('powershell Enable-PSRemoting -Force')
Enabling with psexec:
psexec.exe \\computername -h -s powershell.exe Enable-PSRemoting -Force
Get an orphaned computer instantly back on the domain or fixes its account:
Reset-ComputerMachinePassword -Server $Computername
Fixing domain join issues without a reboot:
Test-ComputerSecureChannel -Server $Computername -Repair
Test network connection (ping), result is bool:
Test-Connection -ComputerName $Computername -Count 3 -Quiet
Ping sweep
(((0..255).ForEach( { "192.168.0.$_" }) | ForEach-Object {
(New-Object Net.NetworkInformation.Ping).SendPingAsync($_, 250)
}).Result.Where{ $_.Status -eq 'Success' }).Address.IPAddressToString
Test network connection (TCP Port), result is bool (telnet alternative):
(Test-NetConnection -ComputerName $Computername -Port $TCPPort).TcpTestSucceeded
Create, start and stop TCP Listener:
$Listener = [System.Net.Sockets.TcpListener]$TCPPort
$Listener.Start()
$Listener.Stop()
Get IP network configuration (ipconfig -all alternative):
Get-NetIPConfiguration -All
Change the network category of a connection profile form public to private:
Get-NetConnectionProfile |
Where-Object -Property NetworkCategory -eq 'Public' |
Set-NetConnectionProfile -NetworkCategory Private
Perform a DNS name query resolution:
Resolve-DnsName -Name $Computername
Perform a DNS name query resolution (query type is mail routing):
Resolve-DnsName -Name $Computername -Type MX
foreach ($Item in $ItemColl)
{
try
{
$Item = Get-Item -ErrorAction Stop
}
catch
{
$Item = 'Error'
}
finally
{
Write-Output $Item
}
}
Invoke-RestMethod:
Write-Output "StatusCode:" $_.Exception.Response.StatusCode.value__
Write-Output "StatusDescription:" $_.Exception.Response.StatusDescription
Save credential
Get-Credential | Export-Clixml -Path ('{0}\[email protected]' -f ${env:\userprofile})
Load credential
$Credential = Import-Clixml -Path ('{0}\[email protected]' -f ${env:\userprofile})
Create SecureString, write it to file
ConvertTo-SecureString –String 'F987sdh4dfd3DPiSM4DLGJ-wiWePUJkl77Mo' -AsPlainText -Force |
Export-Clixml -Path ('{0}\[email protected]' -f ${env:\userprofile})
Get String From SecureString
$SecureString = Import-Clixml -Path ('{0}\[email protected]' -f ${env:\userprofile})
$bstr = [Runtime.InteropServices.Marshal]::SecureStringToBSTR($SecureString)
[Runtime.InteropServices.Marshal]::PtrToStringBSTR($bstr)
Get Validators
[psobject].Assembly.GetType('System.Management.Automation.TypeAccelerators')::Get | Sort-Object -Property Value
IP Address
[ValidateScript({$_ -match [IPAddress]$_ })]
MAC Address
[ValidatePattern('(([0-9A-Fa-f]{2}[-:]){5}[0-9A-Fa-f]{2})|(([0-9A-Fa-f]{4}\.){2}[0-9A-Fa-f]{4})')]
Not Null or Empty
[ValidateNotNullOrEmpty()]
Path
[ValidateScript({
if(-Not ($_ | Test-Path) )
{
throw "File or folder does not exist"
}
if(-Not ($_ | Test-Path -PathType Leaf) )
{
throw "The Path argument must be a file. Folder paths are not allowed."
}
return $true
})]
[System.IO.FileInfo]$Path
[string[]]
$MultipleItems = 'apple', 'orange', 'banana'
$PSDefaultParameterValues = @{
'*:Computername' = 'Computer01'
}
Check for Type [array]
,@(1, 4, 5) | Should -HaveType [Array]
Should -HaveType ([Array]) -ActualValue @(1, 4, 5)
Create new Module
Invoke-Plaster -TemplatePath C:\Path\To\PlasterTemplate -DestinationPath C:\Path\To\NewModule -Verbose
Find
Find-Module -Name remote
Find Path
(Get-Module -Name ((Get-Command Get-Process).ModuleName) | Select-Object -Property ).ModuleBase
Publish
Publish-Module -Repository PSRepository -Path C:\Path\To\Module
Get
Get-Module -Name Mappings -ListAvailable
Uninstall
Uninstall-Module -Name ModuleName -Force
Install
Install-Module -Name ModuleName -Repository RepositoryName -Scope AllUsers
Check for outdated Modules:
Get-InstalledModule |
Select-Object Name, @{
n = 'Installed'; e = {$_.Version}
}, @{n = 'Available'; e = {
(Find-Module -Name $_.Name).Version}
} |
Where-Object {$_.Available -gt $_.Installed}
join
-join('aaa', 'bbb')
f operator
'{0}{1}' -f 'aaa', 'bbb'
substring
$FirstTwoChars = ('abcdefg').Substring(0, 2)
Left and right part from delimiter
$Name = 'aaaaaaaaaa;bbbbbbbbb'
$Pos = $Name.IndexOf(';')
$LeftPart = $Name.Substring(0, $Pos)
$RightPart = $Name.Substring($Pos + 1)
(Get-Culture).TextInfo.ToTitleCase("maX MusTerMann")
$HereString = @'
sadsada
asdsadas
dasssd
fsf ff
'@
$HereStringA = @"
asdasd
dgfg
dfg
"@
$HereStringB = @'
asdfsdassdfdfd
ds gfdg
dfgd
'@
$HereStringA, $HereStringB -join "`n"
[datetime]::ParseExact("2020-04-16T14:10:23-05:00","yyyy-MM-ddTHH:mm:ss-05:00",$Null)
@($OneItemColl)
Unlike eg. an array it's not fixed size and you can add and remove items from it to your hearts content with several types of Add and Remove methods. Also has methods for sorting and more.
New-Object 'System.Collections.Generic.List[System.Object]'
[System.Collections.Generic.List[System.Object]]::new()
Using New-Object and hashtables
$properties = @{
firstname = 'Peter'
lastname = 'Miller'
}
New-Object psobject -Property $properties
Convert Hashtables to [PSCustomObject]
[pscustomobject]@{
firstname = 'Peter'
lastname = 'Miller'
}
Return | Write-Output |
---|---|
only $Variable | all Outputs |
Avoid, instead use
$Obj1 = foreach ($item in $items)
{
$item
}
$Obj2 = 1..10000 | Foreach-Object { $_ }
$Obj3 = foreach($element in (1..10000)) { $element }
Use if first collect subroutine
$Obj = @()
foreach ($item in $items)
{
$Obj += $item
}
Write-Output $Obj
Add
$Coll = Get-Coll |
Add-Member -MemberType NoteProperty -Name $PropertyName -Value $PropertyValue -PassThru
Rename (Avoid Alias)
Get-ADComputer -Filter | Select-Object -Property @{name = 'Computername'; expression = {$_.name}}
Order by multiple
Get-Service | Sort-Object -Property @{
Expression = "Status"; Descending = $True
}, @{
Expression = "DisplayName"; Descending = $False
}
Calculated
Get-ChildItem -Path $Path -Filter '.txt' |
Sort-Object -Property @{
Expression = {$_.LastWriteTime - $_.CreationTime}; Ascending = $False
} |
Format-Table LastWriteTime, CreationTime
where method:
(Get-Service).where{$_.Status -eq 'running'}
foreach method:
(Get-Service).foreach{$_.DisplayName}
$OrderedHashTable = [ordered]@{
a = 1
b = 2
c = 3
d = 4
}
$HashTable = @{}
Get-ChildItem -Path $env:windir -Filter .exe | ForEach-Object {
$HashTable.Add($_.Name.ToString() , $_.Length.ToString())
}
$HashTable
$peopleArray = @(
@{
name = 'Kevin'
age = 37
city = 'Irvine'
}
@{
name = 'Alex'
age = 9
city = 'Irvine'
}
)
$peopleArray | ConvertTo-Json
Proxy functions with PSBoundParameters:
function Get-ProxyWMIObject
{
[cmdletbinding()]
param(
$Class,
$ComputerName
)
Get-WmiObject @PSBoundParameters
}
Get-ProxyWMIObject -Class WIN32_BIOS
Get-Help -ShowWindow -Name Get-Process
Get-Help -Name Get-Process -Detailed
Get-Help -Name Get-Process -Examples
(Get-Help -Name remote).where{$_.Category -eq 'Function'}
Turns a collection of data into a hashtable of that data that you can index into. This will add each row into a hashtable and use the specified property as the key to access it.
$Employee = @"
LastName,FirstName,Location
Schmidt,Hans,Leipzig
Schmidt,Thomas,Berlin
Mueller,Thomas,Leipzig
Mueller,Klaus,Berlin
Meier,Hans,Leipzig
"@ | ConvertFrom-Csv | Group-Object -AsHashtable -Property LastName
$Employee.Mueller
LastName FirstName Location
-------- --------- --------
Mueller Thomas Leipzig
Mueller Klaus Berlin
Provides a graphical interface to let you explore and navigate an object.
Get-Process | Show-Object
quick replacement for Out-Gridview, Excel has to be installed
Get-Process | Export-Excel -Now -WarningAction SilentlyContinue
#Requires -Version N[.n] #Requires -PSEdition [ Core | Desktop ] #Requires –PSSnapin PSSnapin-Name [-Version N[.n]] #Requires -Modules { Module-Name | Hashtable } #Requires –ShellId ShellId #Requires -RunAsAdministrator
advanced function
[CmdletBinding(DefaultParameterSetName = 'Set1', SupportsShouldProcess = $true, ConfirmImpact = 'Medium')]
WhatIf, Confirm Support
if ($PSCmdlet.ShouldProcess('ID: {0}' -f $ID))
{
Remove-Something -ID $ID
}
Whenever the ConfirmImpact is equal or higher than the $ConfirmPreference (Default 'High'), a confirmation is required.
Line too long
Get-WmiObject -Class 'Win32_LogicalDisk' -Filter 'DriveType=3' -Computername 'localhost'
Backticks
hard to read trailing spaces break code
Get-WmiObject -Class 'Win32_LogicalDisk' `
-Filter 'DriveType=3' `
-ComputerName 'localhost'
Splatting
$GetWmiObjectParams = @{
Class = 'Win32_LogicalDisk'
Filter = 'DriveType=3'
Computername = 'localhost'
}
Get-WmiObject @GetWmiObjectParams
Other
line break after almost any comma, pipe character, or semicolon
Powershell: The many ways to use regex
$Text = '192.168.0.1 computer01.domain.com 001122334455'
$Pattern = '^(?<IPv4>\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})\s+(?<Computername>(\w|\d|\.)+)\s+(?<MAC>\d{12})'
if ($Text -match $Pattern)
{
$matches
}
Part of an OU
$Text = 'cn=JSmith,ou=Management,ou=users,ou=London,dc=company,dc=com'
$Pattern = '^.+ou=(?<Location>(\w|\d|\s)+)(?!.+ou){1}'
$Location = ([regex]::match($Text, $Pattern).captures.groups).Where{$_.Name -eq 'Location'}.Value
Filename and Path
$Text = 'C:\Temp\Subdir01\Test.txt'
$Pattern = '(?<Path>.+)\\(?<Filename>(?:.(?!\\))+$)'
$Filename = ([regex]::match($Text, $Pattern).captures.groups).Where{$_.Name -eq 'Filename'}.Value
$Path = ([regex]::match($Text, $Pattern).captures.groups).Where{$_.Name -eq 'Path'}.Value
create object
$TextColl = '192.168.0.1 computer01.domain.com 001122334455', '192.168.0.2 computer02.domain.com 001122334466'
$Pattern = '^(?<IPv4>\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})\s+(?<Computername>(\w|\d|\.)+)\s+(?<MAC>\d{12})'
$Result = foreach ($Text in $TextColl)
{
if ($Text -match $Pattern)
{
New-Object -TypeName PsObject -Property $matches
}
}
$Result
between quotation marks
$Pattern = '\"(?<BetweenQuotationMarks>.)\"'
abc until first space
$Pattern = '(?<ABCUntilFirstpace>abc[^\s])'
get methods
[regex]::new($pattern) | Get-Member
match string
[regex]::match($string,"^(\w{3})(\w{2,3})-.$")
[System.IO.File]::WriteAllLines($FilePath, (Get-Content -Path $FilePath))
(Get-Content -Path $FilePath) -replace '\xEF\xBB\xBF', '' |
Set-Content -Path $FilePath
Get-ChildItem | ConvertTo-Csv -NoTypeInformation |
ForEach-Object { $_.Replace('"', '') } | Out-File output.csv
if ($Property.Value -is [System.DBNull])
{
$Value = $Null
}
ISO 8601:
(Get-Date).ToString('s')
2018-09-14T13:08:14
ISO 8601 + UTC offset:
(Get-Date).ToString('o')
2018-09-14T13:19:38.7241894+02:00
FileDate(Time):
Get-Date -Format FileDateTime
20200111T1721060231
Get-Date -Format FileDate
20200111
Disable-WindowsOptionalFeature -Online –FeatureName MicrosoftWindowsPowerShellV2Root –norestart
Get-Command | Out-GridView -PassThru | Get-Help -ShowWindow
Show-command $(Get-Command | Out-GridView -PassThru).Name
(New-Object -ComObject 'Microsoft.Update.AutoUpdate').DetectNow()
Generates an 8-char PW including 3 special characters
[system.web.security.membership]::GeneratePassword(8,3)
=^l.dN!h
$($executionContext.SessionState.Path.CurrentLocation)
Path
----
C:\GitHub
[System.Security.Principal.WindowsPrincipal]::new([System.Security.Principal.WindowsIdentity]::GetCurrent() ).IsInRole("Administrators")
false
$BeginWith = [WildcardPattern]::Escape('Mich')
'Michael', 'Michelle', 'Jonathan' -like "$BeginWith"
Michael
Michelle
$itemColl = Get-ChildItem -Path ('{0}' -f [IO.Path]::GetTempPath()) -File
$step = 10
$i = 0
foreach ($item in $itemColl)
{
If ($i%$step -eq 0)
{
Write-Host ('[{0}/{1}]' -f $i, ($itemColl).Count)
$item | Do-Something
}
$i++
}
[10/96]
[20/96]
[30/96]
[40/96]
[50/96]
[60/96]
[70/96]
[80/96]
[90/96]
(Get-Command Get-UMSDevice).ScriptBlock.Ast.Body.paramblock.Parameters |
Select-Object -Property Name, DefaultValue
Name DefaultValue
---- ------------
$Computername
$TCPPort 8443
$ApiVersion 3
$SecurityProtocol 'Tls12'
$WebSession
$Filter 'short'
$Id
as opposed to GUI
Set-ItemProperty "HKLM:\SOFTWARE\Microsoft\PowerShell\1\ShellIds" ConsolePrompting True
https://acme.com/Shared Documents/
[System.Web.HttpUtility]::UrlEncode('https://acme.com/Shared Documents/')
https%3a%2f%2facme.com%2fShared+Documents%2f
[System.Web.HttpUtility]::UrlDecode('https%3a%2f%2facme.com%2fShared+Documents%2f')
https://acme.com/Shared Documents/