「[[マイクロソフト系技術情報 Wiki>http://techinfoofmicrosofttech.osscons.jp/]]」は、「[[Open棟梁Project>https://github.com/OpenTouryoProject/]]」,「[[OSSコンソーシアム .NET開発基盤部会>https://www.osscons.jp/dotNetDevelopmentInfrastructure/]]」によって運営されています。

-戻る
--[[シェル]]
--[[スクリプティング]]
-[[戻る>PowerShell]]

* 目次 [#t6edc4f1]
#contents

* 概要 [#m1e4b186]
PS1ファイルの作成と実行について。

* .ps1ファイルと実行ポリシー [#i305d670]
*実行ポリシー [#i305d670]
-PowerShell の スクリプトファイルは、 拡張子 .ps1 のテキストファイル。
-*.ps1スクリプトファイルは、コマンドプロンプトの中で
--「powershell .\script.ps1」、
--または、PowerShellコマンドプロンプトの中で「.\script.ps1」

>の様にして実行できる。

-が既定では、PowerShell スクリプト そのものについて、~
実行が抑止されているので *.ps1 を実行するには、~
以下の設定変更または回避方法を検討する。

-実行ポリシーを変更
-PowerShell -Command - 構文でスクリプトを読み込ませる
-PowerShellコマンドプロンプトの中に貼り付ける
--[[実行ポリシーを変更>#jdedd4bd]]
--[[PowerShell -Command - 構文でスクリプトを読み込ませる>#wc5bad1b]]
--[[PowerShellコマンドプロンプトの中に貼り付ける>#g659c33b]]

**実行ポリシーを変更 [#jdedd4bd]
-実行ポリシーを変更するには、 Set-ExecutionPolicy を実行します。

***Set-ExecutionPolicy [#s515974f]
-実行ポリシーを変更するには、Set-ExecutionPolicy を実行します。
 Set-ExecutionPolicy RemoteSigned

-RemoteSigned を指定すると、
--ローカルコンピュータの.ps1ファイルか、
--ファイル共有またはダウンロードした署名付きの.ps1ファイルが

>実行できます。

-Set-ExecutionPolicy の設定は、恒久的に設定される。
--Bypass (=無制限に.ps1を実行可能) に変更してそのまま放置しないように。
--用が済んだら、既定値の Restricted に戻しておきます。
 Set-ExecutionPolicy Restricted
--scope を指定して、設定変更の対象を限定することもできます。
--scope を指定して、設定変更の対象を限定することもできます。~
※ CurrentUser はこのコマンドを実行したユーザーだけ、設定変更します。
 Set-ExecutionPolicy RemoteSigned -Scope CurrentUser

-CurrentUser はこのコマンドを実行したユーザーだけ、設定変更します。
>メンテナンスや運用作業で.ps1を使用する場合は、~
***運用時の実行ポリシー [#a21472bb]
メンテナンスや運用作業で.ps1を使用する場合は、~
通常時にどの実行ポリシーにしておくか、検討ください。
-.ps1ファイルに署名を行い、AllSigned にしておくか。
-あるいは、RemoteSigned にしておくか。
-それとも Restricted にしておき、都度実行ポリシーを変更するか。等

**PowerShell -Command - 構文でスクリプトを読み込ませる [#wc5bad1b]
PowerShell コマンドプロンプトに手入力して逐次実行するかわりに、 -Command - を使用して、標準入力からコマンドを連続実行することができます。~
手打ちと同じなので、 Set-ExecutionPolicy Restricted のままでも、実行可能です。~
-PowerShell コマンドプロンプトに手入力して逐次実行するかわりに、~
'-Command - を使用して、標準入力からコマンドを連続実行できる。~

-手打ちと同じなので、 Set-ExecutionPolicy Restricted のままでも、実行可能。~
実行ポリシーをどうしても変更したくない場合の次善策として、使用できるか検討する意味は有ります。~
下の例の様に、 batファイルとecho を組み合わせて、引数を与えることも出来ます。~

**batファイル [#c35ff7a4]
***batファイル [#c35ff7a4]
ps_test.bat

 @( echo $arg1 = "%~1"
    echo $arg2 = "%~2"
    type ps_test.ps1 ) | powershell -command -

**ps1ファイル [#k5dc1c30]
***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
-.ps1 の try/catch の } の下に空行があることに注意。
-powershellコマンドを -Command - で読み込ませる場合、~
手入力と同じようにコードブロックの後に空行が必要です。

***実行例 [#cb11fd36]
これを実行すると、echo の2つが  ps_test.ps1 の先頭に挿入されて、~
PowerShellコマンドプロンプトに手入力して逐次実行することになります。

 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の使用をあきらめるしかありません。~
-PowerShellコマンドプロンプトの画面に、クリップボードからスクリプトを貼り付けます。

* 引数 [#r5aa018b]
ps1スクリプトへの引数
--スクリプトは、テキストファイルなどで用意しておき、
--メモ帳などで開いたら、テキスト全体をクリップボードにコピー。
--それを、PowerShellコマンドプロンプトに貼り付けます。

ps1ファイルの最初に param(..) を記述することで、引数を定義出来ます。
  param (
    [string]$filename,
    [int]$count = 5
  )
-実行ポリシーを変更しない、上のようなバッチファイルも不可であれば、
--手動でPowerShellコマンドプロンプトへ貼り付けをするか、
--PowerShellの使用をあきらめるか

[型] と引数名、 省略時の既定値 も指定できます。~
引数名を定義すると 「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

* 変数のスコープ [#d923bb09]
**スクリプト [#r9abb657]
-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]
**実行例 [#l44741d7]
  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 しても値は設定されたまま。~
**解説 [#y3af1648]
-$v1 は
--.ps1 の中で最初に設定している値が、 関数test1 の中でも参照できますが、
--関数test1 の中で設定した値は、関数test1 の外では有効ではありません。~

通常は、.ps1の中でスコープが閉じると考えておき、
.ps1の中から write-output 以外の方法でスクリプト呼び出し元へ返す情報がある場合に、$global: を使用するか検討するのがいいでしょう。~
あとは、.ps1 の中に限らず、関数間で共有の変数の場合、$script: を使用すると考えておけばいいでしょう。~
-$v2 は
--.ps1 の中で未定義のため、 関数test1 の中でのみ有効。

変数のスコープは、「get-help about_Scopes」、または、下の情報も参考。~
-$script:s1 $v1 $v2
--.ps1 の中だけで有効なため、 スクリプトを終了した後で write-host しても値は設定されていない。

-about_Scopes~
http://technet.microsoft.com/ja-jp/library/dd315289.aspx
-$global:g1
--スコープがグローバルなので、スクリプトを終了しや後で write-host しても値は設定されたまま。

* if文 [#b3a3550b]
-通常は、
--.ps1の中でスコープが閉じると考えておき、
--.ps1の中から write-output 以外の方法でスクリプト呼び出し元へ返す情報がある場合に、$global: を使用するか検討するのがいいでしょう。
--あとは、.ps1 の中に限らず、関数間で共有の変数の場合、$script: を使用すると考えておけばいいでしょう。~

if文は、下の様に -で始まる比較演算子を使います。
  $var1 = sub2 $arg1 $arg2
  if ( ( $var1 -eq 1 ) -or ( $var1 -gt 10 ) ) {
     ...
  }
条件のANDやORは、 それぞれを ( ... )で囲んで -and や -or で結びます。
* 引数 [#r5aa018b]
ps1スクリプトへの引数

論理のANDやORによるビット演算は、 -band や -bor の -b で始まる演算子を使います。
  $file = get-item $dirname
  if ( $file.Attributes -band [System.IO.FileAttributes]::Directory ) {
     ...
  }
bit演算結果が0以外の場合は、真 とみなされます。
-ps1ファイルの最初に param(..) を記述することで、引数を定義出来ます。
  param (
    [string]$filename,
    [int]$count = 5
  )

if文の演算子の詳細は、powershellコマンドプロンプトの中で 「get-help about_Comparison_Operators」を参照してください。
-引数名を定義すると 
 powersehll .\test.ps1 -filename c:\temp\testt.txt -count 2

** 配列 [#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,
-また、Mandatory属性を指定すると、必須の引数になり、省略した場合には、~
PowerShellによって、追加の引数を要求するプロンプトが表示されます。
  param (
    [Parameter(Mandatory=$True)]
    [string]$filename,
 
    [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
 }
    [int]$count = 5
  )

**実行例: [#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行に入力してください。)
-詳細は、
--下のページを参照。
---Windows PowerShell: スクリプト作成の短期集中講座~
http://technet.microsoft.com/ja-jp/magazine/hh551144.aspx
---Windows PowerShell: パラメーターを定義する~
http://technet.microsoft.com/ja-jp/magazine/jj554301.aspx~

実行例のパイプラインでは、以下のことをしています~
+get-item で C:\Program Files フォルダのオブジェクトを取得して、~
+dirinfo でサブフォルダのサイズを集計、~
+sort-obejct で TotalSize の大きい順に並び替えて、~
+where で TotalSize が 1以上のオブジェクトだけ抽出して、~
+select-object で 最初の 5 個だけ取り出し、~
+format-list で 特定のプロパティのみ表示。
--または、PowerShellコマンドプロンプト内で、~
「get-help about_Functions_Advanced_Parameters」を実行。

Add-Member の解説については、下も参照ください。
*参考 [#i3bf7513]
-Windows PowerShell: スクリプト作成の短期集中講座~
http://technet.microsoft.com/ja-jp/magazine/hh551144.aspx

-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 で指定する ユーザー について~
&nbsp;-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をブラウザで表示して構文を確認ください。

----
Tags: [[:シェル]], [[:インフラストラクチャ]], [[:Windows]], [[:クラウド]], [[:Azure]]
Tags: [[:シェル]], [[:インフラストラクチャ]], [[:Windows]]


トップ   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS