2014年10月23日木曜日

Windowsサービスで「一覧のエクスポート」と同じような機能をバッチで作ってみた

概要

パッチ適用やHW交換の際のシステム停止でサービスの状態を変更する必要がある場合、
GUIから「一覧のエクスポート」を実行しているとその分時間が掛かってしまうため、
同等の情報採取をバッチでできなか試してみた。

準備

今回のメインは「sc」コマンドです。

Windows2003以降は標準コマンドとして搭載されていると思います。
Windows2000では追加インストールが必要だったかもしれません。



使用方法: sc <サーバー> [コマンド] [サービス名] <オプション1> <オプション2>
簡易説明:
 サービスの起動停止や、設定の変更、状態表示が可能

コマンド:
オプション
説明
query
サービスの状態を表示
queryex
拡張されたサービスの状態を表示(Win2003だとPID,FLAGSが追加)
start
サービスの開始
pause
サービスに PAUSE 制御要求を送信
interrogate
サービスに INTERROGATE 制御要求を送信
continue
サービスに CONTINUE 制御要求を送信
stop
サービスに STOP 要求を送信
config
サービスの構成を変更 (恒久的)
description
サービスの説明を変更
failure
エラー発生時のサービスの動作を変更
failureflag
サービスの障害動作フラグを変更
sidtype
サービスのサービス SID の種類を変更
privs
サービスの必要な特権を変更
qc
サービスの構成情報を表示
qdescription
サービスの説明を表示
qfailure
エラー発生時のサービスの動作を表示
qfailureflag
サービスの障害動作フラグを表示
qsidtype
サービスのサービス SID の種類を表示
qprivs
サービスの必要な特権を表示
qtriggerinfo
サービスのトリガー パラメーターを表示
qpreferrednode
サービスの優先 NUMA ノードを表示
delete
レジストリからサービスを削除
create
サービスを作成(レジストリ追加)
control
サービスに CONTROL コードを送信
sdshow
サービスのセキュリティ記述子を表示
sdset
サービスのセキュリティ記述子を設定
showsid
任意の名前に対応するサービス SID 文字列を表示
triggerinfo
サービスのトリガー パラメーターを構成
preferrednode
サービスの優先 NUMA ノードを設定
GetDisplayName
サービスの DisplayName を表示
GetKeyName
サービスの ServiceKeyName を取得
EnumDepend
サービスの依存関係を列挙
boot
最後に行われたブートを前回正常起動時の構成として保存するかどうか
Lock
サービス データベースをロック
QueryLock
SCManager データベースの LockStatus を表示


補足:
 ・[サービス名]は、
[管理ツール]-[サービス]の名前や、「net start」コマンドで表示されているのが
 「SERVICE_NAME」ではなく、「DISPLAY_NAME」であることに注意

 ・オプション指定はイコールの後にスペースが必要なので注意
  例) sc query state= all type= service

 ・依存関係があるサービスは、起動/停止できないことがある


オプション無しで実行




E:\wk>sc
説明:
        SC はサービス コントロール マネージャーやサービスと通信するために使用
        するコマンド ライン プログラムです。
使用法:
        sc <サーバー> [コマンド] [サービス名] <オプション1> <オプション2>...


       オプションの <サーバー> は "\\サーバー名" の形式です。
        「sc [コマンド]」と入力すると詳細なヘルプが表示されます。
        コマンド一覧:
          query-----------サービスの状態を照会したりサービスの種類ごと
                          に状態を列挙したりします。
          queryex---------拡張されたサービスの状態を照会したりサービス
                          の種類ごとに状態を列挙したりします。


 ~以降、省略~




サービスの状態表示


E:\wk>sc query wudfsvc

SERVICE_NAME: wudfsvc
        TYPE               : 20  WIN32_SHARE_PROCESS
        STATE              : 4  RUNNING
                                (NOT_STOPPABLE, NOT_PAUSABLE, IGNORES_SHUTDOWN)
        WIN32_EXIT_CODE    : 0  (0x0)
        SERVICE_EXIT_CODE  : 0  (0x0)
        CHECKPOINT         : 0x0
        WAIT_HINT          : 0x0





サービス名を指定せずに実行するとアクティブなサービス、ドライバが表示される。
インストールされている全てのサービスを表示したい場合、
「state= all type= service」を指定する


サービスの状態表示(拡張):


E:\wk>sc queryex wudfsvc

SERVICE_NAME: wudfsvc
        TYPE               : 20  WIN32_SHARE_PROCESS
        STATE              : 4  RUNNING
                                (NOT_STOPPABLE, NOT_PAUSABLE, IGNORES_SHUTDOWN)
        WIN32_EXIT_CODE    : 0  (0x0)
        SERVICE_EXIT_CODE  : 0  (0x0)
        CHECKPOINT         : 0x0
        WAIT_HINT          : 0x0
        PID                : 1120
        FLAGS              :



サービスの構成情報を表示:


E:\wk>sc qc wudfsvc
[SC] QueryServiceConfig SUCCESS

SERVICE_NAME: wudfsvc
        TYPE               : 20  WIN32_SHARE_PROCESS
        START_TYPE         : 2   AUTO_START
        ERROR_CONTROL      : 1   NORMAL
        BINARY_PATH_NAME   : C:\Windows\system32\svchost.exe -k LocalSystemNetworkRestricted
        LOAD_ORDER_GROUP   : PlugPlay
        TAG                : 0
        DISPLAY_NAME       : Windows Driver Foundation - User-mode Driver Framework
        DEPENDENCIES       : PlugPlay
                           : WudfPf
        SERVICE_START_NAME : LocalSystem





スクリプト作成


「sc query」の「SERVICE_NAME」からインストールされているサービスの一覧を作成し、
「sc qc」の「START_TYPE」から、「スタートアッ プの種類」
「sc query」の「STATE」から、「状態」をそれぞれ抜出し、csvファイルとして保存している。


svc_list.bat

@echo off
rem : --------------------------------------------------------------------------------------
rem :  サービスの状態取得
rem :
rem :  結果ファイル: yyyymmdd_hhmmssss_%conputername%-svclist.csv
rem : 内容: サービス名,状態,スタートアップの種類
rem : --------------------------------------------------------------------------------------
setlocal

rem : 現在の時刻を取得(hhmmssss)
set t=%time: =%
set t=%t::=%
set t=%t:.=%

rem : 取得するサービスリスト
set slist=%date:/=%_%t%_%computername%-svclist.csv
if exist %slist% del /f/s/q %slist% >nul 2>&1

rem : 一時ファイル
set cklist=svc.txt
if exist %cklist% del /f/s/q %cklist% >nul 2>&1


--------------------------------------------------------------------------------------
rem :  メイン処理
--------------------------------------------------------------------------------------
rem : サーバ上に登録されている全サービスのリスト取得
sc query state= all type= service | find "SERVICE_NAME" >%cklist%
for /F "tokens=1-3 delims=: " %%a IN (%cklist%) do call :sub %%b

rem : 一時ファイルの削除
if exist %cklist% del /f/s/q %cklist% >nul 2>&1

exit /b

--------------------------------------------------------------------------------------
rem :  サブルーチン
--------------------------------------------------------------------------------------
:sub

rem : ごみ掃除(スペースなどの削除)
set svcname=%~1
rem set  svcname=%SVCNAME:~0,-1%

rem : スタートアップの種類の抜き出し
for /F "skip=1 tokens=1-3 delims=: " %%A IN ('sc qc %svcname%') do (
if "%%A" == "START_TYPE" set STYPE=%%C
)

rem : 状態の抜き出し
for /F "skip=1 tokens=1-3 delims=: " %%A IN ('sc queryex %svcname%') do (
if "%%A" == "STATE" set ST=%%C
)

rem : リスト出力
echo %svcname%,%ST%,%STYPE%,%slist%

exit /b

endlocal


スクリプト確認

バッチファイルを実行すると、同じ階層に
「yyyymmdd_hhmmssss_%COMPUTERNAME%-svclist.csv」というファイルが作成される。



 例)20141023_14051264_MyPC-svclist.csv

AeLookupSvc,RUNNING,AUTO_START
Alerter,STOPPED,DISABLED
ALG,STOPPED,DEMAND_START
AppMgmt,STOPPED,DEMAND_START
appmgr,RUNNING,AUTO_START
aspnet_state,STOPPED,DEMAND_START
AudioSrv,RUNNING,AUTO_START
BITS,STOPPED,DEMAND_START
Browser,RUNNING,AUTO_START
CiSvc,STOPPED,DISABLED
ClipSrv,STOPPED,DISABLED
~省略~

ヘッダーは付けませんが、サービス名、状態、スタートアップの種類がcsv形式で出力されています。
また、説明や、アカウントの情報などは表示されません。


なお、サービス名を「SERVICE_NAME」ではなく、「DISPLAY_NAME」で表示することも可能

--------------------------------------------------------------------------------------
rem : サブルーチン
--------------------------------------------------------------------------------------
:sub

rem : ごみ掃除(スペースなどの削除)
set svcname=%~1
rem set svcname=%SVCNAME:~0,-1%

rem : スタートアップの種類の抜き出し
for /F "skip=1 tokens=1-3 delims=: " %%A IN ('sc qc %svcname%') do (
if "%%A" == "START_TYPE" set STYPE=%%C
if "%%A" == "DISPLAY_NAME" set DN=%%C
)

rem : 状態の抜き出し
for /F "skip=1 tokens=1-3 delims=: " %%A IN ('sc queryex %svcname%') do (
if "%%A" == "STATE" set ST=%%C
)

rem : リスト出力
echo %DN%,%ST%,%STYPE%>>%slist%

exit /b




ちなみに、PowerShellだと一瞬で片付きます。しかもこっちが早い。。。

get-wmiobject win32_service | select Name,State,StartMode | Export-csv E:\svc_list.txt


E:\svc_list.txt

#TYPE Selected.System.Management.ManagementObject
"Name","State","StartMode"
"AeLookupSvc","Running","Auto"
"Alerter","Stopped","Disabled"
"ALG","Stopped","Manual"
~省略~