📄 slipstream.vbs
字号:
'Now, if the svcpack.inf file does not exist, create it
Dim txtFileSvcPackFile
if(fso.FileExists(strInstallPath & "\svcpack.inf") = false) then
Set txtFileSvcPackFile = fso.CreateTextFile(strInstallPath & "\svcpack.inf",true,false)
'Write the proper parameters into it
if(strTargetOS = "Win2000") then
txtFileSvcPackFile.WriteLine("[Version]")
txtFileSvcPackFile.WriteLine("Signature=""$Windows NT$""")
txtFileSvcPackFile.WriteLine("MajorVersion=5")
txtFileSvcPackFile.WriteLine("MinorVersion=0")
txtFileSvcPackFile.WriteLine("BuildNumber=2195")
txtFileSvcPackFile.WriteLine("[SetupData]")
txtFileSvcPackFile.WriteLine("CatalogSubDir=""\i386\svcpack""")
txtFileSvcPackFile.WriteLine("[ProductCatalogsToInstall]")
txtFileSvcPackFile.WriteLine("[SetupHotfixesToRun]")
else 'if(strTargetOS = "Win2000") then
if(strTargetOS = "WinXP") then
txtFileSvcPackFile.WriteLine("[Version]")
txtFileSvcPackFile.WriteLine("Signature=""$Windows NT$""")
txtFileSvcPackFile.WriteLine("MajorVersion=5")
txtFileSvcPackFile.WriteLine("MinorVersion=1")
txtFileSvcPackFile.WriteLine("BuildNumber=2600")
txtFileSvcPackFile.WriteLine("[SetupData]")
txtFileSvcPackFile.WriteLine("CatalogSubDir=""\i386\svcpack""")
txtFileSvcPackFile.WriteLine("[ProductCatalogsToInstall]")
txtFileSvcPackFile.WriteLine("[SetupHotfixesToRun]")
else 'if(strTargetOS = "WinXP") then
if(strTargetOS = "Win2003") then
txtFileSvcPackFile.WriteLine("[Version]")
txtFileSvcPackFile.WriteLine("Signature=""$Windows NT$""")
txtFileSvcPackFile.WriteLine("MajorVersion=5")
txtFileSvcPackFile.WriteLine("MinorVersion=2")
txtFileSvcPackFile.WriteLine("BuildNumber=3790")
txtFileSvcPackFile.WriteLine("[SetupData]")
txtFileSvcPackFile.WriteLine("CatalogSubDir=""\i386\svcpack""")
txtFileSvcPackFile.WriteLine("[ProductCatalogsToInstall]")
txtFileSvcPackFile.WriteLine("[SetupHotfixesToRun]")
end if 'if(strTargetOS = "Win2003") then
end if 'if(strTargetOS = "WinXP") then
end if 'if(strTargetOS = "Win2000") then
txtFileSvcPackFile.Close
end if 'if svcpack.inf does not exist
'Now we need to add the current file to the [ProductCatalogsToInstall] and [SetupHotfixesToRun] sections
Dim strCurrLine, txtFileNewFile
Set txtFileNewFile = fso.CreateTextFile(strInstallPath & "\svcPack.inf.new",true,false)
Set txtFileSvcPackFile = fso.OpenTextFile(strInstallPath & "\svcpack.inf")
Do while txtFileSvcPackFile.AtEndOfStream <> true
strCurrLine = txtFileSvcPackFile.ReadLine
txtFileNewFile.WriteLine(strCurrLine) 'We want it in the output file no matter what
if(StrComp(strCurrLine,"[ProductCatalogsToInstall]",vbTextCompare) = 0) then
'We need to also insert our product catalog
txtFileNewFile.WriteLine(strCatalogFile)
end if 'if(strCurrLine "[ProductCatalogsToInstall]") then
if(StrComp(strCurrLine,"[SetupHotfixesToRun]",vbTextCompare) = 0) then
if(strPatchExeName <> "") then
txtFileNewFile.WriteLine(strPatchExeName)
end if
end if 'if(strCurrLine "[SetupHotfixesToRun]") then
loop
'Done writing. Now close both files and replace the original
txtFileNewFile.close
txtFileSvcPackFile.close
fso.DeleteFile strInstallPath & "\svcpack.inf",true
fso.MoveFile strInstallPath & "\svcpack.inf.new", strInstallPath & "\svcpack.inf"
writeSvcPackINF = true
end function
'This function adds a file to the [files] section of a dosnet.inf file
'It's not very performant, but simple. All it does is copy the line by line
'until it finds the [files] section. Then it compares each line
'to the file we want to add. If we find a new section without having found our file
'we add the new file.
'Parameters:
' strInstallPath - full path to the i386 directory
' strFileName - file name (not full path) of the file to add.
function addFileToDOSNetINF(strInstallPath, strFileName)
'Start out by ensuring we have a dosnet.inf file
if(fso.FileExists(strInstallPath & "\dosnet.inf") = false) then
MsgBox "Unable to open the dosnet.inf file. This is a fatal error and might indicate that you gave the incorrect " &_
"path to the target directory. Exiting the program.","ERROR"
addFilFileToDOSNetINF = false
exit function
end if 'if(fso.FileExists(strInstallPath & "\dosnet.inf") = false) then
Dim strCurrLine, txtFileNewFile, strFileToAdd, txtFileDosNetFile
Set txtFileNewFile = fso.CreateTextFile(strInstallPath & "\dosnet.inf.new",true,false)
Set txtFileDosNetFile = fso.OpenTextFile(strInstallPath & "\dosnet.inf",1,false)
strFileToAdd = "d1," & strFileName 'One day I need to find out why this is the right syntax
'For Windows Server 2003 and XP we need to add an "OptionalSrcDirs" to the dosnet.inf. On all three platforms
'we need to add svcpack to that section if it is not already there. The way we are going to do this is by checking
'for it while we are parsing the file.
Dim bFoundFile, bFoundSvcPack, bFoundOptionalSrcDirsSection
bFoundSvcPack = false
bFoundFile = false
bFoundOptionalSrcDirsSection = false
Do while txtFileDosNetFile.AtEndOfStream <> true
strCurrLine = txtFileDosNetFile.ReadLine
txtFileNewFile.WriteLine(strCurrLine) 'We want it in the output file no matter what
'Check for the OptionalSourcDirs section
if( (StrComp(strCurrLine,"[OptionalSrcDirs]",vbTextCompare) = 0) AND bFoundSvcPack = false) then 'Check if we have found it before, just in case.
'We have the optional source dirs section. Let's see if there is an svcpack section
bFoundOptionalSrcDirsSection = true
strCurrLine = txtFileDosNetFile.ReadLine 'Read the next line.
'If this is the last line of the section and we still have not found the service pack entry then add it
if( ( (left(strCurrLine,1) = "[") OR (txtFileDosNetFile.AtEndOfStream = true) ) AND bFoundSvcPack = false) then
'If this last line we read is either the end of the section, or the end of the file
'we need to write the new line and then the current line to the output. Otherwise, we
'will miss things in the output
if(StrComp(strCurrLine,"svcpack",vbTextCompare) <> 0) then 'This will only happen if the file is at the end of the stream.
txtFileNewFile.WriteLine("svcpack")
txtFileNewFile.WriteLine(vbCrLf) 'Make the output prettier.
bFoundSvcPack = true
else
bFoundSvcPack = true 'Found it
end if 'if(strCurrLine <> "svcPack") then
txtFileNewFile.WriteLine(strCurrLine) 'Write this line, whatever it was.
else 'if( ( (left(strCurrLine,1) = "[") OR (txtFileDosNetFile.AtEndOfStream = true) ) AND bFoundSvcPack = false) then
txtFileNewFile.WriteLine(strCurrLine) 'We want it in the output file no matter what
'If this is not the last line, then keep iterating.
'Read the next line
strCurrLine = txtFileDosNetFile.ReadLine
do while( (left(strCurrLine,1) <> "[") AND (txtFileDosNetFile.AtEndOfStream <> true) AND bFoundSvcPack = false)
if(strCurrLine = "svcpack") then 'Is it the svcpack section?
bFoundSvcPack = true 'We found it, no further action necessary
exit do 'Leave the inner loop
end if
txtFileNewFile.WriteLine(strCurrLine) 'Write this line
strCurrLine = txtFileDosNetFile.ReadLine 'and read the next
loop
'We are at the end of the OptionalSrcDirs section, or we found the service pack. Which is it?
if(bFoundSvcPack = false) then
'Nope, we need to add it
txtFileNewFile.WriteLine("svcpack")
txtFileNewFile.WriteLine(vbCrLf) 'Make the output prettier.
end if 'if(bFoundSvcPackSect <> true) then
'We still have one line left to write, which is the next section, or the svcpack line, whichever the case may be.
txtFileNewFile.WriteLine(strCurrLine)
end if 'if( (left(strCurrLine,1) = "[") or (txtFileDosNetFile.AtEndOfStream = true) ) then
end if 'if(strCurrLine = "[OptionalSrcDirs]" then
'Is this file the [Files] section?
'The bFoundFile = false is important because the dosnet.inf
'may have several [files] sections. We don't want to add the file
'to more than one of them.
'BUGBUG: If the file does not exist in the first [files] section
'we will add it there, even if it exists in the second one. I don't
'know what kind of problems that will cause.
if( (StrComp(strCurrLine,"[Files]",vbTextCompare) = 0) AND bFoundFile = false) then
strCurrLine = txtFileDosNetFile.ReadLine
if( (left(strCurrLine,1) = "[") or (txtFileDosNetFile.AtEndOfStream = true) ) then
'If this last line we read is either the end of the section, or the end of the file
'we need to write the new line and then the current line to the output. Otherwise, we
'will miss things in the output
if(StrComp(strCurrLine,strFileToAdd,vbTextCompare) <> 0) then
txtFileNewFile.WriteLine(strFileToAdd)
else
bFoundFile = true
end if 'if(StrComp(strCurrLine,strFileToAdd,vbTextCompare) <> 0) then
txtFileNewFile.WriteLine(strCurrLine)
bFoundFile = true
end if 'if( (left(strCurrLine,1) = "[") or (txtFileDosNetFile.AtEndOfStream = true) ) then
'Otherwise, we will start comparing
Do while ( (left(strCurrLine,1) <> "[") AND (txtFileDosNetFile.AtEndOfStream <> true) )
txtFileNewFile.WriteLine(strCurrLine) 'Ensure it is in the output file
if(StrComp(strCurrLine,strFileToAdd,vbTextCompare) = 0) then
bFoundFile = true
exit do 'We really don't care about the inner loop any more. Just go through the rest of the file
end if 'if(strCurrLine = strFileToAdd) then
strCurrLine = txtFileDosNetFile.ReadLine 'Read the next line
'If we have not found our file and we have a new section, or we are at the
'end of the stream, then add our file now before we write the current line
if( (left(strCurrLine,1) = "[") OR (txtFileDosNetFile.AtEndOfStream) ) then
txtFileNewFile.WriteLine(strFileToAdd)
txtFileNewFile.WriteLine(strCurrLine)
bFoundFile = true
end if 'if( (left(strCurrLine,1) = "[") OR (txtFileDosNetFile.AtEndOfStream) ) then
loop 'Do while txtFileDosNetFile.AtEndOfStream <> true
end if 'if(strCurrLine "[Files]") then
loop 'Do while txtFileDosNetFile.AtEndOfStream <> true
'If we are here and have not found the [OptionalSrcDirs] section, we need to add it before we leave
if(bFoundOptionalSrcDirsSection = false) then
txtFileNewFile.WriteLine(vbCrLf)
txtFileNewFile.WriteLine("[OptionalSrcDirs]")
txtFileNewFile.WriteLine("svcpack")
end if 'if(bFoundOptionalSrcDirsSection = false) then
'Done writing. Now close both files and replace the original
txtFileNewFile.close
txtFileDosNetFile.close
fso.DeleteFile strInstallPath & "\dosnet.inf",true
fso.MoveFile strInstallPath & "\dosnet.inf.new", strInstallPath & "\dosnet.inf"
addFileToDOSNetINF = true
end function
'This function extracts all the patches by simply running them with the /x switch. This will generate
'a user exchange and an error may be thrown. If so we will bail. We will only install the patches that
'include a cat file. All the others will be left untouched.
'Parameters:
' strPatchPath - The path to where the patch executables are located
' aPatchList - OUT - The array containing information on these patches
function extractPatches(strPatchPath, aPatchList)
MsgBox "Extracting patches. You may get syntax errors and other popups. Just click OK and ignore these.",vbOKOnly,"Info"
'Make sure we have a valid folder at the patch path
if(fso.FolderExists(strPatchPath) = false) then
MsgBox "The patch folder does not exist",vbExclamation,"ERROR"
extractPatches = false
exit function
end if
Dim fldrPatchFolder, filePatchFiles, file, i, aPatches, bRetVal
bRetVal = true 'Assume things will work fine.
'fldrPatchFolder is the patch folder
Set fldrPatchFolder = fso.GetFolder(strPatchPath)
Set filePatchFiles = fldrPatchFolder.Files 'filePatchFiles is a list of all the files in that folder
i = 0
For Each file in filePatchFiles ' For each file in the folder
Redim preserve aPatchList(4,i) 'Add it to our array
aPatchList(0,i) = strPatchPath & "\" & file.Name 'Set the full path for the patch
Dim nameNoExt 'holds the name of the patch without the .exe extension
nameNoExt = left(file.Name, InStrRev(file.Name,".")-1 )
aPatchList(1,i) = strPatchPath & "\" & nameNoExt 'Set the name of the directory where the patch is extracted
aPatchList(2,i) = true 'Assume all patches are innocent until proven guilty
'There are two ways to extract patches. Some take a switch like this:
' patch.exe /q /x:"fullpath"
'Others take this command:
' patch.exe /c /t:"fullpath"
'Since we do not know which one is the correct one, we will try the first one first
'If that fails, which we can tell since the directory will be missing, we try
'the second one. If that one fails, we mark the patch as non-slipstreamable.
Dim strCommand
strCommand = aPatchList(0,i) & " /q /x:""" & aPatchList(1,i) & """"
Dim WshShell, oExec
Set WshShell = CreateObject("WScript.Shell")
Set oExec = WshShell.Exec(strCommand)
Do While oExec.Status = 0
WScript.Sleep 100
Loop
if(oExec.ExitCode <> 0) then 'Something went wrong. Unfortunately,
' most patches return 0 even if they failed. Sigh.
MsgBox "Extracting patch " & aPatchList(0,i) & " failed.",vbOK,"INFO"
end if
WScript.Sleep 100
' Let's check if the directory exists
if(fso.FolderExists(aPatchList(1,i))) then
aPatchList(2,i) = true
aPatchList(3,i) = 0 'Standard syntax worked
else
'It didn't work. Try the other syntax
strCommand = aPatchList(0,i) & " /c /t:""" & aPatchList(1,i) & """"
Set oExec = WshShell.Exec(strCommand)
Do While oExec.Status = 0
WScript.Sleep 100
Loop
if(oExec.ExitCode <> 0) then
MsgBox "Extracting patch " & aPatchList(0,i) & " failed.",vbOK,"Error"
end if
'Check it again
if(fso.FolderExists(aPatchList(1,i)) = false) then
'Someone just doesn't like us
aPatchList(2,i) = false
else
aPatchList(2,i) = true 'It worked
aPatchList(3,i) = 1 'We had to use the /c syntax
MsgBox "Patch " & aPatchList(1,i) & " does not follow the new update.exe syntax. I will try to " &_
"slipstream it anyway, but it may not show up in Add/Remove Programs."
end if
end if 'Standard syntax did not work, trying /C syntax.
'Let's check if this is a binary patch. Those can't be slipstreamed. We do that by attempting to open the _sfx_manifest_ file
'which all those patches have. If it has one, we mark it as non-slipstreamable
if(fso.FileExists(aPatchList(1,i) & "\_sfx_manifest_") = true) then
'Too bad
aPatchList(2,i) = false
MsgBox "The Patch" & vbCrLf & aPatchList(0,i) & vbCrLf &_
"is a binary patch and cannot be slipstreamed. You must manually install it once you have " &_
"finished building out the system.",vbOK,"Unable to slipstream"
end if
i = i + 1
Next
extractPatches = bRetVal
end function
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -