スポンサーリンク

コマンドプロンプトでサービス起動判定時の処理を行う場合の注意点

コマンドプロンプトでサービス起動判定時の処理を行う場合の注意点Windows
コマンドプロンプトでサービス起動判定時の処理を行う場合の注意点
スポンサーリンク

主な使用コマンド一覧

実行中のサービス一覧を表示する

net start

全てのサービス一覧を表示する

sc query state=all

停止中のサービス一覧を表示する

sc query state=inactive

Windowsサーバーマネージャー上のサービス一覧を表示する

Powershell Get-service

テキスト文字列を検索する

findstr

netコマンドとscコマンドの違い

注意点としてはnetコマンドは同期scコマンドは非同期であること。つまり、コマンドの終了を待たない処理(非同期)の場合はscコマンドで良いが、それ以外ではnetコマンドを使うべきである。

不具合を生む例として、net stop(停止) → net start(開始) この場合、サービスの終了を待たずにサービスを起動してしまうのでエラーとなる可能性がある。

その時はうまく動作しても不具合を生む可能性があるので基本的にはnet startコマンドで起動中のサービス一覧を取得、起動、停止することが好ましい。

起動判定のロジックについて

net start | findstr サービス名

起動中のサービス名を取得後にfindstrで文字列を検索する。コマンドが成功すればERRORLEVEL=0、失敗すればERRORLEVEL=1となる。これらを利用して判定を行います。

サービス起動判定のコード

net start | findstr サービス名

if %ERRORLEVEL%==0 (
	net start サービス名
	
	set STATUS=%ERRORLEVEL%
	if %STATUS%==1 echo "error"
)

ロジックは問題ないのですが、これだと赤線の部分不具合が発生します。

if文やfor文など()で囲んだ場合は環境変数の即時展開と言って、バッチファイルを読み込んだ時に展開されるという特性があるため注意が必要です。

つまり、()で囲んだ部分で宣言した環境変数は()で囲む前の環境変数を読み込むこととなりますので、set STATUS=%ERRORLEVEL%が宣言されていないのでエラーとなります。

対処方法

対処方法として環境変数の遅延展開を使用することで環境変数が実行時の値に書き換わるようにします。

先頭にsetlocal enabledelayedexpansion 末尾にendlocalを追加して %を!に変更します。

環境変数の遅延展開を使用することで、()内でSTATUSが宣言されて実行時に%ERRORLEVEL%が代入されます。

rem 遅延展開開始
setlocal enabledelayedexpansion

rem 起動:0 停止:1
net start | findstr サービス名

  if %ERRORLEVEL%==0 (
	  rem 起動:1 停止:0
	  net start サービス名
	
	  set STATUS=!ERRORLEVEL!
	  if !STATUS! neq 0 echo "error"
  )

rem 遅延展開終了
endlocal

環境変数の遅延展開を利用することで無事サービス起動時のエラー判定ができました!

参考サイト

scコマンド

コマンドプロンプト/サービス一覧を表示する・scコマンド - Windowsと暮らす

netコマンド

コマンドプロンプト/netコマンドでサービス一覧を表示する・net start - Windowsと暮らす

環境変数の遅延展開

setlocal - Windowsコマンド虎の巻
タイトルとURLをコピーしました