treedown’s Report

システム管理者に巻き起こる様々な事象を読者の貴方へ報告するブログです。会社でも家庭でも"システム"に携わるすべての方の共感を目指しています。

※https化しました。その影響でしばらくリンク切れなどがあるかもしれませんが徐々に修正していきます。 リンク切れなどのお気づきの点がございましたらコメントなどでご指摘いただけますと助かります。

バッチファイルでアプリケーションのバージョンを取得する(ための文字列操作)

以前からやってみようと思っていたバッチファイルをご報告です。
「インストール済アプリケーションのバージョン」と「インストールするファイルのバージョン」を比較して、新しいバージョンならインストール実行、というバッチファイルを作るためにいろいろ調べながらやってみました。

環境

ざっくりとした環境を。
Windows10の64ビット環境のコマンドプロンプトで確認。
インストール対象は仮にCubePDFをインストール・アップデートを想定し、ダウンロードするインストーラ「cubepdf-0.0.0-x64.exe」(※0にはバージョン情報の数字がはいる)をベースにバッチファイルを検討しました。

インストール済のCubePDFのバージョンをバッチファイル内で調べて、インストールファイルとなる「cubepdf-0.0.0-x64.exe」のバージョンと比較して、新しいバージョンならインストール実行、それ以外(それ以下とか同じバージョン)なら何も実行せず終了、という処理を実行してくれるバッチファイルを考えます。

インストール済CubePDFのバージョン収集

Windowsにインストールしたアプリケーションのバージョンを取得して、変数に代入する、というバッチファイルの部品を作っていきます。

インストールアプリケーションの情報が保管されたレジストリキーは下記の三種類のレジストリキーをregコマンド(reg queryに/sオプションを付与)で探すと見つかります。

[HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Uninstall]
[HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Uninstall]
[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall]

※実行したイメージ(こんな感じで画面表示されます。)

f:id:treedown:20211122184036p:plain

CubePDFは"HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Uninstall"で見つかりました。
--------------------------------------------------------------
>reg query "HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Uninstall" /s | findstr "DisplayName"
    DisplayName    REG_SZ    7-Zip 19.00 (x64)
    DisplayName    REG_SZ    Mozilla Firefox ESR (x64 ja)
    DisplayName    REG_SZ    VLC media player
    DisplayName    REG_SZ    paint.net
    DisplayName    REG_SZ    CubePDF Utility 1.5.2 (x64)
    DisplayName    REG_SZ    CubePDF 1.5.1 (x64)
--------------------------------------------------------------

そこで、もうちょっと調べて、UUIDまでを指定して、インストールされているCubePDFのバージョンをDisplayVersionキーから取得できました。

--------------------------------------------------------------
>reg query "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{4DB5CF1C-F10E-4C4D-84D7-2525CFAB8F6C}_is1" | findstr "DisplayVersion"
    DisplayVersion    REG_SZ    1.5.2
--------------------------------------------------------------

実行結果を変数に代入するため、以前<バッチファイルでコマンドの実行結果を変数に代入する - treedown’s Report>のやり方を使って、コマンドの実行結果を変数に入れるため、一時ファイルを使うことにしました。

--------------------------------------------------------------
reg query "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{4DB5CF1C-F10E-4C4D-84D7-2525CFAB8F6C}_is1" | findstr "DisplayVersion">%CD%\CubePVerCHK.txt
--------------------------------------------------------------

ここから、バージョンの数字を変数に代入するための処理を試行錯誤していきました。

取得したバージョン情報を変数に代入する

とりあえず、結論としてできあがったバッチファイルを。
--------------------------------------------------------------
ファイル名:CubePVerCHK.bat
--------------------------------------------------------------
@echo off
set CPver=

rem 一時ファイル生成
reg query "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{4DB5CF1C-F10E-4C4D-84D7-2525CFAB8F6C}_is1" | findstr "DisplayVersion">CubePVerCHK.txt

set /P CPver=<%CD%\CubePVerCHK.txt
echo %CPver%

set CPver=%CPver:~-8%
echo %CPver%

set CPver=%CPver: =%
echo %CPver%

del %CD%\CubePVerCHK.txt
set CPver=
--------------------------------------------------------------

出力結果

f:id:treedown:20211122184247p:plain

--------------------------------------------------------------
>CubePVerCHK.bat
    DisplayVersion    REG_SZ    1.5.2
   1.5.2
1.5.2
--------------------------------------------------------------

「set /P CPver=<%CD%\CubePVerCHK.txt」で取得したコマンドラインの実行結果を変数に代入しています。echoの画面出力では
「    DisplayVersion    REG_SZ    1.5.2」と表示されています。これが素の状態。

お次に「set CPver=%CPver:~-8%」では、変数の後ろから8文字分の文字列を取得して変数に代入しています。echoの画面出力では
「   1.5.2」と表示されています。8文字取得したのはバージョンを示す数字で二桁までの文字列(例:11.22.33など)が想定されるためです。

最後の「set CPver=%CPver: =%」では、ブランク(変数内の文字列の「 」←スペース)を除去しています。
echoの画面出力では
「1.5.2」と表示されています。

ここまででようやく%CPver%という変数に1.5.2というバージョン情報が代入できました。

インストーラファイルからバージョン情報を収集する

ここはそれほど難しいことはやっていなくて、インストールファイルからバージョンを示す文字列を収集して変数に代入しています。
バッチファイル中の「rem インストール場所からファイル名を取得」以降の処理が該当します。
--------------------------------------------------------------
ファイル名:CubePVerCHK.bat
--------------------------------------------------------------
@echo off
set CPver=
set InstFileDir=.\InstFile-Test
set InstFileNum=

rem 一時ファイル生成しそこから変数に代入
reg query "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{4DB5CF1C-F10E-4C4D-84D7-2525CFAB8F6C}_is1" | findstr "DisplayVersion">%CD%\CubePVerCHK.txt
set /P CPver=<%CD%\CubePVerCHK.txt
set CPver=%CPver:~-8%
set CPver=%CPver: =%
del %CD%\CubePVerCHK.txt

rem インストール場所からファイル名を取得
pushd %InstFileDir%
FOR /F %%i in ('dir /b') DO @SET InstFileNum=%%i
echo %InstFileNum%
rem 拡張子を除いてファイル名だけ取得
FOR /F %%i in ('echo %InstFileNum%') DO set InstFileNum=%%~ni
echo %InstFileNum%
rem バージョンだけ抜き出す[cubepdf-0.0.0-x64.exeの「cubepdf-」と「-x64」を取り払う。
rem 例:置き換える場合の書式[set InstFileNum=%InstFileNum:x64=x86%]
set InstFileNum=%InstFileNum:cubepdf-=%
set InstFileNum=%InstFileNum:-x64=%
echo %InstFileNum%
popd

:end
set CPver=
set InstFileDir=
set InstFileNum=
--------------------------------------------------------------

実行結果※画像はまだテストのechoの画面出力を消す前の状態ですが参考まで

f:id:treedown:20211122184326p:plain

--------------------------------------------------------------
>CubePVerCHK.bat
cubepdf-1.5.1-x64.txt
cubepdf-1.5.1-x64
1.5.1
--------------------------------------------------------------

「FOR /F %%i in ('dir /b') DO @SET InstFileNum=%%i」にて「dir /b」実行結果となるファイル名を収集し、変数%InstFileNum%に代入しています。その次のechoで画面には、
「cubepdf-1.5.1-x64.txt」
と表示されています。※ちなみにテストファイルを手動で生成したので、拡張子.txtになっていますが本番は.exeになります。

次に、「FOR /F %%i in ('echo %InstFileNum%') DO set InstFileNum=%%~ni」という行で、収集したファイル名から拡張子を抜いた文字列「cubepdf-1.5.1-x64」を変数%InstFileNum%に代入しています。
for文内で「echo %InstFileNum%」を実行し、その実行結果から「%%~ni」指定で代入することで、ファイル名のみを代入することができます。

※「%~」に特定のアルファベットを付与して、取得したファイル名やパス(ディレクトリまでのフルパス、など)を加工することができます。詳細は省略。

ここまでで画面表示「cubepdf-1.5.1-x64」となります。

後は単純に、文字列を消してしまいました。「cubepdf-1.5.1-x64」のうち、バージョン情報前の「cubepdf-」の文字列と、バージョン後の文字列「-x64」をset文で取っ払った状態で再度同じ変数に代入します。
set文で変数に代入する文字を「%InstFileNum:cubepdf-=%」と「%InstFileNum:-x64=%」と指定します。前出のブランクを削除したのと同じ原理です。

こうしてechoの画面出力は
「1.5.1」
と、ファイル名に記載のバージョンを表現する数字の部分だけを抜き出して変数に格納するところまで完了できました。

ファイル名と比較しようと思ったが…

長くなったので、ひとまずここまでで、いったん一段落。

あとはファイル名にバージョン情報が記載されているので、そのファイル名の数字だけ抜き出して比較すれば、やりたいことはできる、と思っていたのですが、比較には思わぬ落とし穴がありました。

後で追加:参考:PowerShellでアプリケーション情報収集

今回、コマンドプロンプト上でインストール済CubePDFのバージョンを収集しましたのでレジストリキーをコマンドで表示しましたが、PowerShellで実施する場合には、以下の三つのどれかで確認できます。
--------------------------------------------------------------

  • Get-WmiObject Win32_Product | Select-Object Name,Vendor.Version,Caption
    Get-ItemProperty
  • HKLM:\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\* | Select-Object DisplayName,DisplayVersion,Publisher,InstallDate | Format-Table
  • Get-ItemProperty HKLM:\Software\\Microsoft\Windows\CurrentVersion\Uninstall\* | Select-Object DisplayName,DisplayVersion,Publisher,InstallDate | Format-Table

--------------------------------------------------------------

CubePDFは「HKLM:\Software\\Microsoft\Windows\CurrentVersion\Uninstall\」に情報が格納されているので、一番下(三番目)のPowerShellコマンドレットでバージョン情報を表示させることができました。

絞り込むために、「Format-Table」を「Select-String」に置き換えて、CubePDFだけを抜き出すと以下のようになります。
--------------------------------------------------------------
Get-ItemProperty HKLM:\Software\\Microsoft\Windows\CurrentVersion\Uninstall\* | Select-Object DisplayName,DisplayVersion,Publisher,InstallDate | Select-String -Pattern CubePDF
--------------------------------------------------------------
実行結果:
--------------------------------------------------------------
@{DisplayName=CubePDF Utility 0.4.1β (x64); DisplayVersion=0.4.1; Publisher=CubeSoft; InstallDate=20190624}
@{DisplayName=CubePDF Utility 1.5.2 (x64); DisplayVersion=1.5.2; Publisher=CubeSoft; InstallDate=20210908}
@{DisplayName=CubePDF 1.6.0 (x64); DisplayVersion=1.6.0; Publisher=CubeSoft; InstallDate=20211122}
--------------------------------------------------------------
と、画面に表示されます。

※実は後で使うことになった知識のメモ