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