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