HOME > PowerShell > チュートリアル

チュートリアル


作成日 2018年05月31日
更新日 2018年08月03日
スクリプト ファイルの拡張子は「.ps1」です。例では「.\a.ps1」のファイル名を使用します。
スクリプト ファイルを実行できるようにWindows PowerShellを管理者として実行して、実行ポリシーを RemoteSigned などにしてください。
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned

最初は外部リンクを見なくて良いです。
  1. コンソールに表示する(Write-Host、Write-Output)
  2. コンソールから読み込む(Read-Host)
  3. コメント(#以降か、あるいは<#から、#>まで)
  4. 1行に複数のステートメント(;)
  5. 次の行に継続する(`)
  6. 特殊文字を表示する
  7. 変数の名前の先頭はダラー記号($)で、英数字と下線記号( _ )
  8. 複数行の文字列を変数に代入するヒア文字列
  9. 定数(ReadOnly、Constant)
  10. 列挙(enum)
  11. 配列は値をカンマで区切り定義する
  12. ハッシュテーブル(連想配列)
  13. クラス(class)
  14. 演算子
  15. 条件分岐の if
  16. 繰り返し処理の for
  17. foreach
  18. while
  19. switch
  20. 関数(function)
  21. フィルター(filter)
  22. { と } で囲んだ名前のない関数のスクリプト ブロック
  23. オブジェクト(New-Object)
  24. 例外(try、catch、finally)

コンソールに表示する(Write-Host、Write-Output)

Write-Hostコマンドレットはコンソールに表示します。パイプラインや関数の戻り値にはなりません。
Write-Outputコマンドレットは標準出力に出力します。パイプラインや関数の戻り値になります。
コマンドレットなしの出力は、パイプラインや関数の戻り値になります。
下記はスクリプト ファイルの「a.ps1」です。
Write-Host Hello
Write-Output Windows
"PowerShell"
「.\a.ps1」を入力してスクリプト ファイルを実行します。ファイル名は絶対パスか、カレントディレクトリでは相対パスの「.\」をファイル名の前に付けます。
PS > .\a.ps1
Hello
Windows
PowerShell
上記の「PS >」はコマンドのプロンプトです。プロンプトを変更できます。
拡張子の「.ps1」を省略して実行できる場合もあります。例の「.\a.ps1」は「.\a」です。拡張子を省略した場合は、環境変数の「$env:PATHEXT」の値の左側から検索し一致するファイルを実行します。
PowerShellのコマンドラインでファイルの先頭の数文字を入力してTABキーを押すと、候補のファイル名で補完されます。

文字列にスペースが含まれると、Write-Hostコマンドレットは改行しませんが、Write-Outputは改行します。
PS > Write-Host Windows PowerShell
Windows PowerShell

PS > Write-Output Windows PowerShell
Windows
PowerShell
Write-Outputコマンドレットで改行したくない場合は引用符で囲んでください。あるいはバッククォート(`)でスペースをエスケープしてください。
PS > Write-Output "Windows PowerShell"
Windows PowerShell

PS > Write-Output Windows` PowerShell
Windows PowerShell

$PSHomeはWindows PowerShellのホームディレクトリの自動変数です。
変数は二重引用符で囲むと展開しますが、一重引用符の場合は展開しません。
二重引用符内の「`$」は、「$」になり、変数を展開しません。
PS > Write-Output "`$PSHome = $PSHome"
$PSHome = C:\Windows\System32\WindowsPowerShell\v1.0

PS > Write-Output '`$PSHome = $PSHome'
`$PSHome = $PSHome

パラメーターを ( と ) の小括弧で囲むと式モードになり計算してから表示します。
PS > Write-Host 1 + 2
1 + 2

PS > Write-Host (1 + 2)
3

a.ps1
Write-Host "Write-Host"
Write-Output "Write-Output"
"引用符で囲んだ文字列"
「a.ps1」を実行した結果の出力を「a.txt」ファイルにリダイレクトします。記号の > は左側の標準出力を右側のファイルに上書きします。
PS > .\a.ps1 > .\a.txt
Write-Host

PS > Get-Content -LiteralPath .\a.txt
Write-Output
引用符で囲んだ文字列
Write-Hostコマンドレットはリダイレクトしないでコンソールに出力します。
Get-Contentコマンドレットはテキストファイルの内容を表示します。
このページの上

コンソールから読み込む(Read-Host)

Read-Hostコマンドレットでコンソールから入力を読み込みます。
-Promptパラメーターで指定したメッセージの後ろにコロン(:)が付いて表示されます。
下記の「$Name」は変数名です。二重引用符内の変数は展開します。
$Name = Read-Host -Prompt "Name"
Write-Host "Hello $Name !"
下記は上記のスクリプトにファイル名を「a.ps1」にして実行した結果です。「Name:」が表示された後に「tanaka」を入力しました。
PS > .\a.ps1
Name: tanaka
Hello tanaka !
【注意】Read-Hostコマンドレットの入力は変数の型を宣言しないと、数字を入力しても文字列になります。

-AsSecureStringパラメーターは入力した文字を「*」で隠し、System.Security.SecureString型で取得します。
PS > $password = Read-Host -Prompt "Password" -AsSecureString
Password: ************
PS > ($password).GetType().FullName
System.Security.SecureString
このページの上

コメント(#以降か、あるいは<#から、#>まで)

シャープ記号(#)以降から行末まではコメントで実行しません。
<#から、#>までコメントで、複数の行をコメントにできます。
Get-Help -Category HelpFile about_Comment_Based_Help # シャープ記号以降から行末まではコメントです。

<#
複数の行を
コメントにします。
#>
注意 スクリプトの行に含まれる最初の項目が、#Requiresはコメントではありません。「管理者として実行」するように要求する(#Requires)を参照してください。
   関数とスクリプトのコメントベースのヘルプ トピックの場合もあります。「コメントベースのヘルプの作成」を参照してください。
このページの上

1行に複数のステートメント(;)

1行に複数の文を含む場合は、半角のセミコロン(;)で区切ります。
$cnt=0; $MaxCount=128
このページの上

次の行に継続する(`)

文の途中に半角のバッククォート(`)で次の行に継続します。
Get-ItemProperty -LiteralPath "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\Winword.exe" `
                 -Name "(Default)"

等号記号(=)や、パイプライン(|)で終わる場合は、バッククォート記号なしで次の行に継続できます。
$FileList =
            Get-ChildItem *.ps1 |
                Where-Object {$_.Length -gt 5000} |
                Sort-Object -Property Length -Descending
このページの上

特殊文字を表示する

特殊文字はバッククォート記号の(`)でエスケープします。
記号説明
`n改行で、newLineのn。 Windowsの改行は2文字の`r`nを使用します。
`r復帰で、returnのr
`tタブで、tabのt
`'一重引用符
`"二重引用符
``バッククォート
二重引用符内でダラー記号($)を表示するには、バッククォートを前に付けて「`$」にします。
PS > Write-Output "`'は一重引用符、`t`t前にタブ2個、`$はダラー記号、次は改行`r`n`"は二重引用符"
'は一重引用符、		前にタブ2個、$はダラー記号、次は改行
"は二重引用符

二重引用符で囲むと一重引用符を、一重引用符で囲むと二重引用符を使えます。
PS > Write-Output "'は一重引用符"
'は一重引用符

PS > Write-Output '"は二重引用符'
"は二重引用符

囲む引用符と同じ連続する2個の引用符は、1個の引用符になります。
PS > Write-Output '連続する2個の''は、1個の一重引用符'
連続する2個の'は、1個の一重引用符

PS > Write-Output "連続する2個の""は、1個の二重引用符"
連続する2個の"は、1個の二重引用符
このページの上

変数の名前の先頭はダラー記号($)で、英数字と下線記号( _ )

変数の名前の先頭はダラー記号($)で始めます。
英数字と下線記号( _ )以外の文字を使用する場合は、変数名を { と } で囲み、${変数名}にします。マイナス記号を使用する例、 ${Max-Count}
変数でなくアイテムのフルネームを指定すると、例えば ${C:\Windows\System32\WindowsPowerShell\v1.0\profile.ps1} はテキストファイルを表示します。
英字の大文字と小文字を区別しません。
既定でユーザー設定変数、自動変数が定義されてます。下記は変数の一覧を表示します。
Get-ChildItem Variable:
【外部リンク】ユーザー設定変数はマイクロソフトの「about_Preference_Variables」を参照してください。
【外部リンク】自動変数はマイクロソフトの「about_Automatic_Variables」を参照してください。
【外部リンク】環境変数はマイクロソフトの「about_Environment_Variables」を参照してください。

自動変数の「$PSCommandPath」は実行したスクリプトのフルパス名、「$PSScriptRoot」はディレクトリです。
$PSCommandPath
$PSScriptRoot
Split-Path -Path $PSCommandPath -Leaf  # Split-Pathコマンドレットはパスを分割します。-Leafパラメーターはディレクトリを除いたファイル名です。
下記は上記のファイルを「C:\bin\PowerShell\Sample\a.ps1」に保存して実行した場合です。
PS > C:\bin\PowerShell\Sample\a.ps1
C:\bin\PowerShell\Sample\a.ps1
C:\bin\PowerShell\Sample
a.ps1

下記はコマンド プロプトでも使える環境変数の一覧を表示します。
Get-ChildItem Env:

下記は環境変数の「WinDir」の値を表示します。(値は環境により異なります)
PS > $Env:WinDir
C:\WINDOWS

型の宣言は省略でき、代入された値によって型が決定します。GetTypeメソッドのFullNameプロパティで型のフルの名前を取得します。
PS > $i=123
PS > $i.GetType().FullName
System.Int32

PS > $d=3.14
PS > $d.GetType().FullName
System.Double

PS > $s="Hello"
PS > $s.GetType().FullName
System.String

PS > $s.Length  # String型なので、Lengthプロパティで文字数を取得できます。
5

明示的に変数の型を宣言するには、型を [ と ] で囲みます。
System.は省略できます。[System.Xml.XmlDocument]は、[Xml.XmlDocument]でも良いです。
よく使う型はエイリアスが宣言されてます。[System.Xml.XmlDocument]は[Xml]です。一覧は「型エイリアス」を参照してください。
Bool、Boolean、Byte、Char、CultureInfo、DateTime、Decimal、Double、HashTable、Int16、Int32、Int64、SByte、Single、String、UInt16、UInt32、UInt64、Guid、IPAddress、MailAddress、Ref、PsObject、PsCustomObject、Regex、ScriptBlock、SecureString、Switch、TimeSpan、Type、Uri、Void、Xml、WMIなど......
PS > [int]$n = 8 / 3  # 少数が「0.5」以外は、四捨五入します。
PS > $n
3

PS > [int]$n = 5 / 2   # 少数が「0.5」の場合は、最も近い偶数に丸めます。
PS > $n
2

PS > [int]$n = 7 / 2   # 少数が「0.5」の場合は、最も近い偶数に丸めます。
PS > $n
4

下記で型エイリアスの一覧を表示します。
[PSObject].Assembly.GetType("System.Management.Automation.TypeAccelerators")::Get

下記で未定義の変数を参照するとエラーになります。
Set-PSDebug -Strict

変数のスコープについて説明します。
コマンドラインで関数の中を除く変数は、グローバル変数になります。
関数の外の変数の値は、関数の中から普通に取得できます。
関数の中からグローバル変数の値を変更するには、変数の名前の前に「Global:」を付けます。
PS > $Max_Count=12
PS > &{
	  $Max_Count  # 外のグローバル変数の値を表示します。
	  $Global:Max_Count = 999  # グローバル変数の値を変更するには、Global: が必要になります。
	  $Max_Count = 777  # これはスクリプトブロック内のローカル変数です。グローバル変数ではありません。
	  $Max_Count  # ローカル変数です。
      } 
12
777

PS > $Max_Count
999
アンパーサンド記号の&は呼び出し演算子で、{ と } で囲まれたスクリプト ブロック(名前のない関数)を実行します。

同じスクリプト ファイル内の関数の中から、スクリプト変数の値を変更するには、変数の名前の前に「Script:」を付けます。
$dt = Get-Date -DisplayHint Date
&{
    $dt  # 外の変数の値を表示します。
    $Script:dt = Get-Date -DisplayHint Time  # スクリプト変数の値を変更するには、Script: が必要になります。
}
$dt
下記は上のスクリプト ファイルを実行した結果の例です。(実行した日付と時刻により異なります)
2018年5月26日
22:25:31

Private:を付けると、中の関数からも参照できなくなります。
Using:を付けるとリモートコマンド内で、呼び出し元のローカルセッションの変数になります。

詳細は「変数のスコープ」を参照してください。
このページの上

複数行の文字列を変数に代入するヒア文字列

変数を展開するヒア文字列は「@"」で始め、「"@」で終わります。
変数を展開しないヒア文字列は「@'」で始め、「'@」で終わります。
$html = @'
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>PowerShell</title>
</head>
<body>
一重引用符で囲むと変数を展開しません。
$PSHOMEはPowerShellをインストールしたフォルダです。例えば、C:\Windows\System32\WindowsPowerShell\v1.0
</body>
</html>
'@

$html

二重引用符で囲むと場合は、変数を展開できます。
$lines = @"
二重引用符で囲むと変数を展開できます。
$PSHome
ヒア文字列内の # 記号は、コメントではありません。
"@

$lines
二重引用符で囲むと変数を展開できます。
C:\Windows\System32\WindowsPowerShell\v1.0
ヒア文字列内の # 記号は、コメントではありません。
このページの上

定数(ReadOnly、Constant)

16進数は、0xで始めます。
PS > $h = 0xfa  # 16進数は、0xで始めます。「0xfa」は10進数の「250」
PS > $h
250
PS > $h.ToString("X")
FA

下記はNew-Variableコマンドレットで名前が「pi」、値が「3.14」の定数を宣言します。
PS > New-Variable -Name pi -Value 3.14 -Option ReadOnly
PS > $pi
3.14
円周率は [System.Math]::PI を使用してください。(3.14159265358979)

削除する場合はパラメーターの-Forceを付けます。
PS > Remove-Variable -Name pi -Force

Constantで作成した場合は終了するまで削除できません。
PS > New-Variable -Name pi -Value 3.14 -Option Constant
このページの上

列挙(enum)

列挙のenumはバージョン5.0から追加されました。
型は[int]で、解析時には定数です。
enum Signale {
    Red
    Blue
    Green
}

[Signale]$s=[Signale]::Red
Write-Host "Signale = $s"

値を設定することもできます。等号記号の(=)の後はスペースで間を空けてください。(バグ?)
enum Eigyousho {
    Cyuouku = 10
    Sinjyuku = 11
    Osaka = 20
    Nagoya = 30
}

[Eigyousho]$s=[Eigyousho]::Sinjyuku
Write-Host "Eigyousho = $s"
このページの上

配列は値をカンマで区切り定義する

配列は値をカンマ記号の(,)で区切って定義します。型を省略するとObject型の配列になります。
配列の添字は、0から始まります。
PS > $arr = 1, 2, 3  # Object型の配列です、Int32型ではありません。必要なら [Int32[]]$arr のように型を明示してください。
PS > Write-Host $arr[0] $arr[1] $arr[2] 
1 2 3

2個のドット記号の「..」で連続する数字を設定できます。
PS > [Int32[]]$arr = 5..10
PS > Write-Host $arr
5 6 7 8 9 10

添字のマイナス記号の(-)は最後から参照します。-1は最後、-2は最後から2番めの項目を参照します。
PS > Write-Host $arr[-1] $arr[-2]
10 9

【注意】配列は値型ではなく参照型です。配列の項目を追加、削除した場合は、新しく作成した配列を代入します。
$a = 1,2,3
$b = $a  # 参照
Write-Host "`$a = " $a
Write-Host "`$b = " $b
$a =  1 2 3
$b =  1 2 3

参照なので$a[0]の値を変更すると、$b[0]の値も同じになります。
$a[0] = 987  # 参照型なので、$b[0]も987です。 
Write-Host "`$a = " $a
Write-Host "`$b = " $b
$a =  987 2 3
$b =  987 2 3

配列の項目を追加、削除した場合は、新しく作成した配列を代入します。
$a += 654  # 配列の$aと654を足した新しい配列に代入します。
Write-Host "`$a = " $a
Write-Host "`$b = " $b
配列の$aと$bの値は異なります。
$a =  987 2 3 654
$b =  987 2 3

【外部リンク】配列はマイクロソフトの「about_Arrays」を参照してください。
このページの上

ハッシュテーブル(連想配列)

ハッシュテーブル(連想配列)は、System.Collections.Hashtableクラスです。
@{ で始め、項目はキー = 値の形式で、セミコロンの(;)で区切り、} で終わります。
PS > $hash = @{key1="value1"; key2="value2"; key3="value3"}
PS > $hash
Name                           Value
----                           -----
key3                           value3
key1                           value1
key2                           value2 
順番に表示されるとは限りません。

[Ordered]を付けて宣言すると順番になります。
PS > $hash = [Ordered]@{key1="value1"; key2="value2"; key3="value3"}

下記はキーを昇順に並べて表示します。
PS > $hash.GetEnumerator() | Sort-Object -Property key

キーで値を参照します。
PS > $hash["key1"]
value1
$hash.key1でもかまいません。

ハッシュテーブルにキーが含まれているかをContainsメソッドで調べます。
PS > $hash.Contains("key2")
True

項目を追加するには、Addメソッドです。
PS > $hash.Add("key4", "value4")
PS > $hash.Count  # Countプロパティは、ハッシュテーブルの項目数
4

項目を削除するには、Removeメソッドです。
PS > $hash.Remove("key2")
PS > $hash.Count
3

Keysプロパティはキーの一覧、Valuesプロパティは値の一覧です。
PS > Write-Host $hash.Keys
key3 key1 key4

PS > Write-Host $hash.Values
value3 value1 value4

PS > foreach ($key in $hash.Keys) { Write-Host ("$key = " + $hash[$key]) }  # 二重引用符で囲まれた配列の変数は $()演算子で囲み、"$key = $( $hash[$key] )"にしても良いです。
key3 = value3
key1 = value1
key4 = value4
【外部リンク】ハッシュ テーブルはマイクロソフトの「about_Hash_Tables」を参照してください。
このページの上

クラス(class)

クラスのclassはバージョン5.0から追加されました。
class User { 
            [int]$Code
            [string]$Name

            User([int]$Code, [string]$Name)
            {
                $this.Code = $Code
                $this.Name = $Name
            }

            Show() {
                Write-Host ("Code = " + $this.Code)
                Write-Host ("Name = " + $this.Name)
            }
}

$u = [User]::new(123, "Tanaka")
$u.Show()
下記は上記のスクリプトにファイル名を「a.ps1」にして実行した結果です。
PS > .\a.ps1
Code = 123
Name = Tanaka
このページの上

演算子

算術演算子 (+、-、*、/、%)
足し算と引き算の優先順位を高くするには、 ( と ) で囲みます。
PS > 13 / 5  # 割り算の答えが実数になるので、System.Double型になります。4 / 2 はSystem.Int32型です。
2.6

PS > (1 + 2) * 10 / 2 - 1  # 優先順位を高くするには ( と ) で囲みます。
14

PS > "1KB = " + 1KB + "  1MB = " + 1MB + "  1GB = " + 1GB  + "  1TB = " + 1TB 
1KB = 1024  1MB = 1048576  1GB = 1073741824  1TB = 1099511627776

【注意】インクリメントのタイミングは、C#とは違います。
PS > $arr1 = 1, 2
PS > $arr2 = 3, 4
PS > $i=0
PS > $arr1[$i] = $arr2[$i++]  # $arr1[1] = $arr2[0]
PS > Write-Host $arr1
1 3

【注意】割り算の商が整数の場合は最も近い整数値に丸めますが、少数が「.5」の場合だけは、最も近い偶数に丸めます。
PS > [int](5/2)
2

PS > [int](7/2)
4

【注意】数値と文字列の足し算と掛け算は、左側のオブジェクトが優先します。
PS > 1 + "23"
24

PS > "1" + 23  # 【注意】左側の型が優先するので文字列の連結になります。
123

PS > "みーん " * 5  # 【注意】逆にして 5 * "みーん " にするとエラーになります。
みーん みーん みーん みーん みーん

商と余りを求めます。
PS > 13 % 5  # パーセント記号の(%)は除算の余りを求めます。
3

PS > ${分母}=13
PS > ${分子}=5
PS > (${分母} - ${分母} % ${分子}) / ${分子}  # 余りを除いて商のみ求めます。
2

PS > ${余り}=0;
PS > ${商}=[System.Math]::DivRem(13, 5 ,[ref]${余り}); # 整数の商を返します。
PS > ${商}
2
PS > ${余り}
3

数値関数を使います。
PS > [System.Math]::Pow(2, 16)  # 2の16乗。 「System.」を省略して、[Math]::Pow(2, 16) でも良いです
65536
四捨五入はRound、切り上げはCeiling、切り捨てはFloorです。Abs、Cos、DivRem、Exp、Log、Log10、Max、Min、Sign、Sqrt、Tanなどもあります。
【外部リンク】数値関数はマイクロソフトのMath クラスを参照してください。
乱数の取得は、Get-Randomコマンドレットです。

代入演算子 (=、+=、-=、*=、/=、%=)と単項演算子 (++、--)
PS > $a=$b=$c=123  # $aと$bと$cの値を123にします。
PS > Write-Host "`$a = $a  `$b = $b  `$c = $c"
$a = 123   $b = 123   $c = 123

PS > $a++; $a; $a--; $a
124
123

PS > $x, $y = 88, 99  # $xに88、$yに99を代入します。(配列の代入)
PS > Write-Host "`$x = $x  `$y = $y"
$x = 88   $y = 99

PS > $x, $y = $y, $x  # $xと$yの値を交換します。
PS > Write-Host "`$x = $x  `$y = $y"
$x = 99   $y = 88

比較演算子 (-eq、-ne、-gt、-ge、-lt、-le)
比較するために $true、$false、$nullが定義されてます。
CaseSensitiveを意味するCのない演算子は、英字の大文字と小文字を区別しないで比較します。
-eq 等しい。EQual
-ceq 文字列の英字の大文字と小文字を区別して比較して等しい。CaseSensitive EQual
-ne 等しくない。Not Equal
-cne 文字列の英字の大文字と小文字を区別して比較して等しくない。CaseSensitive Not Equal
-gt より大きい。Greater Than
-ge 以上。Greaert than Equal
-lt より小さい。Less Than
-le 以下。Less than Equal
PS > "abc" -eq "ABC"
True

"abc" -ceq "ABC"  # 英字の大文字と小文字を区別します。
False

正規表現を使用してパターンを検索するマッチ演算子 (-match、-notmatch、-cmatch、-cnotmatch)
【外部リンク】正規表現は下記のマイクロソフトのサイトを参照してください。
-matchは英字の大文字と小文字を区別しません。
PS > "ABCD" -match "bc"
True

matchの前にnotを付けるとmatchを否定した値になります。-notmatchは一致すると、Falseになります。
PS > "ABCD" -notmatch "bc"
False

英字の大文字と小文字を区別する場合は、-の後ろにcを付けた-cmatchを使います。(cはCaseSensitiveの頭文字)他の演算子も同じです。
PS > "ABCD" -cmatch "bc"
False

正規表現を使用して入力値を変更する置換演算子 (-replace、-creplace)
PS > "abcABCabc" -replace "ab" ,"XYZ"
XYZcXYZCXYZc

ワイルドカード文字 (*、?) を使用してパターンを検索するライク演算子 (-like、-notlike、-clike、-cnotlike)
*は0文字以上、?は任意の1文字に一致します。
[ と ]で囲んだ文字の中の1文字に一致します。
[abc]はaかbかcの1文字に一致します。
[0-9]は数字の1文字に一致します。
[a-zA-Z]は英字の1文字に一致します。
PS > "ABCD" -like "?b*"
True

包含演算子 (-in、-notin、-cin、-cnotin、-contains、-notcontains、-ccontains、-cnotcontains)
配列などに一致する項目があるか調べます。
-in と -containsは、左の項目と右の項目は逆になります。
PS > $arr = "ABC", "OPQ", "XYZ"
PS > "abc" -in $arr
True

PS > $arr -notcontains "abc"
False

論理演算子 (-and、-or、-xor、-not、!)
-andは論理積、-orは論理和、-xorは排他的論理和、! は -notと同じ否定の演算子です。
PS > $a=1; $b=2; $c=3; $d=4
PS > -not ( ($a -eq 1) -and ($b -eq 2) -or ($c -eq 9) -xor ($d -eq 4) )
True

-orの左側の条件が真の場合は、右の条件を処理しません。
PS > $a=$b=0;
PS > if ($a -eq 0 -or ($b=1)) { '$a=0 $b=1' }
$a=0 $b=1
PS > "`$b=$b"
$b=0

-andの左側の条件が偽の場合は、右の条件を処理しません。
PS > $a=$b=0;
PS > if ($a -eq 1 -and ($b=1)) { $a++ }
PS > "`$b=$b"
$b=0

ビット演算子 (-bAND、-bOR、-bXOR、-bNOT、-shl、-shr)
-shlは左シフト、-shrは算術右シフト(符号は変わりません)です。
例の0xで始まる定数は16進数です。
PS > 7 -bAND 0xE  # 0111 論理積 1110
6

PS > 1 -bOR 2     # 0001 論理和 0010
3

PS > 3 -bXOR 5    # 0011 排他的論理和 0101
6

PS > (-bNOT 0x0000FFFF).ToString("X")  # ビットを反転します。
FFFF0000

PS > 1 -shl 2     # 左に2ビット移動します。
4

PS > 4 -shr 2     # 右に2ビット移動します。
1

PS > (0x9FFFFFFF -shr 8).ToString("X")  # 右に8ビット移動します。算術シフトなので左端の符号の値は変わりません。
FF9FFFFF

リダイレクト演算子 (>、>>)
コマンド プロンプトの入力のリダイレクト記号の < は将来のために予約されています。
テキストファイルを入力するには、Get-Contentコマンドレットで表示して、パイプ記号の | で連結します。
| の左側の標準出力を右側の標準入力とします。
> は右側のファイルに新規作成して出力します。
>> は右側のファイルの最後に追加して出力します。(無ければ新規作成)
PS > Get-ChildItem *.ps1 -Name >  .\FileList.txt  # Get-ChildItemの結果を新規作成した「FileList.txt」ファイルに出力します。
PS > Get-ChildItem *.txt -Name >> .\FileList.txt  # Get-ChildItemの結果を「FileList.txt」ファイルの最後に追加します。
PS > Get-Content -LiteralPath .\FileList.txt | Sort-Object  # 「FileList.txt」ファイルを整列して表示します。

PS > New-Item -Path .\log.txt > $null  # New-Itemコマンドレットの標準出力を廃棄します。(関数の戻り値になりません)

PS > Get-ChildItem *.ps1 | Out-Printer  # Get-ChildItemの結果をプリンターに出力します。
【注意】リダイレクト処理はファイルを開閉するので時間がかかります。繰り返しの中では変数に格納した後でまとめて出力しましょう。

分割演算子 (-split)と結合演算子(-join)
PS > "Apple,Banana,Orange" -split "," 
Apple
Banana
Orange

PS > "Apple,Banana,Orange" -split "," , 2 # 文字列を分割する回数の最大値を2に指定
Apple
Banana,Orange

PS > @("Apple","Banana","Orange") -join " | "
Apple | Banana | Orange

型演算子 (-is、-isnot、-as)
-asは型変換できない場合はエラーでなく、ヌルになります。
PS > ("2018/05/31" -as [DateTime]).AddDays(1).ToString("yyyy/MM/dd")
2018/06/01

PS > ([DateTime]"2018/07/01 12:34:56") -is [DateTime]
True

PS > (Get-Date).GetType().FullName  # 型のフルの名前を取得します。
System.DateTime

-f 書式設定演算子
PS > "{0:yyyy年MM月dd日 dddd}" -f (Get-Date)
2018年05月29日 火曜日

PS > "{0:c}`t`t{1:#,##0}" -f 1234567890, 6789012345
\1,234,567,890		6,789,012,345
書式については下記のマイクロソフトのサイトを参照してください。
@( ) 配列部分式演算子
$arr = @()  # 空の配列

.. 範囲演算子
上限と下限を指定した連続する整数の配列です。下記の $_ はパイプラインの各項目の値の変数です。例では1、2、3となります。
PS > 1..3 | ForEach-Object { "$_ * $_ = " + ($_ * $_) }
1 * 1 = 1
2 * 2 = 4
3 * 3 = 9
降順にも指定できます。「$arr = 9..1」は「$arr = 9, 8, 7, 6, 5, 4, 3, 2, 1」と同じです。

:: 静的メンバー演算子
.NET Frameworkクラスの静的なプロパティとメソッドを呼び出します。
PS > [System.Math]::Pow(2, 16)  # 2の16乗。
65536

$( ) 部分式演算子
1つ以上のステートメントの結果を返します。二重引用符で囲まれた中の配列やプロパティを表示するときに使用します。
$hash = @{key1="value1"; key2="value2"; key3="value3"}
"Count = $($hash.Count)"
foreach ($key in $hash.Keys){
	Write-Host ("$key = $( $hash[$key] )")
}
Count = 3
key3 = value3
key1 = value1
key2 = value2

& 呼び出し演算子
下記はワードパッド(Wordpad.exe)を実行します。
PS > &"C:\Program Files\Windows NT\Accessories\Wordpad.exe"

下記は名前のない関数のスクリプト ブロックを実行します。
PS > &{ Get-Date -DisplayHint Date; Get-Date -DisplayHint Time }
2018年6月1日
6:43:00

【外部リンク】演算子の優先順位はマイクロソフトの「about_Operator_Precedence」を参照してください。
このページの上

条件分岐の if

条件は演算子を参照してください。
if ( 条件 ) の後にステートメント ブロックの { と } で囲みます。文が1つでも必要です。
Test-Pathコマンドレットはアイテムが存在するか調べます。
if ((Test-Path $PSHome\powershell.exe) -eq $true){
    Write-Host "$PSHome\powershell.exe ファイルは存在します。"
}
C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe ファイルは存在します。

if ((Test-Path $PSHome\powershell.exe) -eq $true){
    Write-Host "存在します。"
} else {
    Write-Host "存在しません。" -ForegroundColor Red -BackgroundColor Black
}
存在します。

下記は入力した数値により処理を分岐します。
[int]$Number = Read-Host -Prompt "数字"

if ($Number -eq 0 ){
    Write-Host "Equal 0"
} elseif ($Number -gt 0 ){
    Write-Host "Great than 0"
} else {
    Write-Host "Less than 0"
}
このページの上

繰り返し処理の for

for (初期処理; 繰り返す条件; ステートメント ブロックの後の繰り返し処理) { 繰り返し処理 }
for ($i=0; $i -lt 10; $i++){
    Write-Host -NoNewline $i  # -NoNewlineパラメーターは、改行しません。
}
0123456789

breakは処理を抜け、continueは戻ります。
for ($i=0; $i -lt 10; $i++){
    if ($i -gt 6) { break } # break でこのfor文を抜けます。
    if (($i % 2) -eq 0) { continue } # continue でこれ以降の処理をしないで、forの$i++に移動します。
    Write-Host $i
}
1
3
5

breakに指定したラベルに移動することによって、複数のfor文を抜けます。
:out  # ラベル名は先頭にコロン(:)を付けます。【注意】ラベルはforなどのループのキーワードの前に宣言します。
for ($i=1; $i -lt 10; $i++){
    for ($j=1; $j -lt 10; $j++){
        if (($i * $j) -gt 3) {break out}  # ラベルに移動することによってループから抜けます。
        Write-Host $i * $j
    }
}
Write-Host "End"
1 * 1
1 * 2
1 * 3
End
このページの上

foreach

foreach (項目の変数 in 配列などの変数) { 繰り返し処理 }
$hash = @{key1="value1"; key2="value2"; key3="value3"}
foreach ($item in $hash.Keys){
    Write-Host $hash[$item]
}
value3
value1
value2
このページの上

while

while (繰り返す条件) { 繰り返し処理 } は繰り返す条件が真の間、処理を繰り返します。
$i=0
$sum=0
while ($sum -lt 50){
    $i++
    $sum += $i
    Write-Host "$i --> $sum"
}
1 --> 1
2 --> 3
3 --> 6
4 --> 10
5 --> 15
6 --> 21
7 --> 28
8 --> 36
9 --> 45
10 --> 55

do { 繰り返し処理 } while (繰り返す条件) は最低でも1回は処理を実行します。
[decimal]$sum=0
Write-Host "0を入力すると、終了します。"
do {
    [decimal]$n = Read-Host -Prompt "数字"
    $sum += $n
} while ($n -ne 0)
Write-Host "合計は $sum です。"
0を入力すると、終了します。
数字: 1234500
数字: 3.14
数字: 0
合計は 1234503.14 です。

whileでなくuntilを使用する場合は、終了する条件を指定します。
do { 繰り返し処理 } until (終了する条件)
[decimal]$sum=0
Write-Host "0を入力すると、終了します。"
do {
    [decimal]$n = Read-Host -Prompt "数字"
    $sum += $n
} until ($n -eq 0)
Write-Host "合計は $sum です。"
実行すると先ほどのwhileと同じように動作します。
このページの上

switch

switch文は値により処理を分岐します。PowerShellのswitchの機能は豊富です。
条件にステートメント ブロックの { } も使えます。値は自動変数の「$_」で参照します。
switch [ -regex | -wildcard | -exact ] [ -casesensitive ] (値)
-regexパラメーターは正規表現で比較します。
-wildcardパラメーターはワイルドカードで比較します。
-exactパラメーターは完全一致で比較します。
-casesensitiveパラメーターを指定すると、英字の大文字と小文字を区別します。
値にコレクションを指定すると、各項目の値で分岐します。一致してもbreak文がない場合は繰り返します。

-fileパラメーターで指定したテキストファイルの各行で分岐します。一致してもbreak文がない場合は繰り返します。
switch [ -regex | -wildcard | -exact ] [ -casesensitive ] -file ファイル名
$buf = Read-Host -Prompt "文字列"
switch ($buf){
    1                { Write-Host "1"; break; }  # 重複しないこの例では、breakを省略しても同じ結果です。
    'a'              { Write-Host "a か A"; break; }  # 英字の大文字と小文字を区別しません。
    {$_ -match "ab"} { Write-Host "ab か AB か Ab か aB"; break; }  # 英字の大文字と小文字を区別しません。
    default          { Write-Host "入力した値は $_ です。" }  # $_ は自動変数で、この例の$bufはコレクションではないので $_ と同じ値です。
}
breakは必要、不要、どちらでも同じ場合があります。
【外部リンク】switchはマイクロソフトの「about_Switch」を参照してください。
このページの上

関数(function)

Write-Hostコマンドレットは、関数の戻り値にはなりません。
コマンドレットを省略した定数と変数、Write-Outputコマンドレットによる表示は標準出力なので関数の戻り値になります。
Returnは戻り値を指定して関数から戻ります。
function Get-Time { # 時間を取得します。
    Return (Get-Date -DisplayHint Time)
}

Get-Time

コマンドレットによる標準出力は、関数の戻り値になります。
必要なければ[void]、$nullにリダイレクト、Out-Nullでパイプするなど出力しないようにしてください。
[void](New-Item -Name .\a.tmp -ItemType File)
New-Item -Name .\a.tmp -ItemType File > $null
New-Item -Name .\a.tmp -ItemType File | Out-Null

【注意】パラメーターを指定して関数を呼び出すには、パラメーターをスペースで区切ります。カンマで区切ると配列になります。
$argsは自動変数で、使用されなかったパラメーターの配列です。
function Write-Arguments { # パラメーターの数と値を返します。
    '$args.Count = ' + $args.Count  # 一重引用符(')で文字列を囲むと、ダラー記号($)はそのままで変数になりません
    Write-Host $args # Write-Hostコマンドレットは、関数の戻り値にはなりません!
    for ($i=0; $i -lt $args.Count; $i++){
        "`$args[$i] = " + $args[$i]  # バッククォート記号(`)でダラー記号($)をエスケープ
    }
}

$ret = Write-Arguments one two three
$ret
上記の例ではWrite-Hostコマンドレット以外の表示される値のすべてが戻り値になります。下記は実行結果で、この関数の戻り値の型は、System.Object型の配列になります。
one two three
$args.Count = 3
$args[0] = one
$args[1] = two
$args[2] = three
関数の戻り値を表示する前に、Write-Hostコマンドレットの出力の「one two three」が表示されてます。

パラメーターを指定します。
function Get-Quotient (${分子}, ${分母}) { # 割り算の整数商を返します。
    Return (${分母} - ${分母} % ${分子}) / ${分子}
}

Get-Quotient 7 20
2
パラメーターはスクリプト ブロック内のParamで宣言してもかまいません。
function Get-Quotient {
    Param(${分子}, ${分母})
	
    Return (${分母} - ${分母} % ${分子}) / ${分子}
}
もしこのGet-Quotient関数を3個以上のパラメーターで呼ぶと、自動変数の$argsに3個目以降が設定されます。$argsは余ったパラメーターです。

パラメーターの型は変数名の前に指定します。
下記のパラメーターの$Countを省力すると、値は2になります。
function Repeat-Text ([String]$Text, [Int32]$Count=2) { # 文字列を指定した回数、繰り返して連結した文字列を返します。
    $Text * $Count  # 「$Count * $Text」のようにするとエラーになります。数値 * 文字列はエラー
}

Repeat-Text "無駄!" 10
Repeat-Text "ワン"  # Countパラメーターを省略したので「2」になります。
無駄!無駄!無駄!無駄!無駄!無駄!無駄!無駄!無駄!無駄!
ワンワン

パラメーターに[ref]を付けて参照渡しにし、変数のValueプロパティに値を設定します。
function Test-Sample ($a, [ref]$b) { 
    $a = "Value"
    $b.Value = "Reference"  # Valueに値を設定します。
}

$x = ""
$y = ""
Test-Sample $x ([ref]$y)
"`$x = $x"
"`$y = $y"
変数の$yは参照渡しなので値が変更されました。
$x = 
$y = Reference

スクリプト スコープで関数の外の変数に設定します。
function Test-Sample ($a, $b) {
    "`$x = $x"      # 関数の外の変数を読めます。
    "`$y = $y"      # 同上
    $script:x = $a  # script:を付けたので関数の外の変数を設定できます。
    $y = $b         # script:を付けないので、外の変数の値は変化しません。
}

$x = "script x"
$y = "script y"
Test-Sample "Windows" "PowerShell"
"`$x = $x"
"`$y = $y"
$xの変数の前にscript:を付けたので関数の外の同じスクリプト ファイルの変数を設定できました。$yは変わりません。
$x = script x
$y = script y
$x = Windows
$y = script y

次はパイプラインの処理をする関数です。
スクリプト ブロックのbeginは最初に一回、processは繰り返し、endは最後に一回処理します。
変数はbegin、process、endスクリプト ブロックで参照できます。
processスクリプト ブロックの自動変数の $_ はパイプラインの各項目です。
function Get-LineCount { # 行数を付けて返します。
    begin { # 最初に一回処理します。
        $Count=0  # この変数はスクリプト ブロックのprocessとendで共有できます。
    }

    process { # パイプラインの項目を繰り返し処理します。
        $Count++
        $Count.ToString("00000: ") + $_  # $_ はパイプラインの各項目
    }

    end { # 最後に一回処理します。
        Write-Host $Count  # Write-Hostは関数の戻り値にはなりません。
    }

}

"one" ,"two" ,"three" | Get-LineCount
下記は上記の実行結果です。最後の行の3はWrite-Hostコマンドレットの出力なので、関数の戻り値ではありません。
00001: one
00002: two
00003: three
3

CmdletBindingは高度な関数を参照してください。
このページの上

フィルター(filter)

フィルター(filter)はスクリプト ブロックのbeginとendを省略したパイプラインの処理をします。
filter Shift-Right ([int]$Count=1) {  # 指定した数のスペースを左側に連結します。
    Write-Output (" " * $Count + $_)  # パイプラインの各項目の値は、$_ で参照します。
}

"one" ,"two" ,"three" | Shift-Right 4
左側に4個のスペースを連結して表示します。
    one
    two
    three
このページの上

{ と } で囲んだ名前のない関数のスクリプト ブロック

スクリプト ブロックは名前のない関数で { と } で囲みます。if、for文などの { と } はステートメント ブロックで違います。
実行するには呼び出し演算子のアンパーサンド記号の(&)を使います。
下記はファイルのサイズの順番で整列して表示します。
&{ Get-ChildItem | Sort-Object -Property Length }

パラメーターを指定することもできます。
$SortFileSize = {
                    Param($Path=".\*.*", $Descending=$false);
                    Get-ChildItem $Path | Sort-Object -Property Length -Descending:$Descending
                }

&$SortFileSize .\*.ps1  # ファイルのサイズの昇順で表示します。
Pause  # 一時停止、Entrerキーを押すと処理を続けます。
&$SortFileSize .\*.ps1 $true  # ファイルのサイズの降順で表示します。
このページの上

オブジェクト(New-Object)

New-Objectコマンドレットでオブジェクトを作成します。
-TypeNameパラメーターでクラス名を指定します。
-ComObjectパラメーターでComの名前を指定します。
下記はフォームを表示します。
Add-Type -AssemblyName System.Windows.Forms  # アセンブリの読み込み
$Form = New-Object -TypeName System.Windows.Forms.Form
$ModalResult = $Form.ShowDialog()

下記はメッセージを表示して、3秒後に閉じます。
$WS = New-Object -ComObject WScript.Shell
$WS.Popup("メッセージを表示して、3秒後に閉じます。", 3, "ポップアップ ウィンドウ", 0)
このページの上

例外(try、catch、finally)

変数の$ErrorActionPreferenceの値により、エラーメッセージは表示されない場合があります。
catchの後にエラーの型を指定できます。複数ある場合はカンマで区切ります。catch [System.Net.WebException], [System.IO.IOException]
finallyでリソースの解放など後処理をします。
Set-PSDebug -Strict 
$_ErrorActionPreference = $ErrorActionPreference
$ErrorActionPreference = "Stop"

try
{
    Write-Host (1 / 0)
    Write-Host "上の行でエラーなので、この行は実行されません。"
    Exit 0
}
catch 
{
    Write-Error ($Error[0].Exception.Message)
    Exit 1
}
finally
{
    $ErrorActionPreference = $_ErrorActionPreference
}
PS > .\a.ps1
C:\bin\PowerShell\Sample\a.ps1 : 0 で除算しようとしました。
発生場所 C:\bin\PowerShell\Sample\a.ps1:13 文字:5
+     Write-Error ($Error[0].Exception.Message)
+     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [Write-Error], WriteErrorException
    + FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException,a.ps1
コマンドレットによってはパラメーターの-ERRORACTIONでも設定できます。
-ERRORACTION [ CONTINUE | IGNORE | INQUIRE | SILENTLYCONTINUE | STOP | SUSPEND ]

throwで例外を投げます。
throw "エラー"

エラーをトラップする、trapもあります。trapはエラーの発生場所よりも後に記載できます。
Write-Host "開始"
$n = 1 / 0
Write-Host "1 / 0 = $n"  # 上の行でエラーが発生するので表示されません。

trap {
    # エラーメッセージが表示されます。
    # continue # continueは処理を再開します。(エラーメッセージは自分で表示してください)
}
開始
0 で除算しようとしました。
発生場所 C:\bin\PowerShell\Sample\a.ps1:2 文字:1
+ $n = 1 / 0
+ ~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [], ParentContainsErrorRecordException
    + FullyQualifiedErrorId : RuntimeException
このページの上