PowerShell ではレジストリキーや値の取得や作成、更新、削除などができます。この記事では一番頻度が高いと思われるレジストリエントリの取得について、詳しく紹介します。
  
レジストリエントリの取得 レジストリエントリの取得には「Get-Item 」コマンドレットか「Get-ItemProperty 」コマンドレットを利用します。
Get-Item によるレジストリエントリ取得 Get-Item の -Path にレジストリキーを指定すると、配下のレジストリ値が取得できます。
PowerShell でレジストリキーを指定する場合、接頭語に「Registry::」を付与 するか、HKEY_LOCAL_MACHINE を PS ドライブ形式の「HKLM:」に変換 する必要があります。その他、対応するルートキーは以下の通りとなります。
 HKEY_LOCAL_MACHINE → HKLM:  
 HKEY_CURRENT_USER → HKCU:  
 HKEY_USERS → HKU:  
 
PS C:\> Get-Item  -Path  “Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion”    
    Hive: HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT
Name             Property
—-             ——–
CurrentVersion   SystemRoot              : C:\WINDOWS
                 BaseBuildRevisionNumber : 1
                 BuildBranch             : 19h1_release
                 BuildGUID               : ffffffff-ffff-ffff-ffff-ffffffffffff
                 BuildLab                : 18362.19h1_release.190318-1202
                 BuildLabEx              : 18362.1.amd64fre.19h1_release.190318-1202
・・・省略
単純なレジストリエントリの取得であれば、次に紹介する「Get-ItemProperty」を利用した方がスマートになりますが、配下のレジストリキー数やエントリの数を取得したい場合は「Get-Item」コマンドレットを利用するのが便利です。
PS C:\> Get-Item  -Path  “Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion”  `
 | Select-Object  SubKeyCount,ValueCount
SubKeyCount ValueCount
———– ———-
         98         30
また、Get-ChildItem コマンドレットを利用すると、指定したレジストリキー配下のサブキーについて Get-Item を実行したのと同じ結果を得られます。
Get-ItemProperty によるレジストリエントリ取得 Get-ItemProperty の -Path にレジストリキーを指定すると、配下のレジストリ値が取得できます。
PS C:\> Get-ItemProperty  -Path  “Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion” 
SystemRoot              : C:\WINDOWS
BaseBuildRevisionNumber : 1
BuildBranch             : 19h1_release
BuildGUID               : ffffffff-ffff-ffff-ffff-ffffffffffff
BuildLab                : 18362.19h1_release.190318-1202
BuildLabEx              : 18362.1.amd64fre.19h1_release.190318-1202
・・・省略
レジストリエントリがプロパティとして返されるので、値を取得したい場合は以下のようにします。
PS C:\> # コマンドレットの実行結果から直接プロパティ値を取り出す 
PS C:\> (Get-ItemProperty  -Path  “Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion” ).SystemRoot
C:\WINDOWS
PS C:\> # 変数に格納してからプロパティ値を取り出す 
PS C:\> $value  = Get-ItemProperty  -Path  “Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion”  
PS C:\> $value .SystemRoot
C:\WINDOWS
Get-Item と Get-ItemProperty の違いと使い分け どちらも出力の見た目は同じように見えますが、返されるオブジェクトの種類が異なります。
PS C:\> Get-Item  -Path  “Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion”  ‘
 | Get-Member 
   TypeName: Microsoft.Win32.RegistryKey
Name            MemberType  Definition
—-            ———-  ———-
Close            Method      void Close()
CreateObjRef     Method      System.Runtime.Remoting.ObjRef CreateObjRef(type requestedType)
CreateSubKey     Method      Microsoft.Win32.RegistryKey CreateSubKey(string subkey…
・・・省略
PS C:\> Get-ItemProperty  -Path  “Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion”  `
 | Get-Member 
   TypeName: System.Management.Automation.PSCustomObject
Name                    MemberType   Definition
—-                    ———-   ———-
Equals                  Method       bool Equals(System.Object obj)
GetHashCode             Method       int GetHashCode()
GetType                 Method       type GetType()
ToString                Method       string ToString()
BaseBuildRevisionNumber NoteProperty int BaseBuildRevisionNumber=1
BuildBranch             NoteProperty string BuildBranch=19h1_release
・・・省略
Get-Item は Win32.RegistryKey が返され、Get-ItemProperty では PSCustomObject が返されます。 
細かい説明は省きますが、Get-ItemProperty では レジストリエントリの取得は簡単ですが、それ以外に出来ることは何もありません。 
Get-Item では レジストリエントリの追加・更新・削除なども可能 
では、レジストリエントリの追加・更新・削除を行うには Get-Item を使用しなくてはいけないかと言われると、それぞれ別のコマンドレットが用意されています。Get-Item でのレジストリ操作は少し難易度が高いので、基本的には Get-ItemPropery を利用するのがいいかと思います。
参考までに、Get-Item でレジストリの種類を取得する書き方です。
PS C:\> (Get-Item  -Path  “Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion” ).GetValueKind(“SystemRoot” )
String
PS C:\> (Get-Item  -Path  “Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion” ).GetValueKind(“BaseBuildRevisionNumber” )
DWord
取得できるフィールド名とレジストリデータ型の紐づけは以下のようになっています。
フィールド名  レジストリデータ型 Binary REG_BINARY  DWord REG_DWORD  ExpandString  REG_EXPAND_SZ  MultiString  REG_MULTI_SZ  QWord  REG_QWORD  String  REG_SZ  
リモートコンピュータのレジストリを取得する リモートコンピュータのレジストリエントリを取得するには Invoke-Command コマンドレットを利用します。 リモートレジストリを取得するコマンドレットではなく、リモートコンピュータで任意のコマンドを実行する形になります。
 Invoke-Command コマンドレットを利用するための前提条件 Invoke-Command コマンドレットによるリモートコマンド実行には、接続先・接続元で WinRM が有効になっている必要があります 。Windows Server 2012 以降の Server 系 OS では既定で有効になっているため、特に準備は不要ですが、Firewall を構成している場合は TCP 5985 を開放する必要 
Client 系 OS では明示的に有効化する必要 
PS C:\> Enable-PSRemoting  -SkipNetworkProfileCheck 
WinRM は要求を受信するように更新されました。
WinRM サービスの種類を正しく変更できました。
WinRM サービスが開始されました。
WinRM ファイアウォールの例外を有効にしました。
細かい内容については別記事を書きたいと思っています。
リモートコンピュータのレジストリを取得する 以下コマンドレットで取得可能です。
PS C:\> Invoke-Command  -ComputerName  localhost -ScriptBlock  `
 { Get-ItemProperty  -Path  “Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion”  }
SystemRoot               : C:\WINDOWS
BaseBuildRevisionNumber  : 1
BuildBranch              : 19h1_release
BuildGUID                : ffffffff-ffff-ffff-ffff-ffffffffffff
BuildLab                 : 18362.19h1_release.190318-1202
BuildLabEx               : 18362.1.amd64fre.19h1_release.190318-1202
・・・省略
ScriptBlock 内にリモートコンピュータで実行したいコマンドを記述します。
スクリプトブロック内で変数を使う 補足的な内容となりますが、ScriptBlock 内で変数を使うのは少し癖があります。
以下はローカルで実行した場合。変数にレジストリキーを格納し、-Pathに変数を引き渡すことで、正常に動作しているのが確認できます。
PS C:\> $Reg  = “Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion” 
PS C:\> Get-ItemProperty  -Path  $Reg 
SystemRoot               : C:\WINDOWS
BaseBuildRevisionNumber  : 1
BuildBranch              : 19h1_release
BuildGUID                : ffffffff-ffff-ffff-ffff-ffffffffffff
BuildLab                 : 18362.19h1_release.190318-1202
BuildLabEx               : 18362.1.amd64fre.19h1_release.190318-1202
・・・省略
では ScriptBlock 内で変数を利用してみます。
PS C:\> $Reg  = “Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion”  
PS C:\> Invoke-Command  -ComputerName  localhost -ScriptBlock  `
 { Get-ItemProperty  -Path  $Reg  }
 引数が null であるため、パラメーター ‘Path’ にバインドできません。
    + CategoryInfo          : InvalidData: (:) [Get-ItemProperty]、ParameterBindingValidationException
    + FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,Microsoft.PowerShell.Commands.GetItemPropertyCommand
    + PSComputerName        : localhost 
引数が null というエラーが発生しました。原因は ScriptBlock 内のコマンドは呼び出し元と別のプロセスで実行される ためで、ScriptBlock 外の変数を利用するには特別な記述が必要となります。
2つの方法を紹介します。
PS C:\> # Invoke-Commandの-ArgumentListを利用する 
PS C:\> $Reg  = “Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion” 
PS C:\> Invoke-Command  -ComputerName  localhost -ScriptBlock  `
 { Get-ItemProperty  -Path  $Args [0] } -ArgumentList  $Reg 
SystemRoot                : C:\WINDOWS
BaseBuildRevisionNumber   : 1
BuildBranch               : 19h1_release
BuildGUID                 : ffffffff-ffff-ffff-ffff-ffffffffffff
BuildLab                  : 18362.19h1_release.190318-1202
BuildLabEx                : 18362.1.amd64fre.19h1_release.190318-1202
・・・省略
PS C:\> # using:ラベルを利用する 
PS C:\> $Reg  = “Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion” 
PS C:\> Invoke-Command  -ComputerName  localhost -ScriptBlock  `
 { Get-ItemProperty  -Path  $using:Reg  }
SystemRoot                : C:\WINDOWS
BaseBuildRevisionNumber   : 1
BuildBranch               : 19h1_release
BuildGUID                 : ffffffff-ffff-ffff-ffff-ffffffffffff
BuildLab                  : 18362.19h1_release.190318-1202
BuildLabEx                : 18362.1.amd64fre.19h1_release.190318-1202
・・・省略
ArgumentList を利用する場合、ScriptBlock 内の引数は指定しなければ $Args[x] とする必要があります。もちろん ScriptBlock 内で事前に引数について定義することもできます。定義方法については以下のページを参照してください。
一方、using: ラベルは PowerShell 3.0 から利用可能 
レジストリエントリでの条件分岐 一番需要がありそうなレジストリエントリの有無や値による条件分岐を用いたサンプルを紹介します。
OS 情報を取得し、対象 OS の場合のみ処理を行う 簡単ではありますが、対象 OS が Windows 10 Enterprise の場合のみ処理を行うスクリプトのサンプルです。
# sample.ps1
# 取得対象のレジストリキーを格納
$RegKey = "Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion"
# レジストリキーが存在するかチェック
If(Test-Path -Path $RegKey){
    Write-Host $RegKey "を確認できました。"
}Else{
    Write-Host $RegKey "は存在しないため、処理を中止します。"
    Exit(1)
}
# OSがWindows 10 Enterpriseの場合、処理を行う
$ProductName = Get-ItemProperty -Path $RegKey -Name ProductName
If($ProductName.ProductName -eq "Windows 10 Enterprise"){
    Write-Host "対象OSです。処理を行います。"
    # 何かしらの処理を記述
}Else{
    Write-Host "対象外OSです。処理を中止します。"
    Exit(2)
}
PS C:\> C:\sample1.ps1 
Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion を確認できました。
対象OSです。処理を行います。
以上、PowerShell でレジストリを操作する方法でした。
リンク