Jump to content

Welcome to MSFN Forum
Register now to gain access to all of our features. Once registered and logged in, you will be able to create topics, post replies to existing threads, give reputation to your fellow members, get your own private messenger, post status updates, manage your profile and so much more. This message will be removed once you have signed in.
Login to Account Create an Account



Photo

Batch script for windows & software updates installation


  • Please log in to reply
52 replies to this topic

#26
xranger

xranger
  • Member
  • 2 posts
  • Joined 16-January 12
  • OS:none specified
  • Country: Country Flag
hi,Yzowl. I am a newbe here..your code is awesome :thumbup thanks a lot.
But I just got a little problem,when I tested this batch by choosing "run as administrator"(windows7 x64) in a folder with all MSU and EXE update files, .bat processed and listed them,
but in fact none of them was actuelly installed. Then I tried to add "cd /d %~dp0" to change the path at the beginning before your code, and it worked finally.
But in your code these is already "FOR /R "%~dp0" %%A IN (*-KB*.MSU) DO (" , looks like this parte doesn't work for me, I dont understand why, could you please explain?
PS: your second code for .exe file updating woks well.

That is correct.

Do bear in mind that WUSA.EXE is located within %PATH% as is SHUTDOWN.EXE and that executables located within the path do not require their path prepending to the command. You have done so with one and not the other, whilst both are correct it seems pointless to include that which isn't required.
You can also simplify lines 2 & 3 by merging them into one thus

@ECHO OFF
SETLOCAL ENABLEEXTENSIONS ENABLEDELAYEDEXPANSION
FOR /R "%~dp0" %%A IN (*-KB*.MSU) DO (
	CALL :SUB %%~nA
	ECHO= Installing KB!KB_NUM!
	>NUL TIMEOUT /t 3
	WUSA "%%A" /quiet /norestart)
ECHO= == Press any key to restart ==
>NUL PAUSE
SHUTDOWN.EXE /r /t 0
GOTO :EOF

:SUB
SET "KB_NUM=%*"
FOR /F "DELIMS=-" %%B IN ("%KB_NUM:*-KB=%") DO SET "KB_NUM=%%B"




How to remove advertisement from MSFN

#27
Yzöwl

Yzöwl

    Wise Owl

  • Super Moderator
  • 4,078 posts
  • Joined 13-October 04
  • OS:Windows 7 x64
  • Country: Country Flag

Donator

If all of the updates are located within the same directory as the batch file then you don't need the recursion and can indeed navigate to the source directory.
@ECHO OFF
SETLOCAL ENABLEEXTENSIONS ENABLEDELAYEDEXPANSION
PUSHD %~dp0
FOR %%A IN (*-KB*.MSU) DO (
	CALL :SUB %%~nA
	ECHO= Installing KB!KB_NUM!
	>NUL TIMEOUT /t 3
	WUSA "%%~fA" /quiet /norestart)
ECHO= == Press any key to restart ==
>NUL PAUSE
SHUTDOWN.EXE /r /t 0
GOTO :EOF

:SUB
SET "KB_NUM=%*"
FOR /F "DELIMS=-" %%B IN ("%KB_NUM:*-KB=%") DO SET "KB_NUM=%%B"


#28
xranger

xranger
  • Member
  • 2 posts
  • Joined 16-January 12
  • OS:none specified
  • Country: Country Flag
Thank you,Yzowl..
You 're right..I retested the batch file, it works well now..that's odd,maybe I forgot restarting my system after patching Sp1 :P
Anyway.thank again :)

#29
MrAnderson

MrAnderson
  • Member
  • 1 posts
  • Joined 04-March 12
  • OS:Vista Home Premium x86
  • Country: Country Flag
@ECHO OFF
:: Check for permissions
>nul 2>&1 "%SYSTEMROOT%\system32\cacls.exe" "%SYSTEMROOT%\system32\config\system"

:: If error flag set, we do not have admin.
if '%errorlevel%' NEQ '0' (
Echo Requesting administrative privileges...
goto UACPrompt
) else ( goto gotAdmin )

:UACPrompt
Echo Set UAC = CreateObject^("Shell.Application"^) > "%temp%\getadmin.vbs"
Echo UAC.ShellExecute "%~s0", "", "", "runas", 1 >> "%temp%\getadmin.vbs"

"%temp%\getadmin.vbs"
Exit /B

:gotAdmin
if exist "%temp%\getadmin.vbs" ( Del "%temp%\getadmin.vbs" )
Pushd "%CD%"
CD /D "%~dp0"
:--------------------------------------

SETLOCAL ENABLEEXTENSIONS ENABLEDELAYEDEXPANSION
SET ERRORLEVEL=
SET ERRNUM=
FOR /R "%~dp0" %%A IN (*-KB*.MSU) DO (
	CALL :SUB %%~nA
	ECHO= Installing KB!KB_NUM!
	>NUL TIMEOUT /t 3
	SET ERRORLEVEL=
	WUSA "%%A" /quiet /norestart
	SET ERRNUM=!ERRORLEVEL!
	IF !ERRNUM! EQU 3010 (
		ECHO=   == SUCCESS ^(RebootRequired^) ^[!ERRNUM!^] ==
	) ELSE (
		IF ERRORLEVEL 1 (
			ECHO=   == FAILED ^[!ERRNUM!^] ==
		) ELSE (
			ECHO=   == SUCCESS ^[!ERRNUM!^] ==
		)
	)
)
CHOICE /C YN /M "Close all programs and press Y to restart or N to continue."
IF ERRORLEVEL 2 GOTO continue
IF ERRORLEVEL 1 GOTO restart
GOTO end
:continue
	GOTO end
:restart
	ECHO= == Press any key to restart ==
	>NUL PAUSE
	SHUTDOWN.EXE /r /t 0
:end
GOTO :EOF

:SUB
SET "KB_NUM=%*"
FOR /F "DELIMS=-" %%B IN ("%KB_NUM:*-KB=%") DO SET "KB_NUM=%%B"

REM http://www.msfn.org/board/topic/152020-batch-script-for-windows-software-updates-installation/page__view__findpost__p__964942
REM http://www.windows-commandline.com/2011/10/choice-command.html
REM http://blogs.msdn.com/b/oldnewthing/archive/2008/09/26/8965755.aspx
REM http://ss64.com/nt/delayedexpansion.html
REM http://ss64.com/nt/runas.html

+++++++
+ VBScript Alternative
+++++++

'http://ccmexec.com/2012/02/installing-multiple-windows-7-hotfixes-msu-with-sccm/
'http://www.insidethe.com/blog/2009/12/how-to-launch-a-wsh-vbscript-as-administrator-in-windows-7-and-vista/

mytitle="MSU Installer"
mybuttons=65 ' vbOKCancel + vbInformation

If WScript.Arguments.Named.Exists("elevated") = False Then

	'Launch the script again as administrator

	CreateObject("Shell.Application").ShellExecute "wscript.exe", """" & WScript.ScriptFullName & """ /elevated", "", "runas", 1

	WScript.Quit

Else

	'Change the working directory from the system32 folder back to the script's folder.

	Set oShell = CreateObject("WScript.Shell")

	oShell.CurrentDirectory = CreateObject("Scripting.FileSystemObject").GetParentFolderName(WScript.ScriptFullName)

	MsgBox "Now running with elevated permissions",0,mytitle

End If


Dim objfso, objShell

Dim folder, files, sFolder, folderidx, Iretval, return

Set objfso = CreateObject("Scripting.FileSystemObject")

Set objShell = CreateObject("Wscript.Shell")

sFolder = left(WScript.ScriptFullName,(Len(WScript.ScriptFullName))-(len(WScript.ScriptName)))

Set folder = objfso.GetFolder(sFolder)

Set files = folder.Files

something=0 ' there is nothing to do

For each folderIdx In files

If Ucase(Right(folderIdx.name,3)) = "MSU" then

something=1 ' there is something to do.

wscript.echo "wusa.exe " & sfolder & folderidx.name & " /quiet /norestart"
'wscript.echo "wusa.exe " & sfolder & folderidx.name

iretval=objShell.Run ("wusa.exe " & sfolder & folderidx.name & " /quiet /norestart", 1, True)
'iretval=objShell.Run ("wusa.exe " & sfolder & folderidx.name, 1, True)

If (iRetVal = 0) or (iRetVal = 3010) then

'wscript.echo folderidx.name & " Success"
myprompt=folderidx.name & " Success " & "[" & iRetVal & "]"

Else

'wscript.echo folderidx.name & " Failed"
myprompt=folderidx.name & " Failed " & "[" & iRetVal & "]"

End If

	devam=MsgBox(myprompt,mybuttons,mytitle)
	If (devam = 2) or (devam = 3) or (devam = 7) Then
		'Cancel/Abort/No was clicked 
		wscript.quit(1)
	End If

End If

Next

If (something = 0) Then
	MsgBox "Nothing to do.",64,mytitle
Else
	MsgBox "Done.",64,mytitle
	restartla=MsgBox("Close all programs and press Yes to restart or No to continue.",36,mytitle)
	If (restartla = 6) Then
		Set WSHShell = WScript.CreateObject("WScript.Shell")
		WshShell.Run "%SYSTEMROOT%\system32\shutdown.exe /r /t 0"
	End If
End If

Attached Files


  • ngram likes this

#30
dsrtFx

dsrtFx
  • Member
  • 1 posts
  • Joined 12-July 12
  • OS:none specified
  • Country: Country Flag
Yzowl,

What to do to run that batch file for a multiple computers? What commands need to be added?

#31
submix8c

submix8c

    Inconceivable!

  • Patrons
  • 4,582 posts
  • Joined 14-September 05
  • OS:none specified
  • Country: Country Flag
HOLEY KROWS!!!

Sorry to bump this but SILLY ME went nutz trying to figure out why files/paths weren't being found!

HERE is the reason - I had a "!" (exclamation point) as part of a Folder Name! DO NOT DO THIS since
SET ENABLEDELAYEDEXPANSION
specifically EXPECTS to use that as a Variable Delimiter, same case as CMD.EXE "/V:ON".

Do NOT use that anywhere in any Pathname/Filename. (wasted time via experimentation...)

HTH some poor idee-yut that does the same thing. :(

Edited by submix8c, 16 March 2013 - 11:47 AM.

Someday the tyrants will be unthroned... Jason "Jay" Chasteen; RIP, bro!

Posted Image


#32
gohnick

gohnick
  • Member
  • 2 posts
  • Joined 09-April 13
  • OS:none specified
  • Country: Country Flag

For windows xp updates, you can probably get away with simply changing MSU to EXE and removing WUSA.

@ECHO OFF 
SETLOCAL ENABLEEXTENSIONS ENABLEDELAYEDEXPANSION 
FOR /R "%~dp0" %%A IN (*-KB*.EXE) DO ( 
        CALL :SUB %%~nA 
        ECHO= Installing KB!KB_NUM! 
        >NUL PING -n 4 127.0.0.1 
        "%%A" /quiet /norestart) 
ECHO= == Press any key to restart == 
>NUL PAUSE 
SHUTDOWN.EXE /r /t 0 
GOTO :EOF 
 
:SUB 
SET "KB_NUM=%*" 
FOR /F "DELIMS=-" %%B IN ("%KB_NUM:*-KB=%") DO SET "KB_NUM=%%B"


Dear sir,

Is it possible to include a string to output the installed KB numbers into a text file within the directory? Pardon my newbie question as I am a newbie in scripting :(

Edited by gohnick, 09 April 2013 - 09:03 PM.


#33
submix8c

submix8c

    Inconceivable!

  • Patrons
  • 4,582 posts
  • Joined 14-September 05
  • OS:none specified
  • Country: Country Flag
I won't swear to this, but putting
ECHO= == List of KB's installed == >KBLIST.TXT
right after the "SETLOCAL" and then placing
ECHO= Installing KB!KB_NUM! >>KBLIST.TXT
after the other one should do it. :unsure:

Someday the tyrants will be unthroned... Jason "Jay" Chasteen; RIP, bro!

Posted Image


#34
gohnick

gohnick
  • Member
  • 2 posts
  • Joined 09-April 13
  • OS:none specified
  • Country: Country Flag

I won't swear to this, but putting

ECHO= == List of KB's installed == >KBLIST.TXT
right after the "SETLOCAL" and then placing
ECHO= Installing KB!KB_NUM! >>KBLIST.TXT
after the other one should do it. :unsure:


Hi submix8c,

Thanks for the tip! it works! :)

#35
agnimitra1980

agnimitra1980
  • Member
  • 1 posts
  • Joined 20-May 13
  • OS:Server 2008R2
  • Country: Country Flag
Hi using this script is it possible to capture status of each installation? like if there is any update which fails or does not apply, is there any way we can capture that?

#36
centi50

centi50

    Newbie

  • Member
  • 36 posts
  • Joined 25-January 10
Hello to All

I use the following code Batch script to Install the updates in a folder in my Win 7 x64 laptop.

@ECHO OFF
SETLOCAL ENABLEEXTENSIONS ENABLEDELAYEDEXPANSION
FOR /R "%~dp0" %%A IN (*-KB*.MSU) DO (
CALL :SUB %%~nA
ECHO= Installing KB!KB_NUM!
>NUL TIMEOUT /t 3
WUSA "%%A" /quiet /norestart)
ECHO= == Press any key to restart ==
>NUL PAUSE
SHUTDOWN.EXE /r /t 0
GOTO :EOF

:SUB
SET "KB_NUM=%*"
FOR /F "DELIMS=-" %%B IN ("%KB_NUM:*-KB=%") DO SET "KB_NUM=%%B"

The above code will Install all updates of .MSU located in a folder same as the batch script one after the other. What it won't do is, it won't install updates of .EXE e.g .NetFramework 4 updates and also it won't install Silverlight Updates.

Please can some one Kindly re edit the above script for me to include the installation of .EXE files and Silverlight updates.

Also note am totally zero in scripting, so kindly if changes are made please reproduce the above script with changes so i can copy and paste it in my .BAT file.

Also note the code is not mine. i just got it in this thread, as i am the thread starter.


Thanking all in advance for their time and efforts to Help out people like me.

#37
Pikachu

Pikachu
  • Member
  • 1 posts
  • Joined 18-December 13
  • OS:Windows 7 x86
  • Country: Country Flag

 

@ECHO OFF
SETLOCAL ENABLEEXTENSIONS ENABLEDELAYEDEXPANSION
PUSHD
%~dp0
FOR
%%A IN (*-KB*.MSU) DO (
    CALL :SUB %%~nA
    ECHO
= Installing KB!KB_NUM!
    >NUL TIMEOUT /t 3
    WUSA "%%~fA" /quiet /norestart)
ECHO= == Press any key to restart ==
>NUL PAUSE
SHUTDOWN
.EXE /r /t 0
GOTO :EOF

:SUB
SET
"KB_NUM=%*"
FOR /F "DELIMS=-" %%B IN ("%KB_NUM:*-KB=%") DO SET "KB_NUM=%%B"

So this is the script I should use? What about the exe files?



#38
Yzöwl

Yzöwl

    Wise Owl

  • Super Moderator
  • 4,078 posts
  • Joined 13-October 04
  • OS:Windows 7 x64
  • Country: Country Flag

Donator

 

@ECHO OFF
SETLOCAL ENABLEEXTENSIONS ENABLEDELAYEDEXPANSION
PUSHD %~dp0
FOR %%A IN (*-KB*.MSU) DO (

<SNIP />
So this is the script I should use? What about the exe files?

 


If you'd looked a little harder you'd have also noticed an example script for .EXE files too!

All that was needed was to join them into one, perhaps something like this UnTested:

 

Example for recursion:

@ECHO OFF
SETLOCAL ENABLEEXTENSIONS DISABLEDELAYEDEXPANSION
FOR /R "%~dp0" %%A IN (*-KB*.*) DO (
	IF /I %%~xA==.MSU (SET _=WUSA) ELSE (
		IF /I NOT %%~xA==.EXE GOTO :EOF
		SET "_=")
	CALL :SUB "%%~nA"
	>NUL TIMEOUT /t 3
	%_% "%%A" /quiet /norestart)
ECHO= == Press any key to restart ==
>NUL PAUSE
SHUTDOWN /r
GOTO :EOF

:SUB
	SET "KB_NUM=%*"
	FOR /F "DELIMS=-" %%B IN ("%KB_NUM:*-KB=%") DO (
		ECHO= Installing KB%%B)

Example for all in same directory:

@ECHO OFF
SETLOCAL ENABLEEXTENSIONS DISABLEDELAYEDEXPANSION
PUSHD %~dp0
FOR %%A IN (*-KB*.*) DO (
	IF /I %%~xA==.MSU (SET _=WUSA) ELSE (
		IF /I NOT %%~xA==.EXE GOTO :EOF
		SET "_=")
	CALL :SUB %%~nA
	>NUL TIMEOUT /t 3
	%_% "%%~fA" /quiet /norestart)
ECHO= == Press any key to restart ==
>NUL PAUSE
SHUTDOWN /r
GOTO :EOF

:SUB
	SET "KB_NUM=%*"
	FOR /F "DELIMS=-" %%B IN ("%KB_NUM:*-KB=%") DO (
		ECHO= Installing KB%%B)


#39
DosProbie

DosProbie

    MSFN Expert

  • MSFN Sponsor
  • 1,033 posts
  • Joined 16-October 12
  • OS:Windows 8.1 x64
  • Country: Country Flag

Donator

I use this in my 8.1 ua install (batch script is run outside of the Updates\msu directory and should wk with 7 as well), does a update count then log file when done..Happy Holidays

DP  :thumbup

@echo off&setlocal ENABLEDELAYEDEXPANSION&color 1f&&title, [ WUSA - 8.1 UPDATE INSTALLER ]
pushD "%~dp0" & cd /d "%~dp0"


:: ### SCAN FOR UPDATES ----------------------------------------------------------
for /F %%a in ('dir Updates\msu\*.msu ^|findstr /i "file(s)"') do set z=%%a
        echo Number Of Updates Found: %z%
echo:&echo:

:: ### INSTALLING UPDATES (reads updates in numerical order)---------------------
        echo == Installing %z% Windows Updates..(This may take a while, Please Wait)
echo:
for /R "%~dp0" %%A IN (*.MSU) DO (
        SET /A COUNT+=1
        ECHO= Installing !COUNT! of %z% = %%~nA
        >NUL TIMEOUT /t 3
        start /wait WUSA "%%A" /quiet /norestart
)
popD
endlocal
goto :wpi
:wpi
:: ### DATED UPDATE LOG FILE WHEN DONE-------------------------------------------
set wusa=%systemdrive%\HotFixes-%date:~10,4%-%date:~4,2%-%date:~7,2%-%date:~0,3%.htm
wmic qfe list full /format:htable>%wusa%



Edited by DosProbie, 25 December 2013 - 05:04 PM.


#40
magsood

magsood
  • Member
  • 8 posts
  • Joined 29-August 12
  • OS:Windows 8.1 x64
  • Country: Country Flag

How Show Progress Bar with Percent (0~100) for any msu file?


Edited by magsood, 10 February 2014 - 03:48 AM.


#41
yro

yro

    Newbie

  • Member
  • 15 posts
  • Joined 30-September 09
  • OS:Windows 7 x64
  • Country: Country Flag

Guys Im lost here.

 

I need a script to install all msu files on a folder but I need this script to "ignore" an update if its already installed on the system. Is that the normal behavior of these scripts? If not, how can I make this script do the ignore installed thing?

 

script in use is this:

 

@echo off
TITLE INSTALADOR DE ATUALIZACOES DO WINDOWS
CLS
setlocal ENABLEDELAYEDEXPANSION
pushd "%~dp0"
echo:
echo PREPARANDO ATUALIZACOES..
echo:
for /F %%a in ('dir *.msu ^| find /i "file(s)"') do set z=%%a
if "%z%"=="" goto :Failure
echo Atualizacoes encontradas: %z%
echo:
echo Instalando atualizacoes... (Esta tarefa pode demorar)
echo:
FOR /R "%~dp0" %%A IN (*.MSU) DO (
        SET /A COUNT+=1
        ECHO= Instalando !COUNT! de %z% = %%~nA
        >NUL TIMEOUT /t 3
        WUSA "%%A" /quiet /norestart
)
echo Instaladas %z% atualizacoes dia %date% as %time%.
echo:
echo Reinicie o seu computador!
CHOICE /C YN /N /M "Reiniciar agora? [Y]es [N]o :"
if %errorlevel%==1 goto :Reboot
if %errorlevel%==2 goto :Exit
:Failure
CLS
echo ==========================================================
echo:
echo    NENHUMA ATUALIZACAO ENCONTRADA
echo:
echo    ATENCAO: As atualizacoes precisam estar na mesma pasta onde este script se encontra.
echo:
echo ==========================================================
echo:
pause
goto :Exit
:Reboot
ENDLOCAL
start shutdown.exe /r /t 0   
:Exit
ENDLOCAL
exit

 


Sorry about my english :P


#42
jaclaz

jaclaz

    The Finder

  • Developer
  • 15,789 posts
  • Joined 23-July 04
  • OS:none specified
  • Country: Country Flag

I don' tget it.

Where does that script come from?

Have you written it?

What does it does? (I mean does it actually, even minimally, work?)

 

If you set a variable inside a FOR loop, it's "%" value won't be altered, you need to use the expanded "!" value.

 

Example:

@ECHO OFF
SETLOCAL ENABLEEXTENSIONS ENABLEDELAYEDEXPANSION
SET Variable=A suffusion of yellow
FOR /L %%A IN (1,1,10) DO (
SET Variable=%%A
ECHO %Variable%
ECHO !Variable!
)

jaclaz



#43
yro

yro

    Newbie

  • Member
  • 15 posts
  • Joined 30-September 09
  • OS:Windows 7 x64
  • Country: Country Flag

sorry jaclass. that was just a concept that I found (i guess in this forum). I have a fully functional script here but unfortunately its not worth. The script takes too long to install all the msus i have. Now im trying to figureout how to make ntlites nuyhi tool to work with the updates and some removals :P

 

thanks anyway...

 

sorry about my bad english.. :P


Sorry about my english :P


#44
MHz

MHz

    Just simple

  • Member
  • PipPipPipPipPipPipPip
  • 1,689 posts
  • Joined 02-August 04
  • OS:Windows 7 x64
  • Country: Country Flag

yro,

 

The update files have a KB number in the filenames and systeminfo gives KB numbers installed so I looked at how the data could be used to set which filename to allow to be installed.

 

This is a test script I came up with.

@echo off
setlocal enabledelayedexpansion

:: Set a counter for the KB[i] series of variables
set i=0

:: Find installed KB numbers from systeminfo and add to KB[i] variables
for /f "tokens=2" %%A in ('systeminfo^|findstr /i "\<KB[0-9][0-9]*$"') do (
	set /a i += 1
	set KB[!i!]=%%A
)

:: Set ubound to 1st KB variable
set KB[0]=%i%

:: Loop through recursive search for msu files
:: In each filename, find KB number, if not found then install filename
:: Remove the echo in front of wusa used in testing to execute the wusa
:: command and remove the pause line
for /R "%~dp0" %%U in (*.msu) do (
	set /a count += 1
	set installed=0
	echo Instalando !count! de %z% = %%~nU
	timeout /t 3 > nul
	for /l %%I in (1, 1, %KB[0]%) do (
		echo %%~nU| find /i "!KB[%%I]!"> nul
		@if not errorlevel 1 set installed=1
	)
	@if !installed! equ 0 echo wusa "%%U" /quiet /norestart
)

endlocal
pause
goto :eof

It puts each KB string into a variable KB[i] where i is a numbered index (like how an array on access works). That makes the data easier to loop through many times over.

 

If the KB string is found in the filename, then installed is set to 1 so installation will not happen.

 

Edit: Added /i to find and findstr so case sensitivity would not be an issue.


Edited by MHz, 15 October 2014 - 06:40 AM.


#45
crobertson

crobertson

    Newbie

  • Member
  • 14 posts
  • Joined 14-December 06

I changed the code to echo/push the update name into a text file. 

I really don't need/want to attempt all updates at one time. It needs to install in 2-3 updates.

Can we use this text files at check if the update has already been installed?

Currently I stop about 40-50% complete and reboot then start again, but it attempts to install from the very beginning.

 

I tried to edit these scripts, but I'm not able to.

any thoughts?



#46
MHz

MHz

    Just simple

  • Member
  • PipPipPipPipPipPipPip
  • 1,689 posts
  • Joined 02-August 04
  • OS:Windows 7 x64
  • Country: Country Flag

@crobertson

 

I guess you are replying to me?

 

I have looked at your requests and created a script based on those requests. It saves the installed hotfixes read from systeminfo\wmi to a file and creates a updates text file with the msu files and their installed state. It has a limit variable so if you have say 200 msu files and want to install in 3 separate executions, then you could set the variable to 70. It would then stop at 70 installs. The next execution of the script would do the next 70 installs. The updates text file will be updated with the istalled status at each script execution.

 

The execution of systeminfo\wmi is done just once so later script executions should perform faster based solely on the updates text file. Using variable substitution instead of using find.exe speeds up the script as well.

@echo off
setlocal enabledelayedexpansion

:: Note: Remove the ECHO in front of the wusa keyword to enable installations.
:: The delimiters in the saved files are tabs.
:: Update the values of the next 4 set variables if needed.
::
:: The filepath used to save the KB information.
set "systeminfo=%~dp0systeminfo.txt"
::
:: The filepath used to save the msu filepaths and the installed status.
set "updates=%~dp0updates.txt"
::
:: Limit number of KB hotfix installs during current script execution.
set /a "limit=9999"
::
:: Use wmi instead of systeminfo. Use 0 for systeminfo.exe.
set "wmi=1"

if not exist "%updates%" (
	rem Find installed KB numbers from wmi\systeminfo and save to file.
	if "%wmi%" == "0" (
		for /f "tokens=2" %%A in ('systeminfo^|findstr /i "\<KB[0-9][0-9]*$"') do (
			(echo %%A) >> "%systeminfo%"
		)
	) else (
		for /f "tokens=1" %%A in ('wmic qfe get hotfixid') do (
			set "hotfixid=%%~A"
			if /i "!hotfixid:~0,2!" == "KB" (echo %%~A) >> "%systeminfo%"
		)
		set "hotfixid="
	)
	if not exist "%systeminfo%" echo.>"%systeminfo%"
	
	rem Find msu files and save to file with the installed status.
	for /R "%~dp0" %%U in (*.msu) do (
		set installed=0
				
		for /f "usebackq" %%I in ("%systeminfo%") do (
			call :find "%%~nU" "%%I"
			if not errorlevel 1 set installed=1
		)
		
		(echo !installed!	%%~U) >> "%updates%"
	)
	set "installed="
)

:: View updates text file.
echo #### BEFORE INSTALLS
type "%updates%"

for /f "usebackq tokens=1,2 delims=	" %%A in ("%updates%") do (
	set "installed=%%~A"
	set "filepath=%%~B"
	
	rem Perform install if required and echo install status to the updates text file.
	if "!installed!" == "0" (
		set /a "count+=1"
		if !count! leq %limit% (
			ECHO wusa "!filepath!" /quiet /norestart
			(echo 1	!filepath!) >> "%updates%.txt"
		) else (
			(echo 0	!filepath!) >> "%updates%.txt"
		)
	) else if "!installed!" == "1" (
		(echo 1	!filepath!) >> "%updates%.txt"
	) else (
		(echo Unknown install status of "!filepath!") >&2
	)
)
set "installed="
set "filepath="

rem Move updates file to overwrite previous file.
move /y "%updates%.txt" "%updates%" >nul

:: View updates text file again.
echo #### AFTER INSTALLS
type "%updates%"

endlocal
goto :eof

:: Find a substring in a string by using substitution.
:find
	setlocal enabledelayedexpansion
	set string=%~1
	set substring=%~2
	if /i "!string:%substring%=!" == "!string!" (
		endlocal & exit /b 1
	)
	endlocal
exit /b 0

This line below from the script will just echo the command for testing. Remove the ECHO keyword to enable wusa to execute.

            ECHO wusa "!filepath!" /quiet /norestart

Some of the TYPE commands can also be removed as they exist for validation purposes.

 

I have tested on some dummy msu files and it seems to be working ok. Try it and see how it performs for you.



#47
crobertson

crobertson

    Newbie

  • Member
  • 14 posts
  • Joined 14-December 06

Wow Mhz.. really well done. I'm running into a few issues. Fist it closes out before I can see what it did, if anything. Can we pause it at the end?

It creates two text files

===system info==== which displays the updates installed?

KB2764913
KB2764916
13 listed.
 
=====updates.txt====which displays all the updates in the folder
1 E:\104 Updates\Win7 x86 Critical\IE11-Windows6.1-KB2909210-x86.msu
1 E:\104 Updates\Win7 x86 Critical\IE11-Windows6.1-KB3008923-x86.msu
1 E:\104 Updates\Win7 x86 Critical\Windows6.1-KB2479943-x86.msu
1 E:\104 Updates\Win7 x86 Critical\Windows6.1-KB2491683-x86.msu
45 more..
 
but it does nothing best I can tell. It appears to error somewhere and quit.
I'm providing this to my techs, and we go though about 5-10 computers a day with 2% re-install
I named them %computername%done & %computername%todo This way It will be different name with each computer.
I'm attempting to test this on the VMs I have running.

Edited by crobertson, 18 February 2015 - 12:27 PM.


#48
MHz

MHz

    Just simple

  • Member
  • PipPipPipPipPipPipPip
  • 1,689 posts
  • Joined 02-August 04
  • OS:Windows 7 x64
  • Country: Country Flag

To pause the script, add pause before the goto :eof near the end of the script.

pause
endlocal
goto :eof

The systeminfo.txt file does have the installed updates. Once the updates.txt file is created then systeminfo.txt is not needed anymore so it could be deleted though I did not add that as it shows you the evidence of what happened.

 

The updates.txt file is a tab delimited file where the first column is 1 for installed and 0 as not installed yet. As an install happens then it will be recorded and the 0 will change to a 1. The 2nd column is the path to the msu files.

 

Remember to remove the ECHO that is in uppercase to execute wusa else it will just print the command to screen.

 

You can change the settings of the 4 variables named systeminfo, updates, limit and wmi at the top of the script. So you can change the systeminfo variable like below.

:: The filepath used to save the KB information.
set "systeminfo=%~dp0%computername%.txt"

That will create the computername text file that you ask about.

 

Test output:

Spoiler


#49
crobertson

crobertson

    Newbie

  • Member
  • 14 posts
  • Joined 14-December 06

I have figured out there are two lines that it writes to the files %variable%.txt  So when %variable%=%computername%.txt the resultant file would be Computername.txt.txt

The program is writing correctly now, but all that displays is the screen showing what has/has not installed. It appears stalled and I see no progress. Is there a way we can see what is installing as it is being installed? 



#50
Yzöwl

Yzöwl

    Wise Owl

  • Super Moderator
  • 4,078 posts
  • Joined 13-October 04
  • OS:Windows 7 x64
  • Country: Country Flag

Donator

It appears stalled and I see no progress. Is there a way we can see what is installing as it is being installed? 

 

Above the line which is installing:

wusa "!filepath!" /quiet /norestart

Add something like:

ECHO; Installing !filepath!





1 user(s) are reading this topic

0 members, 1 guests, 0 anonymous users