ServerspecでWindowsの環境変数「Path」の設定をテストする方法

# はじめに

環境変数に次のように登録した場合
　RUBY_HOME = C:\Ruby22
　Path = %RUBY_HOME%\bin;(省略）

「DOSプロンプトのSET」や「Porwershellの$env:Path」を実行するとPathの値が展開された値で表示される。

```bat
PS C:\> $env:Path.split(";")
%SystemRoot%\system32\WindowsPowerShell\v1.0\
C:\Ruby\pik
C:\Ruby22\bin
C:apache-ant-1.9.4\bin
C:jdk1.7.0_80\bin
C:\Program Files\Intel\iCLS Client\
C:\Windows\system32
C:\Windows
C:\Windows\System32\Wbem
C:\Windows\System32\WindowsPowerShell\v1.0\
C:\Program Files\Intel\Intel(R) Management Engine Components\DAL
C:\Program Files\Intel\Intel(R) Management Engine Components\IPT
C:\Program Files\Intel\OpenCL SDK\2.0\bin\x86
C:\Program Files\Intel\WiFi\bin\
C:\Program Files\Common Files\Intel\WirelessCommon\
C:\Program Files\TortoiseSVN\bin
C:\Tool\Gow\bin
C:\Program Files\Windows Kits\8.1\Windows Performance Toolkit\
C:\Program Files\Microsoft SQL Server\110\Tools\Binn\
C:\Program Files\Microsoft SDKs\TypeScript\1.0\
C:\ProgramData\chocolatey\bin
PS C:\>
```

個人的には、設定した内容をServerspecでテストしたいので、レジストリのExpandString形式の値を展開しないで表示する方法を調べました。

# 環境変数表示コマンドの作成

```ps1:C：\Tool\ps1\WinEnv.ps1
param (
  [string]$h  = "${ENV:COMPUTERNAME}",
  [string]$n  = "Path",
  [string]$v  = "確認する値をここで指定",
  [string]$rh = "SYSTEM\CurrentControlSet\Control\Session Manager\Environment"
)
set-variable -name RET_SUCCESS -value  0 -option constant
set-variable -name RET_EXCPTN  -value -1 -option constant
set-variable -name RET_ERROR   -value 20 -option constant
$ErrorActionPreference = "stop"
$Error.Clear()
$retcd = $RET_ERROR
try {
  $b = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey("LocalMachine", $h)
  $sub = $b.OpenSubKey($rh)
  switch ($n.ToLower()) {
    "path" {
       $str = $sub.GetValue($n, "", [Microsoft.Win32.RegistryValueOptions]::DoNotExpandEnvironmentNames)
       foreach( $elem in $str -split ";") {
         if ($v -eq $elem.Trim()) {
           Write-Output "OK : ${elem}"
           $retcd = $RET_SUCCESS
         } else {
           Write-Output "-- : ${elem}"
         }
       }
    }
    default {
      $str = $sub.GetValue($n)
      if ($v -eq $str.Trim()) {
        Write-Output "OK : ${str}"
        $retcd = $RET_SUCCESS
      } else {
        Write-Output "NG : ${str}"
      }
    }
  }
} catch [Exception] {
  $retcd	= $RET_EXCPTN
  Write-Output $_.Exception.Message
}
Write-Output "[WinEnv.ps1] ===< EXIT($retcd) >==="
exit $retcd
```

# 環境変数表示コマンドの確認 

実行してみましょう。
まずは、OKな場合の動作確認です。

```bat
PS C:\> C:\Tool\ps1\WinEnv.ps1 -n path -v %RUBY_HOME%\bin
-- : %PIK_HOME%
OK : %RUBY_HOME%\bin
-- : %ANT_HOME%\bin
-- : %JAVA_HOME%\bin
-- : C:\Program Files\Intel\iCLS Client\
-- : C:\Windows\system32
-- : C:\Windows
-- : C:\Windows\System32\Wbem
-- : C:\Windows\System32\WindowsPowerShell\v1.0\
-- : C:\Program Files\Intel\Intel(R) Management Engine Components\DAL
-- : C:\Program Files\Intel\Intel(R) Management Engine Components\IPT
-- : C:\Program Files\Intel\OpenCL SDK\2.0\bin\x86
-- : C:\Program Files\Intel\WiFi\bin\
-- : C:\Program Files\Common Files\Intel\WirelessCommon\
-- : C:\Program Files\TortoiseSVN\bin
-- : C:\Tool\Gow\bin
-- : C:\Program Files\Windows Kits\8.1\Windows Performance Toolkit\
-- : C:\Program Files\Microsoft SQL Server\110\Tools\Binn\
-- : C:\Program Files\Microsoft SDKs\TypeScript\1.0\
-- : C:\ProgramData\chocolatey\bin
[WinEnv.ps1] ===< EXIT(0) >===
PS C:\> $LASTEXITCODE
0
PS C:\> C:\Tool\ps1\WinEnv.ps1 -n RUBY_HOME -v C:\Ruby22
OK : C:\Ruby22
[WinEnv.ps1] ===< EXIT(0) >===
PS C:\> $LASTEXITCODE
0
PS C:\> 
```

次にNGの場合の動作確認です。

```bat
PS C:\> C:\Tool\ps1\WinEnv.ps1 -n path -v %DIA_HOME%\bin
-- : %PIK_HOME%
-- : %RUBY_HOME%\bin
-- : %ANT_HOME%\bin
-- : %JAVA_HOME%\bin
-- : C:\Program Files\Intel\iCLS Client\
-- : C:\Windows\system32
-- : C:\Windows
-- : C:\Windows\System32\Wbem
-- : C:\Windows\System32\WindowsPowerShell\v1.0\
-- : C:\Program Files\Intel\Intel(R) Management Engine Components\DAL
-- : C:\Program Files\Intel\Intel(R) Management Engine Components\IPT
-- : C:\Program Files\Intel\OpenCL SDK\2.0\bin\x86
-- : C:\Program Files\Intel\WiFi\bin\
-- : C:\Program Files\Common Files\Intel\WirelessCommon\
-- : C:\Program Files\TortoiseSVN\bin
-- : C:\Tool\Gow\bin
-- : C:\Program Files\Windows Kits\8.1\Windows Performance Toolkit\
-- : C:\Program Files\Microsoft SQL Server\110\Tools\Binn\
-- : C:\Program Files\Microsoft SDKs\TypeScript\1.0\
-- : C:\ProgramData\chocolatey\bin
[WinEnv.ps1] ===< EXIT(20) >===
PS C:\> $LASTEXITCODE
20
PS C:\> C:\Tool\ps1\WinEnv.ps1 -n NOT_EXIST -v C:\Ruby22
null 値の式ではメソッドを呼び出せません。
[WinEnv.ps1] ===< EXIT(-1) >===
PS C:\> $LASTEXITCODE
-1
PS C:\> C:\Tool\ps1\WinEnv.ps1 -n RUBY_HOME -v C:\opt\Ruby22
NG : C:\Opt\Ruby22
[WinEnv.ps1] ===< EXIT(20) >===
PS C:\> $LASTEXITCODE
20
PS C:\>
```

このPowershellスクリプトをテスト対象のサーバに配布すれば、Serverspecで環境変数Pathの登録内容をテストできますね。

```ruby:C：\serverspec\sample\spec\sample\sample_spec.rb
require 'spec_helper'

describe command ("C:\\Tool\ps1\WinEnv.ps1 -n RUBY_HOME -v C:\\ruby22") do
  its(:stdout) { should match /EXIT\(0\)/ }
  #its(:exit_status) { should eq 0 }
end
describe command ("C:\\Tool\ps1\WinEnv.ps1 -n Path -v %RUBY_HOME%\\bin") do
  its(:stdout) { should match /EXIT\(0\)/ }
  #its(:exit_status) { should eq 0 }
end
```