PowerShellでレジストリをいじるときは注意すべし

REG_EXPAND_SZ型の文字列は環境変数(%SOME_VAR%)を値に含めることができるが
これをPowerShellから編集する場合には注意が必要。

例えば、ユーザ環境変数のPATH

$pathFromReg = ([regex]'^\s+(\S.*)\s{4}(\S.*)\s{4}(\S.*)$').Match((& "reg.exe" "query" "HKCU\Environment" "/v" "PATH")).Groups[3].Value;

$pathFromCmdlt = (Get-ItemProperty -Path "Registry::HKCU\Environment").Path;


Write-Host -Object $pathFromReg;
Write-Host -Object $pathFromCmdlt;
if($pathFromReg.ToLower() -ne $pathFromCmdlt.ToLower()) {
    Write-Host -Object ">>Not Equal<<";
}

結果

%USERPROFILE%\AppData\Local\Microsoft\WindowsApps;
C:\Users\oreore\AppData\Local\Microsoft\WindowsApps;
>>Not Equal<<

取得したときに、コマンドレットで行うと展開された状態で取得されてしまう。
この値をもとに現在の値を修正してしまってはせっかくの展開可能文字列の意味がなくなってしまう。

例えば、%ORACLE_HOME%\binをPATHや、%PROGRAMFILES%\SomeApp\binをPATHに含めている場合には
PowerShellのGet-ItemPropertyで取得した値をもとにうっかり更新しちゃうと
将来想定していなかった動作に悩まされる可能性がある。

%ORACLE_HOME%\binをPATHに含めていた場合のうっかりシナリオ

  1. OracleDatabase製品のインストール
  2. PATHの更新(%ORACLE_HOME%\bin;…) : この時はまだバイナリファイルが正しく読み出せる
  3. 別のアプリケーションのインストール
  4. PATHの更新(%SOMEAPP_HOME%\bin;%ORACLE_HOME%\bin;…の想定が%SOMEAPP_HOME%\bin;c:\app\oracle\product\12.1.0\bin;…になる) : この時もまだ正常に動作する
  5. OracleDatabase製品の更新(ORACLE_HOMEを”C:\app\oracle\product\12.1.0″からC:\app\oracle\product\12.2.0″に変えたとか)
  6. ORACLE_HOMEだけ変えればいいと思ってPATHを変更しない → 旧ORACLE_HOMEがPATHに含まれたままになってしまう

%PROGRAMFILES%\SomeApp\binをPATHに含めていた場合のうっかりシナリオ

  1. あるアプリケーションSomeAppをインストールし、%PROGRAMFILES%を使ってPATHを更新
  2. PATHを更新(%PROGRAMFILES%\SomeApp\bin;…)
  3. 別のアプリをインストールし、%PROGGRAMFILES%を使ったPATHの値の更新を、64bitOSの32bitPowerShellで実行(PATH: %PROGRAMFILES%\AnotherApp\bin;C:\Program Files(x86)\SomeApp\bin;…) : SomeAppのバイナリへのパスが通らなくなる
    1. PATHの更新を32bitでやらないだろうと思いがちだが、案外64bitOSでも32bitのPowerShellは使われる。
      というのも、多くのPC管理ソフトは64bitOSも32bitOSも対応させるため、基本的に32bitで動作する。
      こういったソフトから呼び出す場合には特に注意が必要。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です