PowerShell ściągawka
Moja ściągawka (zapewne tylko do użytku własnego) …
1: Podstawy
2: RegExp
3: Ustawienia
4: Array
5: Pliki
6: Operator @
7: Właściwości mutim. plików
8: Odczyt rejestru Windows
9: Zarządzanie aplikacjami - CLI
# Nie będziesz używał!
0: skondensowana przypominajka bez objaśnień
($x='coś') , "2+3=$(2+3)`n" , @(), ${a b}
Write-Host "`$x: $x" -ForegroundColor Yellow
prawie jak py repr(): $o.ToString() | ConvertTo-Json
1: Podstawy
() - wykonaj teraz, np. ($x='coś') podstaw i wyświetl
$() - wykonaj teraz i potraktuj jak zmienną, np. "2+3=$(2+3)"
@() - potraktuj jako tablicę (także pustą lub 1-el.)
, - literał tablicy
& - wykonaj
. - wykonaj skrypt ps1 zapamiętując jego zmienne (spacja po kropce)
.. - zakres liczb całk. np. -5.1..1.9 -eq -5..1
${} - nazwa zmiennej z użyciem znaków niedozwolonych w nazwach, np. ${a b} (ale $ąćę jest ok)
` = \ w innych językach, choć w PowerShell RegExp jest normalnie \
konwersja z wartością domyślną - bez zgłaszania błędów:
$x = $xIn -as [double]; if ($null -eq $x) { $x = 0.0 }
PSCustomObject
$myObj=[PSCustomObject]@{Nm='K'}, $ht=[ordered]@{Nm='K'};$myObj=[pscustomobject]$ht
$myObj | ConvertTo-Json -depth 10 | Set-Content -Path $Path - zapis do pliku
$myObj=Get-Content -Path $Path | ConvertFrom-Json - odczyt z pliku
$myObj | Add-Member -MemberType NoteProperty -Name 'ID' -Value 'KMarquette'
$myObj | Add-Member @{ID='KMarquette'} (krótko, ale nie wiem, czy to to samo co powyżej)
wszystkie własności:
$myObj | Get-Member -MemberType NoteProperty | Select -ExpandProperty Name
czy własność istnieje? (działa także przy wyższych StrictMode):
if( [bool] $myObj.psobject.Properties['ID'] )
$myObj.Nm lub $myObj.'Nm' lub $myObj.$prop - odczytaj wartość
$b=$myObj.psobject.copy() - prawdziwa kopia (a nie tylko referencja)
- PowerShell – mini kompendium -> tymoteuszkestowicz.com
- PowerShell Operators $( ) @( ) :: & -> ss64.com
- Getting started with PowerShell -> riptutorial.com
- Powershell: Everything you wanted to know about arrays -> powershellexplained.com
- Everything you wanted to know about PSCustomObject -> docs.microsoft.com
- PowerShell Commands Every Developer Should Know -> stackify.com
2: RegExp
$a -replace $b,$c to .NET Regex.Replace($a, $b, $c, RegexOptions.IgnoreCase); $a.replace($b, $c) - zwykła zamiana
- Regular Expression Language - Quick Reference; Regex.Replace(…); .NET Replace(String, String), Replace(String, String, StringComparison), StringComparison -> docs.microsoft.com
3: Ustawienia
Przydatne ustawienia
Set-StrictMode -Version 3
$ErrorActionPreference = "Stop" - gdy chcemy na początku nie przeoczyć błędów
$PSDefaultParameterValues['Out-File:Encoding'] = 'utf8' - inaczej UTF16 LE BOM, czyli UCS2 LE BOM - też nieźle.
4: Array
$myArray = @(); $myArray += '...' - bardzo powolne; za każdym += kopiuje całą tablicę
$myArrList = [System.Collections.ArrayList]@(); [void]$myArrList.Add() - lista dynamiczna; gdy brak [void] do drukuje liczbę elementów
$Arr.length szybko dla tablicy, $ArrList.count powolniejsze, używaj dla kolekcji.
$a=@(11,22,33,44); $a[0,2];11,33 $a[0,-1]11,44 $a[($a.Count-1)..0]wspak $b,$c=$a; $b11 $c22,33,44
[string[]]$s3=@('')*3 [string[][]]$s2x4=(,(@('x')*4))*2 $s2x4[1][3]x
$ArrayDeepCopy = $Array | foreach { $_ } # deep copy trick to spłaszcza tablicę;
dla wielowymiarowych: $MultiDimShallowCopy = $Array | foreach { , $_ } $MultiDimDeepCopy = $Array | foreach { , ($_ | foreach{ $_ }) }
$Obj | Export-Clixml -LiteralPath .\serialized.xml $ObjDeepCopy = Import-Clixml .\serialized.xml
- PowerShell add or remove elements from an Array -> pscustomobject.github.io
- Deep copying arrays and objects -> powershelladmin.com
5: Pliki
$EnDefault = [System.Text.Encoding]::Default # gdy potrzeba ANSI, np. dla txt-CSV
[Console]::OutputEncoding = [System.Text.Encoding]::Unicode
Set-Location -Path $PSScriptRoot # gdy używam ścieżek względem położenia bieżącego skryptu
# System.IO.Stream - szybko, ale mało intuicyjnie:
$fWe = new-object System.IO.StreamReader( (Resolve-Path ('we.txt')), $EnDefault)
# ^-- Reader: koniecznie pełna ścieżka!
try { while (($wiersz = $fWe.ReadLine()) -ne $null) { ... } finally { $fWe.Close() }
$fWy = new-object System.IO.StreamWriter( ('..\Wyniki\' + 'wy1.txt'), $false, $EnDefault)
# ^-- konieczny nawias, gdy "+" ^--no-append
try { ...; $fWy.WriteLine( $kolejnyWiersz ) } finally { $fWy.Close() }
- The many ways to read and write to files -> powershellexplained.com
Pliki tekstowe UTF-8 z/bez BOM, ANSI
$txt = Get-Content 'a.txt' -Raw
# tzn. -Encoding Default: gdy 'a.txt' z BOM, np. UTF-8 BOM, to ma UTF ma priorytet, inaczej ANSI
# w $txt całość pliku w jednym łańcuchu (i odpowiednio np. z \r\n, czy \n)
$txt = Get-Content 'b.txt' -Raw -Encoding UTF8
# tu dobrze wczyta 'b.txt' UTF-8 bez BOM, a z BOM też będzie ok
# tak samo jak:
[System.IO.File]::ReadAllText("b.txt")
Set-Content -Encoding UTF8 "b.txt" -Value $txt # zapis - utf-8 BOM
# W Powershell 5.1 jest drobny problem z zapisaniem UTF-8 bez BOM. Na szczęście działa:
[System.IO.File]::WriteAllText("b.txt", $txt)
Lista podfolderów może się przydać do katalogowania dysków z kopiami zapasowymi:
Polecenie PowerShell dla foldera bieżącego '.\', np. głównego na wybranym dysku:
Get-ChildItem -Directory '.\' | ForEach{ $_.Name+'\'; $_ | ForEach {'* '+($_.GetDirectories().Name -join '\, ')+"\`n"} }
Analogiczna wersja do wklejenia w pasku eksploratora plików czy menu Total Comander`a:
Powershell -NoExit -c "Get-ChildItem -Directory '.\' | ForEach{ $_.Name+'\'; $_ | ForEach {'* '+($_.GetDirectories().Name -join '\, ')+\"`\`n\"} }"
Fragment przykładowego wyniku:
Users\
* All Users\, Default\, ...
Windows\
* Boot\, Cursors\, debug\, ...
6: Operator @
@()-array ,@{}-hash table@operator rozwinięcia (splat)function fun1 { param([int]$x, [int]$y) $x + $y } fun1 10 11 #-> 21 ( NIE: fun1(10, 11); NIE: fun1 10, 11 ) $a = @(10, 11) fun1 @a #-> 21- Here string
$c = @" Wiele "wierszy" $a "@
7: Właściwości mutim. plików
Odczyt rozszerzonych własności pliku
$shellFolder = $Shell.NameSpace("$($pwd.Path)\...\").self.GetFolder()
$shellFile = $shellFolder.ParseName('abc.mp4')
$shellFile # m.in. Name ('abc.mp4'), Path, ModifyDate ('2021-04-08 19:11:27'), Size (bajty)
0..400 | where-object {($details=$shellFolder.GetDetailsOf($shellFile,$_))} | ForEach {
" $($_.ToString('000')):$(($shellFolder.GetDetailsOf($null,$_)).PadLeft(40,'.')) : $details"
} #rozmiar np. w MB, czas bez sek.
# albo odczytaj wszystkie, także puste właściwości
0..400 | ForEach {
" $($_.ToString('000')):$(($shellFolder.GetDetailsOf($null,$_)).PadLeft(40,'.')) " +
": $($shellFolder.GetDetailsOf($shellFile,$_))"
}
Odczytywanie tekstów z językowych DLL.MUI, np. z c:\Windows\System32\en-US\propsys.dll.mui
1. Dodaj na końcu rozszerzenie .DLL; 2. Otwórz w Visual Studio; 3. Zapisz jako .RC
- Getting file metadata with PowerShell -> evotec.pl
8: Odczyt rejestru Windows
Zob. przykłady: WinInst_error_migrate_data
m.in. infProfileList_regWrTm.ps1 (html) (.zip)
.
9: Zarządzanie aplikacjami - CLI
- Lista zainstalowanych
Get-AppxPackage -AllUsers
- Odinstalowanie - dla podanego fragmentu nazwy (ostrożnie!).
foreach ($a in @("*Phone*","*zunemusic*")) {Get-AppxPackage -AllUsers Microsoft.$a | Remove-AppxPackage -AllUsers}
- Pełna lista aplikacji
$regPath = 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\*',
'HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*'
Get-ItemProperty -Path $regPath | Where-Object { $_.DisplayName -ne $null } |
Format-Table -Property DisplayName, InstallDate, DisplayVersion, InstallLocation -AutoSize -Wrap |
Out-File -Width 500 a500.txt
-
wingetwinget upgrade --all- lista aplikacji wymagających aktualizacji i ewentualnie zbiorcza aktualizacja po akceptacji.winget search veea- szuka aplikacji zawierającejveeaw Interneciewinget list vee- wyszukuje aplikację lokalnie na PCName Id Version Available Source --------------------------------- ---------------- --------- ---------- ------ Veeam Agent for Microsoft Windows Veeam.VeeamAgent 6.3.0.177 6.3.1.1074 wingetwinget download Veeam.VeeamAgent- zapisuje pliki instalacyjne i licencję do folderaDownload/<app>/(trzeba podać pełne Id jako parametr)
Różne odnośniki:
- unicodeSupSub_test.ps1 (html) (.zip) (zob. przy okazji Przydatne znaki unicode)
# Nie będziesz używał!
... | foreach { ... continuebreak
$a[0 . .-1]
.
- zob. też Hybrydowy skrypt CMD-PowerShell