WSHではWshShellオブジェクトのRegRead、RegWrite、RegDeleteメソッドを用いてレジストリの読み書きが可能であったが、PowerShellではRegistryプロバイダを介してレジストリにもファイル・システムと同様にアクセスできる。デフォルトでは、
というドライブ名が割り当てられている。
注: HKEY_CLASSES_ROOTにはデフォルトではPSドライブが割り当てられていないが、
New-PSDrive -name "HKCR" -PSProvider "Registry" -root "HKEY_CLASSES_ROOT"
■キーの取得
あるレジストリ・キーに含まれるレジストリ・キー(サブキー)の一覧を取得するにはFileSystemドライブと同様、Get-ChildItemコマンドレットを用いる。
ここでデフォルトで表示されるプロパティについてまとめておく。
プロパティ名 | 説明 |
---|---|
SKC | 含まれるサブキーの数(SubKeyCount) |
VC | 含まれるエントリの数(VolumeCount) |
Name | キーの名前 |
Property | エントリの一覧 |
Registryプロバイダでデフォルト表示されるプロパティ |
注意していただきたいのは、Registryプロバイダにおいては、アイテム=レジストリ・キー、アイテムのプロパティ=レジストリ・エントリ(値)である点である。
■エントリの取得
レジストリ・エントリはレジストリ・キーのプロパティなので、エントリの一覧やエントリの値を取得するにはGet-ItemPropertyコマンドレット(エイリアスはgp)を用いる。
# HKEY_CURRENT_USER\ Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Foldersに含まれるエントリの名前と値の一覧を取得
Get-ItemProperty 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders'
# 上記のキーに含まれる“Fonts”エントリの値を取得
(Get-ItemProperty 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders').Fonts
# 上記のキーに含まれるエントリ名の一覧を文字列の配列として取得する
Get-Item 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders' | Select-Object -expandProperty Property
注: この例ではSelect-Objectコマンドレットに-expandPropertyパラメータを付けてRegistryKeyオブジェクトのPropertyプロパティ値の配列(エントリの名前の配列)を展開している。
# HKEY_CLASSES_ROOT\.ps1の「(既定)」のエントリの値を取得
(Get-ItemProperty Microsoft.PowerShell.Core\Registry::HKEY_CLASSES_ROOT\.ps1)."(default)"
注: HKEY_CLASSES_ROOTのように、デフォルトでPSドライブが割り当てられていないリソースにアクセスするには、先ほど述べたようにNew-PSDriveコマンドレットで割り当てるほか、このようにリソースに与えられたPowerShellのパス(PSPath)を指定することでも可能である。
■キーの作成
レジストリ・キーを作成するにはNew-Itemコマンドレットを用いる。
# HKEY_CURRENT_USER\Softwareに“My Company”というキーを作成する
New-Item "HKCU:\Software\My Company"
# HKEY_CURRENT_USER\Softwareに“My Company2”というキーを作成し、キーの“(既定)”の値を “test”にする
New-Item "HKCU:\Software\My Company2" -value "test"
■エントリの作成
エントリの作成にはNew-ItemPropertyコマンドレットを用いる。
# HKEY_CURRENT_USER\Software\My Companyキーに“President”というエントリを作成し、値を文字列値“Daisuke Mutaguchi”にする
New-ItemProperty "HKCU:\Software\My Company" "President" -value "Daisuke Mutaguchi"
# HKEY_CURRENT_USER\Software\My Companyキーに“EmployeesCount”というエントリを作成し、値をDWORD値“10”にする
New-ItemProperty "HKCU:\Software\My Company" "EmployeesCount" -value 10 -propertyType DWord
■キーの削除
キーの削除にはRemove-Itemコマンドレットを用いる。
# HKEY_CURRENT_USER\Software\My Company2キーを削除
Remove-Item " HKCU:\Software\My Company2" ?recurse
■エントリの削除
エントリの削除にはRemove-ItemPropertyコマンドレットを用いる。
# HKEY_CURRENT_USER\Software\My Companyキーの“President”エントリを削除
Remove-ItemProperty "HKCU:\Software\My Company" President
そのほか、キーのコピー、移動、リネームにはFileSystemプロバイダと同様、Copy-Item、Move-Item、Rename-Itemコマンドレットを用いて行うことができる。また、エントリのコピー、移動、リネームはそれぞれ、Copy-ItemProperty、Move-ItemProperty、Rename-ItemPropertyコマンドレットを用いて行うことができる。
PSドライブのパスを扱うためのコマンドレットがいくつか用意されている。ここではよく使われるコマンドレットとパラメータを抜粋して紹介する。
■Convert-Path
相対パスを絶対パスに変換する。もしくはワイルドカードを展開する。FileSystemObjectオブジェクトのGetAbsolutePathNameメソッドと同等の機能である。
# カレント・ディレクトリにあるfile.txtのフルパスを取得する
Convert-Path .\file.txt
# 1つ上の階層のフルパスを取得する
Convert-Path ..
# カレント・ディレクトリにある拡張子.txtのファイルのフルパスを取得する(結果はstringの配列)
Convert-Path .\*.txt
■Join-Path
2つのパスを区切り文字(\など)を適切に補ったうえで結合し、1つのフルパスを得る。FileSystemObjectオブジェクトのBuildPathメソッドと同等の機能である。
# “C:\Windows”と“test.txt”を結合して“C:\windows\test.txt”を得る
Join-Path C:\Windows -childPath test.txt
■Split-Path
パスから特定の要素を切り出す。
# 親ディレクトリのフルパスを取得する。FileSystemObjectオブジェクトのGetParentFolderメソッドと同等
Split-Path C:\Windows\System32 -parent
# ドライブ名を取得。FileSystemObjectオブジェクトのGetDriveNameメソッドと同等
Split-Path C:\Windows\System32 -qualifier
# ファイル名やフォルダ名を取得する。FileSystemObjectオブジェクトのGetFileNameメソッドと同等
Split-Path C:\Windows\System32 -leaf
■Test-Path
パスが実際に存在するかどうかを確認する。存在する場合はTrueを返す。FileSystemObjectオブジェクトのFileExistsメソッド、FolderExistsメソッドと同等である。
# C:\testが存在するかどうかを確認する
Test-Path C:\test
ここではFileSystemプロバイダでの使用法を述べたが、Registryプロバイダをはじめとして、ほかのPSプロバイダでももちろん使用可能である。
これまではコンソールに入力する1行のコマンドを紹介してきたが、これらの知識を組み合わせることで、より複雑な処理を行うスクリプトを記述できる。ここでは例としてフォルダのサイズ(=フォルダに含まれるすべてのファイルの合計サイズ)を取得して表示するスクリプトを紹介する。
$folders = Get-ChildItem | Where-Object {$_ -is [System.IO.DirectoryInfo]}
$foldersHash = @{}
foreach ($folder in $folders)
{
$size = (Get-ChildItem $folder -force -recurse -errorAction SilentlyContinue |
Where-Object {$_ -is [System.IO.FileInfo]} |
Measure-Object Length -Sum).Sum
$foldersHash.Add($folder.Name, $size)
}
$foldersHash
このようなスクリプトを例えばGet-FolderSize.ps1と名前を付けて保存し、実行すると次のようになる。
このスクリプトではまず$folders変数にGet-ChildItemコマンドレットの返す値を代入している。このときWhere-Objectコマンドレットを使い、DirectoryInfoオブジェクトのみを代入するようにしている。
次に結果を保存するための空の連想配列(ハッシュ)、$foldersHashを用意する。連想配列は一意のキーとそれに対応する値からなる配列の一種である。連想配列はキーの検索が高速である点が特徴である。今回はフォルダ名という重複しない値と、それに1対1で対応するフォルダ・サイズを扱うので連想配列を用いた。
そしてforeachステートメントを使用して$foldersに含まれる配列要素(DirectoryInfoオブジェクト)それぞれに対してサイズを求めている。ここではフォルダ配下のすべてのファイルを取得したいので、Get-ChildItemコマンドレットに-recurseパラメータを付与している。また隠しファイルも取得したいので-forceパラメータも付与している。さらにアクセス権がないなどで列挙の際にエラーが起きる場合があるので、それを抑制するため-errorAction SilentlyContinueというパラメータも付けている。こうして得られたFileInfoオブジェクトの配列に対して、Measure-Objectコマンドレットを用いてLength(ファイル・サイズ)プロパティの合計を求め、$size変数に格納している。後はAddメソッドを使ってフォルダ名をキーに、フォルダ・サイズを値として連想配列に要素を追加する。最後にこの連想配列の値を出力してスクリプトは終了する。
Get-ChildItemコマンドレットではファイル・サイズは表示されるがフォルダのサイズが表示されないため、このようなスクリプトは有用であろう。
今回はPowerShellでファイルやレジストリを操作する方法について述べた。コマンド・プロンプトやバッチファイルのようなお手軽さを保ちつつ、WSHのように高度な処理も記述できることを感じていただけただろうか。次回はサービスおよびプロセスを扱う方法について解説する。
「[運用] PowerShell的システム管理入門 ―― PowerShell 2.0で始める、これからのWindowsシステム管理術 ―― 」
Copyright© Digital Advantage Corp. All Rights Reserved.