Skip to content

Instantly share code, notes, and snippets.

@azure365pro
Created May 13, 2020 17:27
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save azure365pro/aa423af149dd5a7b4733a47f92378e77 to your computer and use it in GitHub Desktop.
Save azure365pro/aa423af149dd5a7b4733a47f92378e77 to your computer and use it in GitHub Desktop.
SCCM Task Sequence Scripts
reg load HKU\DefaultProfile C:\Users\default\ntuser.dat
New-Item -path "Microsoft.PowerShell.Core\Registry::HKEY_USERS\DefaultProfile\Software\Microsoft\Windows\CurrentVersion\Explorer\HideDesktopIcons\"
New-Item -path "Microsoft.PowerShell.Core\Registry::HKEY_USERS\DefaultProfile\Software\Microsoft\Windows\CurrentVersion\Explorer\HideDesktopIcons\NewStartPanel"
New-ItemProperty -path "Microsoft.PowerShell.Core\Registry::HKEY_USERS\DefaultProfile\Software\Microsoft\Windows\CurrentVersion\Explorer\HideDesktopIcons\NewStartPanel" -Name "{20D04FE0-3AEA-1069-A2D8-08002B30309D}" -PropertyType Dword -Value "0" -force
#New-ItemProperty -path "Microsoft.PowerShell.Core\Registry::HKEY_USERS\DefaultProfile\Software\Microsoft\Windows\CurrentVersion\Explorer\HideDesktopIcons\NewStartPanel" -Name "{59031a47-3f72-44a7-89c5-5595fe6b30ee}" -PropertyType Dword -Value "0" -force
#reg unload HKU\DefaultProfile
New-ItemProperty -path "Microsoft.PowerShell.Core\Registry::HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\JavaSoft\Java Update\Policy" -Name "EnableJavaUpdate" -PropertyType Dword -Value "0" -force
Import-StartLayout -LayoutPath $PSScriptRoot\Layout.xml -MountPath $env:SystemDrive\
<LayoutModificationTemplate xmlns:defaultlayout="http://schemas.microsoft.com/Start/2014/FullDefaultLayout" xmlns:start="http://schemas.microsoft.com/Start/2014/StartLayout" Version="1" xmlns="http://schemas.microsoft.com/Start/2014/LayoutModification">
<LayoutOptions StartTileGroupCellWidth="6" />
<DefaultLayoutOverride>
<StartLayoutCollection>
<defaultlayout:StartLayout GroupCellWidth="6">
<start:Group Name="Business Apps">
<start:DesktopApplicationTile Size="2x2" Column="4" Row="0" DesktopApplicationLinkPath="%ALLUSERSPROFILE%\Microsoft\Windows\Start Menu\Programs\Excel 2016.lnk" />
<start:DesktopApplicationTile Size="2x2" Column="0" Row="0" DesktopApplicationLinkPath="%ALLUSERSPROFILE%\Microsoft\Windows\Start Menu\Programs\Outlook 2016.lnk" />
<start:DesktopApplicationTile Size="2x2" Column="2" Row="2" DesktopApplicationLinkPath="%ALLUSERSPROFILE%\Microsoft\Windows\Start Menu\Programs\OneNote 2016.lnk" />
<start:DesktopApplicationTile Size="2x2" Column="0" Row="2" DesktopApplicationLinkPath="%ALLUSERSPROFILE%\Microsoft\Windows\Start Menu\Programs\PowerPoint 2016.lnk" />
<start:Tile Size="2x2" Column="4" Row="2" AppUserModelID="Microsoft.MicrosoftEdge_8wekyb3d8bbwe!MicrosoftEdge" />
<start:DesktopApplicationTile Size="2x2" Column="4" Row="4" DesktopApplicationLinkPath="%ALLUSERSPROFILE%\Microsoft\Windows\Start Menu\Programs\Accessories\Paint.lnk" />
<start:DesktopApplicationTile Size="2x2" Column="2" Row="0" DesktopApplicationLinkPath="%ALLUSERSPROFILE%\Microsoft\Windows\Start Menu\Programs\Word 2016.lnk" />
<start:Tile Size="2x2" Column="2" Row="4" AppUserModelID="Microsoft.WindowsCalculator_8wekyb3d8bbwe!App" />
<start:DesktopApplicationTile Size="2x2" Column="0" Row="4" DesktopApplicationLinkPath="%APPDATA%\Microsoft\Windows\Start Menu\Programs\Accessories\Notepad.lnk" />
</start:Group>
</defaultlayout:StartLayout>
</StartLayoutCollection>
</DefaultLayoutOverride>
</LayoutModificationTemplate>
Get-AppxPackage -Allusers | Where-Object{($_.Name -like "Microsoft.XboxApp") -or ($_.Name -like "Microsoft.MicrosoftSolitaireCollection") -or ($_.Name -like "Microsoft.SkypeApp") -or ($_.Name -like "microsoft.windowscommunicationsapps")} | Remove-AppxPackage -Allusers
' // ***************************************************************************
' //
' // Copyright (c) Microsoft Corporation. All rights reserved.
' //
' // Microsoft Deployment Toolkit Solution Accelerator
' //
' // File: ZTIUtility.vbs
' //
' // Version: 6.3.8330.1000
' //
' // Purpose: Common Libraries for Microsoft Deployment Toolkit
' //
' // ***************************************************************************
Option Explicit
' Public constants
Public Const ForReading = 1
Public Const ForWriting = 2
Public Const ForAppending = 8
Public Const Success = 0
Public Const Failure = 1
Public Const LogTypeInfo = 1
Public Const LogTypeWarning = 2
Public Const LogTypeError = 3
Public Const LogTypeVerbose = 4
Public Const LogTypeDeprecated = 5
Public Const TextCompare = 1
Public Const adOpenStatic = 3
Public Const adLockReadOnly = 1
Public Const adLockOptimistic = 3
Public Const Version = "6.3.8330.1000"
' Global variables
Dim oShell, oEnv, oNetwork, oFSO, objWMI, oDrive
Dim oUtility, oLogging, oEnvironment
Dim oStrings
Dim oFileHandling
' Initialization code
On Error Resume Next
Set oUtility = New Utility
oUtility.PrepareEnvironment
function PrnErrValue ( iError )
PrnErrValue = oLogging.FormatError ( iError )
end function
Sub ProcessResults(iRc)
ProcessResults = oLogging.ProcessResults ( iRc )
End Sub
function RunNewInstance
Dim oScriptClass
RunNewInstance = oUtility.RunNewInstanceEx ( oUtility.ScriptName, "oScriptClass", "oScriptClass.Main" )
end function
Function TestAndLog ( iRc , sMessage)
TestAndLog = oLogging.TRACEEX(iRc, "", sMessage, FALSE)
End function
Function TestAndFail ( iRc, iError, sMessage)
TestAndFail = oLogging.TRACEEX(iRc, iError, sMessage, TRUE)
End function
'//---------------------------------------------------------------------------
'// Function: ConvertBooleanToString()
'// Purpose: Perform a Cstr operation manually to prevent localization
'// from converting True/False to non-english values.
'//---------------------------------------------------------------------------
Function ConvertBooleanToString(bValue)
ConvertBooleanToString = oUtility.ConvertBooleanToString(bValue)
End Function
' Public classes
' //////////////////////////////////////////////////////
class Logging
' //
' // Logging is a public class used for trace logging within the BDD/MDT scripting Environment
' //
' // Assumes: oUtility, oEnvironment, oFSO - Must be initialized and active.
' //
' *** Public variables ***
Public LogFile
Public MasterLogFile
Public Component
Public Debug
Public NetworkLogging
' *** Private variables ***
' *** Constructor and destructor ***
Private Sub Class_Initialize
' Set file names and paths
Component = oUtility.ScriptName
LogFile = Component & ".log"
MasterLogFile = "BDD.log"
NetworkLogging = ""
' Set debug to false, allow PrepareEnvironment to override
Debug = False
End Sub
' *** Public methods ***
' //
' // Standard MDT logging routine, used for most logging operations
' //
' // Standard Error Types
' // Public Const LogTypeInfo = 1 ' Informational Message
' // Public Const LogTypeWarning = 2 ' Warning Message
' // Public Const LogTypeError = 3 ' Error Message
' // Public Const LogTypeVerbose = 4 ' Verbose Messages only logged when Debug has been set.
' // Public Const LogTypeDeprecated = 5 ' Informational Message that is elevated to Error when Debug is set.
' //
Public Function CreateEntry(sLogMsg, iType)
Dim sTime, sDate, sTempMsg, oLog, bConsole
' Each of the operations below has the potential to cause a runtime error.
' However, we must not stop operation if there is a failure, so allways continue.
On Error Resume Next
' Special Handling for Debug vs. Non-Debug messages
If not Debug then
If iType = LogTypeVerbose Then
Exit Function ' Verbose Messages are only displayed when Debug = True
Elseif iType = LogTypeDeprecated Then
iType = LogTypeInfo ' Deprecated messages are normally Info messages
End if
Else ' Debug = True
If iType = LogTypeVerbose then
iType = LogTypeInfo
Elseif iType = LogTypeDeprecated Then
iType = LogTypeError
End if
End if
' Suppress messages containing password
If Instr(1, sLogMsg, "password", 1) > 0 then
sLogMsg = "<Message containing password has been suppressed>"
End if
' Populate the variables to log
sTime = Right("0" & Hour(Now), 2) & ":" & Right("0" & Minute(Now), 2) & ":" & Right("0" & Second(Now), 2) & ".000+000"
sDate = Right("0"& Month(Now), 2) & "-" & Right("0" & Day(Now), 2) & "-" & Year(Now)
sTempMsg = "<![LOG[" & sLogMsg & "]LOG]!><time=""" & sTime & """ date=""" & sDate & """ component=""" & Component & """ context="""" type=""" & iType & """ thread="""" file=""" & oUtility.ScriptName & """>"
' Make sure the LogPath directory exists
oUtility.VerifyPathExistsEx LogPath, False
' If debug, echo the message
bConsole = InStr(1,Wscript.FullName,"CSCRIPT.EXE", vbTextCompare ) <> 0
If bConsole = True then
Wscript.echo sLogMsg
End if
' Create the log entry
Set oLog = oFSO.OpenTextFile(LogPath & "\" & LogFile, ForAppending, True)
oLog.WriteLine sTempMsg
oLog.Close
' Create the master log entry
Set oLog = oFSO.OpenTextFile(LogPath & "\" & MasterLogFile, ForAppending, True)
oLog.WriteLine sTempMsg
oLog.Close
' Write to a network Share Entry
If NetworkLogging <> "" then
Set oLog = oFSO.OpenTextFile(NetworkLogging & "\" & MasterLogFile, ForAppending, True)
oLog.WriteLine sTempMsg
oLog.Close
End if
On error goto 0
End Function
' //
' // Standard MDT Event Messaging routine, used To send event status messages to a networked log file.
' //
' // Standard Error Types
' // Public Const LogTypeInfo = 1 ' Informational Message
' // Public Const LogTypeWarning = 2 ' Warning Message
' // Public Const LogTypeError = 3 ' Error Message
' // Public Const LogTypeVerbose = 4 ' Verbose Messages only logged when Debug has been set.
' //
Function CreateEvent(iEventID, iType, sMessage, arrParms)
Dim sEventFile
Dim fptr
Dim sLine
Dim iMOMType
Dim sDomain
Dim sComputer
Dim sPackage
Dim sAdvert
Dim i
Dim sCurrentStep
Dim sTotalSteps
Dim sScript
Dim oService
Dim sID
Dim oResult
On Error Resume Next
' Log the message specified
CreateEntry sMessage, iType
' Get some information from the task sequence environment for use below (if needed)
sCurrentStep = oEnvironment.Item("_SMSTSNextInstructionPointer")
If sCurrentStep = "" then
sCurrentStep = "0"
End if
sTotalSteps = oEnvironment.Item("_SMSTSInstructionTableSize")
If sTotalSteps = "" then
sTotalSteps = "0"
End if
' Send events to the event share if specified
If oEnvironment.Item("EventShare") <> "" then
' Make sure the path is accessible
oUtility.ValidateConnection oEnvironment.Item("EventShare")
' Create a unique file name on the share.
sEventFile = oEnvironment.Item("EventShare") & "\" & oUtility.ComputerName & "_" & oFSO.GetTempName
Set fptr = oFSO.CreateTextFile(sEventFile, True)
If Err then
CreateEntry "Unable to create event file " & sEventFile & ": " & Err.Description & " (" & Err.Number & ")", LogTypeError
Exit function
End if
' Build the first line to write
Select Case iType
Case LogTypeInfo
iMOMType = 4
Case LogTypeWarning
iMOMType = 2
Case LogTypeError
iMOMType = 1
End Select
sDomain = oEnvironment.Item("JoinDomain")
sComputer = oUtility.ComputerName
If oEnvironment.Item("_SMSTSAdvertID") <> "" then
sAdvert = oEnvironment.Item("_SMSTSAdvertId")
sPackage = oEnvironment.Item("_SMSTSPackageID")
ElseIf oEnvironment.Item("OSDADVERTID") = "" then
sAdvert = "OSD00000"
sPackage = "OSD00000"
Else
sAdvert = oEnvironment.Item("OSDADVERTID")
sPackage = oEnvironment.Item("OSDPACKAGEID")
End if
' Write out the first line (common content)
sLine = CStr(iEventID) & "," & CStr(iMOMType) & "," & sDomain & "," & sComputer & "," & sPackage & "," & sAdvert & "," & sCurrentStep & "," & sTotalSteps & "," & oEnvironment.Item("DeploymentMethod")
fptr.WriteLine sLine
If Err then
CreateEntry "Unable to write event file " & sEventFile & ": " & Err.Description & " (" & Err.Number & ")", LogTypeError
Exit function
End if
' Write out the second line (insertion strings)
fptr.WriteLine Join(arrParms, ",")
If Err then
CreateEntry "Unable to write event file " & sEventFile & ": " & Err.Description & " (" & Err.Number & ")", LogTypeError
Exit function
End if
' Write out the third line (message)
fptr.WriteLine sMessage
If Err then
CreateEntry "Unable to write event file " & sEventFile & ": " & Err.Description & " (" & Err.Number & ")", LogTypeError
Exit function
End if
' Close the file
fptr.Close
Set fptr = Nothing
CreateEntry "Event " & CStr(iEventID) & " sent: " & sMessage, LogTypeInfo
End if
' Send events to the event service if specified
If oEnvironment.Item("EventService") <> "" then
' Create a web service object
Set oService = Nothing
Err.Clear
Set oService = new WebService
If Err then
' Load ZTIDataAccess.vbs and try again
sScript = oFSO.OpenTextFile(oEnv("ScriptRoot") & "\ZTIDataAccess.vbs", 1, false).ReadAll
ExecuteGlobal sScript
Set oService = new WebService
End if
If oService is Nothing then
oLogging.CreateEntry "Unable to create WebService class", LogTypeWarning
Exit Function
End if
' Build the parameters to pass to the web service
sService = "PostEvent"
sID = oEnvironment.Item("UUID") & "," & Join(oEnvironment.ListItem("MacAddress").Keys, ",")
sLine = "uniqueID=" & oEnvironment.Item("LTIGUID") & "&computerName=" & oUtility.ComputerName & "&messageID=" & CStr(iEventID) & "&severity=" & CStr(iType) & "&stepName=" & oEnvironment.Item("_SMSTSCurrentActionName") & "&currentStep=" & sCurrentStep & "&totalSteps=" & sTotalSteps & "&id=" & sID & "&message=" & sMessage
sLine = sLine & "&dartIP=" & oEnvironment.Item("DartIP001") & "&dartPort=" & oEnvironment.Item("DartPort001") & "&dartTicket=" & oEnvironment.Item("DartTicket") & "&vmHost=" & oEnvironment.Item("VMHost") & "&vmName=" & oEnvironment.Item("VMName")
' Call the web service
oService.WebService = oEnvironment.Item("EventService") & "/MDTMonitorEvent/PostEvent?" & sLine
oService.Method = "GET"
oService.Quiet = true
Set oResult = oService.Query
' Remember the returned GUID value
If oEnvironment.Item("LTIGUID") <> oResult.DocumentElement.Text then
oEnvironment.Item("LTIGUID") = oResult.DocumentElement.Text
End if
CreateEntry "Event " & CStr(iEventID) & " sent: " & sMessage, LogTypeInfo
End if
End Function
Function GetDiscoveryArray
Dim sLine
Dim dicMac
Dim arrMac
Dim i
' Add the local entries
sLine = oEnvironment.Item("PHASE") & "," & oEnvironment.Item("AssetTag") & "," & oEnvironment.Item("UUID")
Set dicMac = oEnvironment.ListItem("MacAddress")
arrMac = dicMac.Keys
For i = 0 to 4
If i > UBound(arrMac) then
sLine = sLine & ","
Else
sLine = sLine & "," & arrMac(i)
End if
Next
' Add the user data entries (which might not be available yet)
sLine = oEnvironment.Substitute(sLine & "," & oEnvironment.Item("SLShare") & "," & oEnvironment.Item("UDShare") & "," & oEnvironment.Item("UDDir"))
' Split it into an array and return it
GetDiscoveryArray = Split(sLine,",")
End Function
Public Function CopyLog()
Dim oFile
Dim iRetVal, fptr1, fptr2, sLine, sNewLogFolderName, sLogFile
Dim sComputer
Dim sLog
Dim sBootDrive
On Error Resume Next
' Figure out where to copy the local logfile to
If oEnvironment.Item("SLShare") = "" then
oLogging.CreateEntry "Unable to copy log to the network as no SLShare value was specified.", LogTypeInfo
Exit Function
End if
' Make sure the path is accessible
oUtility.ValidateConnection oEnvironment.Item("SLShare")
oUtility.VerifyPathExists oEnvironment.Item("SLShare")
If not oFSO.FolderExists(oEnvironment.Item("SLShare")) then
oLogging.CreateEntry "An invalid SLShare value of " & oEnvironment.Item("SLShare") & " was specified.", LogTypeWarning
Exit Function
End if
' Figure out the computer name
sComputer = oUtility.ComputerName
sBootDrive = oUtility.GetOSTargetDriveLetterEx(false)
if sBootDrive = "" then
oLogging.CreateEntry "Destination Logical Drive was not specificed, defaulting to #:\", LogTypeInfo
sBootDrive = "#:" ' Unknown Boot Drive
End if
' Construct the new folder name
sNewLogFolderName = oEnvironment.Item("SLShare") & "\" & sComputer
oUtility.VerifyPathExists sNewLogFolderName
' Copy all the main logs (except BDD.LOG, which we'll merge later)
For each oFile in oFSO.GetFolder(oLogging.LogPath).Files
If UCase(oFile.Name) <> "BDD.LOG" and (Right(UCase(oFile.Name), 4) = ".LOG" or Right(UCase(oFile.Name), 4) = ".XML") then
oLogging.CreateEntry "Copying " & oLogging.LogPath & "\" & oFile.Name & " to " & sNewLogFolderName & "\" & oFile.Name, LogTypeInfo
oFSO.CopyFile oLogging.LogPath & "\" & oFile.Name, sNewLogFolderName & "\", True
End if
Next
' Copy any exceptions we can find
For each sLog in Array("SMSTS.LOG", "Debug\Netsetup.log", "wpeinit.log", "Debug\DCPROMO.LOG", "Debug\DCPROMOUI.LOG", "OSDSetupWizard.log")
If oFSO.FileExists(oEnvironment.Item("SMSTSLogPath_Cache") & "\" & sLog) then
oLogging.CreateEntry "Copying " & oEnvironment.Item("SMSTSLogPath_Cache") & "\" & sLog & " to " & sNewLogFolderName & "\" & sLog, LogTypeInfo
oFSO.CopyFile oEnvironment.Item("SMSTSLogPath_Cache") & "\" & sLog, sNewLogFolderName & "\", True
ElseIf oFSO.FileExists(oEnvironment.Item("_SMSTSLogPath") & "\" & sLog) then
oLogging.CreateEntry "Copying " & oEnvironment.Item("_SMSTSLogPath") & "\" & sLog & " to " & sNewLogFolderName & "\" & sLog, LogTypeInfo
oFSO.CopyFile oEnvironment.Item("_SMSTSLogPath") & "\" & sLog, sNewLogFolderName & "\", True
ElseIf oFSO.FileExists(oEnv("TEMP") & "\" & sLog) then
oLogging.CreateEntry "Copying " & oEnv("TEMP") & "\" & sLog & " to " & sNewLogFolderName & "\" & sLog, LogTypeInfo
oFSO.CopyFile oEnv("TEMP") & "\" & sLog, sNewLogFolderName & "\", True
ElseIf oFSO.FileExists(oEnv("SystemRoot") & "\" & sLog) then
oLogging.CreateEntry "Copying " & oENV("SystemRoot") & "\" & sLog & " to " & sNewLogFolderName & "\", LogTypeInfo
oFSO.CopyFile oENV("SystemRoot") & "\" & sLog, sNewLogFolderName & "\", True
ElseIf oFSO.FileExists(oEnv("SystemRoot") & "\System32\" & sLog) then
oLogging.CreateEntry "Copying " & oENV("SystemRoot") & "\System32\" & sLog & " to " & sNewLogFolderName & "\", LogTypeInfo
oFSO.CopyFile oENV("SystemRoot") & "\System32\" & sLog, sNewLogFolderName & "\", True
End if
Next
' Copy the Panther Logs
If oFSO.FileExists(oENV("SystemRoot") & "\Panther\setupact.log") Then
oUtility.VerifyPathExists sNewLogFolderName & "\Panther"
OLogging.CreateEntry "Copying " & oENV("SystemRoot") & "\Panther\setupact.log to " & sNewLogFolderName & "\Panther", LogTypeInfo
oFSO.CopyFile oENV("SystemRoot") & "\Panther\setupact.log", sNewLogFolderName & "\Panther\", True
End If
If oFSO.FileExists(oENV("SystemRoot") & "\Panther\setuperr.log") Then
oUtility.VerifyPathExists sNewLogFolderName & "\Panther"
OLogging.CreateEntry "Copying " & oENV("SystemRoot") & "\Panther\setuperr.log to " & sNewLogFolderName & "\Panther", LogTypeInfo
oFSO.CopyFile oENV("SystemRoot") & "\Panther\setuperr.log", sNewLogFolderName & "\Panther\", True
End If
If oFSO.FileExists(oENV("SystemRoot") & "\Panther\cbs_unattend.log") Then
oUtility.VerifyPathExists sNewLogFolderName & "\Panther"
OLogging.CreateEntry "Copying " & oENV("SystemRoot") & "\Panther\cbs_unattend.log to " & sNewLogFolderName & "\Panther", LogTypeInfo
oFSO.CopyFile oENV("SystemRoot") & "\Panther\cbs_unattend.log", sNewLogFolderName & "\Panther\", True
End If
If oFSO.FileExists(oENV("SystemRoot") & "\Panther\UnattendGC\setupact.log") Then
oUtility.VerifyPathExists sNewLogFolderName & "\Panther\UnattendGC"
OLogging.CreateEntry "Copying " & oENV("SystemRoot") & "\Panther\UnattendGC\setupact.log to " & sNewLogFolderName & "\Panther\UnattendGC", LogTypeInfo
oFSO.CopyFile oENV("SystemRoot") & "\Panther\UnattendGC\setupact.log", sNewLogFolderName & "\Panther\UnattendGC\", True
End If
If oFSO.FileExists(oENV("SystemRoot") & "\Panther\UnattendGC\setuperr.log") Then
oUtility.VerifyPathExists sNewLogFolderName & "\Panther\UnattendGC"
OLogging.CreateEntry "Copying " & oENV("SystemRoot") & "\Panther\UnattendGC\setuperr.log to " & sNewLogFolderName & "\Panther\UnattendGC", LogTypeInfo
oFSO.CopyFile oENV("SystemRoot") & "\Panther\UnattendGC\setuperr.log", sNewLogFolderName & "\Panther\UnattendGC\", True
End If
If oFSO.FileExists(sBootDrive & "\$WINDOWS.~BT\Sources\Panther\setupact.log") Then
oUtility.VerifyPathExists sNewLogFolderName & "\Panther"
OLogging.CreateEntry "Copying " & sBootDrive & "\$WINDOWS.~BT\Sources\Panther\setupact.log to " & sNewLogFolderName & "\Panther", LogTypeInfo
oFSO.CopyFile sBootDrive & "\$WINDOWS.~BT\Sources\Panther\setupact.log", sNewLogFolderName & "\Panther\", True
End If
If oFSO.FileExists(sBootDrive & "\$WINDOWS.~BT\Sources\Panther\setuperr.log") Then
oUtility.VerifyPathExists sNewLogFolderName & "\Panther"
OLogging.CreateEntry "Copying " & sBootDrive & "\$WINDOWS.~BT\Sources\Panther\setuperr.log to " & sNewLogFolderName & "\Panther", LogTypeInfo
oFSO.CopyFile sBootDrive & "\$WINDOWS.~BT\Sources\Panther\setuperr.log", sNewLogFolderName & "\Panther\", True
End If
If oFSO.FileExists(sBootDrive & "\$WINDOWS.~BT\Sources\Panther\cbs_unattend.log") Then
oUtility.VerifyPathExists sNewLogFolderName & "\Panther"
OLogging.CreateEntry "Copying " & sBootDrive & "\$WINDOWS.~BT\Sources\Panther\cbs_unattend.log to " & sNewLogFolderName & "\Panther", LogTypeInfo
oFSO.CopyFile sBootDrive & "\$WINDOWS.~BT\Sources\Panther\cbs_unattend.log", sNewLogFolderName & "\Panther\", True
End If
If oFSO.FileExists(sBootDrive & "\$WINDOWS.~BT\Sources\Panther\UnattendGC\setupact.log") Then
oUtility.VerifyPathExists sNewLogFolderName & "\Panther\UnattendGC"
OLogging.CreateEntry "Copying " & sBootDrive & "\$WINDOWS.~BT\Sources\Panther\UnattendGC\setupact.log to " & sNewLogFolderName & "\Panther\UnattendGC", LogTypeInfo
oFSO.CopyFile sBootDrive & "\$WINDOWS.~BT\Sources\Panther\UnattendGC\setupact.log", sNewLogFolderName & "\Panther\UnattendGC\", True
End If
If oFSO.FileExists(sBootDrive & "\$WINDOWS.~BT\Sources\Panther\UnattendGC\setuperr.log") Then
oUtility.VerifyPathExists sNewLogFolderName & "\Panther\UnattendGC"
OLogging.CreateEntry "Copying " & sBootDrive & "\$WINDOWS.~BT\Sources\Panther\UnattendGC\setuperr.log to " & sNewLogFolderName & "\Panther\UnattendGC", LogTypeInfo
oFSO.CopyFile sBootDrive & "\$WINDOWS.~BT\Sources\Panther\UnattendGC\setuperr.log", sNewLogFolderName & "\Panther\UnattendGC\", True
End If
' Make sure we have a local log file; it might not exist if the disk isn't yet writable.
sLogFile = LogPath & "\" & MasterLogFile
If not oFSO.FileExists(sLogFile) then
oLogging.CreateEntry "Master log file " & sLogFile & " was not found, unable to copy to " & sNewLogFolderName & "\BDD.LOG", LogTypeInfo
Exit Function
End if
' Copy the file contents to the end of the network file. (It might already exist from a previous action, so append to it.)
oLogging.CreateEntry "Copying log " & sLogFile & " contents to " & sNewLogFolderName & "\BDD.LOG", LogTypeInfo
Set fptr1 = oFSO.OpenTextFile(sLogFile, ForReading, True)
If Err then
oLogging.CreateEntry "Unable to open " & sLogFile & " for reading: " & Err.Description & " (" & Err.Number & ")", LogTypeInfo
Err.Clear
Exit Function
End if
Set fptr2 = oFSO.OpenTextFile(sNewLogFolderName & "\BDD.LOG", ForAppending, True)
If Err then
oLogging.CreateEntry "Unable to open " & sNewLogFolderName & "\BDD.LOG for appending: " & Err.Description & " (" & Err.Number & ")", LogTypeInfo
Err.Clear
Exit Function
End if
Do while Not fptr1.AtEndOfStream
sLine = fptr1.readline
fptr2.writeline sLine
Loop
fptr1.Close
fptr2.Close
Err.Clear
On Error Goto 0
End Function
Public Function ReportProgress(sMsg, iPercent)
Dim iMaxPercent
Dim oProgress
Dim uStep
Dim uMaxStep
CreateEntry "Update progress [ " & iPercent & " ] : " & sMsg , LogTypeVerbose
' Try to create the progress UI object
On Error Resume Next
Set oProgress = CreateObject("Microsoft.SMS.TSProgressUI")
If Err then
Err.Clear
' Record the progress in the registry
oShell.RegWrite "HKLM\Software\Microsoft\Deployment 4\ProgressPercent", iPercent, "REG_DWORD"
oShell.RegWrite "HKLM\Software\Microsoft\Deployment 4\ProgressText", sMsg, "REG_SZ"
on error goto 0
Exit Function
End if
On Error Goto 0
' Update the progress
On Error Resume Next
iMaxPercent = 100
uStep = CLng(oEnvironment.Item("_SMSTSNextInstructionPointer"))
uMaxStep = CLng(oEnvironment.Item("_SMSTSInstructionTableSize"))
Call oProgress.ShowActionProgress(oEnvironment.Item("_SMSTSOrgName"), oEnvironment.Item("_SMSTSPackageName"), oEnvironment.Item("_SMSTSCustomProgressDialogMessage"), oEnvironment.Item("_SMSTSCurrentActionName"), (uStep), (uMaxStep), sMsg, (iPercent), (iMaxPercent))
If Err then
CreateEntry "Unable to update progress: " & Err.Description & " (" & Err.Number & ")", LogTypeInfo
ReportProgress = Failure
Err.Clear
Exit Function
End if
On Error Goto 0
' Dispose of the object
Set oProgress = Nothing
End Function
Property Get LogPath
Dim iRetVal
LogPath = oUtility.LogPath
'Preserve the existing logpath before creating the new logpath
If Ucase(oUtility.ScriptName) = "ZTIDISKPART" and Left(LogPath,2)<> "X:" Then
oUtility.VerifyPathExistsEx "X:\MININT\SMSOSD\OSDLOGS", FALSE
LogPath = "X:\MININT\SMSOSD\OSDLOGS"
End If
If oEnvironment.Item("LogPath") <> "" AND oEnvironment.Item("LogPath") <> LogPath And Ucase(oUtility.ScriptName) <> "LTICLEANUP" Then
On Error Resume Next
iRetVal = oShell.Run("xcopy """ & oEnvironment.Item("LogPath") & """ """ & LogPath & """ /D /s /e /h /y /c",0, true)
oEnvironment.Item("LogPath") = LogPath
on Error goto 0
End If
If oEnvironment.Item("LogPath") = "" And Ucase(oUtility.ScriptName) <> "LTICLEANUP" Then
oEnvironment.Item("LogPath") = LogPath
End If
End Property
Function ReportFailure ( sMessage, iError )
CreateEvent 41002, LogTypeError, oEnvironment.Substitute( "FAILURE ( " & FormatError(iError) & " ): " & sMessage ), Array(iError)
' It is possible that we are are not running in the Wscript Host ( HTML Page ).
on error resume next
WScript.Quit iError
on error goto 0
End function
' //
' // Perform an inline check of the condition and write out the message
' // iRC can be either SUCCESS (0), FAILURE(not 0) as defined above.
' // or iRC can be Boolean either TRUE or FALSE
' //
' // Anything other than Success or Failure will log a Warning or Error.
' //
Function TRACEEX( iRc, iError, sMessage, bFatal)
TRACEEX = iRc
If Err then
' Error
TRACEEX = Err.Number
sMessage = sMessage & " - " & Err.Description
CreateEntry oEnvironment.Substitute( "FAILURE (Err): " & FormatError(TRACEEX) & ": " & sMessage ), LogTypeWarning
If bFatal then
' Fatial Error
ReportFailure sMessage, iError
End if
Elseif (VarType(iRC) = vbInteger) or (VarType(iRC) = vbLong) or (VarType(iRC) = vbBoolean) then
' iRC is either a Variant Integer (Either SUCCESS or FAILURE), or a Variant Bool (Either True or False)
If ( (iRC = Success or iRC = 3010) and ((VarType(iRC) = vbInteger) or (VarType(iRC) = vbLong)) ) or ( iRC = TRUE and VarType(iRC) = vbBoolean ) then
CreateEntry oEnvironment.Substitute( "SUCCESS: " & FormatError(iRC) & ": " & sMessage ), LogTypeVerbose
ElseIf bFatal then
' Fatial Error
ReportFailure FormatError(iRC) & ": " & sMessage, iError
Else
CreateEntry oEnvironment.Substitute( "FAILURE: " & FormatError(iRC) & ": " & sMessage ), LogTypeWarning
End if
Elseif (VarType(iRC) <> vbEmpty) and (VarType(iRC) <> vbNull ) then
CreateEntry oEnvironment.Substitute( "UNKNOWN: " & TypeName(iRc) & " = " & iRc & " : " & FormatError(iError) & ": " & sMessage ), LogTypeWarning
End if
End function
Function ProcessResults( iRc )
Dim iMainRc
Dim sError
Dim sMainRc
iMainRc = iRc
sMainRc = FormatError ( iMainRc )
If Err then
iMainRc = Err.Number
sError = Err.Description
sMainRc = FormatError ( iMainRc )
CreateEvent 41002, LogTypeError, "ZTI ERROR - Unhandled error returned by " & oUtility.ScriptName & ": " & sError & " (" & sMainRc & ")", Array(iMainRc)
ElseIf iRc <> Success then
CreateEvent 41002, LogTypeError, "ZTI ERROR - Non-zero return code by " & oUtility.ScriptName & ", rc = " & sMainRc, Array(iMainRc)
Else
CreateEvent 41001, LogTypeInfo, oUtility.ScriptName & " processing completed successfully.", Array()
End if
WScript.Quit iMainRc
End function
Function FormatError( iError )
' Error messages above 0x1000000 are most likely Hex values, print both Hex and Decimal
If not isNumeric( iError ) then
FormatError = ""
ElseIf Abs(iError) >= &H1000000 then
FormatError = cstr(iError) & " 0x" & right( "00000000" & hex ( iError ), 8 )
Else
FormatError = cstr(iError)
End if
End function
End Class
' //////////////////////////////////////////////////////
Class Environment
' *** Public variables ***
Public PersistFile
' *** Private variables ***
Private oVariables
Private dLastModified
Private dLastSize
Private osdV4
' *** Constructor and destructor ***
Private Sub Class_Initialize
PersistFile = "VARIABLES.DAT"
On Error Resume Next
Err.Clear
Set oVariables = oUtility.CreateXMLDOMObject
If Err then
' Unable to create XML object
Err.Clear
End if
On Error Goto 0
dLastModified = 0
dLastSize = 0
' Create SMSv4 Task Sequence environment
On Error Resume Next
Err.Clear
Set osdV4 = CreateObject("Microsoft.SMS.TSEnvironment")
If Err then
Set osdV4 = Nothing
Err.Clear
End if
On Error Goto 0
Err.Clear
End Sub
' *** Private methods ***
Function GetOSDV4(sVariable)
GetOSDV4 = ""
On Error Resume Next
If osdV4 is Nothing then
Exit Function
Else
GetOSDV4 = osdV4(sVariable)
If Err then
' oLogging.CreateEntry "WARNING - Unable to get SMSv4 Task Sequencer environment: " & Err.Description & " (" & Err.Number & ")", LogTypeWarning
End if
End if
On Error Goto 0
Err.Clear
End Function
Function SetOSDV4(sVariable, sNew)
On Error Resume Next
If osdV4 is Nothing then
SetOSDV4 = False
Exit Function
Else
osdV4(sVariable) = sNew
If Err then
' oLogging.CreateEntry "WARNING - Unable to get SMSv4 Task Sequencer environment: " & Err.Description & " (" & Err.Number & ")", LogTypeWarning
SetOSDV4 = False
End if
End if
On Error Goto 0
Err.Clear
SetOSDV4 = True
End Function
Property Get VariablesDat
Dim sVariablesFile
' If necessary, load the XML file
sVariablesFile = PersistPath & "\" & PersistFile
If oFSO.FileExists(sVariablesFile) then
If (oFSO.GetFile(sVariablesFile).DateLastModified <> dLastModified) or (oFSO.GetFile(sVariablesFile).Size <> dLastSize) then
On Error Resume Next
Do
oVariables.Load sVariablesFile
dLastModified = oFSO.GetFile(sVariablesFile).DateLastModified
dLastSize = oFSO.GetFile(sVariablesFile).Size
Loop While oVariables.DocumentElement is Nothing
On Error Goto 0
End if
ElseIf dLastModified = 0 then
oVariables.LoadXml "<?xml version=""1.0"" ?><MediaVarList Version=""4.00.5345.0000""></MediaVarList>"
dLastModified = Now ' The file hasn't been saved yet, but we don't want to reset this
End if
' Set the return value to the XML document
Set VariablesDat = oVariables
End Property
Function GetDAT(sVariable)
Dim sLockFile
Dim oNode
Dim fLock
GetDAT = ""
If Ucase(oUtility.ScriptName) <> "LTICLEANUP" Then
sLockFile = PersistPath & "\" & PersistFile & ".LOCK"
On error resume next
Set fLock = nothing
Set fLock = oFSO.CreateTextFile(sLockFile, 2, true)
Do while fLock is nothing
dLastModified = 0 ' FORCE a rescan.
' ologging.CreateEntry sLockFile & " is locked by another process, Wait!", LogTypeVerbose
oUtility.SafeSleep 10
Set fLock = oFSO.CreateTextFile( sLockFile, 2, true)
Loop
On error goto 0
End if
On Error Resume Next
Set oNode = Nothing
Set oNode = VariablesDat.DocumentElement.SelectSingleNode("//var[@name='" & UCase(sVariable) & "']")
On Error Goto 0
If not (oNode is Nothing) then
GetDAT = oNode.Text
End if
End Function
Function SetDAT(sVariable, sNew)
Dim sVariablesFile
Dim sLockFile
Dim oNode, oCDATA, oVD
Dim fLock
If osdv4 is Nothing OR oEnvironment.Item("_SMSTSStandAloneMode") = "true" then
If oFSO.FolderExists(PersistPath) then
sVariablesFile = PersistPath & "\" & PersistFile
If Ucase(oUtility.ScriptName) <> "LTICLEANUP" Then
sLockFile = PersistPath & "\" & PersistFile & ".LOCK"
On error resume next
Set fLock = nothing
Set fLock = oFSO.CreateTextFile(sLockFile, 2, true)
Do while fLock is nothing
dLastModified = 0 ' FORCE a rescan.
' ologging.CreateEntry sLockFile & " is locked by another process, Wait!", LogTypeVerbose
oUtility.SafeSleep 10
Set fLock = oFSO.CreateTextFile(sLockFile, 2, true)
Loop
On error goto 0
End if
Set oVD = VariablesDat
' See if the variable is already defined. If not, append a new node
Set oNode = oVD.DocumentElement.SelectSingleNode("//var[@name='" & UCase(sVariable) & "']")
If oNode is Nothing then
Set oNode = oVD.CreateElement("var")
oVD.DocumentElement.appendChild oNode
Else
If oNode.Text = sNew then
' oLogging.CreateEntry "Not changing variable " & sVariable & " because the value was not changed.", LogTypeInfo
SetDAT = True
Exit Function
End if
End if
' Set the name of the node
oNode.SetAttribute "name", UCase(sVariable)
' Set the value of the node
Set oCDATA = oVD.createCDATASection(sNew)
If oNode.hasChildNodes then
oNode.removeChild(oNode.childNodes.item(0))
End if
oNode.appendChild(oCDATA)
' Save the updated XML file
On Error Resume Next
oVD.Save sVariablesFile
dLastModified = oFSO.GetFile(sVariablesFile).DateLastModified
dLastSize = oFSO.GetFile(sVariablesFile).Size
If Err then
oLogging.CreateEntry "WARNING - Unable to persist items to " & sVariablesFile & ": " & Err.Description & " (" & Err.Number & ")", LogTypeWarning
SetDat = False
Err.Clear
End if
On Error Goto 0
Else
SetDat=False
End if
Else
SetDat = False
End If
SetDat = True
End Function
Function ObfuscateEncode(sVariable, sNew)
Select Case Ucase(sVariable)
Case "USERID", "USERPASSWORD", "USERDOMAIN", "DOMAINADMIN", "DOMAINADMINPASSWORD", "DOMAINADMINDOMAIN", _
"ADMINPASSWORD", "BDEPIN", "TPMOWNERPASSWORD", "ADDSUSERNAME", "ADDSPASSWORD", _
"SAFEMODEADMINPASSWORD", "USERNAME", "USERPASSWORD", "PRODUCTKEY", "OSDJOINACCOUNT", "OSDJOINPASSWORD"
ObfuscateEncode = oStrings.Base64Encode(sNew)
Case Else
ObfuscateEncode = sNew
End Select
End Function
Function ObfuscateDecode(sVariable, sCurrent)
Select Case Ucase(sVariable)
Case "USERID", "USERPASSWORD", "USERDOMAIN", "DOMAINADMIN", "DOMAINADMINPASSWORD", "DOMAINADMINDOMAIN", _
"ADMINPASSWORD", "BDEPIN", "TPMOWNERPASSWORD", "ADDSUSERNAME", "ADDSPASSWORD", _
"SAFEMODEADMINPASSWORD", "USERNAME", "USERPASSWORD", "PRODUCTKEY", "OSDJOINACCOUNT", "OSDJOINPASSWORD"
ObfuscateDecode = oStrings.Base64Decode(sCurrent)
' If the variable wasn't a valid base64 string, an empty string will be returned. Instead of
' passing that back, return the current value. (The Base64Decode method should log a warning.)
If ObfuscateDecode = "" and sCurrent <> "" then
ObfuscateDecode = sCurrent
End if
Case Else
ObfuscateDecode = sCurrent
End Select
End Function
' *** Public methods ***
Public Property Get Exists(sVariable)
If Item(sVariable) <> "" then
Exists = True
Else
Exists = False
End if
End Property
Public Property Get Item(sVariable)
Dim sOriginal
Dim bSync
' First try TS environment, then (for Lite Touch only) try the XML file
Item = GetOSDV4(sVariable)
If Item = "" and GetOSDV4("DeploymentMethod") <> "SCCM" then
' No value retrieved from the task sequence, try the XML file
Item = GetDat(sVariable)
If Item <> "" then
bSync = true
End if
End if
' Decode and sync if not blank
If Item <> "" then
' Decode the variable
sOriginal = Item
Item = ObfuscateDecode(sVariable, sOriginal)
' Try to set the value in the task sequence environment (sync)
If bSync then
SetOSDV4 sVariable, sOriginal
End if
End if
End Property
Public Property Let Item(sVariable, sNew)
Dim sEncoded
' Encode as required
sEncoded = ObfuscateEncode(sVariable, sNew)
' Save to all available environments
If SetOSDV4(sVariable, sEncoded) or SetDat(sVariable, sEncoded) Then
oLogging.CreateEntry "Property " & sVariable & " is now = " & sNew, LogTypeInfo
End If
' For completeness, set the variable in the process's environment as well
oEnv(sVariable) = sNew
End Property
Public Property Get ListItem(sVariable)
Dim i
Dim sPadded
Set ListItem = CreateObject("Scripting.Dictionary")
For i = 1 to 999
sPadded = sVariable & Right("000" & CStr(i), 3)
If Item(sPadded) <> "" then
If not ListItem.Exists(Item(sPadded)) then
ListItem.Add Item(sPadded), ""
End if
ElseIf Item(sVariable & CStr(i)) <> "" then
If not ListItem.Exists(Item(sVariable & CStr(i))) then
ListItem.Add Item(sVariable & CStr(i)), ""
End if
Else
Exit For ' Exit on first "not found" entry
End if
Next
End Property
Public Sub SetListItemEx (sVariable, sNew)
Dim sElement
Dim i
Dim sPadded
i = 0
For each sElement in sNew
i = i + 1
sPadded = sVariable & Right("000" & CStr(i), 3)
Item(sPadded) = sElement
Next
' Blank out the next in case there was something there
sPadded = sVariable & Right("000" & CStr(i+1), 3)
If Exists(sPadded) then
Item(sPadded) = ""
End if
' Blank out the non-list item if it was there
If exists(sVariable) then
Item(sVariable) = ""
End if
End sub
Public Property Set ListItem(sVariable, sNew)
SetListItemEx sVariable, sNew
End Property
Public Property Let ListItem(sVariable, sNew)
SetListItemEx sVariable, sNew
End Property
Public Property Get IndirectItem( sVariable )
IndirectItem = oEnvironment.Item(oEnvironment.Item(sVariable))
End Property
Public Property Let IndirectItem( sVariable, sNew )
If oEnvironment.Item(sVariable) = "" then
oLogging.CreateEntry "Invalid MDT Indirect Variable pointer: " & sVariable, LogTypeWarning
Else
oEnvironment.Item(oEnvironment.Item(sVariable)) = sNew
End if
End Property
Function Substitute(sVal)
Dim sReplace, iPos, iEnd, sEval
' Substitute the appropriate values
iPos = Instr(sVal, "%")
While iPos > 0
' Find ending "%"
iEnd = Instr(iPos+1, sVal, "%")
If iEnd > 0 then
sEval = Mid(sVal, iPos+1, iEnd - iPos - 1)
sReplace = ""
If oEnvironment.ListItem(sEval).Count > 0 then
For each sReplace in oEnvironment.ListItem(sEval).Keys
Exit For ' Grab the first value
Next
ElseIf oEnvironment.Item(sEval) <> "" then
sReplace = oEnvironment.Item(sEval)
End if
If sReplace <> "" then
If iPos = 1 then
sVal = CStr(sReplace) & Mid(sVal, iEnd + 1)
ElseIf iEnd = Len(sVal) then
sVal = Left(sVal, iPos - 1) & CStr(sReplace)
Else
sVal = Left(sVal, iPos - 1) & CStr(sReplace) & Mid(sVal, iEnd + 1)
End if
iPos = Instr(sVal, "%")
Else
iPos = iEnd
End if
Else
iPos = iEnd
End if
WEnd
' Expand any environment variables
sVal = oShell.ExpandEnvironmentStrings(sVal)
' Finally, look for evaluate blocks
iPos = Instr(sVal, "#")
While iPos > 0
' Find ending "#"
iEnd = Instr(iPos+1, sVal, "#")
If iEnd > 0 then
sEval = Mid(sVal, iPos+1, iEnd - iPos - 1)
sReplace = empty
On Error Resume Next
sReplace = Eval(sEval)
On Error Goto 0
If not isEmpty(sReplace) then
If iPos = 1 then
sVal = sReplace & Mid(sVal, iEnd + 1)
ElseIf iEnd = Len(sVal) then
sVal = Left(sVal, iPos - 1) & sReplace
Else
sVal = Left(sVal, iPos - 1) & sReplace & Mid(sVal, iEnd + 1)
End if
iPos = Instr(sVal, "#")
Else
iPos = iEnd
End if
Else
iPos = iEnd
End if
WEnd
Substitute = Trim(sVal)
End Function
Public Property Get PersistPath
Dim oOrigPersistFile
Dim oNewPersistFile
PersistPath = oUtility.LogPath
If oEnv("SystemDrive") = "X:" then
If oFSO.FileExists("X:\minint\smsosd\osdlogs\variables.dat") Then
Set oOrigPersistFile = oFSO.GetFile("X:\minint\smsosd\osdlogs\variables.dat")
If oFSO.FileExists(PersistPath & "\VARIABLES.DAT") Then
Set oNewPersistFile = oFSO.GetFile(PersistPath & "\VARIABLES.DAT")
If oOrigPersistFile.Size > oNewPersistFile.Size Then
oFSO.CopyFile "X:\minint\smsosd\osdlogs\variables.dat", PersistPath & "\VARIABLES.DAT", true
End if
Else
oFSO.CopyFile "X:\minint\smsosd\osdlogs\variables.dat", PersistPath & "\VARIABLES.DAT", true
End if
End if
End if
End Property
Public Function Release
Set osdV4 = Nothing
End Function
End Class
Class Utility
' *** Properties ***
Public isHTML
Public isWSH
Public isMSHTA
Public isCScript
Public isWScript
Public oMSHTA
Public Arguments
' *** Private variables ***
Dim dicNetworkConnections
Dim sScriptDir
Dim oBDDUtility
Dim oSupportedPlatforms
Private sLocalRootPath
Private bCacheLocalRootPath
Private startTime
Private lastHeartbeat
Private iVersionMajor
Private iVersionMinor
Private iBuildNumber
Private iRevision
' *** Constructor and destructor ***
Private Sub Class_Initialize
Dim re
Dim arrDrives, i
Dim oContext, oLocator
' Initialize the objects
Set oFSO = CreateObject("Scripting.FileSystemObject")
Set oShell = CreateObject("WScript.Shell")
Set oEnv = oShell.Environment("PROCESS")
Set oNetwork = CreateObject("WScript.Network")
Set objWMI = Nothing
On Error Resume Next
Set oContext = CreateObject("WbemScripting.SWbemNamedValueSet")
oContext.Add "__ProviderArchitecture", 64
Set oLocator = CreateObject("Wbemscripting.SWbemLocator")
Set objWMI = oLocator.ConnectServer("","root\cimv2","","",,,,oContext)
On Error Goto 0
Set dicNetworkConnections = CreateObject("Scripting.Dictionary")
dicNetworkConnections.CompareMode = TextCompare
Set oBDDUtility = Nothing
Set oSupportedPlatforms = Nothing
isHTML = FALSE
isWSH = FALSE
isMSHTA = FALSE
isCScript = FALSE
isWScript = FALSE
set oMSHTA = nothing
on error resume next
isHTML = IsObject(window.location)
isWSH = IsObject(WScript)
on error goto 0
If isHTML Then
isMSHTA = document.all.tags("Application").length > 0
On error resume next
set oMSHTA = document.all.tags("Application")(0)
if window.location.hostname <> "" then
sScriptDir = oFSO.GetParentFolderName( unescape("\\" & window.location.hostname & window.location.pathname ) )
else
sScriptDir = oFSO.GetParentFolderName( unescape(window.location.pathname) )
end if
On error goto 0
ElseIf isWSH Then
isCScript = ucase(right(WScript.FullName,len("Xscript.exe"))) = "CSCRIPT.EXE"
isWScript = ucase(right(WScript.FullName,len("Xscript.exe"))) = "WSCRIPT.EXE"
sScriptDir = oFSO.GetParentFolderName(WScript.ScriptFullName)
End if
If Mid(sScriptDir, 2, 2) = ":\" then
' Look to see if this is a mapped drive
On Error Resume Next
Set arrDrives = oNetwork.EnumNetworkDrives
If Err then
On Error Goto 0
oLogging.CreateEntry "ERROR - Network is unavailable: " & Err.Description & " (" & Err.Number & ")", LogTypeError
Else
On Error Goto 0
For i = 0 to arrDrives.Count - 1 Step 2
If arrDrives.Item(i) = UCase(Left(sScriptDir,2)) then
If Len(sScriptDir) > 3 then
sScriptDir = arrDrives.Item(i+1) & Mid(sScriptDir, 3)
Else
sScriptDir = arrDrives.Item(i+1)
End if
Exit For
End if
Next
End if
On Error Goto 0
End if
' By default, set a flag to cache the local root path
bCacheLocalRootPath = True
' Record times for heartbeat events
startTime = Now
lastHearbeat = startTime
End Sub
' *** Public methods ***
Public Sub PrepareEnvironment
Dim sArg
Set oLogging = New Logging
Set oEnvironment = New Environment
Set oStrings = New Strings
Set oFileHandling = New FileHandling
set Arguments = GetArguments
' Loop through all the parameters and turn them into environment variables. Enforce debug values.
On Error Resume Next
For each sArg in Arguments
If UCase(sArg) = "DEBUG" then
If UCase(Arguments(sArg)) = "TRUE" or UCase(Arguments(sArg)) = "FALSE" then
oLogging.CreateEntry "'debug' parameter was specified.", LogTypeInfo
Else
oLogging.CreateEntry "Invalid 'debug' parameter specified: " & Arguments(sArg), LogTypeError
WScript.Quit Failure
End if
oEnvironment.Item(sArg) = UCase(Arguments(sArg))
Else
oEnvironment.Item(sArg) = Arguments(sArg)
End if
Next
On Error Goto 0
Err.Clear
' Log the version
oLogging.CreateEntry "Microsoft Deployment Toolkit version: " & Version, LogTypeInfo
' Log where the SMSTS.LOG can be found
If oEnvironment.Item("_SMSTSLogPath") <> "" then
oEnvironment.SetDAT "SMSTSLogPath_Cache", oEnvironment.Item("_SMSTSLogPath")
oLogging.CreateEntry "The task sequencer log is located at " & oEnvironment.Item("_SMSTSLogPath") & "\SMSTS.LOG. For task sequence failures, please consult this log.", LogTypeInfo
End if
' Set a default for debug (if necessary)
If oEnvironment.Item("Debug") = "" then
oEnvironment.Item("Debug") = "FALSE"
End if
If UCase(oEnvironment.Item("Debug")) = "TRUE" then
oLogging.Debug = True
Else
oLogging.Debug = False
End if
If oEnvironment.Item("SLShareDynamicLogging") <> "" then
If oEnvironment.Item("UserID") <> "" and oEnvironment.Item("UserDomain") <> "" and oEnvironment.Item("UserPassword") <> "" then
If oFSO.FolderExists( LogPath ) then
oLogging.CreateEntry "Write all logging text to " & oEnvironment.Item("SLShareDynamicLogging") , LogTypeInfo
ValidateConnection oEnvironment.Item("SLShareDynamicLogging")
oUtility.VerifyPathExists oEnvironment.Item("SLShareDynamicLogging")
If not oFSO.FolderExists(oEnvironment.Item("SLShareDynamicLogging")) then
oLogging.CreateEntry "An invalid SLShareDynamicLogging value of " & oEnvironment.Item("SLShareDynamicLogging") & " was specified.", LogTypeWarning
Else
oLogging.NetworkLogging = oEnvironment.Item("SLShareDynamicLogging")
End if
End if
End if
End if
End Sub
' This function converts the string representation of a version "xx.xx.xx.xx" to int
' The function captures the version major/minor and build major/minor into Utility class variables.
' It can be accessed via properties Utility.VersionMajor and Utility.VersionMinor
' e.g.
' 1. GetMajorMinorVersion("10.0.12.1234") this will capture
' Utility.VersionMajor = 10 and Utility.VersionMinor = 0 (BuildMajor and BuildMinor are not yet exposed as properties but the function still captures it)
' 2. GetMajorMinorVersion("10.110")
' Utility.VersionMajor = 10 and Utility.VersionMinor = 110 (no BuildMajor and BuildMinor)
' in case of invalid string representation of version (e.g. GetMajorMinorVersion("Thisisfun") function will set values to Int.Max (32767)
Public Function GetMajorMinorVersion(sVersion)
Dim length
Dim splitArray
splitArray = Split(sVersion,".")
length = UBound(splitArray)
If length >=0 then
Select case length
Case 1
iVersionMinor = CInt(splitArray(1))
Case 2
iVersionMinor = CInt(splitArray(1))
iBuildNumber = CInt(splitArray(2))
Case 3
iVersionMinor = CInt(splitArray(1))
iBuildNumber = CInt(splitArray(2))
iRevision = CInt(splitArray(3))
Case Else
iVersionMinor = 32767
iBuildNumber = 32767
iRevision = 32767
End select
iVersionMajor = CInt(splitArray(0))
Else
iVersionMajor = 32767 'Int.Max for VbScript is 32767
iVersionMinor = 32767
iBuildNumber = 32767
iRevision = 32767
End if
End Function
' This function retrieves MSXML DOM document using MSXML2.DomDocument.6.0
' If it cannot load tries to get from MSXML2.DOMDocument.3.0
Public Function GetMSXMLDOMDocument
On Error Resume Next
Set GetMSXMLDOMDocument = CreateObject("MSXML2.DOMDocument.6.0")
If Err Then
Set GetMSXMLDOMDocument = CreateObject("MSXML2.DOMDocument")
End If
On Error Goto 0
End Function
Private Function GetArguments
Dim RegExObj
Dim Match
set RegExObj = New RegExp
RegExObj.Global = TRUE
RegExObj.Multiline = TRUE
RegExObj.IgnoreCase = TRUE
RegExObj.Pattern = "\/([^\ ""\:\=]+)(?:(?:[\:\=]""([^""]+)"")|(?:[\:\=]([^\ ""]+)))?"
if isWSH then
set GetArguments = wscript.arguments.Named
elseif isMSHTA and (not oMSHTA is nothing) then
Set GetArguments = CreateObject("Scripting.Dictionary")
GetArguments.CompareMode = vbTextCompare
for each Match in RegExObj.Execute(oMSHTA.CommandLine)
If not isempty(Match.submatches(0)) then
if not GetArguments.Exists(Match.submatches(0)) then
GetArguments.Add Match.submatches(0), Match.submatches(1) & Match.submatches(2)
End if
End if
next
elseif IsHTML then
Set GetArguments = CreateObject("Scripting.Dictionary")
GetArguments.CompareMode = vbTextCompare
for each Match in oStrings.ForceAsArray( window.location.search,"&")
If Instr(1,Match,"=",vbTextCompare) <> 0 then
If not GetArguments.Exists(left(Match,Instr(1,Match,"=",vbTextCompare)-1)) then
GetArguments.Add left(Match,Instr(1,Match,"=",vbTextCompare)-1), mid(Match,Instr(1,Match,"=",vbTextCompare)+1)
End if
End if
next
else
Set GetArguments = CreateObject("Scripting.Dictionary")
GetArguments.CompareMode = vbTextCompare
end if
End function
Function GetPA
GetPA = Replace(oShell.Environment("PROCESS")("Processor_Architecture"),"amd64","x64",1,-1,vbTextCompare)
end function
Public Function RunNewInstanceEx ( sClassName, sClassInstance, sMain )
Dim oScriptClass
Dim iScriptRc
' Disable On Error Resume next for advanced debugging
If not oUtility.Arguments.Exists("DebugCapture") then
On Error Resume next
End if
execute "Set " & sClassInstance & " = New " & sClassName
TestAndFail SUCCESS, 5400, "Create object: Set " & sClassInstance & " = New " & sClassName
If oUtility.Arguments.Exists("TestHook") then
' Hook for Unit Test code. Allows us to run Unit Tests without modification of the Original script.
oLogging.CreateEntry "Run Test Script [" & oUtility.Arguments.Item("TestHook") & "]...", LogTypeInfo
Execute oFSO.OpenTextFile(oUtility.Arguments.Item("TestHook")).ReadAll
oLogging.CreateEntry "Finished with Test Script! iScriptRc = " & iScriptRc, LogTypeInfo
End if
' Standard execution, call the main function in the created class.
iScriptRc = eval(sMain)
ProcessResults iScriptRc
Wscript.quit iScriptRc
end function
Function ConvertBooleanToString(bValue)
Dim iRetVal
iRetVal = Failure
If bValue = -1 Then
iRetVal = "True"
ElseIf bValue = 0 Then
iRetVal = "False"
End If
ConvertBooleanToString = iRetVal
End Function
Sub ResetLocalRootPath
sLocalRootPath = empty
End sub
Property Get CacheLocalRootPath
CacheLocalRootPath = bCacheLocalRootPath
End Property
Property Let CacheLocalRootPath(bNew)
bCacheLocalRootPath = bNew
End Property
Public Property Get VersionMajor
VersionMajor = iVersionMajor
End Property
Public Property Get VersionMinor
VersionMinor = iVersionMinor
End Property
Public Property Get BuildNumber
BuildNumber = iBuildNumber
End Property
Public Property Get RevisionNumber
RevisionNumber = iRevision
End Property
Property Get LocalRootPath
Dim sFallBack
If bCacheLocalRootPath and (not IsEmpty(sLocalRootPath)) then
LocalRootPath = sLocalRootPath ' Cache the value. Enumeration of Drives can be time expensive.
Exit property
End if
If oEnvironment.GetOSDV4("_SMSTSBootImageID") <> "" then
LocalRootPath = oEnvironment.GetOSDV4("_SMSTSMDataPath")
Else
LocalRootPath = ""
If oEnv("SystemDrive") = "X:" then
' We're in PE
sFallBack = "X:\MININT"
Else
' We're in a full OS
sFallBack = "C:\MININT"
End if
End if
' --------------------------------------------
If LocalRootPath = "" or IsEmpty(LocalRootPath) then
For each oDrive in oFSO.Drives
If oDrive.DriveType = 2 and oDrive.DriveLetter<>"X" then
If oDrive.IsReady Then
If OFSO.FolderExists(oDrive.DriveLetter & ":\MININT\SMSOSD\OSDLOGS") then
LocalRootPath = oDrive.DriveLetter & ":\MININT"
Exit For
End if
If oFSO.FolderExists(oDrive.DriveLetter & ":\_SMSTaskSequence") then
sFallBack = oDrive.DriveLetter & ":\MININT"
End if
End If
End if
Next
If LocalRootPath = "" or IsEmpty(LocalRootPath) then
LocalRootPath = sFallBack
End if
End if
' Make sure the root path exists
oUtility.VerifyPathExists LocalRootPath
' Cache the value
sLocalRootPath = LocalRootPath
End Property
Property Get BootDevice
BootDevice = UCase(oShell.Regread("HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SystemBootDevice"))
End Property
Property Get LogPath
If oEnvironment.GetOSDV4("_SMSTSBootImageID") <> "" then
LogPath = oEnvironment.GetOSDV4("_SMSTSLogPath")
Else
LogPath = LocalRootPath & "\SMSOSD\OSDLOGS"
End if
oUtility.VerifyPathExistsEx LogPath, False
End Property
Property Get StatePath
Dim sBasePath
' Always use the root of the drive.
sBasePath = "\"
' We want to store user state on the same volume as the OS.
If oEnv("SystemDrive") <> "X:" then
StatePath = oEnv("SystemDrive") & sBasePath & "StateStore"
Else
' We're offline, so try to use OSDWinPEWinDir, which should be set before reaching here
If oFSO.FolderExists(oEnvironment.Item("OSDWinPEWinDir")) then
' Use the drive that OSDWinPEWinDir points to
StatePath = Left(oEnvironment.Item("OSDWinPEWinDir"), 2) & sBasePath & "StateStore"
Else
' Fallback logic - put the folder on the local root path
StatePath = Left(LocalRootPath, 2) & sBasePath & "StateStore"
End if
End if
End Property
Property Get ScriptName
On Error Resume Next
ScriptName = oFSO.GetBaseName(Wscript.ScriptName)
If Err then
ScriptName = oFSO.GetBaseName(Unescape(window.location.pathname))
End if
On Error Goto 0
End Property
Property Get ScriptDir
ScriptDir = sScriptDir
End Property
Public Function ReadIni(file, section, item)
Dim line, equalpos, leftstring, ini
ReadIni = ""
file = Trim(file)
item = Trim(item)
On Error Resume Next
Set ini = oFSO.OpenTextFile( file, 1, False)
If Err then
Err.Clear
Exit Function
End if
On Error Goto 0
Do While (not ini.AtEndOfStream)
line = ini.ReadLine
line = oStrings.TrimAllWS(line)
If LCase(line) = "[" & LCase(section) & "]" and (not ini.AtEndOfStream) Then
line = ini.ReadLine
line = oStrings.TrimAllWS(line)
Do While Left( line, 1) <> "["
'If InStr( 1, line, item & "=", 1) = 1 Then
equalpos = InStr(1, line, "=", 1 )
If equalpos > 0 Then
leftstring = Left(line, equalpos - 1 )
leftstring = oStrings.TrimAllWS(leftstring)
If LCase(leftstring) = LCase(item) Then
ReadIni = Mid( line, equalpos + 1 )
ReadIni = oStrings.TrimAllWS(ReadIni)
Exit Do
End If
End If
If ini.AtEndOfStream Then Exit Do
line = ini.ReadLine
line = oStrings.TrimAllWS(line)
Loop
Exit Do
End If
Loop
ini.Close
End Function
Public Sub WriteIni( file, section, item, myvalue )
Dim in_section, section_exists, item_exists, wrote, itemtrimmed
Dim read_ini, write_ini, temp_ini, linetrimmed, line, equalpos
Dim leftstring
in_section = False
section_exists = False
item_exists = ( ReadIni( file, section, item ) <> "" )
wrote = False
file = Trim(file)
itemtrimmed = Trim(item)
myvalue = Trim(myvalue)
temp_ini = oFSO.GetParentFolderName(file) & "\" & oFSO.GetTempName
Set read_ini = oFSO.OpenTextFile( file, 1, True, False )
Set write_ini = oFSO.CreateTextFile( temp_ini, False)
While read_ini.AtEndOfStream = False
line = read_ini.ReadLine
linetrimmed = Trim(line)
If wrote = False Then
If LCase(line) = "[" & LCase(section) & "]" Then
section_exists = True
in_section = True
ElseIf InStr( line, "[" ) = 1 Then
in_section = False
End If
End If
If in_section Then
If itemtrimmed = "" then
' Do nothing: we want to wipe the section
ElseIf item_exists = False Then
write_ini.WriteLine line
If myvalue <> "" then
write_ini.WriteLine item & "=" & myvalue
End if
wrote = True
in_section = False
Else
equalpos = InStr(1, line, "=", 1 )
If equalpos > 0 Then
leftstring = Left(line, equalpos - 1 )
leftstring = Trim(leftstring)
If LCase(leftstring) = LCase(item) Then
If myvalue <> "" then
write_ini.WriteLine itemtrimmed & "=" & myvalue
End if
wrote = True
in_section = False
End If
End If
If Not wrote Then
write_ini.WriteLine line
End If
End If
Else
write_ini.WriteLine line
End If
Wend
If section_exists = False and itemtrimmed <> "" Then ' section doesn't exist
write_ini.WriteLine
write_ini.WriteLine "[" & section & "]"
If myvalue <> "" then
write_ini.WriteLine itemtrimmed & "=" & myvalue
End if
End If
read_ini.Close
write_ini.Close
If oFSO.FileExists(file) then
oFSO.DeleteFile file, True
End if
oFSO.CopyFile temp_ini, file, true
oFSO.DeleteFile temp_ini, True
End Sub
Public Function Sections(file)
Dim oContents
Dim line, equalpos, leftstring, ini
Set oContents = CreateObject("Scripting.Dictionary")
file = Trim(file)
On Error Resume Next
Set ini = oFSO.OpenTextFile( file, 1, False)
If Err then
Err.Clear
Exit Function
End if
On Error Goto 0
Do While ini.AtEndOfStream = False
line = ini.ReadLine
line = Trim(line)
If Left(line,1) = "[" then
equalpos = Instr(line, "]")
leftstring = Mid(line, 2, equalpos - 2)
oContents.Add leftstring, ""
End if
Loop
Set Sections = oContents
End Function
Public Function SectionContents(file, section)
Dim oContents
Dim line, equalpos, leftstring, ini
Set oContents = CreateObject("Scripting.Dictionary")
file = Trim(file)
section = Trim(section)
On Error Resume Next
Set ini = oFSO.OpenTextFile( file, 1, False)
If Err then
Err.Clear
Exit Function
End if
On Error Goto 0
Do While ini.AtEndOfStream = False
line = ini.ReadLine
line = Trim(line)
If LCase(line) = "[" & LCase(section) & "]" Then
line = ini.ReadLine
line = Trim(line)
Do While Left( line, 1) <> "["
'If InStr( 1, line, item & "=", 1) = 1 Then
equalpos = InStr(1, line, "=", 1 )
If equalpos > 0 Then
leftstring = Left(line, equalpos - 1 )
leftstring = Trim(leftstring)
oContents(leftstring) = Trim(Mid(line, equalpos + 1 ))
End If
If ini.AtEndOfStream Then Exit Do
line = ini.ReadLine
line = Trim(line)
Loop
Exit Do
End If
Loop
ini.Close
Set SectionContents = oContents
End Function
Function RegReadEx ( sRegValue, bError )
on error resume next
RegReadEx = oShell.Regread( sRegValue )
If bError then
TestAndLog not isempty(RegReadEx), "ReadRead(" & sRegValue & ")"
End if
on error goto 0
End function
Function RegWriteEx ( sKey, sValue, bError )
on error resume next
if VarType(sValue) = vbString then
RegWriteEx = oShell.RegWrite ( sKey, sValue, "REG_SZ" )
elseif VarType(sValue) = vbInteger or VarType(sValue) = vbLong or VarType(sValue) = vbBoolean then
RegWriteEx = oShell.RegWrite ( sKey, sValue, "REG_DWORD" )
end if
If bError then
TestAndLog (err = 0), "RegWriteEx( " & sKey & " , " & sValue & " , REG_Type )"
End if
on error goto 0
End function
Function RegRead( sRegValue )
RegRead = RegReadEx(sRegValue, True)
end Function
Function RegWrite ( sKey, sValue )
RegWrite = RegWriteEx(sKey, sValue, True)
end Function
Function SafeSleep ( iTime )
On error resume next
WScript.Sleep iTime
On error goto 0
End function
' ---------------------------------------------------------------
Function RunCommandLog( oExec, fExternalHook, iLimit )
Dim HeartbeatStart
Dim iMinutes
Dim iHeartBeat
Dim iLastProgress
Dim iResult
' Initialize the last heartbeat time (start the timer) and interval
HeartbeatStart = Now
iLastProgress = 0
iResult = SUCCESS
' Main Processing Loop
do while oExec.Status = 0
' See if it is time for a heartbeat
iMinutes = DateDiff("n", HeartbeatStart, now )
If iMinutes >= iLimit and iLimit <> -1 and VarType(iLimit) = 2 then
oLogging.CreateEvent 41009, LogTypeError, "Command has been running for " & CStr(iMinutes) & " minutes (process ID " & oExec.ProcessID & "). Now over limit!", Array(iMinutes)
RunCommandLog = False
exit function
End if
Heartbeat "ZTI Heartbeat: command has been running for " & CStr(iMinutes) & " minutes (process ID " & oExec.ProcessID & ")"
If IsNull(fExternalHook) then
SafeSleep 100
Else
SafeSleep 1
If VarType(fExternalHook) = 9 then
iResult = fExternalHook(oExec, iLastProgress) ' fExternal Hook is a GetRef( function )
ElseIf VarType(fExternalHook) = 8 then
iResult = execute( fExternalHook ) ' fExternalHook is a string function
Else
iResult = StandardConsoleProcessing(oExec, iLastProgress) ' Do standard processing
End if
If iResult <> SUCCESS then
Exit do
End if
End if
loop
If IsNull(fExternalHook) or iResult <> SUCCESS then
SafeSleep 100
Else
' Jump to the end of the sub-progress if started
If not IsEmpty(iLastProgress) and iLastProgress > 9 and iLastProgress < 91 then
oLogging.ReportProgress "process ID " & oExec.ProcessID & " Finished ", 100
End if
If VarType(fExternalHook) = 9 then
iResult = fExternalHook(oExec, iLastProgress) ' fExternal Hook is a GetRef( function )
ElseIf VarType(fExternalHook) = 8 then
iResult = execute( fExternalHook ) ' fExternalHook is a string function
Else
iResult = StandardConsoleProcessing(oExec, iLastProgress) ' Do standard processing
End if
End if
' Return the exit code to the caller
oLogging.CreateEntry "Return code from command = " & oExec.ExitCode, LogTypeInfo
RunCommandLog = oExec.ExitCode
End function
Function Heartbeat(sMessage)
Dim iMinutes
If DateDiff("n", lastHeartbeat, Now ) >= 5 then
lastHeartbeat = Now
iMinutes = DateDiff("n", startTime, lastHeartbeat)
oLogging.CreateEvent 41003, LogTypeInfo, sMessage, Array(iMinutes)
End if
End function
Function StandardConsoleProcessing ( oExec, byRef iLastProgress )
Dim sLines
Dim sLine
Dim oMatch
StandardConsoleProcessing = SUCCESS
Do Until oExec.StdOut.atEndOfStream
sLines = oExec.StdOut.ReadLine
if vartype(sLines) = 8 then
For each sLine in split(sLines,vbNewLine)
If asc(mid(sline,1,1)) = 0 then
sLine = replace(sLine,chr(0),"") ' Quick and dirty Unicode to ANSI fix.
End if
oLogging.CreateEntry " Console > " & sLine, LogTypeInfo
if oExec.Status = 0 then
' If the output contains a percentage, then interpret it a status.
' Check for DISM-style progress
Set oMatch = oRegEx.GetRegExMatches("([01]?[0-9]?[0-9])\.[0-9]\%",sLine)
If oMatch.Count > 0 then
iLastProgress = cint(oMatch(oMatch.Count -1).SubMatches(0))
oLogging.ReportProgress sLine, iLastProgress
Else
' Check for "other" percentage
set oMatch = oRegEx.GetRegExMatches("([01]?[0-9]?[0-9]) ?\%",sLine)
If oMatch.Count > 0 then
iLastProgress = cint(oMatch(oMatch.Count -1).SubMatches(0))
oLogging.ReportProgress sLine, iLastProgress
End if
End if
End if
Next
End if
if oExec.Status = 0 then
Exit Function
End if
Loop
if oExec.Status <> 0 then
StandardConsoleProcessing = FAILURE
Else
do until oExec.StdErr.atEndOfStream
sLines = oExec.StdErr.ReadAll
if vartype(sLine) = 8 then
For each sLine in split(sLines,vbNewLine)
If asc(mid(sline,1,1)) = 0 then
sLine = replace(sLine,chr(0),"") ' Quick and dirty Unicode to ANSI fix.
End if
oLogging.CreateEntry " Console # " & sLine, LogTypeError
Next
End if
loop
End if
End Function
Function StandardFileProcessing ( oExec, ByRef iLastProgress, sExternalLogFile )
Dim oMatch
If oExec.Status = 0 then
If oFSO.FileExists(sExternalLogFile) then
set oMatch = oRegEx.GetRegExMatchesFromFile(sProgress,sExternalLogFile)
If oMatch.Count > 0 then
If cint(oMatch(oMatch.Count - 1).SubMatches(0)) > iLastProgress then
iLastProgress = cint(oMatch(oMatch.Count - 1).SubMatches(0))
oLogging.ReportProgress "Progress [" & sExternalLogFile & "] ... " & iLastProgress & "%", iLastProgress
exit function
End if
End if
End if
End if
oUtility.SafeSleep 100
End function
Function RunCommandStart(sCmd, aInput)
Dim oExec
Dim sLine
' Start the command
oLogging.CreateEntry "About to run command: " & sCmd, LogTypeInfo
Set oExec = oShell.Exec(sCmd)
oLogging.CreateEntry "Command has been started (process ID " & oExec.ProcessID & ")", LogTypeInfo
' Log any input lines
If isArray( aInput ) then
For each sLine in aInput
RunCommandWrite oExec, sLine
next
End if
set RunCommandStart = oExec
End function
Function RunCommandWrite( oExec, sCommand )
If sCommand <> "" then
oLogging.CreateEntry " Console + " & sCommand, LogTypeInfo
oExec.stdIn.WriteLine sCommand
End if
End function
Function RunCommandEx(sCmd, aInput, fExternalHook, iLimit )
Dim oExec
' Start the command
set oExec = RunCommandStart(sCmd, aInput)
SafeSleep 500
' Wait for the results
RunCommandEx = RunCommandLog (oExec, fExternalHook, iLimit )
End function
Function RunWithHeartbeat(sCmd)
RunWithHeartbeat = RunCommandEx(sCmd, null, null, -1)
End function
Function RunWithConsoleLogging(sCmd)
RunWithConsoleLogging = RunCommandEx(sCmd, empty, empty, -1)
End function
Function RunWithConsoleLoggingAndHidden(sCmd)
Dim iRC
Dim sScriptFile
iRC = oUtility.FindFile( "ztiRunCommandHidden.wsf", sScriptFile )
TestAndLog iRC, "Verify ztiRunCommandHidden.wsf is in the path"
If iRC = Success then
RunWithConsoleLoggingAndHidden = RunCommand ( "cscript.exe //nologo """ & sScriptFile & """ """ & sCmd & """", 0, True)
Else
oLogging.CreateEntry "Visible console fallback." , LogTypeInfo
RunWithConsoleLoggingAndHidden = oUtility.RunWithConsoleLogging( sCmd )
End if
End function
Function FindExeAndRunWithLogging( sCmd, sParameters )
Dim iRC
Dim sFoundFile
iRC = oUtility.FindFile ( sCmd, sFoundFile )
TestAndFail iRC, 5441, "FindFile: " & sCmd
FindExeAndRunWithLogging = RunWithConsoleLogging( """" & sFoundFile & """ " & sParameters )
End function
Function FindExeAndRun( sCmd, sParameters )
Dim iRC
Dim sFoundFile
iRC = oUtility.FindFile ( sCmd, sFoundFile )
TestAndFail iRC, 5442, "FindFile: " & sCmd
FindExeAndRun = RunWithHeartbeat( """" & sFoundFile & """ " & sParameters )
End function
Function RunCommand ( sCmd, iWindowStyle, bWaitOnReturn )
oLogging.CreateEntry "About to run command: " & sCmd, LogTypeInfo
RunCommand = oShell.Run ( sCmd, iWindowStyle, bWaitOnReturn )
oLogging.CreateEntry "Command has returned: " & RunCommand, LogTypeInfo
End Function
Function ComputerName
Dim re
Dim sComputer
Set re = New RegExp
' Figure out the computer name to include
If oEnvironment.Item("_SMSTSMachineName") <> "" then
If oEnvironment.Item("OSDCOMPUTERNAME") <> "" and Instr(oEnvironment.Item("OSDCOMPUTERNAME"),":") = 0 then
sComputer = oEnvironment.Item("OSDComputerName")
Else
sComputer = oEnvironment.Item("_SMSTSMachineName")
End If
ElseIf oEnvironment.Item("OSDCOMPUTERNAME") <> "" and Instr(oEnvironment.Item("OSDCOMPUTERNAME"),":") = 0 then
sComputer = oEnvironment.Item("OSDCOMPUTERNAME")
ElseIf oEnvironment.Item("OSDNEWMACHINENAME") <> "" then
oEnvironment.Item("OSDComputerName") = oEnvironment.Item("OSDNEWMACHINENAME")
sComputer = oEnvironment.Item("OSDCOMPUTERNAME")
ElseIf oEnvironment.Item("ComputerName") <> "" then
oEnvironment.Item("OSDComputerName") = oEnvironment.Item("ComputerName")
sComputer = oEnvironment.Item("OSDComputerName")
ElseIf oEnvironment.Item("OSVersion") = "WinPE" and oEnvironment.Item("OSDCOMPUTERNAME") <> "" then
sComputer = oEnvironment.Item("OSDCOMPUTERNAME")
re.Pattern = ":"
sComputer = re.Replace(sComputer, "")
Else
sComputer = oEnvironment.Item("HostName")
End if
ComputerName = oEnvironment.Substitute(sComputer)
End Function
Function FindFile(sFilename, sFoundPath)
Dim iRetVal
Dim sDir
iRetVal = Failure
sFoundPath = ""
' Look through the standard locations
If oEnvironment.Item("DeployRoot") <> "" then
For each sDir in Array("\", "\Tools\", "\Servicing\", "\Scripts\", "\Control\", "\Templates\", "\x86\", "\amd64\")
If oFSO.FileExists(oEnvironment.Item("DeployRoot") & sDir & sFileName) then
sFoundPath = oEnvironment.Item("DeployRoot") & sDir & sFileName
iRetVal = Success
Exit For
ElseIf oEnvironment.Item("Architecture") <> "" and oFSO.FileExists(oEnvironment.Item("DeployRoot") & sDir & oEnvironment.Item("Architecture") & "\" & sFileName) then
sFoundPath = oEnvironment.Item("DeployRoot") & sDir & oEnvironment.Item("Architecture") & "\" & sFileName
iRetVal = Success
Exit For
' oEnvironment.Item("Architecture") *can* be blank, search in the %Processor_Architecture% directory.
ElseIf ucase(oEnv("Processor_Architecture")) = "AMD64" and oFSO.FileExists(oEnvironment.Item("DeployRoot") & sDir & "x64\" & sFileName) then
sFoundPath = oEnvironment.Item("DeployRoot") & sDir & "x64\" & sFileName
iRetVal = Success
Exit For
ElseIf oFSO.FileExists(oEnvironment.Item("DeployRoot") & sDir & oEnv("Processor_Architecture") & "\" & sFileName) then
sFoundPath = oEnvironment.Item("DeployRoot") & sDir & oEnv("Processor_Architecture") & "\" & sFileName
iRetVal = Success
Exit For
End if
Next
End if
If sFoundPath <> "" then
FindFile = iRetVal
Exit Function
End if
' Check resource root locations (normally OSD only)
If oEnvironment.Item("ResourceRoot") <> "" and oEnvironment.Item("ResourceRoot") <> oEnvironment.Item("DeployRoot") then
For each sDir in Array("\", "\Tools\", "\Servicing\", "\Scripts\", "\Templates\", "\Control\")
If oFSO.FileExists(oEnvironment.Item("ResourceRoot") & sDir & sFileName) then
sFoundPath = oEnvironment.Item("ResourceRoot") & sDir & sFileName
iRetVal = Success
Exit For
ElseIf oFSO.FileExists(oEnvironment.Item("ResourceRoot") & sDir & oEnvironment.Item("Architecture") & "\" & sFileName) then
sFoundPath = oEnvironment.Item("ResourceRoot") & sDir & oEnvironment.Item("Architecture") & "\" & sFileName
iRetVal = Success
Exit For
End if
Next
End if
If sFoundPath <> "" then
FindFile = iRetVal
Exit Function
End if
' Now look in the log directory, this directory, working directory, and SYSTEM32 directory
If oFSO.FileExists(oUtility.LogPath & "\" & sFilename) then
sFoundPath = oUtility.LogPath & "\" & sFilename
iRetVal = Success
ElseIf oFSO.FileExists(oUtility.ScriptDir & "\" & sFilename) then
sFoundPath = oUtility.ScriptDir & "\" & sFilename
iRetVal = Success
ElseIf oFSO.FileExists(oUtility.LocalRootPath & "\" & sFileName) then
sFoundPath = oUtility.LocalRootPath & "\" & sFileName
iRetVal = Success
ElseIf oFSO.FileExists(".\" & sFileName) then
sFoundPath = oShell.CurrentDirectory & "\" & sFilename
iRetVal = Success
ElseIf oFSO.FileExists(oEnvironment.Substitute("%WINDIR%\SYSNATIVE\" & sFilename)) then
sFoundPath = oEnvironment.Substitute("%WINDIR%\SYSNATIVE\" & sFilename)
iRetVal = Success
ElseIf oFSO.FileExists(oEnvironment.Substitute("%WINDIR%\SYSTEM32\" & sFilename)) then
sFoundPath = oEnvironment.Substitute("%WINDIR%\SYSTEM32\" & sFilename)
iRetVal = Success
ElseIf oEnvironment.Item("OSDPACKAGEPATH") <> "" and oFSO.FileExists(oEnvironment.Item("OSDPACKAGEPATH") & "\" & sFilename) then
sFoundPath = oEnvironment.Item("OSDPACKAGEPATH") & "\" & sFilename
iRetVal = Success
ElseIf oEnvironment.Item("_SMSTSPackagePath") <> "" and oFSO.FileExists(oEnvironment.Item("_SMSTSPackagePath") & "\" & sFilename) then
sFoundPath = oEnvironment.Item("_SMSTSPackagePath") & "\" & sFilename
iRetVal = Success
ElseIf oFSO.FileExists(".\x86\" & sFileName) then
sFoundPath = oShell.CurrentDirectory & "\x86\" & sFilename
iRetVal = Success
ElseIf oFSO.FileExists(".\x64\" & sFileName) then
sFoundPath = oShell.CurrentDirectory & "\x64\" & sFilename
iRetVal = Success
ElseIf oFSO.FileExists(".\amd64\" & sFileName) then
sFoundPath = oShell.CurrentDirectory & "\amd64\" & sFilename
iRetVal = Success
ElseIf oFSO.FileExists(sFileName) then
sFoundPath = sFilename
iRetVal = Success
End if
If iRetVal <> Success then
oLogging.CreateEntry "FindFile: The file " & sFilename & " could not be found in any standard locations.", LogTypeInfo
End if
FindFile = iRetVal
End Function
Function FindMappedDrive(sServerUNC)
Dim arrSplit
Dim sServerShare, sServerName
Dim arrDrives, i
' If the UNC isn't a UNC, just return the drive letter
If Len(sServerUNC) < 3 then
FindMappedDrive = ""
EXIT FUNCTION
End if
If Mid(sServerUNC,2,2) = ":\" then
FindMappedDrive = Left(sServerUNC, 2)
EXIT FUNCTION
End if
' Build the UNC
If Instr(Mid(sServerUNC, 3), "\") <= 0 or Left(sServerUNC, 2) <> "\\" then
FindMappedDrive = ""
EXIT FUNCTION
End if
arrSplit = Split(Mid(sServerUNC,3), "\",2)
sServerName = arrSplit(0)
sServerShare = "\\" & sServerName & "\" & arrSplit(1)
' Look to see if this is a mapped drive
On Error Resume Next
Set arrDrives = oNetwork.EnumNetworkDrives
If Err then
FindMappedDrive = ""
Exit Function
Else
On Error Goto 0
For i = 0 to arrDrives.Count - 1 Step 2
If UCase(sServerShare) = UCase(arrDrives.Item(i+1)) and arrDrives.Item(i) <> "" then
FindMappedDrive = arrDrives.Item(i)
Exit Function
End if
Next
End if
On Error Goto 0
FindMappedDrive = ""
End Function
Function ValidateConnection(sServerUNC)
ValidateConnection = ValidateConnectionEx(sServerUNC, False)
End function
Function GetNextNAACred(Index)
Dim iMaxNumLength
Dim sNumberAsString
Dim sNAAName
Dim sNAAPass
iMaxNumLength = 3
sNAAName = "_SMSTSReserved1-"
sNAAPass = "_SMSTSReserved2-"
If Index <= 0 Then
sNumberAsString = "000"
Else
sNumberAsString = String(iMaxNumLength - Fix(Log(Fix(Index)) / Log(10)) - 1, "0") & CStr(Fix(Index))
End If
sNAAName = sNAAName & sNumberAsString
sNAAPass = sNAAPass & sNumberAsString
If oEnvironment.Item(sNAAName) <> "" AND oEnvironment.Item(sNAAPass) <> "" Then
OEnvironment.Item("UserDomain") = Left(oEnvironment.Item(sNAAName),Instr(oEnvironment.Item(sNAAName),"\")-1)
oEnvironment.Item("UserID")= Mid(oEnvironment.Item(sNAAName),Instr(oEnvironment.Item(sNAAName),"\")+1)
oEnvironment.Item("UserPassword")=oEnvironment.Item(sNAAPass)
GetNextNAACred = True
Else
GetNextNAACred = False
End if
End Function
Function ValidateConnectionEx(sServerUNC, bForceConnection)
Dim iRetVal
Dim arrSplit
Dim sServerShare, sServerName, sFoundDrive
Dim sOSDConnectToUNC, sRIPInfo, sCmd
Dim sWizardHTA, sUserID
Dim sCurrentServerName, i
' Make sure a UNC is specified
If sServerUNC = "" then
oLogging.CreateEntry "WARNING - Unable to validation connection because a blank UNC was specified.", LogTypeWarning
ValidateConnectionEx = Failure
EXIT FUNCTION
End if
If Mid(sServerUNC,2,2) = ":\" then
oLogging.CreateEntry "Using a local or mapped drive, no connection is required.", LogTypeInfo
ValidateConnectionEx = Success
EXIT FUNCTION
End if
oLogging.CreateEntry "Validating connection to " & sServerUNC, LogTypeInfo
iRetVal = ValidateNetworkConnectivity
If iRetVal <> Success then
'blow up
ValidateConnectionEx = Failure
Exit Function
End IF
' See if we've already connected
If bForceConnection then
' When forcing a connection, map all the way down to the specified folder
arrSplit = Split(Mid(sServerUNC,3), "\", 2)
Else
' When not forcing, split into more chunks so we only get server and share
arrSplit = Split(Mid(sServerUNC,3), "\")
End if
sServerName = arrSplit(0)
sServerShare = "\\" & sServerName & "\" & arrSplit(1)
oLogging.CreateEntry "Mapping server share: " & sServerShare, LogTypeInfo
' This isn't necessary if we're trying to connect to the current DP, so check that.
If Left(oUtility.ScriptDir, 2) = "\\" then
arrSplit = Split(Mid(oUtility.ScriptDir, 3), "\")
sCurrentServerName = arrSplit(0)
If UCase(sServerName) = UCase(sCurrentServerName) then
oLogging.CreateEntry "Already connected to server " & sServerName & " as that is where this script is running from.", LogTypeInfo
If bForceConnection then
' We want a mapped drive in this case, without credentials because we are already connected
If MapNetworkDrive(sServerShare, "", "") <> Success then
oLogging.CreateEntry "Unable to map a drive to the deployment share.", LogTypeInfo
End if
End if
ValidateConnectionEx = Success
EXIT FUNCTION
End if
End if
' Now see if there is already a server connection.
' We may wish to use bForceConnection if we *Require* the Drive letter,
' even though the computer may be connected to the sever via another share.
If dicNetworkConnections.Exists(sServerName) and not bForceConnection then
oLogging.CreateEntry "Already connected to server " & sServerName, LogTypeInfo
ValidateConnectionEx = Success
EXIT FUNCTION
End if
'Map the SCCM user variables to the CS.INI variables
GetNextNAACred 0 'Attempt to get first NAA info
' It is possible that the server allows anonymous connections, skip if the share is readable.
'if oFso.FolderExists(sServerName) then
' oLogging.CreateEntry "Already connected to server " & sServerName, LogTypeInfo
' ValidateConnectionEx = Success
' EXIT FUNCTION
'end if
' If no credentials are available, prompt. (Only works in WinPE)
If oEnvironment.Item("UserID") = "" or oEnvironment.Item("UserPassword") = "" or ( oEnvironment.Item("UserDomain") = "" and _
instr(1,oEnvironment.Item("UserID"),"\",vbTextCompare) = 0 and instr(1,oEnvironment.Item("UserID"),"@",vbTextCompare) = 0 ) then
' Find the HTA that prompts for credentials
iRetVal = FindFile("Wizard.hta", sWizardHTA)
If iRetVal <> Success then
oLogging.CreateEntry "ERROR - Unable to find Wizard.hta, so it is impossible to prompt for credentials.", LogTypeError
ValidateConnectionEx = Failure
Exit Function
End if
' Execute the HTA
oShell.Run "mshta.exe """ & sWizardHTA & """ /NotWizard /LeaveShareOpen /ValidateAgainstUNCPath:""" & sServerShare & """ /Definition:Credentials_ENU.xml", 1, true
' See if the values are populated now
If oEnvironment.Item("UserID") = "" then
oLogging.CreateEntry "ERROR - no credentials were returned from LTICredentials.hta, so no connection is possible.", LogTypeError
ValidateConnectionEx = Failure
Exit Function
End if
End if
' Map a drive
Dim iTryIteration
Dim bAnotherNAA
iTryIteration = 1
bAnotherNAA = True
Do
If oEnvironment.Item("UserDomain") <> "" then
sUserID = oEnvironment.Item("UserDomain") & "\" & oEnvironment.Item("UserID")
Else
sUserID = oEnvironment.Item("UserID")
End if
For i = 1 to 5
If MapNetworkDrive(sServerShare, sUserID, oEnvironment.Item("UserPassword")) = Success then
Exit for
End If
oLogging.CreateEntry "Unable to connect to " & sServerShare & ". Sleeping for " & CStr(i * 5) & " seconds.", LogTypeInfo
On error Resume next
WScript.Sleep i * 5000
on error goto 0
Next
If IsNetworkDriveMapped(sServerShare) = True Then Exit Do
'After 5 failures, try another account
bAnotherNAA = GetNextNAACred(iTryIteration)
iTryIteration = iTryIteration + 1
If Not bAnotherNAA Then
oLogging.CreateEntry "ERROR - Unable to map a network drive to " & sServerShare & ".", LogTypeError
ValidateConnectionEx = Failure
Exit Function
End If
Loop While bAnotherNAA = True
' Record the mapped drive
oLogging.CreateEntry "Successfully established connection using supplied credentials.", LogTypeInfo
If not dicNetworkConnections.Exists(sServerName) then
dicNetworkConnections.Add sServerName, sServerShare
End if
iRetVal = Success
ValidateConnectionEx = iRetVal
End Function
Function ValidateNetworkConnectivity
Dim Entity, ID, oAdapter, oAdapter2, colAdapters, colAdapters2, sIPConnectionMetric, sWirelessConnectionMetric
Dim bValidIP
' Check for networkadapters present
bValidIP = True
If objWMI.ExecQuery("select * from win32_NetworkAdapter where Installed = true and adaptertypeid = 0").Count = 0 then
oLogging.CreateEntry "No networking adapters found, The network drivers for your device are not present",LogTypeError
ValidateNetworkConnectivity = Failure
exit function
End if
'Check for IP address
Set colAdapters = objWMI.ExecQuery("select * from win32_NetworkAdapterConfiguration where IPEnabled=True")
For Each oAdapter in colAdapters
If oAdapter.DHCPEnabled = TRUE Then
If oAdapter.DHCPServer = "255.255.255.255" Then
bValidIP = False
Else
bValidIP = True
Exit For
End if
Else
oLogging.CreateEntry "DHCP is not enabled, assuming static IP address", LogTypeInfo
bValidIP = True
Exit For
End if
Next
If bValidIP <> True Then
'No IP Address, do an ipconfig /renew
oShell.Run "ipconfig /renew",0,true
on error resume next
wscript.sleep 5000
on error goto 0
Set colAdapters2 = objWMI.ExecQuery("select * from win32_NetworkAdapterconfiguration where IPEnabled = True")
For Each oAdapter2 in colAdapters2
If oAdapter2.DHCPEnabled = TRUE Then
If oAdapter2.DHCPServer = "255.255.255.255" Then
oLogging.CreateEntry "IP Address could not be obtained",LogTypeError
ValidateNetworkConnectivity = Failure
Exit Function
Else
Exit for
End if
End if
Next
End If
'Check for wireless connectivity
Set colAdapters = objWMI.ExecQuery("select * from win32_NetworkAdapterconfiguration where IPEnabled = True")
For Each oAdapter in colAdapters
If Instr(UCase(oAdapter.Caption),"WIRELESS") = 0 Then
If oAdapter.IPConnectionMetric < sIPConnectionMetric Or sIPConnectionMetric = "" Then
sIPConnectionMetric = oAdapter.IPConnectionMetric
End If
End IF
If Instr(UCase(oAdapter.Caption),"WIRELESS") Then
sWirelessConnectionMetric = oAdapter.IPConnectionMetric
End If
Next
If sIPConnectionMetric = "" Then
oLogging.CreateEntry "No physical adapters present, cannot deploy over wireless", LogTypeError
ValidatenetworkConnectivity = Failure
Exit Function
End IF
'TODO Check for VPN connectivity
ValidateNetworkConnectivity = Success
End Function
Function IsNetworkDriveMapped(sShare)
IsNetworkDriveMapped = False
If IsEmpty(sShare) Or IsNull(sShare) Or TypeName(sShare) = "Nothing" Then
oLogging.CreateEntry "Specified network path is null or invalid.", LogTypeError
Exit Function
End if
Dim i
Dim arrDrives
On Error Resume Next
Set arrDrives = oNetwork.EnumNetworkDrives
If Err then
oLogging.CreateEntry "Unable to enumerate network drives (is the network initialized?): " & Err.Description & " (" & Err.Number & ")", LogTypeWarning
Else
' Find any previous connections (skip connections without drive letters)
For i = 0 to arrDrives.Count - 1 Step 2
If UCase(sShare) = UCase(arrDrives(i+1)) and arrDrives(i) <> "" then
IsNetworkDriveMapped = True
oLogging.CreateEntry "Found Existing UNC Path " & arrDrives(i) & " = " & sShare , LogTypeInfo
Exit function
End if
Next
End if
End Function
' For Backwards Compatiblity
Function MapNetworkDrive (sShare, sDomID, sDomPwd )
' Make sure networking is initialized
If IsNetworkDriveMapped(sShare) Then
MapNetworkDrive = Success
Exit Function
End If
If Len(MapNetworkDriveEx (sShare, sDomID, sDomPwd, LogTypeError )) = 2 then
MapNetworkDrive = Success
Else
MapNetworkDrive = Failure
End if
End function
'
' maps a drive letter to the sShare UNC path.
' Returns the drive letter example: "C:", otherwise returns an error string!
' sDomID and sDomPwd can be EMPTY.
'
Function MapNetworkDriveEx (sShare, sDomID, sDomPwd, iLogType )
Dim sDrive
Dim HasError
Dim ErrDesc
Dim i
On Error Goto 0
' Find the first available drive letter
For sDrive = asc("Z") to asc("C") step -1
On Error Resume Next
If sDomID <> "" and sDomPwd <> "" then
oNetwork.MapNetworkDrive chr(sDrive)&":", sShare, False, sDomID, sDomPwd
Else
oNetwork.MapNetworkDrive chr(sDrive)&":", sShare, False
End if
HasError = err.number
ErrDesc = err.Description
On Error Goto 0
Select case HasError
Case 0 ' No Error, SUCCESS
MapNetworkDriveEx = chr(sDrive)&":"
oLogging.CreateEntry "Mapped Network UNC Path " & MapNetworkDriveEx & " = " & sShare , LogTypeInfo
Exit function
Case &h80070055 ' The local device name is already in use.
Case &h800704B2 ' The local device name has a remembered connection to another network resource.
' Case &h800704C3 ' Multiple connections to a server or shared resource by the same user, using more than one user name, are not allowed.
' Case &h8007052E ' Logon failure: unknown user name or bad password.
Case Else
oLogging.CreateEntry "Unable to connect to share: " & ErrDesc & "( 0x" & hex(HasError) & " ) , trying to connect without username. ", LogTypeInfo
Err.Clear
On Error Resume Next
oNetwork.MapNetworkDrive chr(sDrive)&":", sShare, False
HasError = err.number
ErrDesc = err.Description
On Error Goto 0
If HasError <> 0 Then
' There was a some kind of fatal error.
If ErrDesc <> "" then
MapNetworkDriveEx = ErrDesc
Else
MapNetworkDriveEx = "Unable to map UNC Path " & sShare & " :" & "( 0x" & hex(HasError) & " ) "
End if
oLogging.CreateEntry MapNetworkDriveEx & "", iLogType
Exit function
Else
MapNetworkDriveEx = chr(sDrive)&":"
Exit Function
End If
End select
Next
MapNetworkDriveEx = "Unable to map UNC Path " & sShare & " : No available local device names! "
oLogging.CreateEntry MapNetworkDriveEx , iLogType
End function
Public Function VerifyPathExistsEx(strPath, bAdjustSD)
Dim oHelper, sSDDL, oLogicalFile, oDescriptor
If strPath = "" then
VerifyPathExistsEx = True
Exit Function
End if
If oFSO.FolderExists(strPath) then
VerifyPathExistsEx = true
Exit Function
Else
VerifyPathExists oFSO.GetParentFolderName(strPath)
On Error Resume Next
oFSO.CreateFolder strPath
'Set Permissions if it is not a UNC path
If Left(strPath, 2) <> "\\" and bAdjustSD Then
strPath = Replace(strPath, "\", "\\")
Set oHelper = objWMI.Get("Win32_SecurityDescriptorHelper")
sSDDL = "O:BAG:SYD:PAI(A;OICI;FA;;;BA)(A;OICI;FA;;;SY)"
oHelper.SDDLToWin32SD sSDDL, oDescriptor
Set oLogicalFile = objWMI.Get("Win32_LogicalFileSecuritySetting.Path='" & strPath & "'")
TestAndLog oLogicalFile.SetSecurityDescriptor(oDescriptor), "Set security on folder " & strPath
End If
On Error Goto 0
End if
End function
Public Function VerifyPathExists(strPath)
VerifyPathExists = VerifyPathExistsEx(strPath, false)
End Function
Function GetAllFixedDrives(bReturnOnlyBootable)
Dim oWMIDiskPart
Dim oDiskPart
Dim oDisk
oLogging.CreateEntry "ZTIUtility!GetAllFixedDrives (" & bReturnOnlyBootable & ")", LogTypeInfo
for each oWMIDiskPart in AllDiskPart
set oDiskPart = new ZTIDiskPartition
set oDiskPart.DiskPart = oWMIDiskPart
set oDisk = oDiskPart.GetDiskObject
If oDisk.IsOSReady("0.0.0.0") then
GetAllFixedDrives = GetAllFixedDrives & " " & oDiskPart.Drive
End if
next
oLogging.CreateEntry "ZTIUtility!GetAllFixedDrives = " & GetAllFixedDrives, LogTypeInfo
GetAllFixedDrives = split(trim(GetAllFixedDrives)," ")
End function
'
' Create an XMLDOM Object
'
Function CreateXMLDOMObjectEx( sFileName )
Dim bRetVal
on error resume next
Set CreateXMLDOMObjectEx = nothing
Set CreateXMLDOMObjectEx = oUtility.GetMSXMLDOMDocument
TestAndFail not (CreateXMLDOMObjectEx is nothing), 5490, "Create MSXML2.DOMDocument."
CreateXMLDOMObjectEx.Async = FALSE
If sFileName <> "" then
oLogging.CreateEntry "CreateXMLDOMObjectEx(" & sFileName & ")", LogTypeVerbose
bRetVal = CreateXMLDOMObjectEx.Load (sFileName )
TestAndLog bRetVal, "CreateXMLDOMObjectEx...Length = " & CreateXMLDOMObjectEx.documentElement.childNodes.Length
With CreateXMLDOMObjectEx.ParseError
If .errorCode <> 0 then
oLogging.CreateEntry "File: " & sFileName & " Line: " & .Line & " - " & .Reason & " - " & .SrcText, LogTypeWarning
End if
End with
End if
on error goto 0
End function
' Create an XMLDOM Object, do not return if there is a parse error.
Function CreateXMLDOMObjectSafe( sFileName )
Set CreateXMLDOMObjectSafe = CreateXMLDOMObjectEx( sFileName )
TestAndFail CreateXMLDOMObjectSafe.ParseError.ErrorCode, 5495, "Create MSXML2.DOMDocument .ParseErr.ErrCode."
End function
Function CreateXMLDOMObject
Set CreateXMLDOMObject = CreateXMLDOMObjectEx( empty )
End function
' Load an XML file via FindFile
Function LoadConfigFile( sConfigFile )
Set LoadConfigFile = LoadConfigFileEx( sConfigFile, false )
End function
' Load an XML file via FindFile, do not return if there is any error.
Function LoadConfigFileSafe( sConfigFile )
Set LoadConfigFileSafe = LoadConfigFileEx( sConfigFile, TRUE )
End function
' Load an XML file via FindFile, do not return if there is any error.
Function LoadConfigFileEx( sConfigFile, bMustSucceed )
Dim sFoundFile
Dim iRetVal
iRetVal = oUtility.FindFile( sConfigFile , sFoundFile)
If bMustSucceed then
TestAndFail iRetVal, 5496, "LoadControlFile.FindFile: " & sConfigFile
set LoadConfigFileEx = CreateXMLDOMObjectSafe (sFoundFile)
Else
set LoadConfigFileEx = CreateXMLDOMObjectEx (sFoundFile)
End if
End function
Function BDDUtility
Dim sBDDUtility
Dim iRetval
Dim sProc
' Already retrieved an instance? Return it.
If not (oBDDUtility is Nothing) then
Set BDDUtility = oBDDUtility
Exit Function
End if
' Already registered? Call Routine.
on error resume next
Set oBDDUtility = CreateObject("Microsoft.BDD.Utility")
on error goto 0
If not (oBDDUtility is Nothing) then
Set BDDUtility = oBDDUtility
Exit Function
End if
' Find each Microsoft.BDD.Utility.dll file, and copy locally if over the network.
for each sProc in array("x86","x64")
If not oFSO.FileExists(oEnv("TEMP") & "\Tools\" & sProc & "\Microsoft.BDD.Utility.dll") then
iRetVal = FindFile( sProc & "\Microsoft.BDD.Utility.dll", sBDDUtility)
oLogging.CreateEntry "FindFile(...\Microsoft.BDD.Utility.dll) Result : " & iRetVal, LogTypeInfo
If left(sBDDUtility,2) = "\\" then
oUtility.VerifyPathExistsEx oEnv("TEMP") & "\Tools\" & sProc , false
oFileHandling.CopyFile sBDDUtility, oEnv("TEMP") & "\Tools\" & sProc & "\", True
End if
End if
If oFSO.FileExists(oEnv("TEMP") & "\Tools\" & sProc & "\Microsoft.BDD.Utility.dll") then
sBDDUtility = oEnv("TEMP") & "\Tools\" & sProc & "\Microsoft.BDD.Utility.dll"
End if
' Register the DLL
oLogging.CreateEntry "RUN: regsvr32.exe /s """ & sBDDUtility & """", LogTypeInfo
oShell.Run "regsvr32.exe /s """ & sBDDUtility & """", 0, true ' Always returns 0 - Success
next
' Create an instance
on error resume next
Set oBDDUtility = CreateObject("Microsoft.BDD.Utility")
TestAndLog not oBDDUtility is nothing, "CreateObject(Microsoft.BDD.Utility)"
on error goto 0
Set BDDUtility = oBDDUtility
End Function
Sub SetTaskSequenceProperties(tsID)
Dim oTaskSequences
Dim oTaskSequence
Dim oOperatingSystems
Dim oOS
Dim oImageLang
Dim sImageLang
Dim oLanguage
Dim sImagePath
Dim oWDSServer
Dim sWDSServer
Dim objTmp
Dim oTS
Dim oOSGUID
Dim oDestinationDisk,oDestinationPartition,ODestinationLogicalDrive
Dim sSourcePath
' If there is task sequence ID set, get the properties
If tsID <> "" then
' Get the build record
tsID = Ucase(tsID)
Set oTaskSequences = oUtility.CreateXMLDOMObjectEx(oEnvironment.Item("DeployRoot") & "\Control\TaskSequences.xml")
Set oTaskSequence = oTaskSequences.selectSingleNode("//ts[ID='" & tsID & "']")
If oTaskSequence is Nothing then
oLogging.CreateEntry "ERROR: Invalid task sequence ID " & tsID & " specified", LogTypeError
Exit Sub
End if
' Set the simple build properties
oEnvironment.Item("TaskSequenceName") = oUtility.SelectSingleNodeString(oTaskSequence,"Name")
oEnvironment.Item("TaskSequenceVersion") = oUtility.SelectSingleNodeStringEx(oTaskSequence,"Version", False)
oEnvironment.Item("TaskSequenceTemplate") = oUtility.SelectSingleNodeStringEx(oTaskSequence,"TaskSequenceTemplate", False)
' Load the TS.XML and get the OSGUID
Set oTS = oUtility.CreateXMLDOMObjectEx(oEnvironment.Item("DeployRoot") & "\Control\" & tsID & "\TS.xml")
Set oOSGUID = oTS.SelectSingleNode("//globalVarList/variable[@name='OSGUID']")
If oOSGUID is Nothing then
Exit Sub
End if
oEnvironment.Item("OSGUID")=oOSGUID.text
' Get the OS record
Set oOperatingSystems = oUtility.CreateXMLDOMObjectEx(oEnvironment.Item("DeployRoot") & "\Control\OperatingSystems.xml")
Set oOS = oOperatingSystems.selectSingleNode("//os[@guid='" & oOSGUID.text & "']")
If oOS is Nothing then
oLogging.CreateEntry "ERROR: Invalid OS GUID " & oOSGUID.text & " specified for task sequence " & tsID & " specified", LogTypeInfo
Exit Sub
End if
' Set the simple OS properties
oEnvironment.Item("ImageIndex") = oUtility.SelectSingleNodeString(oOS,"ImageIndex")
oEnvironment.Item("ImageSize") = oUtility.SelectSingleNodeString(oOS,"Size")
on error resume next
oEnvironment.Item("ImageFlags") = oOS.selectSingleNode("Flags").text
on error goto 0
oEnvironment.Item("ImageBuild") = oUtility.SelectSingleNodeString(oOS,"Build")
oEnvironment.Item("ImageProcessor") = oUtility.SelectSingleNodeString(oOS,"Platform")
' Get the languages
Set oImageLang = oOS.selectNodes("Language")
sImageLang = ""
If not (oImageLang is Nothing) then
For each oLanguage in oImageLang
sImageLang = sImageLang & oLanguage.text & vbTab
Next
End if
If right(sImageLang,1) = vbTab then
sImageLang = Left(sImageLang, Len(sImageLang)-1) ' Remove trailing tab
End if
oEnvironment.ListItem("ImageLanguage") = split(sImageLang, vbTab)
' Set the image path
If oOS.selectSingleNode("ImageFile") is nothing then
sImagePath = "."
Else
sImagePath = oOS.selectSingleNode("ImageFile").Text
If sImagePath = "" and left(oEnvironment.Item("ImageBuild"),1) = "5" then
sImagePath = "."
End if
End if
If Left(sImagePath, 1) = "." then
' See if this is a WDS image
Set oWDSServer = oOS.selectSingleNode("WDSServer")
If not (oWDSServer is Nothing) then
sWDSServer = oWDSServer.Text
End if
' Make sure that's where we want to pull it from
If sWDSServer <> "" then
If oEnvironment.Item("WDSServer") <> "" then
sWDSServer = oEnvironment.Item("WDSServer")
End if
End if
' Set the actual image path
If sWDSServer <> "" then
sImagePath = "\\" & sWDSServer & "\REMINST" & Mid(sImagePath, 2)
Else
sImagePath = oEnvironment.Item("DeployRoot") & Mid(sImagePath, 2)
End if
End if
oLogging.CreateEntry "InstallFromPath: " & sImagePath, LogTypeInfo
oEnvironment.Item("InstallFromPath") = oFileHandling.NormalizePath(sImagePath)
sSourcePath = oUtility.SelectSingleNodeString(oOS,"Source")
If Left(sSourcePath, 1) = "." then
sSourcePath = oEnvironment.Item("DeployRoot") & Mid(sSourcePath, 2)
End if
oLogging.CreateEntry "SourcePath: " & sSourcePath, LogTypeInfo
oEnvironment.Item("SourcePath") = sSourcePath
End if
End Sub
Function IsSupportedPlatform(sPlatform)
Dim iRetVal
Dim sSupportedPlatforms
Dim oPlatformNode
Dim oNode
Dim oResults
Dim oResult
Dim bFound
' Special case: check for Windows PE
If oEnvironment.Item("OSVersion") = "WinPE" then
If sPlatform = "Windows PE" then
IsSupportedPlatform = true
Else
IsSupportedPlatform = false
End if
Exit Function
End if
' Load the XML file if not yet loaded
If oSupportedPlatforms is Nothing then
iRetVal = oUtility.FindFile("ZTISupportedPlatforms.xml", sSupportedPlatforms)
Set oSupportedPlatforms = CreateXMLDOMObjectEx(sSupportedPlatforms)
End if
' Find the selected platform
Set oPlatformNode = oSupportedPlatforms.SelectSingleNode("//SupportedPlatform[@name='" & sPlatform & "']")
If oPlatformNode is Nothing then
oLogging.CreateEntry "Platform " & sPlatform & " is not found.", LogTypeInfo
IsSupportedPlatform = False
Exit Function
End if
' Check each of the expressions. If any don't return a record, return false
For each oNode in oPlatformNode.SelectNodes("Expression")
bFound = false
Set oResults = objWMI.ExecQuery(oNode.Text)
For each oResult in oResults
bFound = true
Exit For
Next
If not bFound then
oLogging.CreateEntry "Condition " & oNode.Text & " not satisfied, platform " & sPlatform & " is not supported.", LogTypeInfo
IsSupportedPlatform = False
Exit Function
End if
Next
' All conditions satisfied, return true
oLogging.CreateEntry "Platform " & sPlatform & " is supported on this computer.", LogTypeInfo
IsSupportedPlatform = True
End Function
Function SetTagForDrive( sDriveLetter, sTagVariable )
Dim oDiskPart
oLogging.CreateEntry "Set the Tag variable: " & sTagVariable, LogTypeInfo
oEnvironment.Item(sTagVariable) = ""
For each oDiskPart in objWMI.ExecQuery( "SELECT * FROM Win32_LogicalDisk WHERE DeviceID = '" & left(sDriveLetter,2) & "'" )
oEnvironment.Item(sTagVariable) = "SELECT * FROM Win32_LogicalDisk WHERE Size = '" & oDiskPart.Size & "' and VolumeName = '" & oDiskPart.VolumeName & "' and VolumeSerialNumber = '" & oDiskPart.VolumeSerialNumber & "'"
exit For
next
End function
Function GetDriveFromTag ( sTagVariable )
Dim oDiskPart
oLogging.CreateEntry "Search for Drive: " & sTagVariable & " " & oEnvironment.Item(sTagVariable), LogTypeInfo
For each oDiskPart in objWMI.ExecQuery( oEnvironment.Item(sTagVariable) )
oLogging.CreateEntry "Found Drive: " & oDiskPart.DeviceID, logTypeInfo
GetDriveFromTag = left(oDiskPart.DeviceID,2)
Exit For
next
End function
Function ClearRelativeDriveLetters
oLogging.CreateEntry "If there is a drive letter defined, make sure we clear it now so we can *force* recalcutation.", logTypeInfo
oEnvironment.Item("OSDTargetDriveCache") = "DIRTY"
End function
Function ForceRelativeDriveReCalc
oLogging.CreateEntry "We can no longer assume any information on drive letters, reset everything!.", logTypeInfo
ClearRelativeDriveLetters
If oEnvironment.Item("TargetPartitionIdentifier") <> "" Then
oEnvironment.Item("TargetPartitionIdentifier") = "DIRTY"
End if
End function
Function GetOSTargetDriveLetterEx( bRequired )
Dim oDiskPart
Dim bDiskPartFound
' First check to see if the full OS is running
If oEnv("SystemDrive") <> "X:" then
' We are not running within WinPE, Drive Letter may be easy to determine.
If ucase(oEnvironment.Item("DestinationOSRefresh")) = "OKTOUSEOTHERDISKANDPARTITION" and ucase(oEnvironment.Item("DeploymentType")) = "REFRESH" and ucase(oEnvironment.Item("PHASE")) <> "STATERESTORE" then
oLogging.CreateEntry "It is possible that the Existing SystemRoot is not the Destiation Drive", logTypeInfo
Else
oLogging.CreateEntry "TargetOS is the current SystemDrive", logTypeInfo
GetOSTargetDriveLetterEx = left(oEnv("SystemDrive"),2)
exit function ' Easy case, exit now!
End if
End if
' We may wish to use some advanced Disk Partitioning Routines from ZTIDIskPart.vbs. Check availabiltiy.
On error resume next
bDiskPartFound = false
bDiskPartFound = not isempty(ZTIDiskPart_Script)
on error goto 0
If oEnvironment.Item("OriginalPartitionIdentifier") <> "" and ucase(oEnvironment.Item("DestinationOSRefresh")) <> "OKTOUSEOTHERDISKANDPARTITION" Then
oLogging.CreateEntry "OriginalPartitionIdentifier is set, find disk: " & oEnvironment.Item("OriginalPartitionIdentifier"), logTypeInfo
GetOSTargetDriveLetterEx = GetDriveFromTag ( "OriginalPartitionIdentifier" )
ElseIf oEnvironment.Item("OSDTargetDriveCache") <> "" and oEnvironment.Item("OSDTargetDriveCache") <> "DIRTY" and Ucase(oUtility.ScriptName) <> "ZTIDISKPART" Then
oLogging.CreateEntry "OSDTargetDriveCache was determined earlier : " & oEnvironment.Item("OSDTargetDriveCache"), logTypeInfo
GetOSTargetDriveLetterEx = left(oEnvironment.Item("OSDTargetDriveCache") ,2)
ElseIf oEnvironment.Item("TargetPartitionIdentifier") <> "" and oEnvironment.Item("TargetPartitionIdentifier") <> "DIRTY" Then
oLogging.CreateEntry "TargetPartitionIdentifier is set, find disk: " & oEnvironment.Item("TargetPartitionIdentifier"), logTypeInfo
GetOSTargetDriveLetterEx = GetDriveFromTag ( "TargetPartitionIdentifier" )
ElseIf oEnvironment.Item("DeploymentMethod") <> "SCCM" then
'
' Litetouch Scenarios:
'
If ucase(oEnvironment.Item("DestinationOSInstallType")) = "BYDRIVELETTER" and oEnvironment.Item("DestinationOSDriveLetter") <> "" then
oLogging.CreateEntry "DestinationOSInstallType = BYDRIVELETTER (Generally not recomended scenario, drive letters *can* change between reboots).", LogTypeInfo
GetOSTargetDriveLetterEx = left(oEnvironment.Item("DestinationOSDriveLetter") ,1) & ":"
ElseIf ucase(oEnvironment.Item("DestinationOSInstallType")) = "BYVARIABLE" and oEnvironment.IndirectItem("DestinationOSVariable") <> "" then
oLogging.CreateEntry "Found: DestinationOSVariable: " & oEnvironment.IndirectItem("DestinationOSVariable"), LogTypeInfo
GetOSTargetDriveLetterEx = left(oEnvironment.IndirectItem("DestinationOSVariable") ,2)
Elseif bDiskPartFound then
' Uses functions within ztidiskutility.vbs
If ucase(oEnvironment.Item("DestinationOSInstallType")) = "NEXTPARTITION" then
oLogging.CreateEntry "Found: DestinationOSInstallType = NEXTPARTITION ", LogTypeInfo
GetOSTargetDriveLetterEx = left(GetFirstPossibleSystemDrive,2)
ElseIf (ucase(oEnvironment.Item("DestinationOSInstallType")) = "BYDISKPARTITION" or oEnvironment.Item("DestinationOSInstallType") = "" ) and isnumeric(oEnvironment.Item("DestinationDisk")) and isnumeric(oEnvironment.Item("DestinationPartition")) then
oLogging.CreateEntry "DestinationOSInstallType = BYDISKPARTITION", LogTypeInfo
oLogging.CreateEntry "Found: DestinationDisk: " & oEnvironment.Item("DestinationDisk"), LogTypeInfo
oLogging.CreateEntry "Found: DestinationPartition: " & oEnvironment.Item("DestinationPartition"), LogTypeInfo
set oDiskPart = new ZTIDiskPartition
oDiskPart.SetDiskPart oEnvironment.Item("DestinationDisk"), oEnvironment.Item("DestinationPartition")
If isEmpty( oDiskPart.oWMIDiskPart ) then
oLogging.CreateEntry "No partition Found!", logTypeInfo
ElseIf IsEmpty(oDiskPart.Drive) then
oLogging.CreateEntry "No drive mapped to Disk Partition: " & oDIskPart.oWMIDiskPart.Path_, logTypeInfo
Else
oLogging.CreateEntry "Disk Size : " & FormatLargeSize( oDiskPart.oWMIDiskPart.Size ), logTypeInfo
oLogging.CreateEntry "Min Size : " & FormatLargeSize(GetMinimumDiskPartitionSizeMB * 1000 * 1000) , logTypeInfo
If (oDiskPart.oWMIDiskPart.Size /1000 /1000) < (GetMinimumDiskPartitionSizeMB) and 1 = cint(oEnvironment.Item("DestinationPartition")) then
oLogging.CreateEntry "Partition is set too small, assume BDEPartition and recover.", logTypeInfo
set oDiskPart = new ZTIDiskPartition
oDiskPart.SetDiskPart oEnvironment.Item("DestinationDisk"), 2
If isEmpty( oDiskPart.oWMIDiskPart ) then
oLogging.CreateEntry "No partition Found!", logTypeInfo
ElseIf IsEmpty(oDiskPart.Drive) then
oLogging.CreateEntry "No drive mapped to Disk Partition: " & oDIskPart.oWMIDiskPart.Path_, logTypeInfo
Else
oLogging.CreateEntry "Disk Size : " & FormatLargeSize( oDiskPart.oWMIDiskPart.Size ), logTypeInfo
oLogging.CreateEntry "Min Size : " & FormatLargeSize(GetMinimumDiskPartitionSizeMB * 1000 * 1000) , logTypeInfo
If (oDiskPart.oWMIDiskPart.Size /1000 /1000) > (GetMinimumDiskPartitionSizeMB) then
GetOSTargetDriveLetterEx = left(oDiskPart.Drive,2)
oEnvironment.Item("DestinationPartition") = "2"
End if
End if
Else
GetOSTargetDriveLetterEx = left(oDiskPart.Drive,2)
End if
End if
End if
If isempty(GetOSTargetDriveLetterEx) then
oLogging.CreateEntry "Unable to yield a target Partition (Special Recovery option for Litetouch).", logTypeInfo
If AllDiskDrives.Count = 1 then
oLogging.CreateEntry "There is only one disk, so assume that this is the Destination disk.", logTypeInfo
GetOSTargetDriveLetterEx = left(GetFirstPossibleSystemDrive,2)
End if
End if
End if
Else
'
' SCCM Scenarios:
'
If oEnvironment.Item("_SMSTSMediaType") = "OEMMedia" and oEnvironment.Item("OSDUseAlreadyDeployedImage") = "TRUE" then
oLogging.CreateEntry "Prestaged media deployment, use data path drive.", LogTypeInfo
GetOSTargetDriveLetterEx = Left(oEnvironment.Item("_SMSTSMDataPath"), 2)
ElseIf oEnvironment.Item("OSDTargetDrive") <> "" Then
oLogging.CreateEntry "OSDTargetDrive is set, find disk: " & oEnvironment.Item("OSDTargetDrive"), logTypeInfo
GetOSTargetDriveLetterEx = Left(oEnvironment.Item("OSDTargetDrive"), 2)
ElseIf oEnvironment.Item("OSDisk") <> "" Then
oLogging.CreateEntry "OSDisk is set, find disk: " & oEnvironment.Item("OSDisk"), logTypeInfo
GetOSTargetDriveLetterEx = Left(oEnvironment.Item("OSDisk") ,2)
ElseIf oEnvironment.Item("OSDTemporaryDrive") <> "" Then
oLogging.CreateEntry "OSDTemporaryDiskDrive is set. Most likely a early setup scenario.", logTypeInfo
GetOSTargetDriveLetterEx = Left(oEnvironment.Item("OSDTemporaryDrive"), 2)
' Hard Exit
Exit function
End if
End if
If IsEmpty(GetOSTargetDriveLetterEx) then
oLogging.CreateEntry "DestinationDisk and Partition did not yield a target Partition.", logTypeInfo
If bRequired then
oLogging.ReportFailure "Unable to determine Destination Disk, Partition, and/or Drive. See BDD.LOG for more information.", 5456
End if
Else
' Cache the Deployment drive if found
oEnvironment.Item("OSDTargetDriveCache") = GetOSTargetDriveLetterEx
oEnvironment.Item("OSDisk") = GetOSTargetDriveLetterEx
' Cache the Partition if not set already.
If oEnvironment.Item("TargetPartitionIdentifier") = "" then
SetTagForDrive left(GetOSTargetDriveLetterEx,2), "TargetPartitionIdentifier"
End if
oLogging.CreateEntry "Found GetOSTargetDriveLetterEx: " & GetOSTargetDriveLetterEx, logTypeVerbose
End if
End function
Function DeterminePartition
oLogging.CreateEntry "DeterminePartition is deprecated.", logTypeDeprecated
If true then
DeterminePartition = false
Else
' Legacy solution
ReCalculateDestinationDiskAndPartition (true)
DeterminePartition = true
End if
End function
Function ReCalculateDestinationDiskAndPartition ( bRequired )
Dim sDriveLetter
Dim oDiskPart
Dim bDiskPartFound
' We may wish to use some advanced Disk Partitioning Routines from ZTIDIskPart.vbs. Check availabiltiy.
On error resume next
bDiskPartFound = false
bDiskPartFound = not isempty(ZTIDiskPart_Script)
on error goto 0
sDriveLetter = GetOSTargetDriveLetterEx(bRequired)
If bRequired then
TestAndFail bDiskPartFound , 5452, "Verify ZTIDiskPArt is loaded"
set oDiskPart = new ZTIDiskPartition
oDiskPart.Drive = sDriveLetter
TestAndFail not isEmpty(oDiskPart.Drive),5451, "Verify oDiskPart.Drive is found!"
oEnvironment.Item("DestinationDisk") = oDiskPart.Disk
oEnvironment.Item("DestinationPartition") = oDiskPart.Partition
ElseIf bDiskPartFound then
set oDiskPart = new ZTIDiskPartition
oDiskPart.Drive = sDriveLetter
If not isEmpty(oDiskPart.Drive) then
oEnvironment.Item("DestinationDisk") = oDiskPart.Disk
oEnvironment.Item("DestinationPartition") = oDiskPart.Partition
Else
oLogging.CreateEntry "Drive not found: " & sDriveLetter, LogTypeINfo
End if
Else
oLogging.CreateEntry "ZTIDiskPart_Script not found ", LogTypeINfo
End if
End function
Function GetOSTargetDriveLetter
GetOSTargetDriveLetter = GetOSTargetDriveLetterEx(true)
End function
Function SelectSingleNodeString( oXMLDomNode, sXPath )
SelectSingleNodeString = SelectSingleNodeStringEx(oXMLDomNode, sXPath, True )
End function
Function SelectSingleNodeStringEx( oXMLDomNode, sXPath, bError )
If bError then
'TestAndLog not oXMLDomNode is nothing, "verify oXMLDomNode is object."
End if
If not oXMLDomNode.SelectSingleNode(sXPath) is nothing then
SelectSingleNodeStringEx = oXMLDomNode.SelectSingleNode(sXPath).Text
Else
If bError then
oLogging.CreateEntry "SelectSingleNodeString(" & sXPath & ") Missing Node.", LogTypeWarning
End if
SelectSingleNodeStringEx = ""
End if
End function
Function SelectNodesSafe ( oXMLDomNode, sXPath )
set SelectNodesSafe = SelectNodesSafeEx ( oXMLDomNode, sXPath, True )
End function
Function SelectNodesSafeEx ( oXMLDomNode, sXPath, bError )
If bError then
'TestAndLog not oXMLDomNode is nothing, "verify oXMLDomNode is object."
End if
set SelectNodesSafeEx = oXMLDomNode.SelectNodes(sXPath)
If SelectNodesSafeEx is nothing then
If bError then
oLogging.CreateEntry "SelectNodesSafeEx(" & sXPath & ") Missing Node.", LogTypeWarning
End if
set SelectNodesSafeEx = CreateObject("Scripting.Dictionary") ' Empty object
End if
End function
Function FindSysprepAnswerFile
Dim sSysprepInf
Dim sBuildPath
Dim iRetVal
Dim sBootDrive
iRetVal = SUCCESS
If oEnvironment.Item("TaskSequenceID") = "" Then
oLogging.CreateEntry "The TaskSequenceID is blank, possibly a misconfigured customsettings.ini or task sequence",LogTypeWarning
End If
sBuildPath = oEnvironment.Item("DeployRoot") & "\Control\" & oEnvironment.Item("TaskSequenceID")
If not oFSO.FolderExists(sBuildPath) then
sBuildPath = oEnvironment.Item("DeployRoot")
End if
sBootDrive = oUtility.GetOSTargetDriveLetterEx(false)
if sBootDrive = "" then
oLogging.CreateEntry "Destination Logical Drive was not specificed, defaulting to #:\", LogTypeInfo
sBootDrive = "#:" ' Unknown Boot Drive
End if
oLogging.CreateEntry "Looking for Sysprep.inf in " & sBootDrive & "\sysprep\Sysprep.inf", LogTypeInfo
If oFSO.FileExists(oEnvironment.Item("OSDAnswerFilePathSysprep")) Then
FindSysprepAnswerFile = iRetVal
Exit Function
ElseIf oFSO.FileExists(sBootDrive & "\sysprep\Sysprep.inf") then
sSysprepInf = sBootDrive & "\sysprep\Sysprep.inf"
oLogging.CreateEntry "Found Sysprep.inf at " & sSysprepInf & ".", LogTypeInfo
ElseIf oFSO.FileExists("x:\sysprep\Sysprep.inf") then
sSysprepInf = "x:\sysprep\Sysprep.inf"
oLogging.CreateEntry "Found Sysprep.inf at " & sSysprepInf & ".", LogTypeInfo
ElseIf oFSO.FileExists(sBuildPath & "\Sysprep.inf") then
' Copy it locally
sSysprepInf = sBootDrive & "\sysprep\Sysprep.inf"
oLogging.CreateEntry "Found Sysprep.inf at " & sBuildPath & "\Sysprep.inf, will copy to " & sSysprepInf, LogTypeInfo
If not oFSO.FolderExists(sBootDrive & "\Sysprep") then
oFSO.CreateFolder sBootDrive & "\Sysprep"
End if
oFSO.CopyFile sBuildPath & "\Sysprep.inf", sSysprepInf
oFSO.GetFile(sSysprepInf).Attributes = 0
oLogging.CreateEntry "Copied " & sBuildPath & "\Sysprep.inf to " & sBootDrive & "\sysprep", LogTypeInfo
ElseIf oEnvironment.Item("OSDTargetSystemDrive")<> "" and oFSO.FileExists(oEnvironment.Item("OSDTargetSystemDrive") & "\sysprep\sysprep.inf") then
sSysprepInf = oEnvironment.Item("OSDTargetSystemDrive") & "\sysprep\sysprep.inf"
oLogging.CreateEntry "Found Sysprep.inf at " & sSysprepInf & ".", LogTypeInfo
Else
oLogging.CreateEntry "The sysprep.inf file was not found.", LogTypeInfo
End if
oEnvironment.Item("OSDAnswerFilePathSysprep") = sSysprepInf
FindSysprepAnswerFile = iRetVal
End Function
Function FindUnattendAnswerFile
Dim sUnattendXML, sUnattendTxt
Dim sBuildPath
Dim iRetVal
iRetVal = SUCCESS
If oEnvironment.Item("TaskSequenceID") = "" Then
oLogging.CreateEntry "The TaskSequenceID is blank, possibly a misconfigured customsettings.ini or task sequence",LogTypeWarning
End If
sBuildPath = oEnvironment.Item("DeployRoot") & "\Control\" & oEnvironment.Item("TaskSequenceID")
If not oFSO.FolderExists(sBuildPath) then
sBuildPath = oEnvironment.Item("DeployRoot")
End if
If oFSO.FileExists(sBuildPath & "\Unattend.txt") then
' Copy it locally
sUnattendTxt = oUtility.LocalRootPath & "\unattend.txt"
oLogging.CreateEntry "Found Unattend.txt at " & sBuildPath & "\Unattend.txt, will copy to " & sUnattendTxt, LogTypeInfo
oFSO.CopyFile sBuildPath & "\Unattend.txt", sUnattendTxt, true
oFSO.GetFile(sUnattendTxt).Attributes = 0
oLogging.CreateEntry "Copied " & sBuildPath & "\Unattend.txt to " & sUnattendTxt, LogTypeInfo
ElseIf oFso.FileExists(oEnvironment.Item("OSDAnswerFilePath")) and Instr(1,oEnvironment.Item("OSDAnswerFilePath"),".txt",vbTextCompare) > 0 then
sUnattendTxt = oEnvironment.Item("OSDAnswerFilePath")
oLogging.CreateEntry "Found unattend.txt at " & sUnattendTxt,LogTypeInfo
Else
oLogging.CreateEntry "The unattend.txt file was not found.", LogTypeInfo
End if
' First see if there is already a local unattend.xml. If not, copy one.
If oFSO.FileExists(Left(oUtility.LocalRootPath, 2) & "\Windows\Panther\unattend\unattend.xml") then
sUnattendXml = Left(oUtility.LocalRootPath, 2) & "\Windows\Panther\unattend\unattend.xml"
oLogging.CreateEntry "Found existing unattend.xml at " & sUnattendXml, LogTypeInfo
ElseIf oFSO.FileExists(oUtility.LocalRootPath & "\unattend.xml") then
sUnattendXml = oUtility.LocalRootPath & "\unattend.xml"
oLogging.CreateEntry "Found existing unattend.xml at " & sUnattendXml, LogTypeInfo
ElseIf oFSO.FileExists(sBuildPath & "\Unattend.xml") then
sUnattendXml = oUtility.LocalRootPath & "\Unattend.xml"
oLogging.CreateEntry "Found unattend.xml at " & sBuildPath & "\Unattend.xml, will copy to " & sUnattendXml, LogTypeInfo
oFSO.CopyFile sBuildPath & "\Unattend.xml", sUnattendXml, true
oLogging.CreateEntry "Copied " & sBuildPath & "\Unattend.xml to " & sUnattendXml, LogTypeInfo
oFSO.GetFile(sUnattendXml).Attributes = 0
ElseIf oFso.FileExists(oEnvironment.Item("OSDAnswerFilePath")) and Instr(1,oEnvironment.Item("OSDAnswerFilePath"),".xml",vbTextCompare) >0 then
sUnattendXML= oEnvironment.Item("OSDAnswerFilePath")
oLogging.CreateEntry "Found existing unattend.xml at " & sUnattendXml, LogTypeInfo
Else
sUnattendXml = ""
oLogging.CreateEntry "File " & sBuildPath & "\Unattend.xml does not exist, unable to copy", LogTypeInfo
End if
If sUnattendTxt <> "" AND sUnattendXML <> "" Then
oLogging.CreateEntry "Found an unattend.xml and an unattend.txt file, Invalid configuration", LogTypeError
iRetVal = FAILURE
FindUnattendAnswerFile = iRetVal
Exit Function
ElseIf sUnattendTxt <> "" AND sUnattendXML = "" Then
oEnvironment.Item("OSDAnswerFilePath") = sUnattendTxt
ElseIF sUnattendXML <> "" AND sUnattendTxt = "" Then
oEnvironment.Item("OSDAnswerFilePath") = sUnattendXML
Else
oLogging.CreateEntry "No answer file could be found",LogTypeWarning
End If
FindUnattendAnswerFile = iRetVal
End Function
Function IsHighEndSKUEx( sSKU )
' Windows Ultimate/Enterprise and Server SKU's allow for some
' higher-end features, like Bitlocker and Multiple Language Packs.
select case (ucase(trim(sSKU)))
case "ULTIMATE", "ULTIMATEE", "ULTIMATEN"
IsHighEndSKUEx = TRUE
case "ENTERPRISE", "ENTERPRISEN", "ENTERPRISES", "ENTERPRISESN"
IsHighEndSKUEx = TRUE
case "PROFESSIONAL", "PROFESSIONALN"
IsHighEndSKUEx = TRUE
case "EDUCATION", "EDUCATIONN"
IsHighEndSKUEx = TRUE
case "HYPERV"
IsHighEndSKUEx = TRUE
case "PRERELEASE"
IsHighEndSKUEx = TRUE
case else
If Instr(1, ucase(trim(sSKU)), "SERVER", vbTextCompare) > 0 then
IsHighEndSKUEx = TRUE
Else
IsHighEndSKUEx = FALSE
End if
End Select
End function
Function IsHighEndSKU
TestAndLog oEnvironment.Item("OSSKU") <> "", "Verify %OSSKU% is defined."
IsHighEndSKU = IsHighEndSKUEx( oEnvironment.Item("OSSKU") )
End function
Function InternetFileDownload(sInternetURL, sDest)
Dim oInternetBuffer
Dim oADODB
' Assume failure
InternetFileDownload = false
' Create the web request using ADO
Set oADODB = CreateObject("ADODB.Stream")
Set oInternetBuffer = CreateObject("Msxml2.XmlHttp")
oInternetBuffer.open "GET", sInternetURL, false
On Error Resume Next
oInternetBuffer.send ""
On Error Goto 0
' Check that the request is completed (ReadyState=4). If it isn't, log it as a warning (will likely fail below
' because the status won't be 200).
If oInternetBuffer.ReadyState = 4 then
oLogging.CreateEntry "Status: " & oInternetBuffer.Status & " " & sInternetURL, LogTypeInfo
Else
oLogging.CreateEntry "Ready State : " & oInternetBuffer.ReadyState & " " & sInternetURL, LogTypeWarning
End if
' If the status indicates a successful download, save the file to the specified path
If oInternetBuffer.Status = 200 then
If oADODB.State <> 0 then ADODB.Close
oADODB.Type = 1 '(1=binary,2=Text)
oADODB.Mode = 3 '(1=Read,2=Write,3=RW)
oADODB.Open
oADODB.Write oInternetBuffer.ResponseBody
oADODB.SaveToFile sDest, 2
oADODB.Close
InternetFileDownload = True
End if
End function
End Class
'
' Common String Processing Routines
'
Class Strings
Function isNullOrEmpty( sString )
isNullOrEmpty = false
If isEmpty(sString) or isNull(sString) then
isNullOrEmpty = True
ElseIf VarType(sString) = 8 then
isNullOrEmpty = (sString = "")
End if
End function
' Create a delimited list of items.
Sub AddToList(byref List, Item, Delimiter)
if isempty(list) then
List = cstr(item)
else
list = list & delimiter & cstr(Item)
end if
end Sub
' Display a Hex value with width
Function HexWidth ( Value, Width )
HexWidth = right( "00000000" & hex ( value ), Width)
end Function
' Display a Hex value with width
Function HexWidthByte ( Value, Width )
HexWidthByte = right( "00000000" & hex ( ascb( value ) ), Width )
end Function
Function IsWhiteSpace (MyChar)
' Whitespace defined as vtTab[9], vbLF[10], vbVerticalTab[11], vbFormFeed[12], vbCr[13]
IsWhiteSpace = MyChar = " " or ( MyChar >= chr(9) and MyChar <= chr(13) ) or MyChar = chr(160)
end Function
Function TrimAllWS( MyString )
TrimAllWS = MyString
While len(TrimAllWS) > 0 and IsWhiteSpace(left(TrimAllWS,1))
TrimAllWS = Mid(TrimAllWS,2)
wend
While len(TrimAllWS) > 0 and IsWhiteSpace(right(TrimAllWS,1))
TrimAllWS = Mid(TrimAllWS,1,len(TrimAllWS)-1)
wend
end Function
Function RightAlign( MyString, Width )
RightAlign = Right( Space(Width) & MyString, Width )
end Function
Function LeftAlign( MyString, Width )
LeftAlign = Left( MyString & Space(Width), Width )
end Function
'
' Force a value to a string format.
' Non-printable types will return empty.
'
Function ForceAsString ( InputVar )
dim InputType, Item
InputType = VarType(InputVar)
if isObject(InputVar) or isNull(InputVar) or isEmpty(InputVar) then
ForceAsString = ""
elseif InputType = vbError or InputType = vbVariant or InputType = vbDataObject then
ForceAsString = ""
elseif InputType = ( vbArray or vbByte ) then
for item = 1 to LenB( InputVar )
AddToList ForceAsString, ForceAsString( HexWidthByte(midb(InputVar,Item,1),2) ), ""
next
elseif isArray(InputVar) then
for each item in InputVar
AddToList ForceAsString, ForceAsString(Item), " " ' recurse
next
elseif InputType = vbByte then
ForceAsString = HexWidthByte(InputVar,2)
else
ForceAsString = cstr(InputVar)
end if
end Function
'
' Given a variant, will ensure the Function returns an array
'
' Parameters:
' InputVar - Variable to convert to an array
' sDelimiter - OPTIONAL delimiter to force spliting in the array
' If sDelimiter is empty or blank, Function will return an array of 1 element.
' Notes
Function ForceAsArray( InputVar, sDelimiter )
dim i
if isArray(InputVar) then
ForceAsArray = InputVar
elseif VarType(InputVar) = vbObject then
redim newarray(InputVar.Count-1)
for i = 0 to InputVar.Count-1
newarray(i) = InputVar(i)
next
ForceAsArray = NewArray
elseif VarType(InputVar) = vbString and VarType(sDelimiter) = vbString then
ForceAsArray = split(InputVar,sDelimiter, -1, vbTextCompare )
else
ForceAsArray = array(InputVar)
end if
end Function
Function GenerateRandomGUID
GenerateRandomGUID = left( CreateObject("Scriptlet.TypeLib").GUID, 38 )
end Function
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'
' Base64 Functions
'
Function BASE64_TABLE
BASE64_TABLE = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
End function
Function SafeAsc ( sPlainText, pos )
if VarType(sPlainText) = (vbArray or vbByte) then
SafeAsc = cint(midb(sPlainText, pos + 1 , 1))
elseif (pos + 1) <= len(sPlainText) then
SafeAsc = asc(mid(sPlainText, pos + 1, 1))
else
SafeAsc = 0
end if
End Function
Function SafeEnc( n, x )
SafeEnc = mid(BASE64_TABLE, ((n\(2^x)) and 63) + 1,1)
End Function
Function base64Encode( sPlainText )
Dim i, n
if 0 < len(sPlainText) then
for i = 0 to len(sPlainText) - 1 step 3
' Add a new line ...
if i > 0 and i mod 57 = 0 then
base64Encode = base64Encode & vbNewLine
end if
' three 8-bit characters become one 24-bit number
n = (SafeAsc(sPlainText,i)*&h10000 + SafeAsc(sPlainText,i+1)*&h100 + SafeAsc(sPlainText,i+2))
' the 24-bit number becomes four 6-bit numbers
base64Encode = base64Encode & SafeEnc( n, 18 ) & SafeEnc( n, 12 ) & SafeEnc( n, 6 ) & SafeEnc( n, 0 )
next
end if
' Pad Text at End of String
n = (3-(len(sPlainText)mod 3)) mod 3
base64Encode = left ( base64Encode, len(base64Encode) - n ) + string( n, "=" )
End Function
Function SafeDecode( s, i, x )
SafeDecode = ( InStr(1, BASE64_TABLE, mid(s,i,1), vbBinaryCompare) - 1) * (2 ^ x)
End Function
Function base64Decode( sEncodedText )
Dim sEncText
Dim regex
Dim p, i, n
' Remove all non base64 text
set regex = new RegExp
regex.pattern = "[^=" & BASE64_TABLE & "]"
regex.global = true
sEncText = regex.Replace(sEncodedText,"")
sEncText = replace( sEncText, vbLF, "")
sEncText = replace( sEncText, vbCR, "")
' Verify String is in Base64 format (multiple of 4 chars)
if len(sEncText) mod 4 <> 0 then
oLogging.CreateEntry "Variable is not a valid string (not Base64 Format)", LogTypeInfo
base64Decode = ""
exit function
end if
if right(sEncText,2) = "==" then
p = 2
elseif right(sEncText,1) = "=" then
p = 1
end if
sEncText = left(sEncText,len(sEncText)-p) & string(p,"A")
for i = 1 to len(sEncText) step 4
' Convert four 6-bit numbers into one 24 bit value
n = SafeDecode(sEncText,i+3,0) + SafeDecode(sEncText,i+2,6) + SafeDecode(sEncText,i+1,12) + SafeDecode(sEncText,i+0,18)
' Convert the 24-bit value back into three 8-bit values.
base64Decode = base64Decode & chr( (n \ (2^16)) and 255 ) & chr( (n \ (2^8)) and 255 ) & chr( n and 255 )
next
' Trim off any excess space.
base64Decode = left(base64Decode,len(base64Decode)-p)
End Function
End Class
Class FileHandling
Function RemoveFolder(sPath)
RemoveFolder = RemoveFolderEx (sPath, TRUE)
End Function
Function RemoveFolderEx(sPath, bLogging )
Dim oFile, oFolder
If bLogging then
oLogging.CreateEntry "Remove Folder: " & sPath, LogTypeInfo
End if
' Make sure the folder exists
If not oFSO.FolderExists(sPath) then
Exit Function
End if
' First try to remove any files
on error resume next
For each oFile in oFSO.GetFolder(sPath).Files
DeleteFileEx oFile.Path, bLogging
Next
On Error Goto 0
' Then take care of subfolders
on error resume next
For each oFolder in oFSO.GetFolder(sPath).Subfolders
RemoveFolderEx oFolder.Path, bLogging
Next
On Error Goto 0
' Now try to remove the folder
On Error Resume Next
oFSO.DeleteFolder sPath, true
If bLogging then
TestAndLog Err = 0, "Delete Folder: " & sPath
End if
RemoveFolderEx = Err
Err.Clear
On Error Goto 0
End Function
Function DeleteFile(sFile)
DeleteFile = DeleteFileEx ( sFile, TRUE )
End function
Function DeleteFileEx(sFile, bLogging)
If bLogging then
oLogging.CreateEntry "Delete File: " & sFile, LogTypeInfo
End if
On Error Resume Next
oFSO.DeleteFile sFile, TRUE
If bLogging then
TestAndLog Err = 0, "Delete File: " & sFile
End if
DeleteFileEx = Err
Err.Clear
On Error Goto 0
End function
Function MoveFile(sFile,sDest)
MoveFile = MoveFileEx(sFile,sDest,True)
End function
Function MoveFileEx(sFile,sDest,bLogging)
If bLogging then
oLogging.CreateEntry "Move File: " & sFile & " to " & sDest , LogTypeInfo
End if
On Error Resume Next
oFSO.MoveFile sFile, sDest
If bLogging then
TestAndLog Err = 0, "Move File: " & sFile & " to " & sDest
End if
MoveFileEx = Err
Err.Clear
On Error Goto 0
End function
Function CopyFile(sFile,sDest, bOverwrite)
CopyFile = CopyFileEx(sFile,sDest, bOverwrite,True)
End function
Function CopyFileEx(sFile,sDest, bOverwrite,bLogging)
If bLogging then
oLogging.CreateEntry "Copy File: " & sFile & " to " & sDest , LogTypeInfo
End if
On Error Resume Next
oFSO.CopyFile sFile, sDest, bOverwrite
If bLogging then
TestAndLog Err = 0, "Copy File: " & sFile & " to " & sDest
End if
CopyFileEx = Err
Err.Clear
On Error Goto 0
End function
Function CopyFolder (sSource, sDest, bOverwrite)
CopyFolder = CopyFolderEx(sSource, sDest, bOverwrite, True)
End function
Function CopyFolderEx (sSource, sDest, bOverwrite,bLogging)
If bLogging then
oLogging.CreateEntry "Copy Folder: " & sSource & " to " & sDest , LogTypeInfo
End if
On Error Resume Next
oFSO.CopyFolder sSource, sDest, bOverwrite
If bLogging then
TestAndLog Err = 0, "Copy Folder: " & sSource & " to " & sDest
End if
CopyFolderEx = Err
Err.Clear
On Error Goto 0
End function
Function MoveFolder (sSource, sDest )
MoveFolder = MoveFolderEx (sSource, sDest, True )
End function
Function MoveFolderEx (sSource, sDest, bLogging )
If bLogging then
oLogging.CreateEntry "Move Folder " & sSource & " to " & sDest , LogTypeInfo
End if
On Error Resume Next
oFSO.MoveFolder sSource,sDest
If bLogging then
TestAndLog Err = 0, "Move Folder " & sSource & " to " & sDest
End if
MoveFolderEx = Err
Err.Clear
On Error Goto 0
End function
Function NormalizePath( Path )
NormalizePath = oFSO.GetAbsolutePathName (Path )
End function
Function GetTempFile
GetTempFile = oFso.BuildPath( GetTempFolder, oFSO.GetTempName )
End function
Function GetTempFileEx(sExt)
GetTempFileEx = oFso.BuildPath( GetTempFolder, oFSO.GetBaseName(oFSO.GetTempName) & "." & sExt )
End function
Function GetTempFolder
GetTempFolder = oFSO.GetSpecialFolder(2) 'TemporaryFolder
End function
Function GetWindowsFolder
GetWindowsFolder = oFSO.GetSpecialFolder(0) 'WindowsFolder
End function
Function CheckFileVersion ( sFileName, sMinVersion )
' Returns True if the sFileName is the sMinVersion or greater, False if less, or not found.
Dim sFoundFile
Dim sMSIVer
Dim sMSIVer2
Dim i
CheckFileVersion = oUtility.FindFile(sFileName, sFoundFile) = SUCCESS
TestAndLog CheckFileVersion, "FindFile (" & sFileName & ")"
If CheckFileVersion then
sMSIVer = split(oFSO.GetFileVersion(sFoundFile),".")
sMSIVer2 = split(sMinVersion,".")
i = 0
do while CheckFileVersion and ( i <= ubound(sMSIVer) ) and ( i <= ubound(sMSIVer2) )
If sMSIVer(i) <> sMSIVer2(i) then
CheckFileVersion = clng(sMSIVer(i)) >= clng(sMSIVer2(i))
exit do
End if
i = i + 1
Loop
oLogging.CreateEntry sFileName & " version: [ " & join(sMSIVer,".") & " | " & sMinVersion & " ]. Is version found? " & ( CheckFileVersion ), LogTypeInfo
Else
oLogging.CreateEntry sFileName & " Not found! Needs upgrade. " & ( CheckFileVersion ), LogTypeInfo
End if
End function
End Class
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'
' Regular Expression Helper functions
' http://msdn.microsoft.com/en-us/library/6wzad2b2(VS.85).aspx
'
' Usage:
' for each Match in oRegEx.GetRegExMatchesFromFile( "\[([^\]]*)\]","c:\boot.ini" )
' Wscript.echo "Match: " & Match
' next
'
dim g_oRegEx
Function oRegEx
if isempty(g_oRegEx) then
set g_oRegEx = new clsRegEx
end if
set oRegEx = g_oRegEx
end Function
class clsRegEx
Private Function ReadEntireFile( sFileName )
' TestAndLog oFSO.FileExists(sFileName), "File Test: " & sFileName
ReadEntireFile = oFSO.OpenTextFile(sFileName, ForReading, FALSE ).ReadAll
End function
private Function RegExObj ( SearchPattern, IgnoreCase, IsGlobal )
set RegExObj = New RegExp
RegExObj.Global = IsGlobal
RegExObj.Multiline = TRUE
RegExObj.IgnoreCase = IgnoreCase
RegExObj.Pattern = SearchPattern
end Function
Function GetRegExMatches ( SearchPattern, Buffer )
set GetRegExMatches = RegExObj ( SearchPattern, TRUE, TRUE ).Execute(Buffer)
end Function
Function TestRegEx ( SearchPattern, Buffer )
TEstRegEx = RegExObj ( SearchPattern, TRUE, TRUE ).Test(Buffer)
end Function
Function ReplaceRegEx ( SearchPattern, ReplacementString, Buffer )
ReplaceRegEx = RegExObj ( SearchPattern, TRUE, TRUE ).Replace(Buffer, ReplacementString)
end Function
Function GetRegExMatchesFromFile ( SearchPattern, FileName )
set GetRegExMatchesFromFile = GetRegExMatches ( SearchPattern, ReadEntireFile(FileName) )
end Function
Function TestRegExFromFile ( SearchPattern, FileName )
TestRegExFromFile = TestRegEx ( SearchPattern, ReadEntireFile(FileName) )
end Function
Function ReplaceRegExFromFile ( SearchPattern, ReplacementString, FileName )
ReplaceRegExFromFile = ReplaceRegEx ( SearchPattern, ReplacementString, ReadEntireFile(FileName) )
end Function
Function FindStrInFile( SearchStr, FileName )
FindStrInFile = InStr(1, ReadEntireFile( sFileName ), SearchStr, vbTextCompare)
end Function
end class
<job id="ZTIWindowsUpdate">
<script language="VBScript" src="ZTIUtility.vbs"/>
<script language="VBScript">
' // ***************************************************************************
' //
' // Copyright (c) Microsoft Corporation. All rights reserved.
' //
' // Microsoft Deployment Toolkit Solution Accelerator
' //
' // File: ZTIWindowsUpdate.wsf
' //
' // Version: 6.3.8330.1000
' //
' // Purpose: Installs all needed updates (drivers, patches, service packs,
' // etc.) from the Windows Update/Microsoft Update site or WSUS
' // server, rebooting as required until no more updates are needed.
' //
' // Usage: cscript.exe [//nologo] ZTIWindowsUpdate.wsf [/debug:true]
' //
' // ***************************************************************************
Option Explicit
RunNewInstance
'//----------------------------------------------------------------------------
'// Global Constants
'//----------------------------------------------------------------------------
Const MSIT_WU_REBOOT_MAX = 7
Const MAX_UPDATES = 100
'//----------------------------------------------------------------------------
'// Main Class
'//----------------------------------------------------------------------------
Class ZTIWindowsUpdate
'//----------------------------------------------------------------------------
'// Class instance variable declarations
'//----------------------------------------------------------------------------
Public globalVariable
Private privateVariable
'//----------------------------------------------------------------------------
'// Constructor to initialize needed global objects
'//----------------------------------------------------------------------------
Private Sub Class_Initialize
' No initialization is required
End Sub
'//----------------------------------------------------------------------------
'// Main routine
'//----------------------------------------------------------------------------
Function Main
Dim iRetVal
Dim Item
Dim MSIT_WU_Count
Dim MSIT_LogType
Dim ServiceManager
Dim bFoundMU
Dim NewUpdateService
Dim strCabPath
Dim iResult
Dim oProgress
Dim bFailure, bReboot
Main = Success
' Validate that are not restarting from a failed install.
If ucase(oEnv("SystemDrive")) = "X:" Then
oLogging.CreateEntry "Environment Error: ManualRetry (From ZTIWindowsUpdate).", LogTypeInfo
oEnvironment.Item("LTISuspend") = "LiteTouch is trying to install Windows Updates." & _
vbNewLine & "This cannot be performed in Windows PE." & _
vbNewLine & "If booting from a USB Flash Disk, please remove all drives before Retrying." & _
vbNewLine & "Otherwise, ensure the hard disk is selected first in the boot order of the BIOS."
oEnvironment.Item("SMSTSRebootRequested") = "true"
oEnvironment.Item("SMSTSRetryRequested") = "true"
Main = SUCCESS
exit function
End if
'//----------------------------------------------------------------------------
'// Initialization
'//----------------------------------------------------------------------------
MSIT_WU_Count = oEnvironment.Item("MSIT_WU_Count")
If not IsNumeric(MSIT_WU_Count) then
MSIT_WU_Count = 0
End if
oLogging.CreateEntry "Begin Windows Update. Reboot=[" & oEnvironment.Item("SMSTSRebootRequested") & "] Retry=[" & oEnvironment.Item("SMSTSRetryRequested") & "] Count = " & MSIT_WU_Count , LogTypeInfo
MSIT_WU_Count = MSIT_WU_Count + 1
oEnvironment.Item("MSIT_WU_Count") = MSIT_WU_Count
If oEnvironment.Item("WsusServer") = "" then
oLogging.ReportProgress "Initializing Windows Update process (pass " & MSIT_WU_Count & ")", 0
Else
oLogging.ReportProgress "Initializing WSUS update process (pass " & MSIT_WU_Count & ")", 0
End if
If oEnvironment.Item("SMSTSRebootRequested") <> "" then
oEnvironment.Item("SMSTSRebootRequested") = ""
End if
If oEnvironment.Item("SMSTSRetryRequested") <> "" then
oEnvironment.Item("SMSTSRetryRequested") = ""
End if
If MSIT_WU_Count > MSIT_WU_REBOOT_MAX then
oLogging.ReportFailure "ZTIWindowsUpdate has run and failed too many times. Count = " & MSIT_WU_Count, 9902
End if
' Make sure the necessary agent is in place
iRetVal = VerifyWUA
If iRetVal = 3010 then
' Initiate a reboot and ask that we be re-executed
oEnvironment.Item("SMSTSRebootRequested") = "true"
oEnvironment.Item("SMSTSRetryRequested") = "true"
Exit Function
ElseIf iRetVal <> 0 then
oLogging.ReportFailure "Unexpected issue installing the updated Windows Update Agent, rc = " & iRetVal, 9903
End if
' Opt-In to the Microsoft Update Agent
On Error Resume Next
Item = oFSO.GetFileVersion ( ees("%SystemRoot%\System32\WUAUENG.DLL" ) )
oLogging.CreateEntry "Ready to Opt-In to Microsoft Update: WUA Version: " & Item , LogTypeInfo
Set ServiceManager = nothing
Set ServiceManager = CreateObject("Microsoft.Update.ServiceManager")
On Error Goto 0
If ServiceManager is nothing then
oLogging.CreateEntry "Failed to Create Object: Microsoft.Update.ServiceManager" , LogTypeWarning
Else
bFoundMU = False
For each Item in ServiceManager.Services
WScript.Echo "Registered Update Service: " & Item.ServiceID & " " & Item.Name
If Item.ServiceID = "7971f918-a847-4430-9279-4a52d1efe18d" then
bFoundMU = True
End if
Next
oLogging.CreateEntry "Microsoft Update Service: Enabled = " & bFoundMU, LogTypeInfo
If not bFoundMU then
On Error Resume Next
Err.clear
ServiceManager.ClientApplicationID = "My App"
If Err.Number <> 0 then
oLogging.CreateEntry "There was an error getting Windows Update to opt into Microsoft Update. Please verify you are running the latest version of Windows Update Agent." , LogTypeWarning
End if
If oEnvironment.Item("WsusServer") = "" then
'//----------------------------------------------------------------------------
'// Try to find the standalone muauth.cab file and install from it
'//----------------------------------------------------------------------------
'
' From http://download.windowsupdate.com/v9/microsoftupdate/redir/muauth.cab
'
' Place this file in the Distribution\Tools folder so this script can find them.
iResult = oUtility.FindFile("muauth.cab", strCabPath)
If iResult <> Success then
'// "" will force a internet search for cab file
strCabPath = ""
End if
oLogging.CreateEntry " about to begin add service ["+ strCabPath +"]", LogTypeInfo
Set NewUpdateService = ServiceManager.AddService2("7971f918-a847-4430-9279-4a52d1efe18d",6,strCabPath)
oLogging.CreateEntry " Status: " & NewUpdateService.RegistrationState, LogTypeInfo
End if
On error goto 0
End if
End if
'//----------------------------------------------------------------------------
'// Process the command line
'//----------------------------------------------------------------------------
Dim IsRegistered, Query_Only, UpdateCommand, BadKBArticlesList
Dim BadGUIDList
Query_Only = FALSE or WScript.Arguments.Named.Exists("QUERY")
IsRegistered = FALSE
If WScript.Arguments.Unnamed.Count > 0 then
UpdateCommand = WScript.Arguments.Unnamed.Item(0)
Elseif Ucase(oEnvironment.Item("DoCapture")) = "YES" or Ucase(oEnvironment.Item("DoCapture")) = "PREPARE" then
UpdateCommand = "IsInstalled = 0 and IsHidden = 0 and Type = 'Software'"
Else
UpdateCommand = "IsInstalled = 0 and IsHidden = 0"
End if
' Check to see if this version of Windows has been registered
IsRegistered = FALSE
On Error Resume Next
For each Item in objWMI.InstancesOf("Win32_WindowsProductActivation")
IsRegistered = Item.ActivationRequired = 0
Exit for
Next
On Error Goto 0
oLogging.CreateEntry "Command Line Procesed Query=" & QUery_Only & " Registered=" & IsRegistered & " UpdateCommand=[" & UpdateCommand & "]" , LogTypeInfo
Set BadKBArticlesList = oEnvironment.ListItem("WUMU_ExcludeKB")
Set BadGUIDList = oEnvironment.ListItem("WUMU_ExcludeID")
'//----------------------------------------------------------------------------
'// Search Windows Update
'//----------------------------------------------------------------------------
oLogging.ReportProgress "Searching for updates", 0
Dim UpdateSession, searchResults, updatesToDownload
Dim Downloader, Installer, UpdateResult
Dim kbArticle, bInstall, kb, iSize
Dim i
On Error Resume Next
Set updateSession = CreateObject("Microsoft.Update.Session")
Set updatesToDownload = CreateObject("Microsoft.Update.UpdateColl")
On Error Goto 0
If updateSession is nothing then
oLogging.ReportFailure "Failed to Create Object: Microsoft.Update.Session.", 9904
End if
If updatesToDownload is nothing then
oLogging.ReportFailure "Failed to Create Object: Microsoft.Update.UpdateColl.", 9905
End if
oLogging.CreateEntry "Start Search..." , LogTypeInfo
On Error Resume Next
Set searchResults = updateSession.CreateupdateSearcher().Search(UpdateCommand)
If Err then
If Err.Number = &h8024402c then
oLogging.CreateEntry "Error searching for updates: Not Connected to Internet? (" & Err.Number & ")", LogTypeInfo
Main = Success
ElseIf Err.Number = &h80072ee2 then
oLogging.CreateEntry "Error searching for updates: ERROR_INTERNET_TIMEOUT: Retry! (" & Err.Number & ")", LogTypeInfo
oEnvironment.Item("SMSTSRebootRequested") = "true"
oEnvironment.Item("SMSTSRetryRequested") = "true"
ElseIf Err.Number = &h80244010 then
oLogging.CreateEntry "Timeout Error WU_E_PT_EXCEEDED_MAX_SERVER_TRIPS : Retry! (" & Err.Number & ")", LogTypeInfo
' See: http://blogs.technet.com/sus/archive/2008/09/18/wsus-clients-fail-with-warning-syncserverupdatesinternal-failed-0x80244010.aspx
oEnvironment.Item("SMSTSRebootRequested") = "false"
oEnvironment.Item("SMSTSRetryRequested") = "true"
Else
TestAndLog err = 0, "Windows Update, search for updates."
Main = Failure
End if
CleanupWhenDone
Exit Function
End if
On Error Goto 0
oLogging.ReportProgress "Processing " & searchResults.Updates.Count & " updates.", 0
For each item in searchResults.Updates
bInstall = TRUE
On Error Resume Next
item.AcceptEula
If item.InstallationBehavior.CanRequestUserInput then
bInstall = FALSE ' Do NOT install anything that can Request User Input!
End if
For each kb in Item.Categories
if ucase(kb.Name) = "DRIVERS" then
bInstall = TRUE ' Some XP drivers may be marked as CanRequestUserInput. Override!
exit for
elseif ucase(kb.Name) = "WINDOWS VISTA ULTIMATE LANGUAGE PACKS" then
bInstall = FALSE ' Most users don't want *ALL* Language Packs. Too much. Override!
exit for
end if
Next
If BadKBArticlesList.Count > 0 then
For each kbArticle in item.KBArticleIDs
For each kb in BadKBArticlesList
If lcase(kb) = lcase(kbArticle) then
bInstall = FALSE ' Do NOT install any patch in the Bad KB articles list!
End if
Next
Next
End if
For each kbArticle in BadGUIDList
If lcase(item.Identity.UpdateID) = lcase(kbArticle) then
bInstall = FALSE ' Do NOT install any patch in the Bad GUID articles list!
End if
Next
iSize = empty
kb = ""
for i = 0 to item.KBArticleIDs.Count - 1
If instr(1,Item.Title,item.KBArticleIDs(i),vbTextCompare) = 0 then
oStrings.AddToList kb, "KB" & item.KBArticleIDs(i), " "
End if
next
iSize = item.MinDownloadSize
If item.MaxDownloadSize > 0 then
iSize = Item.MaxDownloadSize
End if
If kb <> "" then
kb = " [ " & kb & " ]"
End if
If iSize > 0 then
kb = kb & " - " & FormatLargeSize(iSize)
End if
If bInstall = TRUE and updatesToDownload.count < MAX_UPDATES then
oLogging.CreateEntry "INSTALL - " & item.Identity.UpdateID & " - " & Item.Title & kb, LogTypeInfo
updatesToDownload.Add(Item)
Else
oLogging.CreateEntry " SKIP - " & item.Identity.UpdateID & " - " & Item.Title & kb, LogTypeInfo
End if
On Error Goto 0
Next
oLogging.CreateEntry "Scan complete, ready to install updates. Count = " & updatesToDownload.Count, LogTypeInfo
If updatesToDownload.Count = 0 or Query_Only then
oLogging.CreateEntry "This computer is up to date (Success)" , LogTypeInfo
oEnvironment.Item("MSIT_WU_Count") = "" ' Reset the counter
CleanupWhenDone
Main = Success
Exit Function
End if
If MSIT_WU_Count > MSIT_WU_REBOOT_MAX - 1 then
MSIT_LogType = LogTypeWarning
Else
MSIT_LogType = LogTypeInfo
End if
'//----------------------------------------------------------------------------
'// Download binaries
'//----------------------------------------------------------------------------
Set oProgress = new Progress
oLogging.CreateEntry "Begin Downloading...", LogTypeInfo
Set Downloader = updateSession.CreateUpdateDownloader()
Downloader.Updates = UpdatesToDownload
Set UpdateResult = Downloader.BeginDownload(oProgress, oProgress, vbNull)
On Error Resume Next
While not UpdateResult.IsCompleted
oLogging.ReportProgress "Downloading " & UpdatesToDownload(UpdateResult.GetProgress.CurrentUpdateIndex).Title, UpdateResult.GetProgress.PercentComplete
WScript.Sleep 500
WEnd
On Error Goto 0
For item = 0 to UpdatesToDownload.Count - 1
If not UpdatesToDownload.Item(item).IsDownloaded then
oLogging.CreateEntry " Failed to download: " & UpdatesToDownload.Item(item).Identity.UpdateID & _
" result(" & UpdateResult.GetProgress.GetUpdateResult(item).ResultCode & ") : " & UpdatesToDownload.Item(item).Title, MSIT_LogType
End if
Next
On Error Resume Next
Downloader.EndDownload UpdateResult
On Error Goto 0
'//----------------------------------------------------------------------------
'// Install Binaries
'//----------------------------------------------------------------------------
oLogging.CreateEntry "Begin Installation...", LogTypeInfo
Set Installer = updateSession.CreateUpdateInstaller()
Installer.Updates = UpdatesToDownload
Set UpdateResult = nothing
On Error Resume Next
Set UpdateResult = Installer.BeginInstall(oProgress, oProgress, vbNull)
If UpdateResult is nothing then
' Some unknown error returned from the installer, reboot and try again.
oLogging.CreateEntry "Installer.Install() returned Unknown failure! " & err.number & " " & Err.Description, LogTypeInfo
oEnvironment.Item("SMSTSRebootRequested") = "true"
oEnvironment.Item("SMSTSRetryRequested") = "true"
Exit Function
End if
On Error Goto 0
On Error Resume Next
While not UpdateResult.IsCompleted
oLogging.ReportProgress "Installing " & UpdatesToDownload(UpdateResult.GetProgress.CurrentUpdateIndex).Title, UpdateResult.GetProgress.PercentComplete
WScript.Sleep 500
WEnd
On Error Goto 0
bReboot = False
bFailure = False
For item = 0 to UpdatesToDownload.Count - 1
If not UpdatesToDownload.Item(item).IsInstalled then
If UpdateResult.GetProgress.GetUpdateResult(item).ResultCode <> 2 then
oLogging.CreateEntry " " & UpdatesToDownload.Item(item).Identity.UpdateID & _
" result(" & UpdateResult.GetProgress.GetUpdateResult(item).ResultCode & " / HR = " & hex(UpdateResult.GetProgress.GetUpdateResult(item).HResult) & _
" ) : " & UpdatesToDownload.Item(item).Title , MSIT_LogType
bFailure = True
End if
If UpdateResult.GetProgress.GetUpdateResult(item).RebootRequired then
bReboot = True
End if
End if
Next
On Error Resume Next
Installer.EndInstall UpdateResult
On Error Goto 0
'//----------------------------------------------------------------------------
'// Cleanup
'//----------------------------------------------------------------------------
If bFailure then
oLogging.CreateEntry "Failure, Please run again!" , LogTypeInfo
oEnvironment.Item("SMSTSRetryRequested") = "true"
oEnvironment.Item("SMSTSRebootRequested") = "true"
ElseIf bReboot then
oLogging.CreateEntry "More to install, Please reboot and run again!" , LogTypeInfo
oEnvironment.Item("SMSTSRetryRequested") = "true"
oEnvironment.Item("SMSTSRebootRequested") = "true"
Else
' A recently installed MicrosoftUpdate/WindowsUpdate component *may* require more/new updates.
' Rerun Main() to ensure that all updates are installed. Exit above when MU/WU returns NO updates.
oLogging.CreateEntry "Success! Please rerun WindowsUpdate to ensure machine is FULLY up to date." , LogTypeInfo
Main = Main()
If LCase(oEnvironment.Item("SMSTSRetryRequested")) <> "true" then
CleanUpWhenDone
End if
End if
End function
'//----------------------------------------------------------------------------
'// Functions
'//----------------------------------------------------------------------------
Function CleanUpWhenDone
Dim NoAutoUpdateState
NoAutoUpdateState = oEnvironment.Item("NoAutoUpdate_Previous")
If NoAutoUpdateState = "<empty>" or NoAutoUpdateState= "" then
oLogging.CreateEntry "Restore NoAutoUpdateKey to <empty>.", LogTypeInfo
On Error Resume Next
oShell.RegDelete "HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\AU\NoAutoUpdate"
On Error Goto 0
ElseIf NoAutoUpdateState <> "" then
oLogging.CreateEntry "Restore NoAutoUpdateKey to " & NoAutoUpdateState, LogTypeInfo
oShell.RegWrite "HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\AU\NoAutoUpdate", NoAutoUpdateState, "REG_DWORD"
Else
oLogging.CreateEntry "Unknown previous NoAutoUpdateKey State, Do Nothing [" & NoAutoUpdateState & "].", LogTypeInfo
End if
End Function
Function VerifyWUA
Dim iResult
Dim strExePath, bUpdateNeeded, objAgentInfo
Dim intMajorVersion
Dim sArchitecture
Dim iNoAutoUpdate
'//----------------------------------------------------------------------------
'// Ensure the desired tracing registry entries are in place
'//----------------------------------------------------------------------------
On error resume next
If UCase(oEnvironment.Item("Debug")) = "TRUE" then
oShell.RegWrite "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Trace\Level", 3, "REG_DWORD"
oShell.RegWrite "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Trace\Handler\Flags", &h000000ff, "REG_DWORD"
oShell.RegWrite "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Trace\Handler\Level", 3, "REG_DWORD"
oShell.RegWrite "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Trace\COMAPI\Flags", &h000000ff, "REG_DWORD"
oShell.RegWrite "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Trace\COMAPI\Level", 3, "REG_DWORD"
On error goto 0
End if
'//----------------------------------------------------------------------------
'// Configure Windows Update settings
'//----------------------------------------------------------------------------
If oEnvironment.Item("WsusServer") <> "" then
' Configure the WSUS server in the registry. This needs to be a URL (e.g. http://myserver).
oLogging.CreateEntry "Configuring client to use WSUS server " & oEnvironment.Item("WsusServer"), LogTypeInfo
oShell.RegWrite "HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\WUServer", oEnvironment.Item("WsusServer"), "REG_SZ"
oShell.RegWrite "HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\WUStatusServer", oEnvironment.Item("WsusServer"), "REG_SZ"
End if
oLogging.CreateEntry "Configuring Windows Update settings (manual update, use server)", LogTypeInfo
If oEnvironment.Item("NoAutoUpdate_Previous") = "" then
On Error Resume Next
iNoAutoUpdate = oShell.RegRead("HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\AU\NoAutoUpdate")
If iNoAutoUpdate = "" then
iNoAutoUpdate = "<empty>"
End if
oLogging.CreateEntry "Archive NoAUtoUpdate State: Was [" & iNoAutoUpdate & "].", LogTypeInfo
oEnvironment.Item("NoAutoUpdate_Previous") = iNoAutoUpdate
On Error Goto 0
End if
oShell.RegWrite "HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\AU\UseWUServer", 1, "REG_DWORD"
oShell.RegWrite "HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\AU\NoAutoUpdate", 1, "REG_DWORD"
' Restart the service to get the latest settings
oShell.Run "net stop wuauserv", 0, true
oShell.Run "net start wuauserv", 0, true
'//----------------------------------------------------------------------------
'// Ensure the needed Windows Update Agent version is installed
'//----------------------------------------------------------------------------
bUpdateNeeded = True ' init value, do not touch
' See if the version is sufficient
On Error Resume Next
Set objAgentInfo = CreateObject("Microsoft.Update.AgentInfo")
If Err.Number = 0 then
' Make sure ApiMajorVersion is 4 or higher (Version 4 is needed to opt-in to Microsoft Update)
intMajorVersion = 0 ' init value
intMajorVersion = objAgentInfo.GetInfo("ApiMajorVersion")
If intMajorVersion >= 4 Then
bUpdateNeeded = False
oLogging.CreateEntry "Windows Update Agent verion " & intMajorVersion & " found, OK to continue", LogTypeInfo
Else
oLogging.CreateEntry "Windows Update Agent verion " & intMajorVersion & " found, upgrade needed", LogTypeInfo
End if
Else
oLogging.CreateEntry "Unable to create Microsoft.Update.AgentInfo object, Windows Update Agent upgrade is needed", LogTypeInfo
End if
If not bUpdateNeeded then
VerifyWUA = 0
Exit Function
End if
'//----------------------------------------------------------------------------
'// Try to find the standalone installer file and install from it
'//----------------------------------------------------------------------------
' From http://technet.microsoft.com/en-us/library/bb932139.aspx, you can obtain the
' Windows Update Agent stand-alone installer from:
'
' http://go.microsoft.com/fwlink/?LinkID=100334 (WindowsUpdateAgent30-x86.exe)
' http://go.microsoft.com/fwlink/?LinkID=100335 (windowsupdateagent30-x64.exe)
'
' Place these files in the Distribution\Tools\<platform> folder so this script can find them.
sArchitecture = lcase(oEnvironment.Item("Architecture"))
If sArchitecture = "" then
sArchitecture = lcase(EES("%Processor_Architecture%"))
End if
If sArchitecture = "amd64" then
sArchitecture = "x64"
End if
iResult = oUtility.FindFile("WindowsUpdateAgent30-" & sArchitecture & ".exe", strExePath)
If iResult = Success then
oLogging.CreateEntry "About to install updated Windows Update Agent from " & strExePath, LogTypeInfo
iResult = oShell.Run(strExePath & " /quiet /norestart", 0, true)
oLogging.CreateEntry "Windows Update Agent installation return code = " & iResult, LogTypeInfo
VerifyWUA = 3010
Exit Function
End if
oLogging.CreateEntry "Unable to find WindowsUpdateAgent30-" & sArchitecture & ".exe, will attempt to download", LogTypeInfo
'//----------------------------------------------------------------------------
'// Download the Windows Update Agent
'//----------------------------------------------------------------------------
' See http://msdn2.microsoft.com/en-us/library/aa387285.aspx for the basic logic used here.
Dim sWURedistCab, oWUXML, sFileVer1, sFileVer2, sWUDownload
sWURedistCab = InternetFileDownload("http://update.microsoft.com/redist/wuredist.cab")
VerifyCriticalFile sWURedistCab, "wuredist.cab"
' Extract XML File
oUtility.RunWithHeartbeat ees("Expand.exe -r " & sWURedistCab & " -F:wuRedist.xml %temp%")
VerifyCriticalFile "%Temp%\WURedist.xml", "wuRedist.xml"
' Load XML File
Set oWUXML = oUtility.CreateXMLDOMObjectEx(EES("%Temp%\WURedist.xml"))
If oWUXML is nothing then
oLogging.CreateEntry "Failed to load: %Temp%\WURedist.xml" , LogTypeError
VerifyWUA = 1
Exit function
End if
' Get Local File Version
sFileVer1 = oFSO.GetFileVersion ( ees("%SystemRoot%\System32\WUAUENG.DLL" ) )
oLogging.CreateEntry "Current Version %SystemRoot%\System32\WUAUENG.DLL : " & sFileVer1 , LogTypeInfo
' Get New File Version
sFileVer2 = oWUXML.selectSingleNode ("//WURedist/StandaloneRedist/architecture[@name='" & sArchitecture & "']/@clientVersion").Text
oLogging.CreateEntry "Current Version wuredist.cab : " & sFileVer2 , LogTypeInfo
' Download and install if file Versions don't match
If sFileVer1 <> sFileVer2 then
sWUDownload = InternetFileDownload( oWUXML.DocumentElement.selectSingleNode ("//WURedist/StandaloneRedist/architecture[@name='" & sArchitecture & "']/@downloadUrl").Text )
VerifyCriticalFile sWUDownload, "WUDownload.exe"
iResult = oUtility.RunWithHeartbeat(sWUDownload & " /wuforce /quiet /norestart")
VerifyWUA = iResult
Exit Function
End if
' Cleanup
On Error Resume Next
For each item in array ( sWURedistCab, EES("%Temp%\WURedist.xml"), sWUDownload )
If oFSO.FileExists(item) then
oFSO.DeleteFile item
End if
Next
On Error Goto 0
End Function
Function InternetFileDownload( InternetURL )
Dim InternetBuffer
Dim ADODB
Set ADODB = CreateObject("ADODB.Stream")
Set InternetBuffer = CreateObject("Msxml2.XmlHttp")
InternetBuffer.open "GET", InternetURL , false
On Error Resume Next
InternetBuffer.send ""
On Error Goto 0
If InternetBuffer.ReadyState = 4 then
oLogging.CreateEntry "Status: " & InternetBuffer.Status & " " & InternetURL, LogTypeInfo
Else
oLogging.CreateEntry "Ready State : " & InternetBuffer.ReadyState & " " & InternetURL , LogTypeWarning
End if
If InternetBuffer.Status = 200 then
If ADODB.State <> 0 then ADODB.Close
ADODB.Type = 1 '(1=binary,2=Text)
ADODB.Mode = 3 '(1=Read,2=Write,3=RW)
ADODB.Open
ADODB.Write InternetBuffer.ResponseBody
ADODB.SaveToFile EES( "%temp%\" & oFSO.GetFileName(InternetURL) ) , 2
ADODB.Close
End if
If InternetBuffer.Status = 200 then
InternetFileDownload = EES( "%temp%\" & oFSO.GetFileName(InternetURL) )
End if
End function
Function FormatLargeSize( lSize )
Dim i
For i = 1 to len(" KMGTPEZY")
If cdbl(lSize) < 1024 ^ i then
FormatLargeSize = int(cdbl(lSize)/(1024^(i-1))) & " " & mid(" KMGTPEZY",i,1) & "B"
Exit function
End if
next
End function
Function EES ( EnvStr )
EES = oShell.ExpandEnvironmentStrings( EnvStr )
End function
Sub VerifyCriticalFile (FileName, Description)
If FileName = "" or not oFSO.FileExists(ees(FileName)) then
oLogging.CreateEntry Description & " not found: " & FileName , LogTypeError
oLogging.CreateEntry " Most likely cause: No Internet Access or unconfigured Proxy settings!", LogTypeError
oLogging.ReportFailure "Critical file " & FileName & " was not found, aborting", 9906
End if
End sub
End Class
Class Progress
Public Default Function Process
End Function
End Class
</script>
</job>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment