今日は、改めてMicrosoftのサイトを見返してPowerShellの勉強をしました。
詳細をしっかり学びたい方は、本家のサイト見て下さい。
概要から含め、ザザザーッと基本構文からフォーム利用事例のサンプルまで走り抜けて作ったメモを張り付けていきます。
細かな説明は抜きにしても、こんな感じの1行目メモとサンプルコードをまとめるだけで技術的な概要はつかめるようになるのでおすすめです。
各セクションごとに、さんぷるこーどばんくの方にもメニュー化して追加しておいた。
これで備忘録としても引き出しやすい。。。(完全に個人メモですが。)
1.概要
- コメントアウトはシャープ(#) 複数行コメントは<# ~ #>
- 変数は「$変数名」
- 変数名が二重引用符内に存在した場合、それを対応する値に置き換えようと試みます。
- 一重引用符を使用した場合、変数値の置き換えは行われません。
そのまま.ps1ファイル実行しようとすると署名の警告でるから、こんな記述でbatファイルから起動するのがオススメ。
powershell -ExecutionPolicy RemoteSigned -File ~.ps1
ヘルプ機能から基本構文、環境に関わる部分。
@(...)で配列、@{...}で連想配列は抑えておこう。
# 変数の削除 $ie = $null # または Remove-Variable ie # ヘルプの表示 Get-Help コマンドレット コマンドレット -? # より詳細なヘルプ情報 Get-Help コマンドレット -Detailed # ヘルプ記事のすべてを表示 Get-Help コマンドレット -Full # PowerShellバージョンの確認 Get-Host # 詳細プロパティにアクセスする場合 $host.Version $host.Version.Major # コマンドレットから直接詳細プロパティを呼び出す場合は(カッコ)で囲む (Get-Host).Version # コマンドレットの検索 例:「-Service」で終わるコマンドレットを表示 Get-Command *-Service # 特定の動詞を含むコマンド一覧(Getを含む) Get-Command -Verb Get # 同じ種類のオブジェクトに影響を及ぼすコマンド一覧(Serviceの場合) Get-Command -Noun Service # コマンドレットの構文を取得 Get-Command コマンドレット -Syntax # Dosコマンドも使えるけども、本当はコマンドに該当するコマンドレット名がある。 # 関連付けられたコマンドレット名を表示する方法 Get-Alias dir <# Aliasの例 Get-Item ⇒ gi Set-Item ⇒ si Get-Location ⇒ gl Set-Location ⇒ sl Get-Command ⇒ gcm Get-Alias ⇒ gal #> # エイリアスの作成 Set-Alias -Name gi -Value Get-Item # すべての変数をクリア Remove-Variable -Name * -Force -ErrorAction SilentlyContinue # すべての PowerShell 変数を表示 Get-ChildItem variable: # オブジェクトがどんな名前のメソッドやプロパティを持っているか表示(パイプして使う) Get-Member # 配列の宣言 @(arg...) $Computers = @("Server1", "Server2", "Server3") # 連想配列の宣言 @{id=val} $dic = @{var1=1; var2="b"} <# 自動変数 #> # 入力行一行分 $_ # 入力行の行頭単語 $^ # 入力行の行末単語 $$ # 直前のコマンド実行結果のBool値 $? # 引数リスト $Args # 偽のBool値 $False # ドライブレター込みのホームディレクトリパス $Home # 直前のコマンドの戻り値 $LastExitCode # 実行コマンド自身の情報 $MyInvocation # awkでお馴染みの出力時フィールドセパレータ $OFS # PowerShellのバージョン情報 $PsVersionTable # ドライブレター込みのカレントディレクトパス $Pwd # 真のBool値 $True
2.基本的なコマンドレット
出力の制御・整形、拡張機能の使い方さわり部分まで
# 並べ替え 降順の場合は、-Descending Sort-Object <# 出力のレイアウト #> # 単一項目 Format-Wide # リスト ビュー Format-List # 表形式 Format-Table # 一部選択 Select-Object # 出力内容のフィルタリング Where-Object -FilterScript { フィルタ内容 } # フィルタ内容で使える比較演算子 <# -eq ⇒ 次の値と等しい -ne ⇒ 次の値と等しくない -lt ⇒ 次の値未満 -le ⇒ 次の値以下 -gt ⇒ 次の値より大きい -ge ⇒ 次の値以上 -like ⇒ 次の文字列と類似 (テキストのワイルドカード比較) -nolike ⇒ 次の文字列と類似していない (テキストのワイルドカード比較) -contains ⇒ [内容に含む] -notcontains ⇒ [次の値を含まない] #> # フィルタ内容で使える論理演算子 <# -and -or -not ! #> # 繰り返し処理 ForEach-Object デフォルトでAliasあり(foreach、%) Get-WmiObject -Class Win32_LogicalDisk | ForEach-Object -Process {($_.FreeSpace)/1024.0/1024.0} # コンソール出力のページング Get-Command | Out-Host -Paging # 出力の破棄 Get-Command | Out-Null # データの印刷 Get-Command Get-Command | Out-Printer -Name 'Microsoft Office Document Image Writer' # データの保存(デフォルトはUnicode) Get-Process | Out-File -FilePath C:\temp\processlist.txt Get-Process | Out-File -FilePath C:\temp\processlist.txt -Encoding ASCII # 現在の場所の取得 Get-Location # 現在の場所の設定 Set-Location -Path C:\Windows # 最近使用した場所の保存と呼び出し Push-Location -Path "Local Settings" Push-Location -Path Temp Get-Location # -> C:\Documents and Settings\PowerUser\Local Settings\Temp Pop-Location Get-Location # -> C:\Documents and Settings\me\Local Settings # フォルダー内のすべての項目を直接取得 # Forceで非表示の項目やシステム項目を表示 # Recurseで内包されている項目を表示 # Include 該当 # Exclude 除外 Get-ChildItem -Path C:\ -Force # ファイルとフォルダーのコピー # Force 上書き Copy-Item -Path C:\boot.ini -Destination C:\boot.bak # 再帰的に Copy-Item C:\temp\test1 -Recurse C:\temp\DeleteMe # 絞り込みして Copy-Item -Filter *.txt -Path c:\data -Recurse -Destination C:\temp\text # ファイルとフォルダーの作成 New-Item -Path 'C:\temp\New Folder' -ItemType Directory New-Item -Path 'C:\temp\New Folder\file.txt' -ItemType File # フォルダー内のすべてのファイルとフォルダーの削除 Remove-Item -Path C:\temp\DeleteMe # 内包されている項目ごとに削除の確認が行われないようにする場合 Remove-Item -Path C:\temp\DeleteMe -Recurse # 配列へのテキスト ファイルの読み込み(行ごとに要素化した配列になる) Get-Content -Path C:\boot.ini # 行数の取得 (Get-Content -Path C:\boot.ini).Length
3.コンピュータの制御
マシン自体の制御、レジストリ操作まで
# コンピューターをロックする rundll32.exe user32.dll,LockWorkStation # ログオフする logoff # または shutdown.exe -l # コンピューターをシャットダウンする Stop-Computer # オペレーティング システムを再起動する Restart-Computer # コンピューターを強制的に直ちに再起動する Restart-Computer -Force # 名前が "ex" で始まるプロセスを取得 Get-Process -Name ex* # プロセスの停止 Stop-Process -Name プロセス名 # ConFirmパラメーターで確認メッセージ表示 Stop-Process -Name t*,e* -Confirm # 応答のないアプリケーションをすべて停止する Get-Process | Where-Object -FilterScript {$_.Responding -eq $false} | Stop-Process # サービスの取得 Get-Service -Name se* Get-Service -DisplayName se* # そのサービスに依存するサービスを取得 Get-Service -Name サービス名 -DependentServices # そのサービスが依存しているサービスを取得 Get-Service -Name サービス名 -RequiredServices # サービスの停止 Stop-Service -Name サービス名 # サービスの開始 Start-Service -Name サービス名 # サービスの一時停止 Suspend-Service -Name サービス名 # サービスの再開 Restart-Service -Name サービス名 # レジストリ エントリの一覧表示 Get-Item -Path Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion | Select-Object -ExpandProperty Property Get-ItemProperty -Path Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion # CurrentVersion レジストリのコンテナーに変更 Set-Location -Path Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion # 1つのレジストリ エントリの取得 Get-ItemProperty -Path HKLM:\Software\Microsoft\Windows\CurrentVersion -Name DevicePath # 1つのレジストリ エントリの設定 $value = Get-ItemProperty -Path HKCU:\Environment -Name Path $newpath = $value.Path += ";C:\src\bin\" Set-ItemProperty -Path HKCU:\Environment -Name Path -Value $newpath # 新しいレジストリ エントリの作成 New-ItemProperty -Path HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion -Name PowerShellPath -PropertyType String -Value $PSHome # レジストリ エントリの名前変更 Rename-ItemProperty -Path HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion -Name PowerShellPath -NewName PSHome # レジストリ エントリの削除 Remove-ItemProperty -Path HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion -Name PSHome Remove-ItemProperty -Path HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion -Name PowerShellPath
4.トピックとして、Alias一覧
Get-Item Alias:
このコマンドでデフォルト状態で登録されているAliasの一覧
%の一文字の記号がForEach-Objectになっていて、%{...}でループってのは抑えておこう。
foreach -> ForEach-Object % -> ForEach-Object where -> Where-Object ? -> Where-Object ac -> Add-Content clc -> Clear-Content cli -> Clear-Item clp -> Clear-ItemProperty clv -> Clear-Variable compare -> Compare-Object cpi -> Copy-Item cpp -> Copy-ItemProperty cvpa -> Convert-Path dbp -> Disable-PSBreakpoint diff -> Compare-Object ebp -> Enable-PSBreakpoint epal -> Export-Alias epcsv -> Export-Csv fc -> Format-Custom fl -> Format-List ft -> Format-Table fw -> Format-Wide gal -> Get-Alias gbp -> Get-PSBreakpoint gc -> Get-Content gci -> Get-ChildItem gcm -> Get-Command gdr -> Get-PSDrive gcs -> Get-PSCallStack ghy -> Get-History gi -> Get-Item gl -> Get-Location gm -> Get-Member gmo -> Get-Module gp -> Get-ItemProperty gpv -> Get-ItemPropertyValue gps -> Get-Process group -> Group-Object gsv -> Get-Service gu -> Get-Unique gv -> Get-Variable iex -> Invoke-Expression ihy -> Invoke-History ii -> Invoke-Item ipmo -> Import-Module ipal -> Import-Alias ipcsv -> Import-Csv measure -> Measure-Object mi -> Move-Item mp -> Move-ItemProperty nal -> New-Alias ndr -> New-PSDrive ni -> New-Item nv -> New-Variable nmo -> New-Module oh -> Out-Host rbp -> Remove-PSBreakpoint rdr -> Remove-PSDrive ri -> Remove-Item rni -> Rename-Item rnp -> Rename-ItemProperty rp -> Remove-ItemProperty rmo -> Remove-Module rv -> Remove-Variable rvpa -> Resolve-Path sal -> Set-Alias sasv -> Start-Service sbp -> Set-PSBreakpoint sc -> Set-Content select -> Select-Object si -> Set-Item sl -> Set-Location sleep -> Start-Sleep sort -> Sort-Object sp -> Set-ItemProperty saps -> Start-Process start -> Start-Process spps -> Stop-Process spsv -> Stop-Service sv -> Set-Variable tee -> Tee-Object write -> Write-Output irm -> Invoke-RestMethod iwr -> Invoke-WebRequest asnp -> Add-PSSnapin gsnp -> Get-PSSnapin gwmi -> Get-WmiObject iwmi -> Invoke-WmiMethod ogv -> Out-GridView ise -> powershell_ise.exe rsnp -> Remove-PSSnapin rwmi -> Remove-WmiObject swmi -> Set-WmiInstance shcm -> Show-Command trcm -> Trace-Command wget -> Invoke-WebRequest curl -> Invoke-WebRequest lp -> Out-Printer cat -> Get-Content cd -> Set-Location clear -> Clear-Host cp -> Copy-Item h -> Get-History history -> Get-History kill -> Stop-Process ls -> Get-ChildItem man -> help mount -> New-PSDrive md -> mkdir mv -> Move-Item popd -> Pop-Location ps -> Get-Process pushd -> Push-Location pwd -> Get-Location r -> Invoke-History rm -> Remove-Item rmdir -> Remove-Item echo -> Write-Output cls -> Clear-Host chdir -> Set-Location copy -> Copy-Item del -> Remove-Item dir -> Get-ChildItem erase -> Remove-Item move -> Move-Item rd -> Remove-Item ren -> Rename-Item set -> Set-Variable type -> Get-Content icm -> Invoke-Command clhy -> Clear-History gjb -> Get-Job rcjb -> Receive-Job rjb -> Remove-Job sajb -> Start-Job spjb -> Stop-Job wjb -> Wait-Job sujb -> Suspend-Job rujb -> Resume-Job npssc -> New-PSSessionConfigurationFile ipsn -> Import-PSSession epsn -> Export-PSSession cnsn -> Connect-PSSession dnsn -> Disconnect-PSSession nsn -> New-PSSession gsn -> Get-PSSession rsn -> Remove-PSSession etsn -> Enter-PSSession rcsn -> Receive-PSSession exsn -> Exit-PSSession sls -> Select-String CFS -> ConvertFrom-String fhx -> Format-Hex gcb -> Get-Clipboard gin -> Get-ComputerInfo gtz -> Get-TimeZone scb -> Set-Clipboard stz -> Set-TimeZone
5..NETとCOMとWMIのオブジェクト
この辺からコアな感じになってくる。。。
特に、インスタンスの作成と静的クラスの表現の違いは抑えておこう。
# .NET Framework クラスの新しいインスタンスを作成 例:イベントログ # -ArgumentListでコンストラクタ呼び出し $AppLog = New-Object -TypeName System.Diagnostics.EventLog -ArgumentList Application # COM オブジェクトの作成 $WshShell = New-Object -ComObject WScript.Shell $WshNet = New-Object -ComObject WScript.Network $ScrDic = New-Object -ComObject Scripting.Dictionary $ScrFso = New-Object -ComObject Scripting.FileSystemObject $WshShell | Get-Member # IEの制御 $ie = New-Object -ComObject InternetExplorer.Application $ie.Visible = $true $ie.Navigate("https://devblogs.microsoft.com/scripting/") $ie.Document.Body.InnerText $ie.Quit() # 静的なクラスとメソッドはNew-Objectでは作成できない # System.Environment、System.Mathなど。静的なクラスは[クラス名]と表記する。 [System.Environment] [Math] # Get-Member で静的メンバーを表示するには、Static パラメーターを指定 [System.Environment] | Get-Member -Static # 静的プロパティの表示には、コロンコロン:: # 例:Windows PowerShell の起動に使ったコマンドを表示 [System.Environment]::Commandline # 例:オペレーティング システムのバージョンを確認 [System.Environment]::OSVersion # System.Math クラスのメソッドを一覧表示 [System.Math] | Get-Member -Static -MemberType Methods # WMIオブジェクトを使う (オプションはデフォルトが-Classになる) Get-WmiObject Win32_OperatingSystem # プリンター接続の一覧表示 Get-WmiObject -Class Win32_Printer # コンピューターの IP アドレスの一覧表示 Get-WmiObject -Class Win32_NetworkAdapterConfiguration -Filter IPEnabled=$true -ComputerName . | Format-Table -Property IPAddress # コンピューターへの ping の送信 Get-WmiObject -Class Win32_PingStatus -Filter "Address='127.0.0.1'" -ComputerName . | Format-Table -Property Address,ResponseTime,StatusCode -Autosize
6.【基礎】メッセージボックスを出してみる。
Formsで最もシンプルな例。
Add-Type -AssemblyName System.Windows.Forms $result = [System.Windows.Forms.MessageBox]::Show("メッセージボックスのテスト","タイトル","YesNo","Question","Button2") If($result -eq "Yes"){ [void][System.Windows.Forms.MessageBox]::Show("Yesをクリック","タイトル","OK","Information") }Else{ [void][System.Windows.Forms.MessageBox]::Show("Noをクリック","タイトル","OK","Exclamation") }
7.【応用】UIを使うサンプル - 入力フォーム
違いをよく見て、感じろ。
Add-Type -AssemblyName System.Windows.Forms Add-Type -AssemblyName System.Drawing $form = New-Object System.Windows.Forms.Form $form.Text = 'Data Entry Form' $form.Size = New-Object System.Drawing.Size(300,200) $form.StartPosition = 'CenterScreen' $OKButton = New-Object System.Windows.Forms.Button $OKButton.Location = New-Object System.Drawing.Point(75,120) $OKButton.Size = New-Object System.Drawing.Size(75,23) $OKButton.Text = 'OK' $OKButton.DialogResult = [System.Windows.Forms.DialogResult]::OK $form.AcceptButton = $OKButton $form.Controls.Add($OKButton) $CancelButton = New-Object System.Windows.Forms.Button $CancelButton.Location = New-Object System.Drawing.Point(150,120) $CancelButton.Size = New-Object System.Drawing.Size(75,23) $CancelButton.Text = 'Cancel' $CancelButton.DialogResult = [System.Windows.Forms.DialogResult]::Cancel $form.CancelButton = $CancelButton $form.Controls.Add($CancelButton) $label = New-Object System.Windows.Forms.Label $label.Location = New-Object System.Drawing.Point(10,20) $label.Size = New-Object System.Drawing.Size(280,20) $label.Text = 'Please enter the information in the space below:' $form.Controls.Add($label) $textBox = New-Object System.Windows.Forms.TextBox $textBox.Location = New-Object System.Drawing.Point(10,40) $textBox.Size = New-Object System.Drawing.Size(260,20) $form.Controls.Add($textBox) $form.Topmost = $true $form.Add_Shown({$textBox.Select()}) $result = $form.ShowDialog() if ($result -eq [System.Windows.Forms.DialogResult]::OK) { $x = $textBox.Text $x }
8.【応用】UIを使うサンプル - リストボックス
7との違いを見て、感じろ。
Add-Type -AssemblyName System.Windows.Forms Add-Type -AssemblyName System.Drawing $form = New-Object System.Windows.Forms.Form $form.Text = 'Select a Computer' $form.Size = New-Object System.Drawing.Size(300,200) $form.StartPosition = 'CenterScreen' $OKButton = New-Object System.Windows.Forms.Button $OKButton.Location = New-Object System.Drawing.Point(75,120) $OKButton.Size = New-Object System.Drawing.Size(75,23) $OKButton.Text = 'OK' $OKButton.DialogResult = [System.Windows.Forms.DialogResult]::OK $form.AcceptButton = $OKButton $form.Controls.Add($OKButton) $CancelButton = New-Object System.Windows.Forms.Button $CancelButton.Location = New-Object System.Drawing.Point(150,120) $CancelButton.Size = New-Object System.Drawing.Size(75,23) $CancelButton.Text = 'Cancel' $CancelButton.DialogResult = [System.Windows.Forms.DialogResult]::Cancel $form.CancelButton = $CancelButton $form.Controls.Add($CancelButton) $label = New-Object System.Windows.Forms.Label $label.Location = New-Object System.Drawing.Point(10,20) $label.Size = New-Object System.Drawing.Size(280,20) $label.Text = 'Please select a computer:' $form.Controls.Add($label) $listBox = New-Object System.Windows.Forms.ListBox $listBox.Location = New-Object System.Drawing.Point(10,40) $listBox.Size = New-Object System.Drawing.Size(260,20) $listBox.Height = 80 [void] $listBox.Items.Add('atl-dc-001') [void] $listBox.Items.Add('atl-dc-002') [void] $listBox.Items.Add('atl-dc-003') [void] $listBox.Items.Add('atl-dc-004') [void] $listBox.Items.Add('atl-dc-005') [void] $listBox.Items.Add('atl-dc-006') [void] $listBox.Items.Add('atl-dc-007') $form.Controls.Add($listBox) $form.Topmost = $true $result = $form.ShowDialog() if ($result -eq [System.Windows.Forms.DialogResult]::OK) { $x = $listBox.SelectedItem $x }
9.【応用】UIを使うサンプル - カレンダーによる日付選択
ただただ、感じろ。
Add-Type -AssemblyName System.Windows.Forms Add-Type -AssemblyName System.Drawing $form = New-Object Windows.Forms.Form -Property @{ StartPosition = [Windows.Forms.FormStartPosition]::CenterScreen Size = New-Object Drawing.Size 243, 230 Text = 'Select a Date' Topmost = $true } $calendar = New-Object Windows.Forms.MonthCalendar -Property @{ ShowTodayCircle = $false MaxSelectionCount = 1 } $form.Controls.Add($calendar) $OKButton = New-Object Windows.Forms.Button -Property @{ Location = New-Object Drawing.Point 38, 165 Size = New-Object Drawing.Size 75, 23 Text = 'OK' DialogResult = [Windows.Forms.DialogResult]::OK } $form.AcceptButton = $OKButton $form.Controls.Add($OKButton) $CancelButton = New-Object Windows.Forms.Button -Property @{ Location = New-Object Drawing.Point 113, 165 Size = New-Object Drawing.Size 75, 23 Text = 'Cancel' DialogResult = [Windows.Forms.DialogResult]::Cancel } $form.CancelButton = $CancelButton $form.Controls.Add($CancelButton) $result = $form.ShowDialog() if ($result -eq [Windows.Forms.DialogResult]::OK) { $date = $calendar.SelectionStart Write-Host "Date selected: $($date.ToShortDateString())" }
10.【番外編】リモートマシンの制御
いずれ、必要になる日がくるであろう。
ここでリモート操作に関する記述を見た、という記憶だけ作っておけ。
<# 操作される側の設定 #> Enable-PSRemoting # または (内部的には同じ?) Set-ExecutionPolicy RemoteSigned -Force Set-WSManQuickConfig -Force # 操作する側の設定 (winrmがエラーになる場合は、-forceを-pにする。) Set-ExecutionPolicy RemoteSigned -Force winrm quickconfig -force Set-Item WSMan:\localhost\Client\TrustedHosts * -Force # リモート接続 Enter-PSSession 接続先 -Credential 接続アカウント # コマンドやスクリプトをリモート投入し、結果をローカルに返す $Return = Invoke-Command TergetServer -ScriptBlock { dir c:\ } # リモートセッションの終了 Exit-PSSession <# セッションを事前に取得してコマンド投入 #> # セッションの取得 $PSSession = New-PSSession TergetServer -Credential TergetServer\administrator # コマンドの投入 Invoke-Command -Session $PSSession -ScriptBlock { dir c:\ } Invoke-Command -Session $PSSession -ScriptBlock { dir d:\ } # セッションの解放 Remove-PSSession $PSSession # リモートセッションに引数を渡す例 $Drive = "C:\" Invoke-Command TergetServer -ScriptBlock { dir $args[0] } -ArgumentList $Drive # リモートに格納されているスクリプトを起動 Invoke-Command TergetServer -ScriptBlock { c:\Test\submit.ps1 $args[0] } -ArgumentList "aaa" # ローカルにあるスクリプトを投入 Invoke-Command TergetServer -FilePath c:\windowsupdate\autowindowsupdate.ps1 -ArgumentList "aaaa" # パラレル バッチ操作 $Return = Invoke-Command log -ScriptBlock { dir c:\ } -AsJob
.NETでも、COMでも、WMIでも使える。使い方もわかった。
あとは、『何をしたいか?』ですね。