1. 程式人生 > >系統補丁檢測並安裝批處理

系統補丁檢測並安裝批處理

命令systeminfo,可以列出打過的補丁,當然,也可以使用下面的方法來檢測和打補丁。

@ECHO off
REM By Leo
SET TITLE=Windows 補丁安裝指令碼 V0.070408
TITLE %TITLE%
SETLOCAL ENABLEDELAYEDEXPANSION
SET PATCHFLAG=KB
SET CAT=%PATCHFLAG%*.cat
SET PATCHLIST="%temp%\patcheslist.tmp"
SET INSTALLED=√ 已安裝
SET NOTINSTALLED=× 未安裝
SET DELIMS=-----------------------------------------
SET PATCH_TOTAL=0
SET PATCH_NOTINSTALLED=0
SET FLAG_INSTALLED=1*
SET FLAG_NOTINSTALLED=0*
 
:main
TITLE 正在搜尋... -- %TITLE%
ECHO 正在搜尋當前目錄"%cd%"及其子目錄下的補丁...
ECHO 如果想在搜尋完成後立即安裝未安裝的補丁,請按回車。
ECHO.
REM 搜尋補丁,沒有搜尋到則退出,否則繼續。
CALL :pfind || (call :error 1& goto :eof)
ECHO.
:confirm
TITLE 請選擇要安裝的補丁 -- %TITLE%
ECHO 搜尋到如上%PATCH_TOTAL%個補丁,其中%PATCH_NOTINSTALLED%個未安裝。安裝全部請輸入ALL,否則請直接按回車安裝尚未安裝的補丁。
SET confirm=
SET /p confirm=
IF /i "%confirm%" == "ALL" (SET confirm=
 ) ELSE IF not defined confirm (SET confirm=%FLAG_INSTALLED:~0,1%
 ) ELSE GOTO confirm
ECHO %DELIMS%
ECHO.
ECHO 正在安裝,請稍候。安裝程式不會搶佔視窗焦點,所以你可以乾點別的:)
ECHO.
CALL :setup %confirm%
del %PATCHLIST% 2>nul >nul
TITLE 安裝已結束 -- %TITLE%
ECHO %DELIMS%
ECHO.
ECHO 安裝已結束。要使補丁生效,你可能需要手動重新啟動計算機。
ECHO 按任意鍵退出。
SET TITLE=
ENDLOCAL
PAUSE >nul
TITLE %ComSpec%
goto :eof
 
REM 安裝補丁
:setup
if "%1" == "" (set patchsum=%PATCH_TOTAL%) ELSE set patchsum=%PATCH_NOTINSTALLED%
set patch_counter=0
FOR /f "eol=%1 usebackq tokens=2,*" %%i in (%PATCHLIST%) DO (
 set /a patch_counter+=1
 TITLE !patch_counter!/%patchsum%-%%i -- %TITLE%
 set nobackup=nobackup
 echo %%i | find /i "%PATCHFLAG%8" 2>nul >nul && set nobackup=n
 %%j /quiet /passive /norestart /!nobackup! 2>nul >nul
 ECHO !patch_counter!/%patchsum% %%i √)
goto :eof
 
REM 搜尋當前目錄下的補丁,返回非零值為失敗。
:pfind
SET REG=HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall
SET listinreg="%temp%\listinreg.tmp"
reg query %reg%>%listinreg%
del %PATCHLIST% 2>nul >nul
REM 補丁是一個壓縮包
FOR /r %%i in (*%PATCHFLAG%*.exe) DO CALL :pfind.sub "%%~ni" "%%~fi" "%%~sfi"
REM 補丁在壓縮包展開後的目錄內
FOR /r %%i in (%cat%) DO IF exist %%~dpiupdate.exe FOR /f %%j in ("%%~dpiupdate.exe") DO CALL :pfind.sub "%%~ni" "%%~fj" "%%~sfj"
IF not exist %PATCHLIST% EXIT /b 1
sort %PATCHLIST% /o %PATCHLIST%
rem 得到補丁個數
FOR /f "tokens=3 delims= " %%i in ('find /c /i "%FLAG_NOTINSTALLED%" %PATCHLIST%') DO SET PATCH_NOTINSTALLED=%%i
FOR /f "tokens=3 delims= " %%i in ('find /c /i "%FLAG_INSTALLED%" %PATCHLIST%') DO SET /a PATCH_TOTAL=%%i + %PATCH_NOTINSTALLED%
del %listinreg% 2>nul >nul
IF not defined patch_total EXIT /b 2
IF %patch_total% LSS 1 EXIT /b 3
EXIT /b 0
goto :eof
REM 看看補丁安裝了沒,然後寫到標準輸出和%PATCHLIST%內
:pfind.sub
IF "%~3" == "" GOTO :eof
CALL :getkbnum %1
SET id=!errorlevel!
IF not "!id!" == "-1" (
 find /i "!id!" %listinreg% 2>nul >nul && (
 set status=%FLAG_INSTALLED%& set isinstalled=%INSTALLED%
 )||(set status=%FLAG_NOTINSTALLED%& set isinstalled=%NOTINSTALLED%)
 ECHO !status! %PATCHFLAG%!id! %2>>%PATCHLIST%
 ECHO !isinstalled! %PATCHFLAG%!id! %3
)
goto :eof
 
REM 返回給定字串中的KB號,返回-1表示失敗。
:getkbnum
SETLOCAL ENABLEDELAYEDEXPANSION
SET str=%~1
IF not defined str EXIT /b -1
IF not defined PATCHFLAG SET PATCHFLAG=KB
echo %PATCHFLAG%>getsize.tmp
for %%i in (getsize.tmp) do SET /a offset=%%~zi-2
del getsize.tmp 2>nul >nul
SET start=0
REM 僅有%PATCHFLAG%則返回-1
IF /i "%str%" == "%PATCHFLAG%" EXIT /b -1
REM 刪除%PATCHFLAG%前的字元,刪除失敗則返回-1
:getkbnum.findkb
IF "%~1" == "!str!" (IF "!str:~%start%,%offset%!" == "" (EXIT /b -1
 ) ELSE IF /i "!str:~%start%,%offset%!" == "%PATCHFLAG%" (SET str=!str:~%start%!
 ) ELSE (SET /a start+=1 & goto getkbnum.findkb))
REM 僅有%PATCHFLAG%則返回-1
SET str=!str:~%offset%!
IF "%str%" == "" EXIT /b -1
SET start=0
REM 保證%PATCHFLAG%後的第一個字元不是數字時,仍能返回-1
IF "!str:~%start%,1!" GTR "9" EXIT /b -1
IF "!str:~%start%,1!" LSS "0" EXIT /b -1
REM 返回%PATCHFLAG%後的數字
:getkbnum.findnum
IF "!str:~%start%,1!" GTR "9" EXIT /b !str:~0,%start%!
IF "!str:~%start%,1!" LSS "0" EXIT /b !str:~0,%start%!
SET /a start+=1
goto getkbnum.findnum
ENDLOCAL
EXIT /b -1
 
:error
TITLE ERROR -- %TITLE%
IF "%1" == "1" (ECHO 沒有找到補丁。使用的搜尋規則是:CAT:%cat%,PATCHFLAG:%PATCHFLAG%。程式已結束。)
SET TITLE=
PAUSE >nul
TITLE %ComSpec%
goto :eof