サービスの開始/停止を行うバッチです。なるべく最小化して実行し、その結果をメッセージボックスで表示してみたいと思います。
目次
1. サービスを開始する
サービスを開始するためのバッチファイルを早速見ていきます。
以下の3行目、「rem —イコールの後に~—」の下の行に、開始したいサービス名を指定します。
サービス名は、タスクマネージャーの「サービス」タブ、「名前」に表示される文字列を指定します。
下記では例として「spooler」(印刷に使われるサービス)を指定してあります。
@echo off
rem ---イコールの後に開始するサービス名を入力(例としてspoolerを記述)---
set ServiceName=spooler
whoami /priv | find "SeLoadDriverPrivilege" > nul
if %ERRORLEVEL% equ 0 (
goto ServiceStart
)
if not %0=="%~dp0.\%~nx0" (
start /min "" cmd /c,"%~dp0.\%~nx0" %*
exit /b
)
rem サービスが開始されているかどうか確認
sc query %ServiceName% | findstr STATE | findstr RUNNING > nul
if %ERRORLEVEL% equ 0 (
echo msgbox "「%ServiceName%」サービスは既に開始されています。",vbInformation,"サービス開始済み" > %TEMP%\resultmsg.vbs & %TEMP%\resultmsg.vbs
goto DelVBS
) else (
rem 管理者権限で再度実行
powershell.exe -Command Start-Process ""%0"" -Verb Runas -WindowStyle Hidden
exit /b
)
:ServiceStart
rem サービス開始
net start %ServiceName%
if %ERRORLEVEL% equ 0 (
echo msgbox "「%ServiceName%」サービスを開始しました。",vbInformation,"サービス開始" > %TEMP%\resultmsg.vbs & %TEMP%\resultmsg.vbs
) else (
echo msgbox "予期しないエラーが発生しました。サービスは開始されていない可能性があります。",vbCritical,"予期しないエラー" > %TEMP%\resultmsg.vbs & %TEMP%\resultmsg.vbs
)
:DelVBS
del %TEMP%\resultmsg.vbs
exit /b
サービスの開始と停止を行うにはバッチファイルを管理者権限で実行する必要がありますが、通常の実行では権限が付与されません。それを踏まえ、サービスの開始状況を事前に判定し、サービスが停止しているときだけアカウント制御ダイアログを出して開始させるようにしてみました。
まず「whoami ~」で管理者権限の有無を判定しています。初めは権限が無いのでifの分岐には入りません。
次にバッチのウィンドウを出さないよう、「if not %0== ~」のところで最小化して実行し直しています。
そして「sc query %ServiceName% ~」で、指定されたサービスの開始/停止状況を確認します。
「sc query」で状況を表示し、「STATE」項目の中に「RUNNING」という文字列があるか探しています。
既に開始されている場合はエラーレベルが0になり、直後のif分岐でメッセージを表示して終了します。アカウント制御のダイアログは出ません。
サービスが停止している状態なら「powershell.exe ~」に進み、管理者権限でバッチを実行し直します。このときアカウント制御のダイアログが出ます。
バッチファイルを管理者権限で実行する の記事を元に、「-WindowStyle Hidden」で最小化して実行し直します。
実行し直されたときには「whoami ~」の分岐に入って「:ServiceStart」までgotoで飛びます。
「net start ~」が実際にサービスを開始するコマンドです。このコマンドのエラーレベルは次のようになります。
- 0 … 正常にサービスを開始
- 2 … サービスが既に開始されている / アクセス拒否 / サービス名の誤り
エラーレベル2のうち、サービスが既に開始されている場合については最初の方で確認済みです。
また、管理者権限でバッチを実行し直しているため、アクセス拒否のエラーになることはまずありません。
したがって、サービス名の記述が誤っている場合に「else」の分岐に入り、予期しないエラーのメッセージが表示されることになります。
2. サービスを停止する
今度はサービスを停止させるバッチです。大まかな流れは開始する場合と同様です。
@echo off
rem ---イコールの後に停止するサービス名を入力(例としてspoolerを記述)---
set ServiceName=spooler
whoami /priv | find "SeLoadDriverPrivilege" > nul
if %ERRORLEVEL% equ 0 (
goto ServiceStop
)
if not %0=="%~dp0.\%~nx0" (
start /min "" cmd /c,"%~dp0.\%~nx0" %*
exit /b
)
rem サービスが停止されているかどうか確認
sc query %ServiceName% | findstr STATE | findstr STOPPED > nul
if %ERRORLEVEL% equ 0 (
echo msgbox "「%ServiceName%」サービスは既に停止しています。",vbInformation,"サービス停止済み" > %TEMP%\resultmsg.vbs & %TEMP%\resultmsg.vbs
goto DelVBS
) else (
rem 管理者権限で再度実行
powershell.exe -Command Start-Process ""%0"" -Verb Runas -WindowStyle Hidden
exit /b
)
:ServiceStop
rem サービス停止コマンド
net stop %ServiceName%
if %ERRORLEVEL% equ 0 (
echo msgbox "「%ServiceName%」サービスを停止しました。",vbInformation,"サービス停止" > %TEMP%\resultmsg.vbs & %TEMP%\resultmsg.vbs
) else (
echo msgbox "予期しないエラーが発生しました。サービスは停止されていない可能性があります。",vbCritical,"予期しないエラー" > %TEMP%\resultmsg.vbs & %TEMP%\resultmsg.vbs
)
:DelVBS
del %TEMP%\resultmsg.vbs
exit /b
「sc query」で探す文字列は、停止を指す「STOPPED」になっています。
「net stop」コマンドのエラーレベルは先ほどの「net start」コマンドと同様ですので、分岐の仕方も変わりません。
以上の記述により、指定されたサービスが既に開始/停止している場合はメッセージを表示するのみで、実際に開始/停止させる場合はアカウントパスワードの入力を求めて実行する、という動作になります。