要件
- とあるアプリケーションのレジストリをバッチで更新したい
-
HKLM\SOFTWARE
以下なので、管理者権限ユーザのみ実行可能とする
-
- 対象OSは、Windows8.1、10
- 32bit版と64bit版両方を対象とする
- アプリケーションがインストールされてない場合は、処理を実行しない
- 不要なレジストリは登録しない
処理の流れ
- 管理者ユーザで、かつ、管理者権限でプロンプトを実行する
- ローカルユーザの場合、処理中断
- 管理者ユーザで、かつ通常プロンプトでバッチが実行された場合、管理者権限プロンプトに昇格し、以降の処理を実行する
- OSのバージョンをチェックする
- Win8.1、10のみ、次処理に引き継ぐ
- bitをチェックする
- レジストリが64bitと32bitで格納場所が異なるため、bitに応じて処理対象レジストリパスを判定する
- レジストリキーをチェックする
- 更新対象レジストリキーが存在する事をチェックする
- アプリケーションの存在有無は、レジストリチェックを持って代用する
- レジストリキーを更新する
レジストリ更新バッチ
RegistoryUpdater.bat
@echo off
echo **** レジストリ更新処理: %date% %time%
SETLOCAL enabledelayedexpansion
rem -- 64bit版 レジストリのパス
set REG_64_ROOT=HKLM\SOFTWARE\Wow6432Node\Sample
rem -- 32bit版 レジストリのパス
set REG_32_ROOT=HKLM\SOFTWARE\Sample
rem -- カレントディレクトリを基準とする
cd /d %~dp0
rem ----------------------------------------------
rem --- 管理者実行チェック&昇格処理
:checkMandatoryLevel
rem --- ▼管理者として実行されているか確認 START
for /f "tokens=1 delims=," %%i in ('whoami /groups /FO CSV /NH') do (
if "%%~i"=="BUILTIN\Administrators" set ADMIN=yes
if "%%~i"=="Mandatory Label\High Mandatory Level" set ELEVATED=yes
)
if "%ADMIN%" neq "yes" (
rem -- Administratorsグループでない(ローカルユーザの場合)
echo 管理者権限を持たない為、処理を中断します。
rem --- 処理終了
goto exit1
)
if "%ELEVATED%" neq "yes" (
rem -- (プロセスが昇格されていない) Admin権限ありユーザが通常実行した場合
echo このファイルは管理者権限での実行が必要です
echo 昇格を行いますので、しばらくお待ちください
goto runas
)
rem --- ▲管理者として実行されているか確認 END
:admins
rem --- ▼管理者として実行したいコマンド START
rem --- OSチェック処理
CALL :checkOS
rem --- ▲管理者として実行したいコマンド END
goto exit1
:runas
if "%1" == "" (
rem --- 引数なしのため、★管理者として再実行
@powershell -NoProfile -ExecutionPolicy unrestricted -Command "Start-Process %~f0 REPEATED -Verb runas"
) else (
rem --- 引数ありのため、すでに自身を再実行している。
rem --- 処理終了
echo 管理者への昇格に失敗しました。処理を中断します。
)
goto exit1
rem ----------------------------------------------
rem --- OSチェックサブルーチン
:checkOS
echo OS:
call ver
rem --- OSのバージョン確認(Win7) → 処理中断
ver | find /i "Version 6.1." > nul
if %ERRORLEVEL% equ 0 goto :checkOS_WIN7
rem --- OSのバージョン確認(Win8.1) → bitチェック
ver | find /i "Version 6.3." > nul
if %ERRORLEVEL% equ 0 goto :checkBit
rem --- OSのバージョン確認(Win10) → bitチェック
ver | find /i "Version 10.0." > nul
if %ERRORLEVEL% equ 0 goto :checkBit
rem --- それ以外の場合、処理終了
goto :exit1
exit /B
rem ----------------------------------------------
rem -- OSチェック結果:Win7
:checkOS_WIN7
echo Windows7は処理対象外のため、終了します。
goto :exit1
exit /B
rem ----------------------------------------------
rem -- bitチェック
:checkBit
echo bit: %PROCESSOR_ARCHITECTURE%
rem --- OSのbit確認(64bit)
if %PROCESSOR_ARCHITECTURE% == AMD64 GOTO :checkBitResult64
rem --- OSのbit確認(32bit)
if %PROCESSOR_ARCHITECTURE% == x86 GOTO :checkBitResult32
rem --- それ以外の場合、処理終了
goto :exit1
exit /B
rem ----------------------------------------------
rem -- bitチェック結果(64bit)
:checkBitResult64
rem -- 64bit版のパスを保持する
set REG_ROOT=%REG_64_ROOT%
rem -- レジストリ確認処理実行
goto :checkpRegistory
exit /B
rem ----------------------------------------------
rem -- bitチェック結果(32bit)
:checkBitResult32
rem -- 32bit版のパスを保持する
set REG_ROOT=%REG_32_ROOT%
rem -- レジストリ確認処理実行
goto :checkpRegistory
exit /B
rem ----------------------------------------------
rem -- レジストリ確認処理
:checkpRegistory
echo レジストリ確認: %REG_ROOT%
reg query %REG_ROOT% /v EnableSample | find /i "EnableSample" > nul
rem -- レジストリが存在するため、レジストリ更新処理実行
if %ERRORLEVEL% equ 0 goto :updatepRegistory
rem --- それ以外の場合、処理終了
echo 更新対象レジストリが存在しないため、処理を中断します。
goto :exit1
exit /B
rem ----------------------------------------------
rem -- レジストリ更新処理
:updatepRegistory
echo レジストリを更新します。
rem -- レジストリ更新処理実行
reg add %REG_ROOT% /v EnableSample /t REG_DWORD /d 1 /f
rem -- 処理終了
goto :exit1
exit /B
rem ----------------------------------------------
rem -- 終了処理
:exit1
echo **** レジストリ更新処理終了
exit
参考)
- バッチファイル(*.bat) を管理者として実行するための バッチファイル
- Windows OS のバージョン情報を判定して条件分岐させるバッチファイル【共通編】
- コマンドプロンプトで64bitか32bitを調べる方法: 京都きもの屋IT系ブログ
おまけ
上記バッチには不採用になったが、色々なパターンを想定してたサンプルを作ったので、供養。
アプリケーションのバージョンチェック
EXEやDLLのプロパティ>詳細>ファイルバージョンに記載されている値を取得するバッチコマンド
#どっちかというと、Powershellの結果をバッチ側で取得するサンプル、かな…
ExeVerCheck.bat
set EXE_PATH=C:\Program Files\Microsoft Office\Office14\EXCEL.EXE
echo EXEパス: %EXE_PATH%
FOR /F "usebackq" %%i IN (`Powershell -Command "return (Get-ItemProperty '%EXE_PATH%').VersionInfo.FileVersion"`) DO SET EXE_VER=%%i
echo EXEバージョン: %EXE_VER%
レジストリの更新チェック
該当レジストリキーの項目だけ更新できているかチェック。
他のキーを更新している等、diff結果が該当キー以外にもヒットした場合、リストアする。
RegDiff.bat
rem -- 管理者権限チェック・昇格処理は省略。
rem -- 更新対象レジストリパス
set REG_ROOT=HKLM\SOFTWARE\Sample\
rem -- ★比較用レジストリファイル
set REG_BEFORE=RegBefore.reg
set REG_AFTER=RegAfter.reg
rem -- カレントディレクトリを基準とする
cd /d %~dp0
rem ---------------------------------------------------
rem -- レジストリ確認処理
:checkRegistory
echo レジストリルート: %REG_ROOT%
rem -- レジストリ存在チェック
reg query %REG_ROOT% /v EnableSample | find /i "EnableSample" > nul
rem -- レジストリが存在するため、レジストリ更新処理実行
if %ERRORLEVEL% equ 0 goto :changeRegistory
rem --- それ以外の場合、処理終了
echo レジストリが存在しないため、処理を中断します。
goto :exit1
rem - サブルーチンの終了
exit /B
rem ---------------------------------------------------
rem -- レジストリ更新処理
:changeRegistory
rem -- ★変更前レジストリを保存(上書き許可)
reg export %REG_ROOT% %REG_BEFORE% /y
echo レジストリを更新します。
reg add %REG_ROOT% /v EnableSample /t REG_DWORD /d 1 /f
rem -- ★更新後のレジストリを保存(上書き許可)
reg export %REG_ROOT% %REG_AFTER% /y
rem -- ★レジストリファイルの比較
rem -- fc: Windows標準diffコマンド
rem -- 不一致行の前後の一致行も常に表示される
rem -- /uオプション: unicodeで比較する
fc /U %REG_AFTER% %REG_BEFORE%
rem -- レジストリ比較結果保持
set REG_DIFF=""
rem -- ★実際に相違のある行のみを表示する
rem -- F=0 → ***** に囲まれたファイル1表示の外側
rem -- F=1 → ファイル1表示の先頭行なので表示しない
rem -- F=2 → ファイル1表示の2行目。F=3の処理と合わせるため一時保管しておく
rem -- F=3 → 同3行目以降。最終行かもしれないのですぐに表示出来ないので一時保管する
rem -- ただし、さっき一時保管した行があるはずなのでまずそれを表示する
rem -- ***** %1 と等しい行 → F=1にする
rem -- ***** %2 と等しい行 → 最終行が保管されているが表示せずF=0にする
set F=0
for /f "skip=1 delims=" %%A in ('fc /U %REG_AFTER% %REG_BEFORE%') do (
if /i "%%A"=="***** %REG_BEFORE%" ( set F=0
) else if /i "%%A"=="***** %REG_AFTER%" ( set F=1
) else if !F!==1 ( set F=2
) else if !F!==2 ( set F=3&set SAVE=%%A&set REG_DIFF=%REG_DIFF%_%%A
) else if !F!==3 ( echo.!SAVE!&set SAVE=%%A)
)
rem -- 比較部分の文字列からダブルクォーテーションを除く
set REG_DIFF=%REG_DIFF:"=%
rem -- 正常に更新された場合
if "%REG_DIFF%" == "_EnableSample=dword:00000001" goto :updatedRegistory
rem -- 更新が行われなかった(既に更新済み)の場合
if "%REG_DIFF%" == "" goto :updatedRegistory
echo レジストリが不正に更新された可能性があります。restoreします。
goto :restoreRegistory
exit /B
rem ---------------------------------------------------
rem -- レジストリ更新正常終了
:updatedRegistory
echo レジストリが正常に更新されました。
goto exit1
exit /B
rem ---------------------------------------------------
rem -- レジストリ更新以上終了
:restoreRegistory
echo レジストリの更新に失敗したため、リストアします。
reg import %REG_BEFORE%
goto exit1
exit /B
:exit1
exit