前回<バッチファイル内でバッチファイルの連続実行をテストしてみる - treedown’s Report>でテストをしているときに、PowerShellの動作で気づいたことがあったのでご報告です。
PowerShellでWindowsの環境変数を参照するときの注意点です。
環境変数の参照方法
環境変数の中でも今回取り扱うシステム環境変数というのは、Windowsに標準で用意されている変数で、Windows環境であれば共通で使用できるラベルと言えます。
同じWindowsであっても、OSがWindows10とWindows11で異なったり、ユーザ名、コンピュータ名はPCによって異なったり、ユーザがカスタマイズしている環境ではファイルのパス(フォルダ・ディレクトリ)なども異なることになります。
しかしシステム環境変数を参照するようにすると、あらかじめWindowsのシステム上で環境変数にセットされている値を使うことができるようになるため、コマンドやバッチの実行時に異なるPC間で同じコマンドやバッチで命令を実行することができるようになります。
コマンドプロンプトでの環境変数は「set」コマンドをオプションなしで実行すると一覧を確認出来ます。
PowerShellでは、「Get-ChildItem env:」コマンドレットで確認出来ます。
各画面で表示されている左の"○○="にある名称が環境変数です。
PowerShellとバッチファイルで相違するケース
今回、環境変数の参照の仕方で違いに気づいたのは、PowerShellでバッチファイル内で使用する同等のコマンド(PowerShell -commandで使うコマンドレット)の動作を確認したときに気づきました。
VLCのファイルパスである<C:\Program Files\VideoLAN\VLC\vlc.exe>を取得したかったので、環境変数<%PROGRAMFILES%>を使ってフォルダ指定をした時に、コマンドプロンプトとPowerShellのコンソールで表示が異なることに気づきました。
まずはバッチファイルの場合、環境変数「%PROGRAMFILES%」は以下のように表示されます。
単純に環境変数「%PROGRAMFILES%」をechoコマンドで画面表示しただけです。環境変数を組み合わせたフルパスでのファイル指定も上手くいっています。
これが同じことをPowerShellで実施した時、バッチファイルのように%PROGRAMFILES%では参照出来ないことに気づきました。
--------------------------------------------------------------
PS C:\> Get-ItemProperty '%PROGRAMFILES%\VideoLAN\VLC\vlc.exe'
Get-ItemProperty : パス 'C:\%PROGRAMFILES%\VideoLAN\VLC\vlc.exe' が存在しないため検出できません。
発生場所 行:1 文字:1
+ Get-ItemProperty '%PROGRAMFILES%\VideoLAN\VLC\vlc.exe'
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (C:\%PROGRAMFILES%\VideoLAN\VLC\vlc.exe:String) [Get-ItemProperty], Item
NotFoundException
+ FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.GetItemPropertyCommand
--------------------------------------------------------------
とエラーになってしまいます。
試しに画面表示してみるためechoしてみたら
--------------------------------------------------------------
PS C:\> echo %PROGRAMFILES%
%PROGRAMFILES%
--------------------------------------------------------------
そのまま表示されてしまいました。
PowerShellで環境変数を参照する方法
バッチファイルでは「%」囲みで環境変数を参照していたのですが、PowerShellの記載方法は「%」囲みでは環境変数の参照が出来ないようです。
このため表示方法は、PowerShell用の作法に則った書式で記述する必要があります。
書式:
$env:%環境変数名%
例えば、今回のように%PROGRAMFILES%を表示させる場合には、
$env:PROGRAMFILES
ユーザプロファイル(%USERPROFILE%)なら
$env:USERPROFILE
と記述します。やってみましょう。
--------------------------------------------------------------
PS C:\> echo $env:PROGRAMFILES
C:\Program Files
PS C:\> echo $env:USERPROFILE
C:\Program Files
--------------------------------------------------------------
できました。
じゃあ前述のGet-ItemPropertyに環境変数指定してみます。
--------------------------------------------------------------
PS C:\> Get-ItemProperty '$env:PROGRAMFILES\VideoLAN\VLC\vlc.exe'
Get-ItemProperty : ドライブが見つかりません。名前 '$env' のドライブが存在しません。
発生場所 行:1 文字:1
+ Get-ItemProperty '$env:PROGRAMFILES\VideoLAN\VLC\vlc.exe'
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: ($env:String) [Get-ItemProperty], DriveNotFoundException
+ FullyQualifiedErrorId : DriveNotFound,Microsoft.PowerShell.Commands.GetItemPropertyCommand
--------------------------------------------------------------
ん?エラーになりました。「'」囲みが良くなかったか。
--------------------------------------------------------------
PS C:\> Get-ItemProperty $env:PROGRAMFILES\VideoLAN\VLC\vlc.exe
ディレクトリ: C:\Program Files\VideoLAN\VLC
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a---- 2023/10/31 4:40 989312 vlc.exe
--------------------------------------------------------------
上手くいきました。さらに「.versioninfo.productversiuon」を付加してファイルのバージョン情報を取得してみます。
--------------------------------------------------------------
PS C:\> (Get-ItemProperty $env:PROGRAMFILES\VideoLAN\VLC\vlc.exe).versioninfo.productversion
3,0,20,0
--------------------------------------------------------------
ファイルのプロパティからバージョン番号だけが取得できました。
つまり、Get-ItemPropertyコマンドレットなどをPowerShellで使う場合に指定する環境変数というのは「$env:環境変数名」で指定する必要があるということです。
例外
本ブログで、バッチファイルに組み合わせて「Powershell -Command」に続けてPowerShellコマンドレットを実行しているケースがあります。例えば、
--------------------------------------------------------------
Powershell -Command (Get-ItemProperty '%PROGRAMFILES%\VideoLAN\VLC\vlc.exe').VersionInfo.ProductVersion
--------------------------------------------------------------
こういう感じでバッチファイル内で一行だけPowerShellコマンドレットを指定している場合、環境変数の参照が「%PROGRAMFILES%」でも動作します。
その一方で、PowerShellの書式である
--------------------------------------------------------------
Powershell -Command (Get-ItemProperty $env:PROGRAMFILES\VideoLAN\VLC\vlc.exe).versioninfo.productversion
--------------------------------------------------------------
という書き方をしても正常に動作します。バッチファイル内ではどちらでも正常に動作することが確認できました。