批处理启动/停止Windows服务(升级版)
1 goto explain 2 学习批处理写法,其中用到的内容包含:批处理函数参数传递、字符串分割、读写文件、本地变量延迟以及注释等。 3 这里以批处理控制几个指定的Windows服务的启动/停止以及服务状态设置为例。 4 :explain 5 6 @echo off 7 rem Run as administrator 8 %1 mshta vbscript:CreateObject("Shell.Application").ShellExecute("cmd.exe","/c %~s0 ::","","runas",1)(window.close)&&exit 9 rem Switch to the file current directory 10 cd /d "%~dp0" 11 12 rem 设置本地为延迟扩展 13 setlocal enabledelayedexpansion 14 15 :flag_loop 16 17 cls 18 rem echo %0 19 20 rem 如果要增加其他的服务,只需要增加服务名称(服务名称可以包含空格),按分号分隔(仅修改这一处地方就可以) 21 set WS=MariaDB10.4;MariaDB10.5;MSSQLSERVER;aspnet_state;ZyrhDeviceService; 22 23 24 rem 数组下标开始,这里特意设计为从1开始 25 set WS_START=1 26 rem 数组元素数量,自动增长 27 set WS_COUNT=1 28 29 :flag_split 30 rem 分割字符串WS,按分号;分隔 31 rem tokens=1*,tokens表示分段的方式,tokens=1*表示第一个分隔符;之前的作为一部分,剩下的(*表示)作为一部分。这两部分在循环体总可以用%%a表示第一部分,%%b表示第二部分 32 rem delims=;表示以分号作为分隔符 33 for /f "tokens=1* delims=;" %%a in ("%WS%") do ( 34 rem echo n:%%a 35 rem 将分割出来的字符串赋值给数组元素 36 set WS[%WS_COUNT%]="%%a" 37 set /a WS_COUNT+=1 38 rem 将截取剩下的部分赋给变量WS 39 set WS=%%b 40 ) 41 rem 如果还有剩余,则继续分割 42 if defined WS goto :flag_split 43 44 set /a WS_COUNT-=1 45 46 echo [:Loop] Action Type: 47 echo S - Start, X - Stop, C - Config, N - Name, D - Description 48 49 echo. 50 echo Please select service id: 51 for /l %%n in (%WS_START%, 1, %WS_COUNT%) do ( 52 rem echo wn:!WS[%%n]! 53 rem 启用了变量延迟,变量需要用!!括起来 54 call :flag_state !WS[%%n]! %%n 55 ) 56 57 :flag_type 58 echo. 59 set /p "input= [:Type] Please input service id (%WS_START% - %WS_COUNT%) (R - :Loop, Q - Exit) : " 60 61 ::获取输入字符串的长度 62 call :get_len %input% len 63 64 set type=%input% 65 set action_str= 66 67 rem 如果输入2个(或2个以上)字符,如S1或X2等,则拆分前2个字符,第1个字符作为action动作:S-启用,X-停止,后面的字符作为类型数字 68 rem 按照之前的设计规则,应该是1S而不是S1,这样做的目的是为了兼容类型超出10个以上,10S处理起来比S10要麻烦很多 69 if %len% geq 2 ( 70 set action_str=%input:~0,1% 71 set type=%input:~1% 72 call :upper_case !action_str! action_str 73 ) 74 call :upper_case %type% type 75 set input=%type% 76 set /a num=%type%*1 77 78 call :check_exit %type% 79 80 if %type%==%num% ( 81 if %num% gtr %WS_COUNT% ( 82 echo Please enter the numbers %WS_START% - %WS_COUNT% . 83 goto flag_type 84 ) else if %num% leq 0 ( 85 echo Please enter the numbers %WS_START% - %WS_COUNT% ! 86 goto flag_type 87 ) else ( 88 call :flag_state !WS[%type%]! %type% 89 if "%action_str%" == "S" ( 90 call :flag_start "!WS[%type%]!" %type% 91 ) else if "%action_str%" == "X" ( 92 call :flag_stop "!WS[%type%]!" %type% 93 ) else if "%action_str%" == "C" ( 94 call :flag_config "!WS[%type%]!" 95 ) else if "%action_str%" == "N" ( 96 call :flag_name "!WS[%type%]!" 97 ) else if "%action_str%" == "D" ( 98 call :flag_desc "!WS[%type%]!" 99 ) else ( 100 call :flag_action !WS[%type%]! %type% 101 ) 102 ) 103 ) else if "%type%" == "R" ( 104 goto flag_loop 105 ) else ( 106 goto flag_type 107 ) 108 109 goto comments 110 函数 111 根据用户输入确定不同的操作 112 参数1: 要操作的服务名称,字符串 113 参数2: 要操作的服务的编号(即上面打印的服务列表的编号ID) 114 :comments 115 :flag_action 116 echo. 117 rem 这里的□ (<0x08>)是一个退格符,是为了显示出后面的两个空格位置 118 set /p "action= Please input action key (S - Start, X - Stop, C - :Config, N - :Name, D - :Desc, R - :Type, Q - Exit) : " 119 120 call :upper_case %action% action 121 122 call :check_exit %action% 123 124 if "%action%" == "S" ( 125 call :flag_start "%~1" %~2 126 ) else if "%action%" == "X" ( 127 call :flag_stop "%~1" %~2 128 ) else if "%action%" == "C" ( 129 call :flag_config "%~1" 130 ) else if "%action%" == "N" ( 131 call :flag_name "%~1" 132 ) else if "%action%" == "D" ( 133 call :flag_desc "%~1" 134 ) else if "%action%" == "R" ( 135 goto flag_type 136 ) else ( 137 goto flag_action 138 ) 139 goto:eof 140 141 goto comments 142 函数 143 查询服务状态,并返回明确的服务状态,如 RUNNING 或 STOPPED,接受两个参数 144 参数1: 要查询的服务名称,字符串 145 参数2: 接受返回结果的变量 146 :comments 147 :flag_state 148 set st= 149 call :flag_qc "%~1" %~2 st 150 151 set fn="%~1_tmp_123.log" 152 rem 查询服务状态信息,提取 STATE 内容并写入到文件中 153 sc query "%~1" |findstr "STATE" > %fn% 154 155 set value= 156 rem 读取文件内容到value变量 157 set /p value=<./%fn% 158 159 del %fn% 160 161 set index=2 162 rem 按冒号:分割字符串,并提取第2部分的内容(下标是从1开始的) 163 for /F "tokens=%index% delims=:" %%a in ("%value%") do set value=%%a 164 165 rem 按空格分割字符串,并提取第2部分的内容(下标是从1开始的) 166 for /F "tokens=%index% delims= " %%a in ("%value%") do set value=%%a 167 echo %~2 %~1 ---- %value% ---- %st% 168 goto:eof 169 170 :flag_qc 171 set fn="%~1_qc_123.log" 172 rem 查询服务配置信息,提取 START_TYPE 内容并写入到文件中 173 sc qc "%~1" |findstr "START_TYPE" > %fn% 174 175 set value= 176 rem 读取文件内容到value变量 177 set /p value=<./%fn% 178 179 del %fn% 180 181 set index=2 182 rem 按冒号:分割字符串,并提取第2部分的内容(下标是从1开始的) 183 for /F "tokens=%index% delims=:" %%a in ("%value%") do set value=%%a 184 185 rem 截取字符串,从第5个字符开始(空格也算是字符) 186 set value=%value:~5% 187 188 rem 替换双空格为单个空格 189 set value=%value: = % 190 191 rem echo %~2 %~1 -------- %value% 192 193 rem 将返回值赋值给变量3 194 set %~3=%value% 195 goto:eof 196 197 :flag_start 198 echo start %~1 199 sc start "%~1" 200 timeout 2 201 call :flag_state "%~1" %~2 202 goto flag_type 203 goto:eof 204 205 :flag_stop 206 echo stop %~1 207 sc stop "%~1" 208 timeout 2 209 call :flag_state "%~1" %~2 210 goto flag_type 211 goto:eof 212 213 :flag_config 214 echo. 215 set /p "config= Please input config key (1 - Automatic, 2 - Manual, 3 - Disabled, 4 - Delayed Auto, R - :Type, Q - Exit) : " 216 217 call :upper_case %config% config 218 219 call :check_exit %config% 220 221 rem 设置服务启动方式 auto - Automatic, demand - Manual, disabled - Disabled, delayed-auto - Automatic (Delayed Start) 222 if "%config%" == "1" ( 223 rem start= 这里需要一个空格 224 sc config "%~1" start= auto 225 ) else if "%config%" == "2" ( 226 sc config "%~1" start= demand 227 ) else if "%config%" == "3" ( 228 sc config "%~1" start= disabled 229 ) else if "%config%" == "4" ( 230 sc config "%~1" start= delayed-auto 231 ) else if "%config%" == "R" ( 232 goto flag_type 233 ) else ( 234 goto flag_config 235 ) 236 goto:eof 237 238 :flag_name 239 echo. 240 set /p "name= Please input service name (R - :Type, Q - Exit) : " 241 242 call :check_exit %name% 243 244 if "%name%" == "R" ( 245 goto flag_type 246 ) else ( 247 sc config "%~1" DisplayName= "%name%" 248 goto flag_type 249 ) 250 goto:eof 251 252 :flag_desc 253 echo. 254 set /p "desc= Please input service description (R - :Type, Q - Exit) : " 255 256 call :check_exit %desc% 257 258 if "%desc%" == "R" ( 259 goto flag_type 260 ) else ( 261 sc description "%~1" "%desc%" 262 goto flag_type 263 ) 264 goto:eof 265 266 :check_exit 267 if "%~1" == "Q" ( 268 goto flag_exit 269 ) else if "%~1" == "EXIT" ( 270 goto flag_exit 271 ) else if "%~1" == "QUIT" ( 272 goto flag_exit 273 ) 274 goto:eof 275 276 :upper_case 277 set val=%~1 278 for %%i in (A B C D E F G H I J K L M N O P Q R S T U V W X Y Z) do call set val=%%val:%%i=%%i%% 279 set %~2=%val% 280 goto:eof 281 282 :lower_case 283 set val=%~1 284 for %%i in (a b c d e f g h i j k l m n o p q r s t u v w x y z) do call set val=%%val:%%i=%%i%% 285 set %~2=%val% 286 goto:eof 287 288 :get_len 289 set str=%~1 290 set len=0 291 :label 292 set /a len+=1 293 set str=%str:~0,-1% 294 if defined str goto :label 295 ::echo len:%len% 296 set %~2=%len% 297 goto:eof 298 299 :flag_exit 300 exit