「[[マイクロソフト系技術情報 Wiki>http://techinfoofmicrosofttech.osscons.jp/]]」は、「[[Open棟梁Project>https://github.com/OpenTouryoProject/]]」,「[[OSSコンソーシアム .NET開発基盤部会>https://www.osscons.jp/dotNetDevelopmentInfrastructure/]]」によって運営されています。 -戻る --[[シェル]] --[[スクリプティング]] * 目次 [#a80353b5] #contents * 概要 [#l26e6c22] PowerShell の勘所、 -.ps1ファイルと実行ポリシー -param -関数 -パイプライン -オブジェクトへプロパティの追加 -エラー処理 -debugの方法 -cmdletの作り方 などのトピック情報を纏めています。 *特徴 [#r9b4dbd1] -Windows PowerShell - Wikipedia~ https://ja.wikipedia.org/wiki/Windows_PowerShell **オブジェクトベースのシェル [#h3946920] 以前から、オブジェクトベースのプログラム、スクリプト(perl、[[WSH>VBS]])などは存在したが、~ PowerShellが唯一のオブジェクト・ベースのシェル(perlに似ている)である。~ #OSレイヤから少々遠いためシェルというよりシェルスクリプトという意見もある。 -PowerShell:Windowsでおそらく最高のシェル~ http://programming-aip.blogspot.jp/2013/01/powershellwindows.html --最近は、コマンドレットも充実してきて人気も出てきていると思います。 --分析中で面白いのは、~ 「大量の出力を扱う場合は、オブジェクト・ベースが仇となる場合もある」~ という所である。 ---理由は、大量テキスト処理可能なCUIのEXEにパイプさせれば上手く編集できるため。 ---しかし、そもそも、Windowsの場合、強力なテキスト処理を実装するCUIのEXEが充実していない。 **Cmd.exeを置き換えるものではない [#l34fd736] 別物として使用する必要がある。 -例えば、 --ipconfig などのコマンドを実行すると、おなじみの出力が表示される。 --netshなどのコマンドを実行して設定するぐらいはPowerShellで実行可能。 -ただし、Cmd.exeを置き換えるものではない。 --標準出力をテキストとしてパイプできない。 --[[BAT]]の構文を使用できない。 * コンポーネントのダウンロード [#ibc8b5fb] PowerShell の各バージョンは、以下のOSに添付されているか、別途ダウンロードできます。~ 新しいOSほど、新しいPowerShellに対応します。 また、旧OSでは、新しいPowerShellのサポートがありません。 PowerShellのバージョンに依存しそうな場合は、対象とするOSが何か確認ください。~ |--Windows PC-- | PowerShell 1.0 | PowerShell 2.0 | PowerShell 3.0 |PowerShell 4.0 | |Windows XP SP2 | PS1 | | n/a | n/a | |Windows XP SP3 | PS1 | PS2 | n/a | n/a | |Windows Vista SP1 | PS1 | PS2 | n/a | n/a | |Windows Vista SP2 | PS1 | PS2 | n/a | n/a | |Windows 7 | | OS添付 | n/a | n/a | |Windows 7 SP1 | | OS添付 | PS3 | PS4 | |Windows 8 | | OS添付(*1) | OS添付 | PS4 | |Windows 8.1 | | OS添付(*1) | | OS添付 | (*1) Windows 8/8.1 の PowerShell 2.0 スクリプトは、PowerShell 4.0 の下位互換で実行できます。~ PowerShell を -version 2.0 指定で実行する場合は .NET Framework 3.5 をインストールすると有効になります。~ ~ |--Windows Server-- | PowerShell 1.0 | PowerShell 2.0 | PowerShell 3.0 | PowerShell 4.0 | |Windows Server 2003R2 | PS1 | | n/a | n/a | |Windows Server 2003 SP2 | PS1 | PS2 | n/a | n/a | |Windows Server 2008 SP1 | OS添付 | PS2 | PS3 | n/a | |Windows Server 2008 SP2 | OS添付 | PS2 | PS3 | n/a | |Windows Server 2008R2 SP1 | | OS添付 | PS3 | PS4 | |Windows Server 2012 | | OS添付(*1) | OS添付 | PS4 | |Windows Server 2012 R2 | | OS添付(*1) | | OS添付 | (*1) Windows Server 2012/2012R2 の PowerShell 2.0 スクリプトは、PowerShell 4.0 の下位互換で実行できます。~ PowerShell を -version 2.0 指定で実行する場合は .NET Framework 3.5 をインストールすると有効になります。~ **PS1 [#k0e3e8a8] -http://support.microsoft.com/kb/926140 (XP/2003用) -http://support.microsoft.com/kb/928439 (Vista用) **PS2 [#gc3cf7d4] -http://support.microsoft.com/kb/926139 (英語版) -http://support.microsoft.com/kb/968929 (日本語版) **PS3 [#de124eac] http://www.microsoft.com/en-us/download/details.aspx?id=34595 (現在、英語版) **PS4 Preview [#sc27693f] http://www.microsoft.com/en-us/download/details.aspx?id=39347 (現在、英語版) * 勘所1 [#x44711fb] ** 実行方法 [#v29d2093] スタートメニューからPowerShell コマンドプロンプトを開いても、 コマンドプロンプトから PowerShell.exe を実行しても、 PowerShell を手で逐次実行できます。 ** .ps1ファイルと実行ポリシー [#i305d670] PowerShell の スクリプトファイルは、 拡張子 .ps1 のテキストファイル です。~ ps1スクリプトファイルは、コマンドプロンプトの中で「powershell .\script.ps1」、または、PowerShellコマンドプロンプトの中で「.\script.ps1」の様にして実行できますが、既定では、PowerShell スクリプト そのものについて、実行が抑止されています。 .ps1を実行するには、以下の設定変更または回避方法を検討します。~ -実行ポリシーを変更 -PowerShell -Command - 構文でスクリプトを読み込ませる -PowerShellコマンドプロンプトの中に貼り付ける ***実行ポリシーを変更 [#jdedd4bd] 実行ポリシーを変更するには、 Set-ExecutionPolicy を実行します。~ Set-ExecutionPolicy RemoteSigned RemoteSigned を指定すると、ローカルコンピュータの.ps1ファイルか、ファイル共有またはダウンロードした署名付きの.ps1ファイルが実行できます。~ Set-ExecutionPolicy の設定は、恒久的に設定されます。~ Bypass (=無制限に.ps1を実行可能) に変更してそのまま放置しないように。~ 用が済んだら、既定値の Restricted に戻しておきます。~ Set-ExecutionPolicy Restricted scope を指定して、設定変更の対象を限定することもできます。~ Set-ExecutionPolicy RemoteSigned -Scope CurrentUser CurrentUser はこのコマンドを実行したユーザーだけ、設定変更します。~ (メンテナンスや運用作業で.ps1を使用する場合は、通常時にどの実行ポリシーにしておくか、検討ください。.ps1ファイルに署名を行い、AllSigned にしておくか。 あるいは RemoteSigned にしておくか。 それとも Restricted にしておき、都度実行ポリシーを変更するか。等)~ ***PowerShell -Command - 構文でスクリプトを読み込ませる [#wc5bad1b] PowerShell コマンドプロンプトに手入力して逐次実行するかわりに、 -Command - を使用して、標準入力からコマンドを連続実行することができます。~ 手打ちと同じなので、 Set-ExecutionPolicy Restricted のままでも、実行可能です。~ 実行ポリシーをどうしても変更したくない場合の次善策として、使用できるか検討する意味は有ります。~ 下の例の様に、 batファイルとecho を組み合わせて、引数を与えることも出来ます。~ ***batファイル [#c35ff7a4] ps_test.bat @( echo $arg1 = "%~1" echo $arg2 = "%~2" type ps_test.ps1 ) | powershell -command - ***ps1ファイル [#k5dc1c30] ps_test.ps1 function main() { $a = ($arg1 + $arg2) $b = ([int]$arg1 + [int]$arg2) write-output "string : $arg1 + $arg2 = $a" write-output "integer : $arg1 + $arg2 = $b" } $err=0 $ErrorActionPreference = "stop" try { $log = main } catch [Exception] { $err=1 $log = $_ } write-output $log exit $err ***実行例: [#cb11fd36] ps_test 1 2 string : 1 + 2 = 12 integer : 1 + 2 = 3 .ps1 の try/catch の } の下に空行がることに注意。~ powershellコマンドを -Command - で読み込ませる場合、手入力と同じように。コードブロックの後に空行が必要です。~ これを実行すると、echo の2つが ps_test.ps1 の先頭に挿入されて、 PowerShellコマンドプロンプトに手入力して逐次実行することになります。~ 標準入力を手入力の代わりに使用してしまうため、スクリプトのなかでキー打鍵待ちのようなことは難しくなります。~ ***PowerShellコマンドプロンプトの中に貼り付ける [#g659c33b] PowerShellコマンドプロンプトの画面に、クリップボードからスクリプトを貼り付けます。~ スクリプトは、テキストファイルなどで用意しておき、メモ帳などで開いたら、テキスト全体をクリップボードにコピー。それを、PowerShellコマンドプロンプトに貼り付けます。~ 実行ポリシーを変更しない、上のようなバッチファイルも不可であれば、手動でPowerShellコマンドプロンプトへ貼り付けをするか、PowerShellの使用をあきらめるしかありません。~ ** 引数 [#r5aa018b] ps1スクリプトへの引数 ps1ファイルの最初に param(..) を記述することで、引数を定義出来ます。 param ( [string]$filename, [int]$count = 5 ) [型] と引数名、 省略時の既定値 も指定できます。~ 引数名を定義すると 「powersehll .\test.ps1 -filename c:\temp\testt.txt -count 2」の様に -引数名 として使用できます。 下の様に 引数名に 属性を付加することも出来ます。 param ( [Parameter(Mandatory=$True)] [string]$filename, [int]$count = 5 ) Mandatory を指定すると、必須の引数になり、省略した場合には、PowerShellによって、追加の引数を要求するプロンプトが表示されます。 詳細は、下のページを参照。 -Windows PowerShell: スクリプト作成の短期集中講座 http://technet.microsoft.com/ja-jp/magazine/hh551144.aspx -Windows PowerShell: パラメーターを定義する~ http://technet.microsoft.com/ja-jp/magazine/jj554301.aspx~ または、PowerShellコマンドプロンプト内で、「get-help about_Functions_Advanced_Parameters」を参照してください。~ ** 変数 [#n585d270] 変数は $ で始まる 英数字記号 の名前を使用します。~ 後述の様に スコープ($global:, $script:) をつけることも出来ます。~ 下の様に ${ } で囲むと、名前にスペースを含むこともできますが、混乱やスペルミスの元になりやすいので避けましょう。 PS E:\temp> ${var test 1} = 123 PS E:\temp> $a = ${var test 1} + "123" PS E:\temp> $a 246 PS E:\temp> 未初期化の初期状態は $null と同じです。~ 文脈によっては 0 や "" (空文字列) と解釈されます。 PS E:\temp> $var001 PS E:\temp> $var001 -eq 0 False PS E:\temp> $var001 -eq $null True PS E:\temp> $a1 = $var001 + 2 PS E:\temp> $a1 2 PS E:\temp> $a1 = $var001 + "abc" PS E:\temp> $a1 abc PS E:\temp> 上の例では、変数 $var001 は未初期化なので、 $null と同じです。~ 変数をそのまま出力すると、$null は 何も表示されません。~ また、 -eq 比較演算子を使って、 0 や $null と比較すると、$null であることが判断できます。~ ~ 未初期化変数は、数値を足し算した場合は、0 が、文字列を連結した場合は、"" が、それぞれ仮定されます。 Set-StrictMode を使用すると、未初期化変数を参照する際にエラーとして検出できます。 PS E:\temp> Set-StrictMode -Version 1.0 PS E:\temp> $a1 = $var001 + 2 変数 '$var001' は、設定されていないために取得できません。 発生場所 行:1 文字:14 + $a1 = $var001 <<<< + 2 + CategoryInfo : InvalidOperation: (var001:Token) []、RuntimeExcep tion + FullyQualifiedErrorId : VariableIsUndefined PS E:\temp> 変数については、下も参照ください。 -Windows Powershell 変数の機能~ http://lab.technet.microsoft.com/ja-jp/magazine/cc162486 Set-StrictMode については、 「get-help Set-StrictMode」、 または、下のページを参照ください。~ -Set-StrictMode~ http://technet.microsoft.com/ja-jp/library/dd347614.aspx ** 変数のスコープ [#y88b36f0] PowerShellの変数は、変数を使用する場所がスコープの範囲になります。~ functionの中、PowerShellモジュールの中、.ps1スクリプトの中、などがスコープの境界になります。 ***スクリプト: [#j96f9046] ps_scope1.ps1 $global:g1 = "0" $script:s1 = "0" $v1 = "0" write-host "before : g1=$global:g1 s1=$script:s1 v1=$v1 v2=$v2" function test1 { write-host "start test1 : g1=$global:g1 s1=$script:s1 v1=$v1 v2=$v2" $global:g1 = "1" $script:s1 = "1" $v1 = "1" $v2 = "1" write-host "end test1 : g1=$global:g1 s1=$script:s1 v1=$v1 v2=$v2" } test1 write-host "after : g1=$global:g1 s1=$script:s1 v1=$v1 v2=$v2" ***実行例: [#kad3ae1b] E:\temp>powershell Windows PowerShell Copyright (C) 2009 Microsoft Corporation. All rights reserved. PS E:\temp> Set-ExecutionPolicy RemoteSigned -Scope CurrentUser PS E:\temp> .\ps_scope1.ps1 before : g1=0 s1=0 v1=0 v2= start test1 : g1=0 s1=0 v1=0 v2= end test1 : g1=1 s1=1 v1=1 v2=1 after : g1=1 s1=1 v1=0 v2= PS E:\temp> write-host "g1=$global:g1 s1=$script:s1 v1=$v1 v2=$v2" g1=1 s1= v1= v2= PS E:\temp> $v1 は .ps1 の中で最初に設定している値が、 関数test1 の中でも参照できますが、関数test1 の中で設定した値は、関数test1 の外では有効ではありません。~ $v2 は .ps1 の中で未定義のため、 関数test1 の中でのみ有効。~ $script:s1 $v1 $v2 とも、 .ps1 の中だけで有効なため、 スクリプトを終了した後で write-host しても値は設定されていない。~ $global:g1 は スコープがグローバルなので、スクリプトを終了しや後で write-host しても値は設定されたまま。~ 通常は、.ps1の中でスコープが閉じると考えておき、 .ps1の中から write-output 以外の方法でスクリプト呼び出し元へ返す情報がある場合に、$global: を使用するか検討するのがいいでしょう。~ あとは、.ps1 の中に限らず、関数間で共有の変数の場合、$script: を使用すると考えておけばいいでしょう。~ 変数のスコープは、「get-help about_Scopes」、または、下の情報も参考。~ -about_Scopes~ http://technet.microsoft.com/ja-jp/library/dd315289.aspx ** if文 [#b3a3550b] if文は、下の様に -で始まる比較演算子を使います。 $var1 = sub2 $arg1 $arg2 if ( ( $var1 -eq 1 ) -or ( $var1 -gt 10 ) ) { ... } 条件のANDやORは、 それぞれを ( ... )で囲んで -and や -or で結びます。 論理のANDやORによるビット演算は、 -band や -bor の -b で始まる演算子を使います。 $file = get-item $dirname if ( $file.Attributes -band [System.IO.FileAttributes]::Directory ) { ... } bit演算結果が0以外の場合は、真 とみなされます。 if文の演算子の詳細は、powershellコマンドプロンプトの中で 「get-help about_Comparison_Operators」を参照してください。 ** 配列 [#gfd0e13d] 配列は、以下の形式で定義できます。 $array1 = @() $array2 = @(1,2,3) $array3 = 1,2,3 ( ) で囲まなくても、「,」で並べると、配列になります。~ コマンドや関数への引数を「,」で区切った場合も配列になるので、書き間違いに注意。~ $ret1 = sub1 2,3,4 # これは @(2,3,4) の配列で引数1つ $ret2 = sub1 2 3 4 # これは 引数3つ $ret3 = sub1 2,3 4 # これは @(2,3)の配列1つと 数値4 の 引数2つ また、配列の添え字は、$変数名[添え字] で参照します。~ 添え字に 負数 を指定すると、配列の末尾からの添え字を指定できます。~ $var1 = $array2[1] # 上の $array2 から 2 を取り出す $var2 = $array2[-1] # 上の $array2 から 3 を取り出す 配列について詳しくは、 PowerShellコマンドプロンプトで「get-help about_array」 を参照ください。 ** パイプライン [#cac4db70] PowerShellの一番強力な機能が、パイプラインです。 Unix/Linuxのshellコマンドや、Windowsのコマンドプロンプトでも、「|」を使って、コマンドを複数並べてパイプラインが記述できます。~ ですが、それらは、標準出力のテキストを次のコマンドの標準入力へ渡す、にすぎません。~ PowerShellでは、PowerShellのオブジェクトをパイプで渡すことができます。~ そして、ほとんどのPowerShellコマンドがオブジェクトを出力します。~ また、オブジェクトには、多くのプロパティを含んでいます。~ 後処理のために、オブジェクトにプロパティを追加することもできます。~ このため、プロパティを判定してフィルタしたり、プロパティを使ってソートできます。~ 最後に Format-List や Format-Table などのコマンドを使って、一部のプロパティを整形して表示します。 .ps1スクリプト内で定義する関数(function)や、自作のCmdletでも、オブジェクトを返すようにしておくと、再利用しやすくなります。 パイプラインの例は、後述の オブジェクトへメンバー追加 の例を参照ください。 パイプラインの詳細は、PowerShellコマンドプロンプトで「get-help about_pipeline」を参照ください。 ** オブジェクトへメンバー追加 [#pbe1b175] PowerShellでは、Add-Member を使って、オブジェクトに動的にメンバーを追加できます。~ OSや他のライブラリが返したオブジェクトに、情報を追加しながら、パイプラインを使って、順次処理する。といったことができます。~ ***スクリプト: [#l3010bb9] function dirinfo { param( [Parameter(Mandatory = $true, ValueFromPipeline = $true)] [object]$dir, [boolean]$totalup = $false ) # 空っぽの配列 $dirs = @() # $dir へ プロパティ追加 $dir | Add-Member -MemberType NoteProperty -Name TotalFiles -Value 0 $dir | Add-Member -MemberType NoteProperty -Name TotalSize -Value 0 foreach ($f in (get-childitem $dir.FullName)) { if ( $f.Attributes -band [System.IO.FileAttributes]::Directory ) { # サブフォルダの情報 $ret = dirinfo $f $totalup if ( $totalup ) { # 末尾の情報を $dir へ加算 $dir.TotalFiles += $ret[-1].TotalFiles $dir.TotalSize += $ret[-1].TotalSize } $dirs += $ret # サブフォルダ全体を覚える } else { $dir.TotalFiles += 1 $dir.TotalSize += $f.Length $dirs += $f } } $dirs += $dir # $dir自身を末尾に覚える # 覚えたものをまとめて返す write-output $dirs } ***実行例: [#k8ba911b] dirinfo (get-item "c:\program files") | sort-object totalsize -Descending | where { $_.TotalSize -gt 1 } | select-object -first 5 | format-list -Property TotalFiles, TotalSize, Fullname (行は折り返して表示しています。実行する際は、1行に入力してください。) 実行例のパイプラインでは、以下のことをしています~ +get-item で C:\Program Files フォルダのオブジェクトを取得して、~ +dirinfo でサブフォルダのサイズを集計、~ +sort-obejct で TotalSize の大きい順に並び替えて、~ +where で TotalSize が 1以上のオブジェクトだけ抽出して、~ +select-object で 最初の 5 個だけ取り出し、~ +format-list で 特定のプロパティのみ表示。 Add-Member の解説については、下も参照ください。 -Windows PowerShell: オブジェクトをカスタマイズするさまざまな方法~ http://technet.microsoft.com/ja-jp/magazine/hh750381.aspx~ サブフォルダのファイルサイズを集計する例については、下も参照ください。 -コンピューターで多くの領域を占有しているフォルダーを確認する方法はありますか~ http://gallery.technet.microsoft.com/scriptcenter/4e83afe2-ebdf-414a-bfc9-36e76b7e9750 ** リモートコンピューターでコマンド実行 (Workgroup編) [#q2f99e22] Invoke-Command を使って、リモートでコマンド実行ができます。~ ただし、事前に構成を変更しておく必要があります。また、実行する要件によっては追加の構成が必要です。 ***リモート先でリモートコマンドを呼ばれる準備 (PowerShellを 管理者として実行) [#e6d26642] 1. PowerShellリモート処理を有効にする~ Enable-PSRemoting Enable-PSRemoting は、PowerShellを使ってリモートからコマンド実行できるように、以下の様な構成変更をまとめて行います。~ -- WinRM サービスを起動します。 -- WinRM サービスのスタートアップの種類を [自動] に設定します。 -- 任意の IP アドレスで要求を受け入れるためのリスナーを作成します。 -- WS-Management 通信のファイアウォール例外を有効にします。 -- "Microsoft.PowerShell" セッション構成がまだ登録されていない場合は登録します。 -- "Microsoft.PowerShell32" セッション構成が 64 ビット コンピューターでまだ登録されていない場合は登録します。 -- 登録済みのすべてのセッション構成のセキュリティ記述子から "Deny Everyone" 設定を削除します。 -- WinRM サービスを再起動して、変更を有効にします。 > %%解放しすぎる場合は(任意のIPアドレスで..など)、範囲を調整する必要があるか、検討ください。%%~ リモートから実行の可否を制御するには、ユーザーと権限(後述)、または、ファイルウォール例外("Windows リモート管理 (HTTP 受信)")のスコープ設定で行います。 2. PowerShellリモート処理可能なユーザーと権限の設定~ Set-PSSessionConfiguration Microsoft.Powershell -ShowSecurityDescriptorUI 実行すると権限を設定する画面が表示されるので、リモートから指定するユーザーと権限を追加。~ (Administratorsメンバー以外のユーザーを使用する場合に必要)~ ***リモートを呼び出す側の準備 (PowerShellを 管理者として実行) [#e15a4adf] 1. WinRM サービスを開始~ Start-Service WinRM WinRMサービスを開始していなければ実行します。~ 2. UACのリモート設定~ Set-ItemProperty -Path HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System -Name LocalAccountTokenFilterPolicy -Value 1 -Type DWord (上は、行を折り返しています、1行のコマンドです。) 管理者特権を維持するように設定変更します。~ これをしないと、下の wsman:localhost\client\trustedhosts の設定が出来ません。~ 3. 対象のコンピュータを 信頼されたホストの一覧に追加~ set-item wsman:localhost\client\trustedhosts -value リモートコンピュータ名 リモートコンピュータ名 が複数ある場合は、"リモートコンピュータ名,リモートコンピュータ名" の様に 文字列にして , で繋ぎます。~ 依存の設定値に追加する場合は、get-item で値を確認し、 , で連結して設定します。~ ※ LocalAccountTokenFilterPolicy と wsman:localhost\client\trustedhosts の関係について。~ wsman:localhost\client\trustedhosts を設定するためには、以下の条件があります。~ ・管理者実行のコマンドプロンプト(PowerShell) で行う場合は、LocalAccountTokenFilterPolicy を 1 にする~ ・ビルトイン Administrator で行う場合は、 LocalAccountTokenFilterPolicy の変更は不要~ wsman:localhost\client\trustedhosts を設定した後は、LocalAccountTokenFilterPolicy を 0 に戻しても構いません。~ (LocalAccountTokenFilterPolicy を 0 に戻してもすぐには設定不可能に戻りません。その場合はWinRMサービスを再起動します。)~ ***リモートでコマンドを実行 [#m345f230] 1. Invoke-Command を実行~ Invoke-Command -ComputerName リモートコンピュータ名 -Credential (get-credential) -ScriptBlock { リモートコマンド リモートコマンド引数... } (上は、行を折り返しています、1行のコマンドです。) (get-credential) によって、ユーザー名を入力する画面が開きます。~ -Credential (get-credential) を指定しないと、Invoke-Command を実行しているユーザーで、リモートコンピュータへ接続し、コマンド実行されます。~ ユーザー名を入力したくない場合は、 get-credential を先に行って、変数に入れておくか、-Credential を指定しないようにします。~ ***注意事項ほか [#gefb3061] -PowerShellでリモート実行するコマンドから、ファイル共有などのネットワーリソースへアクセスする際は、匿名ユーザーが使われます。~ リモートのコマンド実行の中からネットワークリソースへユーザー指定でアクセスする場合は、後述の [[ダブルホップ編>#ga559ccc]] を参照するか、 sysinternals の psexecツール を検討ください。( psexec は [[サービス・タスク系のいろいろ>サービス・タスク系のいろいろ#a18ceed3]] も参照ください。) -Invoke-Command は リモートとの通信用に http や https も使用できます。それらの構成方法、オプションなどは、各コマンドを get-help で確認ください。~ また、リモートとの通信に proxy を使用することもできます。 必要であれば netsh コマンドなどで winhttp の proxy を設定する、通信できない場合に winhttp proxy が原因になっていないか確認ください。 -Credential を指定しない場合は、PowerShellを実行しているアカウントが使われます。~ Get-Credential はパスワード入力のためにポップアップ画面を表示します。~ バックグラウンド処理など、画面表示をしたくない場合には、パスワードを事前に暗号化してファイルに保存しておくこともできます。~ パスワードをファイルに保存する方法、ファイルから取り出して Credentialオブジェクトを作成する方法は、下のページを参考ください。~ --ヒント: 資格情報を受け付ける Windows PowerShell スクリプトを作成する~ http://technet.microsoft.com/ja-jp/windows/ps_tips13.aspx -Invoke-Command -ComputerName Server1,Server2,... の様に複数のサーバーを記述すると、それらのサーバーに対して同時実行します。~ 実行結果は、PowerShellのオブジェクトとして、1つの配列に混合されて返ります。~(cmd.exeなどPowerShell でないコマンドを実行した場合は String(文字列) の配列になる。)~ オブジェクトにはPSComputerNameプロパティが付加されるので、サーバー別にソートしたり区別したいときはPSComputerNameで判断できます。~ 同時ではなく、順に実行したい場合は、-ComputerNameに1つつず指定します。 -Invoke-Command については、下の ページも参照ください。 --Windows PowerShell: リモート処理について~ http://technet.microsoft.com/ja-jp/magazine/gg981683.aspx ** リモートコンピューターでコマンド実行 (Workgroup + [[ダブルホップ>ベース クライアント セキュリティ モデル]]編) [#ga559ccc] 上の Workgroup編では、リモートコマンドの中から、他サーバーのリソースにアクセスすると、匿名ユーザーが使用されますが、 下の手順の様に、[[ダブルホップ>ベース クライアント セキュリティ モデル]]を使用することで、 -credential で指定するものと同じアカウントで 他サーバーのリソースにアクセスすることができます。~ ~ ***準備 (上の Workgroup編と共通) [#sbcecd9f] - リモート先でリモートコマンドを呼ばれる準備 (PowerShellを 管理者として実行)~ 1. Enable-PSRemoting 2. Set-PSSessionConfiguration Microsoft.Powershell -ShowSecurityDescriptorUI ~ - リモートを呼び出す側の準備 (PowerShellを 管理者として実行)~ 1. Start-Service WinRM 2. Set-ItemProperty -Path HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System -Name LocalAccountTokenFilterPolicy -Value 1 -Type DWord (上は、行を折り返しています、1行のコマンドです。) 3. set-item wsman:localhost\client\trustedhosts -value リモートコンピュータ名 ***[[ダブルホップ>ベース クライアント セキュリティ モデル]]のための 追加の準備 [#f3d0f0af] - リモート先で資格情報を受け取る準備 (PowerShellを 管理者として実行)~ 1. Enable-WSManCredSSP -Role Server ~ - リモートを呼び出す側で、資格情報を送信する準備 (PowerShellを 管理者として実行)~ 2. Enable-WSManCredSSP -Role Client -DelegateComputer リモートコンピュータ名 ~ - リモートを呼び出す側で、資格情報を NTLM 認証で行う様にグループポリシーを設定~ 3. gpedit.msc コマンド コンピューターの構成 >> 管理用テンプレート >> システム >> 資格情報の委任 NTLMのみのサーバー認証で新しい資格情報の委任を許可する (x) 有効 サーバーを一覧に追加: [表示] wsman/リモートコンピュータ名 ***[[ダブルホップ>ベース クライアント セキュリティ モデル]]を使用した、リモートコマンドの実行 [#se005ab2] - リモートでコマンドを実行~ 4. Invoke-Command に -Authentication CredSSP を付けてを実行~ Invoke-Command -ComputerName リモートコンピュータ名 -Credential (get-credential) -ScriptBlock { cmd.exe /c "dir \\リソースサーバー\ファイル共有" } -Authentication CredSSP (上は、行を折り返しています、1行のコマンドです。 -ScriptBlock { ... } の中は例です。) ***注意事項ほか [#d5ac8fb9] - -credential で指定する ユーザー について~ -credential で指定する ユーザーおよびパスワード は、リモートコンピュータ名 と リソースサーバー の両方に共通なものを作成しておきます。~ 上の例で \\リソースサーバー\ファイル共有 の共有フォルダは、指定する ユーザー で参照権限を設定しておきます。~ リモートコンピュータ上のユーザーは、Administrators でなくてもかまいません。リモートコマンドの内容に応じて 権限を付加してください。~ ** エラー処理 [#bb1a74a1] .ps1ファイルの中でエラーが発生すると、既定では、赤文字でエラー表示されて、そのまま次の行が実行されます。~ エラーを処理するには、下のいずれか必要です。 *** -ErrorAction (省略形は -EA) オプション [#zfec5ccb] Trap { エラー処理 } コマンド .... -ErrorAction "stop" *** try/catch で囲む [#ya21a9c5] $ErrorActionPreference = "stop" try { コマンド .... } catch [Exception] { エラー処理 } try/catch の例は、上の [[ps_test.ps1>#k5dc1c30]] を参照ください。~ ***その他 [#w6126274] その他の例、説明は、以下のサイトも参照ください。~ -Windows PowerShell の –ErrorAction (–EA) を使用してエラーをトラップする~ http://technet.microsoft.com/ja-jp/subscriptions/2009.01.windowspowershell ** PSSnapIn と module [#b2d2b641] PowerShell は、 PSSnapin と Module で拡張されます。~ Windows の役割を追加すると、役割を管理する Cmdlet が一緒にインストールされます。~ また、何らかの製品をインストールした際に、PowerShell Cmdlet が追加でインストールされることもあります。 PowerShellコマンドプロンプトを開いた状態では、それらの追加された Cmdlet はまだ使用できません。~ PowerShellコマンドプロンプトの中で、「Add-PSSnapin」あるいは「Import-Module」を使って、読み込みます。 読み込みの際に指定する PSSnapin名、 Module名 は、役割、製品の管理者用ドキュメントを参照してください。 インストールされている module は、 「get-module -listavailable」で確認することができます。 ** cmdlet の作り方 [#qe5ee859] cmdlet は自分で作成することも出来ます。 ***PowerShell で cmdlet が作れます。 [#h72b9cdf] PowerShell で作る場合は、PowerShellの関数を作成して、 .psm1 ファイルに保存します。~ 使用するときは、「import-module .psm1ファイルのフルパス」で読み込むと、関数を使用できます。~ -psm1 の中では、既定では、全ての関数が使用できますが、.psm1ファイルの内部関数を定義して、一部の関数のみ、 使用可能とする場合には、使用可能にする関数名を 「Export-ModuleMember -function 関数名」の様にして列挙します。~ こうすると、Export-ModuleMember に指定されなかった関数が、内部関数とみなされます。 -Windows PowerShell: スクリプトを簡単に共有できるようになりました~ http://technet.microsoft.com/ja-jp/magazine/ff625835.aspx -Windows PowerShell: スクリプトでコマンドレットを記述する~ http://technet.microsoft.com/ja-jp/magazine/ff677563.aspx -Windows PowerShell: Writing Cmdlets in Script~ http://technet.microsoft.com/en-us/magazine/ff677563.aspx ***C# で cmdlet を開発することも出来ます。 [#w3970a37] System.Management.Automation.PSCmdlet クラスから派生するクラスを作成します。~ 関連情報は、以下を参照ください。 -Windows PowerShell コマンドレットの作成~ http://msdn.microsoft.com/ja-jp/events/dd297528.aspx~ -Developing with Windows PowerShell~ http://msdn.microsoft.com/en-us/library/cc303698.aspx~ ** PSDrive と プロバイダ [#a2859d82] PowerShell の中では、 C: や D: などのドライブの他に、 -レジストリのドライブ (HKCU: HKLM:) -証明書ドライブ (Cert:) -Active Directory モジュールが定義する Active Directory ドライブ (AD:) -その他、 追加インストールした モジュール や PSSnapin が定義する ドライブ があり、PowerShell の中では、 cd コマンドを使って カレントドライブを移動したり、 get-childitem AD: の様に、 その他のコマンドで使用することが出来ます。~ ***PSDrive の使い方 [#m6ecf273] PSDrive の使い方は、下を参照ください。 -Windows PowerShell ドライブの管理~ https://msdn.microsoft.com/ja-jp/powershell/scripting/getting-started/cookbooks/managing-windows-powershell-drives ***cert:、AD:、SQLSERVER: [#z5f8de77] また、Certificate(cert:)、Active Directory(AD:)、SQL Server(SQLSERVER:) は、下のサイトを参照ください。 -Certificate Provider~ http://technet.microsoft.com/ja-jp/library/dd347615.aspx~ -AD DS の新機能: Windows PowerShell の Active Directory モジュール~ http://technet.microsoft.com/ja-jp/library/dd378783%28v=ws.10%29.aspx~ -SQL Server PowerShell プロバイダの使用~ http://technet.microsoft.com/ja-jp/library/cc281947%28v=sql.100%29.aspx~ ***既存のパスにドライブ名をつける [#c890901d] New-PSDrive コマンドを使って、既存のパスにドライブ名をつけることも出来ます。(DOSプロンプトのsubstコマンドに似ています。)~ New-PSDrive -Name regms -PSProvider Registry -Root HKLM\Software\Microsoft dir regms: Remove-PSDrive regms: ***PSDriveの開発 [#ac97cd25] C# で PSDrive を開発することも出来ます。 既存のドライブパスの短縮形ではない、~ 全く新しい PSDrive は、C# で プロバイダを開発することで出来ます。 該当のclassは、下のページなどを参照してください。~ -Designing Your Windows PowerShell Provider~ http://msdn.microsoft.com/en-us/library/windows/desktop/ee126198%28v=vs.85%29.aspx -Provider Cmdlets~ http://msdn.microsoft.com/en-us/library/windows/desktop/ee126197%28v=vs.85%29.aspx -DriveCmdletProvider Class~ http://msdn.microsoft.com/en-us/library/windows/desktop/system.management.automation.provider.drivecmdletprovider%28v=vs.85%29.aspx~ ** デバッグ [#gae834c7] debugは、 debug用print文、 デバッグ用環境、を使ってデバッグできます。 ***debug用print文 [#l40d8762] debug用print文は、 スクリプトの中に write-host コマンドを埋め込む方法です。~ write-host を使用すると、 引数に指定した値が PowerShellコマンドプロンプトへ出力されます。~ (write-output は、 関数の出力になるので、debug用には使わないでください。) ***デバッグ用環境 [#u0722db3] デバッグ用環境 は、 PowerShell ISE (Integrated Scripting Environment) 環境が使用できます。~ PowerShell ISE を使用すると、ブレークポイントの設定、ステップ実行が、メニュー操作で行えます。 -PowerShell ISE は、下の情報を参照ください。 --Windows PowerShell ISE の概要~ http://technet.microsoft.com/ja-jp/library/dd367962%28v=vs.85%29.aspx --Windows PowerShell ISE でスクリプトをデバッグする方法~ http://technet.microsoft.com/ja-jp/library/dd819480.aspx -PowerShell ISE でのデバッグ操作の画面例は、下を参照ください。 --Use the Debugger in the Windows PowerShell ISE~ http://blogs.technet.com/b/heyscriptingguy/archive/2011/11/24/use-the-debugger-in-the-windows-powershell-ise.aspx ***debug用のコマンド [#b5352391] 通常の PowerShellコマンドプロンプトのままでも、~ Set-PsBreakpoint 等の debug用のコマンドを使用して、1行ずつステップ実行することも出来ます。 -デバッグ例 PS E:\temp> Set-PsBreakpoint -command .\ps_scope1.ps1 ID Script Line Command Variable Action -- ------ ---- ------- -------- ------ 0 .\ps_scope1.ps1 PS E:\temp> .\ps_scope1.ps1 デバッグ モードを開始します。ヘルプを表示するには、h または ? を使用してください。 ヒット '.\ps_scope1.ps1' のコマンドのブレークポイント .\ps_scope1.ps1 [DBG]: PS E:\temp>>> s ps_scope1.ps1:2 $global:g1 = "0" [DBG]: PS E:\temp>>> s ps_scope1.ps1:3 $script:s1 = "0" [DBG]: PS E:\temp>>> s ps_scope1.ps1:4 $v1 = "0" [DBG]: PS E:\temp>>> s ps_scope1.ps1:6 write-host "before : g1=$global:g1 s1=$script:s1 v1=$v1 v2=$v2" [DBG]: PS E:\temp>>> s before : g1=0 s1=0 v1=0 v2= ps_scope1.ps1:8 function test1 { [DBG]: PS E:\temp>>> s ps_scope1.ps1:17 test1 [DBG]: PS E:\temp>>> s ps_scope1.ps1:9 write-host "start test1 : g1=$global:g1 s1=$script:s1 v1=$v1 v2=$v2" [DBG]: PS E:\temp>>> -Set-PsBreakpoint を使ったデバッグ方法~ 「about_Debuggers」 および下のページを参照ください。 --ブレークポイントを設定、削除、無効化、有効化、および一覧表示する方法~ http://technet.microsoft.com/ja-jp/library/dd819519.aspx~ --about_Debuggers~ http://technet.microsoft.com/ja-jp/library/dd347652.aspx -変数が変更されたときに停止するようにブレークポイントを設定することもできます。~ 手順の例は、下を参照ください。~ --Use the PowerShell Debugger to Troubleshoot Scripts~ http://blogs.technet.com/b/heyscriptingguy/archive/2011/11/22/use-the-powershell-debugger-to-troubleshoot-scripts.aspx ** 情報の探し方 [#g2df6a75] ***Get-Command [#ec95c735] コマンドを探すには、下の様に、コマンド名の一部を*で省略して Get-Command を実行します。~ Get-Command *event ***Get-Member [#zc03dfb2] オブジェクトのメンバーやプロパティを確認するには、下の様にコマンドの出力を パイプ で Get-Member に渡します Get-ChildItem | Get-Member ***get-help コマンド名 [#qdaf661d] コマンドの説明や引数の構文を確認するには、get-help を使います。~ get-help get-childitem Windows Server 2012 では、 ヘルプの文章が online から取得する様になっていることがあります。~ 必要に応じて 「get-help コマンド -online」のようにするか、~ 表示されたURLをブラウザで表示して構文を確認ください。 * 勘所2 [#g3eae783] **WinSvr2012以降の管理 [#o387c11c] WinSvr2012以降は管理コンソールの裏はPowerShellコマンドレットになる。 -現行、管理コンソールはCUI → [[WMI]]で構成されている。 -コマンドレットの裏は.NET、その裏は[[WMI]](Windows Management Instrumentation)。 -MS的には、今後PowerShell押し。 --コマンドレットは<操作>-<ターゲット>の名称ルールに準拠。 --[[WSH>VBS]]([[VBS]]とJS)は凍結される。 --[[BAT]]は今後もエンハンス有り。 --[[PowerShell]]から[[BAT]]や、[[WSH>VBS]]を実行可能。 --また、Get-WmiObjectで[[WMI]]も実行可能。 --難しい事をやるなら、まだ[[WMI]]が必要。 -windows management framework 3.0 RC(Win2008 sp2以降にインストール可能)~ 標準化:[[PowerShell]] → WS-Management → CIMOM、SMI-S(WS-Management 以下から他のPFも管理できる) --Windows PowerShell 3.0 --WinRM --[[WMI]](アップデート) --Windows PowerShell Web Service(WPWS) --Server Manager CIM Provider **テキストベース→オブジェクトベース [#z99a6bd1] 皆、テキストベース→オブジェクトベースのShellの違いに混乱する。 -パイプで渡せる型はある。 -パイプで何が渡るかはGet-Memberコマンドレット調べる~ http://mojibake.seesaa.net/article/53585441.html --シェルだが、プログラム、スクリプト(perl)のような仕様。 --変数、配列、Property、Method(.NETライク)、また、~ 無名関数、delegate、検索条件をラムダ式的に・・・なども可能。~ Like This ↓パイプ ↓ラムダ式的な get-service | where-object {$_.Status -eq "Running"} パイプしなくてもキャスト(暗黙)でつなげられる。 **非同期ジョブ、リモート、ワークフロー [#x461eac9] 非同期ジョブ、リモート、ワークフローなど。 ***非同期ジョブ [#j3087585] -start-job - scriptblock { ・・・コード・・・ } -start-job - filepath ファイルパス -#結果はSessionの範囲でしか有効では無い。 ***リモート接続 [#jcf2a9c1] -invoke-command マシン名やSessionを指定 -scriptblock { ・・・コード・・・ } -invoke-command マシン名やSessionを指定 -filepath ファイルパス -#Sessionを指定すれば処理中のジョブ等に再接続することも可能。 ***ワークロフロー [#w372d1c1] -ファイルとして登録 -クライアントでもサーバでも実行できる。 -サーバが停止しても処理をレジュームできる。~ 非同期ジョブジョブと異なり、結果は永続化されている。 -その他、並列処理等も可能。 **その他 [#tc84bc50] -エイリアスを使ってUnix風にできる。 -Windows2012からuiのアンインストール可能で、サーバコア風に運用可能。 ***探し方いろいろ [#ud6dd738] -Get-Command -Get-Module -Get-WmiObject -Get-Member ***PSドライブ、 [#k574a1a0] いろいろなDirectoryがDirできる。 -HDD -レジストリ -AD Directoryサービス -環境変数 -, etc. * 参考 [#i16bae1b] -PowerShell - Wikipedia~ http://ja.wikipedia.org/wiki/Windows_PowerShell~ -PowerShell 使い方メモ - Qiita~ http://qiita.com/opengl-8080/items/bb0f5e4f1c7ce045cc57 **MSDN magazine [#u859c231] -Windows PowerShell - PowerShell での Windows サービスの作成~ https://msdn.microsoft.com/ja-jp/magazine/mt703436.aspx -Essential .NET - 進化を続ける PowerShell~ https://msdn.microsoft.com/magazine/mt742875 **junichia [#gcdd1643] -blog~ http://blogs.technet.com/b/junichia/archive/tags/powershell/ -SlideShare~ http://www.slideshare.net/junichia/tag/powershell -Windows PowerShell 3.0 によるWindows Server 2012 管理の自動化 v2.2 2012.10.1...~ http://www.slideshare.net/junichia/windows-powershell-30-windows-server-2012 -MS安納さん の セミナー資料、 Tech Fielders PowerShell 3.0 シリーズ(東京)~ 概要から、基本的な使い方、スクリプト例、tipsまで、具体的に解説。~ 以下のサイトから、セミナーの各回ごとの資料がダウンロードできます。~ http://www.microsoft.com/ja-jp/techfielders/seminar.aspx~ --2012.06.25 [10:00-11:30]~ 「開発者のための Windows PowerShell ~ 開発コストを低減する究極のライブラリ集を使い倒そう」~ --2012.06.19 [10:00-11:30]~ 「Windows PowerShell 3.0 による Windows Server 2012 管理の自動化~ワークフロー編」~ --2012.06.12 [10:00-11:30]~ 「Windows PowerShell 3.0 による Windows Server 2012 管理の自動化~リモート サーバー管理編」~ --2012.06.04 [10:00-11:30]~ 「Windows PowerShell 3.0 による Windows Server 2012 管理の自動化~初級編」~ >>#この資料では、PowerShell 3.0 の beta/RC 版をベースにしてるため、 PowerShell 2.0 にはないコマンドも紹介されています。~ #ただ、WMIオブジェクトの使い方、リモートや権限などのtipsは、PowerShell 2.0 でも参考になります。~ **VBScriptから変換 [#l0129022] -VBScript から PowerShell へ変換のパターン --VBScript のスクリプトを Windows PowerShell のスクリプトに変換する方法はありますか~ http://gallery.technet.microsoft.com/scriptcenter/3002aff2-d444-4f6f-b0b7-2ca77f95e9ca~ --VBScript から PowerShell へ~ http://technet.microsoft.com/ja-jp/library/ff852826.aspx~ --その他の検索~ site:microsoft.com vbscript powershell 変換 **PowerShell バージョン と 動作環境 [#z48bba9f] -Windows PowerShell System Requirements~ http://technet.microsoft.com/en-us/library/hh847769.aspx >Updated: June 24, 2013~ Applies To: Windows PowerShell 2.0, Windows PowerShell 3.0, Windows PowerShell 4.0~ **その他のリンク集 [#f940605e] -Windows PowerShell コマンドレットのタスク別ガイド~ http://technet.microsoft.com/ja-jp/scriptcenter/dd772285.aspx ***[[PowerShell ISE]] [#j853d058] ***[[Azure PowerShell]] [#ra40adac] ***[[Azure Cloud Shell]] [#beef7fca] ---- Tags: [[:シェル]], [[:インフラストラクチャ]], [[:Windows]], [[:クラウド]], [[:Azure]]