There are many logic and structural errors which mean that the code will not execute as you expect it to.

You mix "C:\WINNT.." and %WINDIR%, you use "Gosub" in a very odd manner, your main file reading loop is badly constructed, you are not checking for errors in all places that you should be, you are closing a file on which the open may have failed.

I've cleaned it up a bit but there are still some major areas you need to address to make this production quality which I'll mention after the listing.

Note, I cannot test this here, so I'll apologise in advance for any typos:

; install windows 2000 patches
Break ON
? "Windows 2000 automated patch installer"
? "by T.Wiser"
? ""
$sDQ='"'
$sSQ="'"
$sServer="\\nts40bdc"
$sPatchList=$sServer+"\Patches\Index.txt"
$sPatchSrcDir=$sServer+"\Patches\available\"
$sPatchDstDir=%WINDIR%+"\RolledOutPatches\"
$sRunAs=%COMSPEC%+" /C cscript c:\winnt\VBRUNAS.VBS"
$sAccount="DOMAIN\account"
$sPassword="password"

; open the text file that contains the list of patches that are available for installing
$fhPatchFile=FreeFileHandle()
If Open($fhPatchFile,$sPatchList)
$gNull=MessageBox("Your PC could not be updated at this time.", "Software update", 32)
Exit 1
EndIf

; Consider changing this to a single delimited line and using Split()
$sDescription = ReadLine($fhPatchFile)
$sFilename = ReadLine($fhPatchFile)
$sActualFilename = ReadLine($fhPatchFile)
While @ERROR = 0
If $sDescription
If Exist($sPatchDstDir+$sFilename)
? " * Patch "+$sFilename+" is already installed"
Else
? " * New patch available! Installing "+$sFilename+@CRLF+@CRLF+@CRLF
Copy $sPatchSrcDir+$sFilename $sPatchDstDir+$sFilename
Shell $sRunAs+" "+$sAccount+" "+$sPassword+" "+$sDQ+$sPatchDstDir+$sActualFilename+$sDQ
EndIf
EndIf
$sDescription = ReadLine($fhPatchFile)
$sFilename = ReadLine($fhPatchFile)
$sActualFilename = ReadLine($fhPatchFile)
Loop

; close the file as we're finished with it now
If Close($fhPatchFile)
? "Could not close file"
endif

Exit 0



Right, what is left to do.
  • Set "Explicit" on, and dim all your variables
  • I'd change the input file format. Use a single line for the patch, using a delimiter to split the parts. Use Split() to break them out.
  • I couldn't understand the logic of the two different file names. You use "actual filename" only in the execution, not the copy or check. This is illogical and will cause you problems when "filename" and "actual filename" differ.
    I've left the names as they were, but you should review this and correct it.
  • You don't check that the copy completed successfully
  • You don't check that the patch worked or completed.
  • The patch could be copied to local, and aborted by the user. Now that the file is present, the process will not attempt to run the patch again. Consider using a local status file (INI format) to record the state of the patch, and only mark the patch install as completed when it has completed successfully. Also consider checking the registry for patch levels
There are other, quite mature systems already available on the board for rolling out patches. Consider using these (KSMS spring to mind) as they are pretty robust, and include techniques which avoid the possibility of exposing passwords.