Topic: Sysprep: InstallDrivers.vbs

Hi guys,
I thought I should contribute something back to the community. I've written a simple VBScript to extract the Driver packs and add all the paths sysprep.inf and DevicePaths registry. I've only tested this under Windows XP Sp2 and it is working on my system and under WinPE 2004 with WSH & WMI support. I am using this script to help me with Image Deployment via SMS 2003 to many different systems in our compnay. You will need to edit the script so it can work under your environment; 7za.exe needs to be in the same location of the script.

' =========================================================================================================
' Script Name: InstallDrivers.vbs
' Version:     0.04
' Author :     dat2704
' ==========================================================================================================
' CHANGE LOG
' ==========================================================================================================
' Date       |     Version    | Change Description
' -----------|----------------|------------------------------------------------------------------------------
' 28/06/08 |      0.01       | Removed system model detection &  driver selection function
' 30/06/08 |      0.02       | Improve text insertion method
' 01/07/08 |      0.03       | fix bugs in FindDrivers function
' 02/07/08 |      0.04       | Script function: Automatically add driver paths to DevicePaths Registry Value
'===========================================================================================================

Option Explicit

'DECLARE GLOBAL VARIABLES & CONSTANTS
'====================================
Const wbemFlagReturnImmediately = &h10
Const wbemFlagForwardOnly = &h20
Const ForReading   = 1
Const ForWriting   = 2
Const ForAppending = 8
Const TristateTrue  = -1
Const TristateFalse = 0
Const TristateUseDefault = -2

Dim intExitCode
Dim strSystemDrive
Dim strCurrentPath
Dim strDriverPath
Dim str7zipCmd
Dim strSysprepPath
Dim intNoOfPathsPerLine
Dim strOldSysprepPath

' DECLARE AND CREATE OBJECTS
' ==========================
Dim objFSO
Dim objShell
Dim objEnv
Dim objRegExp
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objShell = CreateObject("WScript.Shell")
Set objEnv = objShell.Environment("PROCESS")
Set objRegExp = new regexp  


' PREPARE DRIVER INSTALLATION
' ============================
strSystemDrive = objShell.ExpandEnvironmentStrings("%SystemDrive%")
strCurrentPath = objFSO.GetParentFolderName(WScript.ScriptFullName)
strDriverPath  = strSystemDrive & "\D"
str7zipCmd     = """" & strCurrentPath & "\7za.exe"" x -y -aoa """ & strCurrentPath & "\*.7z" & """ -o""" & strSystemDrive & """"
strSysprepPath = strSystemDrive & "\Sysprep\sysprep.inf"
strOldSysprepPath = strSysprepPath & ".old"
intExitCode    = 0
objEnv("SEE_MASK_NOZONECHECKS") = 1
intNoOfPathsPerLine = 20

' EXTRACT THE DRIVE PACKS
' =======================
If Not (objFSO.FolderExists (strDriverPath)) Then
	objFSO.CreateFolder (strDriverPath)
End If
intExitCode = objShell.Run (str7zipCmd, 0, True)
If intExitCode <> 0 Then
	WScript.Quit 13
End If

' SCAN AND INDEX ALL DRIVER PATHS
' ===============================
Dim arrDriverPaths
arrDriverPaths = Array ()
FindDrivers (strDriverPath)

' ADD DEVICE PATHS TO SYSPREP
' ===========================
If objFSO.FileExists (strSysprepPath) Then
	
	' Open and Read Sysprep.inf
	' -------------------------
	Dim objSysprep, arrSysprep
	arrSysprep = Array ()
	Set objSysprep = objFSO.OpenTextFile (strSysprepPath, ForReading, False, TristateFalse)
	While Not objSysprep.AtEndOfStream
		arrSysprep = AddArrayRecord (arrSysprep, objSysprep.ReadLine)
	Wend
	objSysprep.Close
	
	' Find the line number of [UNATTENDED]
	' ------------------------------------
	Dim intUnattendedPosition, blnFoundUnattended, strLine
	intUnattendedPosition = 0
	blnFoundUnattended = False
	For Each strLine In arrSysprep
		If Not (StringMatch (strLine, "^\s*;.*$", True)) Then
			blnFoundUnattended = StringMatch (strLine, "^\s*\[Unattended\]\s*$", True)
			If blnFoundUnattended Then
				Exit For
			End If
		End If
		intUnattendedPosition = intUnattendedPosition + 1
	Next
	If Not blnFoundUnattended Then WScript.Quit 13
	
	' Insert OemPnPDriversPath lines the correct way
	' -------------------------------------------------------
	Dim arrTempContainer, strInsertLine, strPath, blnQueueCleared, i, j
	arrTempContainer = Array ()
	strInsertLine = "OemPnPDriversPath="
	i = 0
	j = 0
	For Each strLine In arrSysprep
		If i = intUnattendedPosition Then
			arrTempContainer = AddArrayRecord (arrTempContainer, strLine)			
			
			For Each strPath In arrDriverPaths
				If (j = intNoOfPathsPerLine) Or (Len (strPath) + Len (strInsertLine) >= 4096) Then
					If (Right (strInsertLine, 1) = ";" ) Then
						strInsertLine = left (strInsertLine, Len (strInsertLine)-1)
					End If				
					arrTempContainer = AddArrayRecord (arrTempContainer, strInsertLine)
					strInsertLine = "OemPnPDriversPath=" & strPath & ";"
					blnQueueCleared = True
					j = 0
				Else
					strInsertLine= strInsertLine & strPath & ";"
					blnQueueCleared = False
				End If
				j = j + 1
			Next
			If Not blnQueueCleared Then
				If (Right (strInsertLine, 1) = ";" ) Then
						strInsertLine = left (strInsertLine, Len (strInsertLine)-1)
				End If
				arrTempContainer = AddArrayRecord (arrTempContainer, strInsertLine)
			End If
		Else
			arrTempContainer = AddArrayRecord (arrTempContainer, strLine)
		End If
		i = i +1
	Next
	arrSysprep = arrTempContainer
	
	' Write changes to Sysprep.inf
	' ----------------------------
	objFSO.CopyFile strSysprepPath, strOldSysprepPath, True
	objFSO.DeleteFile strSysprepPath, True
	Set objSysprep = objFSO.OpenTextFile (strSysprepPath, ForWriting, True, TristateFalse)
	For Each strLine In arrSysprep
		objSysprep.WriteLine strLine
	Next
	objSysprep.Close
Else
	WScript.Quit 13
End If

' ADD DRIVER PATHS TO THE REGISTRY
' =================================
Dim strSoftwareHive, strDevicePathsValue, strDevicePathsData
strSoftwareHive = strSystemDrive & "\Windows\System32\Config\Software"
strDevicePathsValue = "HKLM\Temp\Microsoft\Windows\CurrentVersion\DevicePath"

If objFSO.FileExists (strSoftwareHive) Then
	intExitCode = objShell.Run ("REG.EXE LOAD HKLM\Temp """ & strSoftwareHive & """", 0, True)
	If intExitCode = 0 Then
		strDevicePathsData = objShell.RegRead (strDevicePathsValue)
		If Not (strDevicePathsData = "") Then
			If Not (Right (strDevicePathsData, 1) = ";") Then
				strDevicePathsData = strDevicePathsData & ";"
			End If
		End If
		
		' Translate Path into Environment Variables & join it all into a single string
		' ----------------------------------------------------------------------------
		For Each strPath In arrDriverPaths
			Select Case strPath
			Case StringMatch (strPath, "^\S*?\\Windows\\.*?$", True)
				strPath = "%SYSTEMROOT%" & Right (strPath, Len (strPath) - 7) & ";"
			Case StringMatch (strPath, "^\S*?\\Program Files\\.*?$", True)
				strPath = "%PROGRAMFILES%" & Right (strPath, Len (strPath) - 13) & ";"
			Case Else
				strPath = "%SYSTEMDRIVE%\" & strPath & ";"
			End Select
			strDevicePathsData = strDevicePathsData & strPath			
		Next
					
		If Right (strDevicePathsData, 1) = ";" Then
			strDevicePathsData = Left (strDevicePathsData, Len (strDevicePathsData) - 1)
		End If
		intExitCode = objShell.RegWrite (strDevicePathsValue, strDevicePathsData, "REG_EXPAND_SZ")
		intExitCode = objShell.Run ("REG.EXE UNLOAD HKLM\Temp", 0, True)		
	End If
Else
	WScript.Quit 13
End If

' PREPARE TO FINISH
' =================
objEnv.Remove("SEE_MASK_NOZONECHECKS")
WScript.Quit intExitCode


' CUSTOM FUNCTIONS
' ================

Function StringMatch (inString, MatchPattern, IgnoreCase)
	objRegExp.Global = True
	objRegExp.IgnoreCase = IgnoreCase
	objRegExp.Pattern = MatchPattern
	StringMatch = objRegExp.Test (inString)
End Function

Function AddArrayRecord (arrTempArray(), strValue)
	ReDim Preserve  arrTempArray (UBound(arrTempArray) + 1)
	arrTempArray (UBound(arrTempArray)) = RealTrim (strValue)
	AddArrayRecord = arrTempArray
End Function

Function FindDrivers(strFolder)
	Dim objFolder, objFile, objSubFolder, strFolderRelPath
	Set objFolder = objFSO.GetFolder(strFolder)
	
	For Each objFile in objFolder.Files
		If UCase(Right(objFile.Name, 3)) = "INF" Then
			strFolderRelPath = Right (objFolder.Path, Len (objFolder.Path) - 3)
			arrDriverPaths = AddArrayRecord (arrDriverPaths, strFolderRelPath)
			Exit For
		End If
	Next
	For Each objSubFolder in objFolder.SubFolders
		FindDrivers objSubFolder.Path
	Next
End Function

Function isWhiteSpace(charIn)
	Dim intValue
	intValue = Asc(charIn)
	isWhiteSpace = intValue = 9 Or intValue = 10 Or intValue = 13 Or intValue = 32
End Function

Function RealTrim(strIn)
	If Len(strIn) = 0 Then
		RealTrim = strIn
		Exit Function
	End If
	Dim intPos, strOut
	intPos = 1
	While isWhiteSpace(Mid(strIn, intPos, 1))
		intPos = intPos + 1
		If intPos > Len(strIn) Then
			RealTrim = ""
			Exit Function
		End If
	Wend
	strOut = Mid(strIn, intPos)
	intPos = Len(strOut)
	While isWhiteSpace(Mid(strOut, intPos, 1))
		intPos = intPos - 1
	Wend
	RealTrim = Left(strOut, intPos)
End Function

Last edited by dat2704 (2008-07-10 17:50:28)

Re: Sysprep: InstallDrivers.vbs

wow that is quite a contribution!

thanks a million...

PS i added code tags to your code... wink

DP BartPE Tutorial   DP_BASE Tutorial   HWID's Tool     Read BEFORE you post    UserBars!
http://driverpacks.net/userbar/admin-1.png
The DriverPacks, the DP_Base program, and Support Forum are FREE!.

Re: Sysprep: InstallDrivers.vbs

Wow thanks for the work. I am having an issue with this.  I am not a programmer or even a scripter so troubleshooting this issue is tough, though it looks like a very simple fix if you have any type of scripting backgound.  Anyway, here is what I am getting when running the script.

C:\InstallDrivers.vbs
193
41
Expected end of statement
800A0401
Microsoft VBScript compilation error

Thanks for any assistance you can provide.

Re: Sysprep: InstallDrivers.vbs

Jeff, the BBS has a tendency to mess with tabs when you put a txt in "code" tags.

(and I think that when I undo the code tags, it will not correctly resolve to original state.)

a link to the code on a skydrive or whatever else that does not drop spyware and adverts (or long waits) is fine by me.

(besides, google loves long posts and code.)

Last edited by Jaak (2008-07-10 13:58:02)

The answer was 42?
Kind regards, Jaak.

Re: Sysprep: InstallDrivers.vbs

Hi dlowe,
I should have mentioned that the script runs under WinPE environment at the Post Install Phase (before sysprep). I assume you tried to run this script in windows, the script will have an error because it can not load the registry hive at %Windir%\System32\Config\Software. I've modified the script so you can run this under windows.

' =========================================================================================================
' Script Name: InstallDrivers.vbs
' Version:     0.04
' Author :     dat2704
' ==========================================================================================================
' CHANGE LOG
' ==========================================================================================================
' Date       |     Version    | Change Description
' -----------|----------------|------------------------------------------------------------------------------
' 28/06/08 |      0.01       | Removed system model detection &  driver selection function
' 30/06/08 |      0.02       | Improve text insertion method
' 01/07/08 |      0.03       | fix bugs in FindDrivers function
' 02/07/08 |      0.04       | Script function: Automatically add driver paths to DevicePaths Registry Value
'===========================================================================================================

Option Explicit

'DECLARE GLOBAL VARIABLES & CONSTANTS
'====================================
Const wbemFlagReturnImmediately = &h10
Const wbemFlagForwardOnly = &h20
Const ForReading   = 1
Const ForWriting   = 2
Const ForAppending = 8
Const TristateTrue  = -1
Const TristateFalse = 0
Const TristateUseDefault = -2

Dim intExitCode
Dim strSystemDrive
Dim strCurrentPath
Dim strDriverPath
Dim str7zipCmd
Dim strSysprepPath
Dim intNoOfPathsPerLine
Dim strOldSysprepPath

' DECLARE AND CREATE OBJECTS
' ==========================
Dim objFSO
Dim objShell
Dim objEnv
Dim objRegExp
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objShell = CreateObject("WScript.Shell")
Set objEnv = objShell.Environment("PROCESS")
Set objRegExp = new regexp  


' PREPARE DRIVER INSTALLATION
' ============================
strSystemDrive = objShell.ExpandEnvironmentStrings("%SystemDrive%")
strCurrentPath = objFSO.GetParentFolderName(WScript.ScriptFullName)
strDriverPath  = strSystemDrive & "\D"
str7zipCmd     = """" & strCurrentPath & "\7za.exe"" x -y -aoa """ & strCurrentPath & "\*.7z" & """ -o""" & strSystemDrive & """"
strSysprepPath = strSystemDrive & "\Sysprep\sysprep.inf"
strOldSysprepPath = strSysprepPath & ".old"
intExitCode    = 0
objEnv("SEE_MASK_NOZONECHECKS") = 1
intNoOfPathsPerLine = 20

' EXTRACT THE DRIVE PACKS
' =======================
If Not (objFSO.FolderExists (strDriverPath)) Then
    objFSO.CreateFolder (strDriverPath)
End If
intExitCode = objShell.Run (str7zipCmd, 0, True)
If intExitCode <> 0 Then
    WScript.Quit 13
End If

' SCAN AND INDEX ALL DRIVER PATHS
' ===============================
Dim arrDriverPaths
arrDriverPaths = Array ()
FindDrivers (strDriverPath)

' ADD DEVICE PATHS TO SYSPREP
' ===========================
If objFSO.FileExists (strSysprepPath) Then
    
    ' Open and Read Sysprep.inf
    ' -------------------------
    Dim objSysprep, arrSysprep
    arrSysprep = Array ()
    Set objSysprep = objFSO.OpenTextFile (strSysprepPath, ForReading, False, TristateFalse)
    While Not objSysprep.AtEndOfStream
        arrSysprep = AddArrayRecord (arrSysprep, objSysprep.ReadLine)
    Wend
    objSysprep.Close
    
    ' Find the line number of [UNATTENDED]
    ' ------------------------------------
    Dim intUnattendedPosition, blnFoundUnattended, strLine
    intUnattendedPosition = 0
    blnFoundUnattended = False
    For Each strLine In arrSysprep
        If Not (StringMatch (strLine, "^\s*;.*$", True)) Then
            blnFoundUnattended = StringMatch (strLine, "^\s*\[Unattended\]\s*$", True)
            If blnFoundUnattended Then
                Exit For
            End If
        End If
        intUnattendedPosition = intUnattendedPosition + 1
    Next
    If Not blnFoundUnattended Then WScript.Quit 13
    
    ' Insert OemPnPDriversPath lines the correct way
    ' -------------------------------------------------------
    Dim arrTempContainer, strInsertLine, strPath, blnQueueCleared, i, j
    arrTempContainer = Array ()
    strInsertLine = "OemPnPDriversPath="
    i = 0
    j = 0
    For Each strLine In arrSysprep
        If i = intUnattendedPosition Then
            arrTempContainer = AddArrayRecord (arrTempContainer, strLine)            
            
            For Each strPath In arrDriverPaths
                If (j = intNoOfPathsPerLine) Or (Len (strPath) + Len (strInsertLine) >= 4096) Then
                    If (Right (strInsertLine, 1) = ";" ) Then
                        strInsertLine = left (strInsertLine, Len (strInsertLine)-1)
                    End If                
                    arrTempContainer = AddArrayRecord (arrTempContainer, strInsertLine)
                    strInsertLine = "OemPnPDriversPath=" & strPath & ";"
                    blnQueueCleared = True
                    j = 0
                Else
                    strInsertLine= strInsertLine & strPath & ";"
                    blnQueueCleared = False
                End If
                j = j + 1
            Next
            If Not blnQueueCleared Then
                If (Right (strInsertLine, 1) = ";" ) Then
                        strInsertLine = left (strInsertLine, Len (strInsertLine)-1)
                End If
                arrTempContainer = AddArrayRecord (arrTempContainer, strInsertLine)
            End If
        Else
            arrTempContainer = AddArrayRecord (arrTempContainer, strLine)
        End If
        i = i +1
    Next
    arrSysprep = arrTempContainer
    
    ' Write changes to Sysprep.inf
    ' ----------------------------
    objFSO.CopyFile strSysprepPath, strOldSysprepPath, True
    objFSO.DeleteFile strSysprepPath, True
    Set objSysprep = objFSO.OpenTextFile (strSysprepPath, ForWriting, True, TristateFalse)
    For Each strLine In arrSysprep
        objSysprep.WriteLine strLine
    Next
    objSysprep.Close
Else
    WScript.Quit 13
End If

' ADD DRIVER PATHS TO THE REGISTRY
' =================================
Dim strSoftwareHive, strDevicePathsValue, strDevicePathsData
' strSoftwareHive = strSystemDrive & "\Windows\System32\Config\Software"
strDevicePathsValue = "HKLM\Software\Microsoft\Windows\CurrentVersion\DevicePath"

'If objFSO.FileExists (strSoftwareHive) Then
'    intExitCode = objShell.Run ("REG.EXE LOAD HKLM\Temp """ & strSoftwareHive & """", 0, True)
'    If intExitCode = 0 Then
        strDevicePathsData = objShell.RegRead (strDevicePathsValue)
        If Not (strDevicePathsData = "") Then
            If Not (Right (strDevicePathsData, 1) = ";") Then
                strDevicePathsData = strDevicePathsData & ";"
            End If
        End If
        
        ' Translate Path into Environment Variables & join it all into a single string
        ' ----------------------------------------------------------------------------
        For Each strPath In arrDriverPaths
            Select Case strPath
            Case StringMatch (strPath, "^\S*?\\Windows\\.*?$", True)
                strPath = "%SYSTEMROOT%" & Right (strPath, Len (strPath) - 7) & ";"
            Case StringMatch (strPath, "^\S*?\\Program Files\\.*?$", True)
                strPath = "%PROGRAMFILES%" & Right (strPath, Len (strPath) - 13) & ";"
            Case Else
                strPath = "%SYSTEMDRIVE%\" & strPath & ";"
            End Select
            strDevicePathsData = strDevicePathsData & strPath            
        Next
                    
        If Right (strDevicePathsData, 1) = ";" Then
            strDevicePathsData = Left (strDevicePathsData, Len (strDevicePathsData) - 1)
        End If
        intExitCode = objShell.RegWrite (strDevicePathsValue, strDevicePathsData, "REG_EXPAND_SZ")
        ' intExitCode = objShell.Run ("REG.EXE UNLOAD HKLM\Temp", 0, True)        
'    End If
'Else
'    WScript.Quit 13
'End If

' PREPARE TO FINISH
' =================
objEnv.Remove("SEE_MASK_NOZONECHECKS")
WScript.Quit intExitCode


' CUSTOM FUNCTIONS
' ================

Function StringMatch (inString, MatchPattern, IgnoreCase)
    objRegExp.Global = True
    objRegExp.IgnoreCase = IgnoreCase
    objRegExp.Pattern = MatchPattern
    StringMatch = objRegExp.Test (inString)
End Function

Function AddArrayRecord (arrTempArray(), strValue)
    ReDim Preserve  arrTempArray (UBound(arrTempArray) + 1)
    arrTempArray (UBound(arrTempArray)) = RealTrim (strValue)
    AddArrayRecord = arrTempArray
End Function

Function FindDrivers(strFolder)
    Dim objFolder, objFile, objSubFolder, strFolderRelPath
    Set objFolder = objFSO.GetFolder(strFolder)
    
    For Each objFile in objFolder.Files
        If UCase(Right(objFile.Name, 3)) = "INF" Then
            strFolderRelPath = Right (objFolder.Path, Len (objFolder.Path) - 3)
            arrDriverPaths = AddArrayRecord (arrDriverPaths, strFolderRelPath)
            Exit For
        End If
    Next
    For Each objSubFolder in objFolder.SubFolders
        FindDrivers objSubFolder.Path
    Next
End Function

Function isWhiteSpace(charIn)
    Dim intValue
    intValue = Asc(charIn)
    isWhiteSpace = intValue = 9 Or intValue = 10 Or intValue = 13 Or intValue = 32
End Function

Function RealTrim(strIn)
    If Len(strIn) = 0 Then
        RealTrim = strIn
        Exit Function
    End If
    Dim intPos, strOut
    intPos = 1
    While isWhiteSpace(Mid(strIn, intPos, 1))
        intPos = intPos + 1
        If intPos > Len(strIn) Then
            RealTrim = ""
            Exit Function
        End If
    Wend
    strOut = Mid(strIn, intPos)
    intPos = Len(strOut)
    While isWhiteSpace(Mid(strOut, intPos, 1))
        intPos = intPos - 1
    Wend
    RealTrim = Left(strOut, intPos)
End Function

Last edited by dat2704 (2008-07-10 17:52:34)

Re: Sysprep: InstallDrivers.vbs

dat2704 wrote:

Hi dlowe,
I should have mentioned that the script runs under WinPE environment at the Post Install Phase (before sysprep). I assume you tried to run this script in windows, the script will have an error because it can not load the registry hive at %Windir%\System32\Config\Software. I've modified the script so you can run this under windows.

Ah, thanks for your help.  I was able to solve the error but yes, it didn't run as expected.  I will try out this.  Thanks again.