Created
May 13, 2020 17:27
-
-
Save azure365pro/aa423af149dd5a7b4733a47f92378e77 to your computer and use it in GitHub Desktop.
SCCM Task Sequence Scripts
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
New-ItemProperty -path "Microsoft.PowerShell.Core\Registry::HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\JavaSoft\Java Update\Policy" -Name "EnableJavaUpdate" -PropertyType Dword -Value "0" -force |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Import-StartLayout -LayoutPath $PSScriptRoot\Layout.xml -MountPath $env:SystemDrive\ |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<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> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
' // *************************************************************************** | |
' // | |
' // 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") & "¤tStep=" & 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 | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<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