Public/Invoke-OSDCloudDriverPackCM.ps1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
function Invoke-OSDCloudDriverPackCM {
    <#
    .SYNOPSIS
    Downloads a matching DriverPack to %OSDisk%\Drivers
 
    .DESCRIPTION
    Downloads a matching DriverPack to %OSDisk%\Drivers
 
    .LINK
    https://github.com/OSDeploy/OSD/tree/master/Docs
 
    .NOTES
    Requires CURL - typically I run this command first in a previous step, "iex (irm sandbox.osdcloud.com)", which will setup your WinPE environment with installing curl.
    #>

    [CmdletBinding()]
    param (
        [string]$Manufacturer = (Get-MyComputerManufacturer -Brief),
        [string]$Product = (Get-MyComputerProduct)
    )
    #=================================================
    # Make sure we are running in a Task Sequence first
    #=================================================
    try {
        $TSEnv = New-Object -COMObject Microsoft.SMS.TSEnvironment
    }
    catch {
        $TSEnv = $false
    }

    if ($TSEnv -eq $false) {
        Write-Warning "This functions requires a running Task Sequence"
        Start-Sleep -Seconds 5
        Continue
    }
    else {
        function Confirm-TSProgressUISetup(){
        if ($Script:TaskSequenceProgressUi -eq $null){
            try{$Script:TaskSequenceProgressUi = New-Object -ComObject Microsoft.SMS.TSProgressUI}
            catch{throw "Unable to connect to the Task Sequence Progress UI! Please verify you are in a running Task Sequence Environment. Please note: TSProgressUI cannot be loaded during a prestart command.`n`nErrorDetails:`n$_"}
            }
        }
        function Confirm-TSEnvironmentSetup(){
            if ($Script:TaskSequenceEnvironment -eq $null){
                try{$Script:TaskSequenceEnvironment = New-Object -ComObject Microsoft.SMS.TSEnvironment}
                catch{throw "Unable to connect to the Task Sequence Environment! Please verify you are in a running Task Sequence Environment.`n`nErrorDetails:`n$_"}
                }
            }
        function Show-TSActionProgress(){
            param(
                [Parameter(Mandatory=$true)]
                [string] $Message,
                [Parameter(Mandatory=$true)]
                [long] $Step,
                [Parameter(Mandatory=$true)]
                [long] $MaxStep
            )

            Confirm-TSProgressUISetup
            Confirm-TSEnvironmentSetup
            $Script:TaskSequenceProgressUi.ShowActionProgress(`
                $Script:TaskSequenceEnvironment.Value("_SMSTSOrgName"),`
                $Script:TaskSequenceEnvironment.Value("_SMSTSPackageName"),`
                $Script:TaskSequenceEnvironment.Value("_SMSTSCustomProgressDialogMessage"),`
                $Script:TaskSequenceEnvironment.Value("_SMSTSCurrentActionName"),`
                [Convert]::ToUInt32($Script:TaskSequenceEnvironment.Value("_SMSTSNextInstructionPointer")),`
                [Convert]::ToUInt32($Script:TaskSequenceEnvironment.Value("_SMSTSInstructionTableSize")),`
                $Message,`
                $Step,`
                $MaxStep)
        }
    }

    #=================================================
    # Get some Task Sequence variables
    #=================================================
    $DEPLOYROOT = $TSEnv.Value("DEPLOYROOT")
    $DEPLOYDRIVE = $TSEnv.Value("DEPLOYDRIVE") # Z:
    $OSVERSION = $TSEnv.Value("OSVERSION") # WinPE
    $RESOURCEDRIVE = $TSEnv.Value("RESOURCEDRIVE") # Z:
    $OSDISK = $TSEnv.Value("OSDISK") # E:
    $OSDANSWERFILEPATH = $TSEnv.Value("OSDANSWERFILEPATH") # E:\MININT\Unattend.xml
    $TARGETPARTITIONIDENTIFIER = $TSEnv.Value("TARGETPARTITIONIDENTIFIER") # [SELECT * FROM Win32_LogicalDisk WHERE Size = '134343553024' and VolumeName = 'Windows' and VolumeSerialNumber = '90D39B87']
    #=================================================
    # Windows Debug Transcript
    #=================================================
    $OSDiskWindowsDebug = Join-Path $OSDISK 'Windows\Debug'

    if (-NOT (Test-Path -Path $OSDiskWindowsDebug)) {
        New-Item -Path $OSDiskWindowsDebug -ItemType Directory -Force -ErrorAction Ignore | Out-Null
    }
    if (-NOT (Test-Path -Path $OSDiskWindowsDebug)) {
        Write-Warning "Could not create $OSDiskWindowsDebug"
        Start-Sleep -Seconds 5
        Continue
    }

    $Transcript = "$((Get-Date).ToString('yyyy-MM-dd-HHmmss'))-Invoke-OSDCloudDriverPackCM.log"
    Start-Transcript -Path (Join-Path $OSDiskWindowsDebug $Transcript) -ErrorAction Ignore
    #=================================================
    # OSDisk Drivers
    #=================================================
    $OSDiskDrivers = Join-Path $OSDISK 'Drivers'
    Write-Host -ForegroundColor DarkGray "$((Get-Date).ToString('yyyy-MM-dd-HHmmss')) DriverPacks will be downloaded to $OSDiskDrivers"

    if (-NOT (Test-Path -Path $OSDiskDrivers)) {
        New-Item -Path $OSDiskDrivers -ItemType Directory -Force -ErrorAction Ignore | Out-Null
    }
    if (-NOT (Test-Path -Path $OSDiskDrivers)) {
        Write-Warning "Could not create $OSDiskDrivers"
        Start-Sleep -Seconds 5
        Continue
    }
    #=================================================
    # Get-MyDriverPack
    #=================================================
    Write-Host -ForegroundColor DarkGray "$((Get-Date).ToString('yyyy-MM-dd-HHmmss')) Processing function Get-MyDriverPack"
    Write-Host
    if ($Manufacturer -in ('Dell','HP','Lenovo','Microsoft')) {
        $GetMyDriverPack = Get-MyDriverPack -Manufacturer $Manufacturer -Product $Product
    }
    else {
        $GetMyDriverPack = Get-MyDriverPack -Product $Product
    }

    if ($GetMyDriverPack) {     
        $GetMyDriverPackBaseName = ($GetMyDriverPack.FileName).Split('.')[0]
        Write-Host -ForegroundColor Cyan "$((Get-Date).ToString('yyyy-MM-dd-HHmmss')) Matching DriverPack identified"
        Write-Host -ForegroundColor DarkGray "-Name $($GetMyDriverPack.Name)"
        Write-Host -ForegroundColor DarkGray "-BaseName $GetMyDriverPackBaseName"
        Write-Host -ForegroundColor DarkGray "-Product $($GetMyDriverPack.Product)"
        Write-Host -ForegroundColor DarkGray "-FileName $($GetMyDriverPack.FileName)"
        Write-Host -ForegroundColor DarkGray "-Url $($GetMyDriverPack.Url)"
        Write-Host
        $OSDiskDriversFile = Join-Path $OSDiskDrivers $GetMyDriverPack.FileName
        Show-TSActionProgress -Message "Found Driver Pack: $($GetMyDriverPack.FileName)" -Step 1 -MaxStep 5 -ErrorAction SilentlyContinue
    }
    else {
        Write-Warning "$((Get-Date).ToString('yyyy-MM-dd-HHmmss')) There are no DriverPacks for this computer"
        Start-Sleep -Seconds 5
        Continue
    }
    #=================================================
    # Get the DriverPack
    #=================================================
    if ($GetMyDriverPack) {
        $ReadyDriverPack = Get-ChildItem -Path $OSDiskDrivers -File -Force -ErrorAction Ignore | Where-Object {$_.Name -match $GetMyDriverPackBaseName} | Where-Object {$_.Extension -in ('.cab','.zip','.exe')}

        if (-Not ($ReadyDriverPack)) {
            if ((-NOT (Test-Path "$env:SystemRoot\System32\curl.exe")) -and (-NOT (Test-Path "$OSDISK\Windows\System32\curl.exe"))) {
                Write-Warning "$((Get-Date).ToString('yyyy-MM-dd-HHmmss')) Curl is required for this to function"
                Start-Sleep -Seconds 5
                Continue
            }
            if ((-NOT (Test-Path "$env:SystemRoot\System32\curl.exe")) -and (Test-Path "$OSDISK\Windows\System32\curl.exe")) {
                Copy-Item -Path "$OSDISK\Windows\System32\curl.exe" -Destination "$env:SystemRoot\System32\curl.exe" -Force
            }
            if (-NOT (Test-Path "$env:SystemRoot\System32\curl.exe")) {
                Write-Warning "$((Get-Date).ToString('yyyy-MM-dd-HHmmss')) Curl is required for this to function"
                Start-Sleep -Seconds 5
                Continue
            }
            Show-TSActionProgress -Message "Downloading Driver Pack: $($GetMyDriverPack.Url)" -Step 2 -MaxStep 5 -ErrorAction SilentlyContinue
            Save-WebFile -SourceUrl $GetMyDriverPack.Url -DestinationDirectory $OSDiskDrivers -DestinationName $GetMyDriverPack.FileName
        }

        $ReadyDriverPack = Get-ChildItem -Path $OSDiskDrivers -File -Force -ErrorAction Ignore | Where-Object {$_.Name -match $GetMyDriverPackBaseName} | Where-Object {$_.Extension -in ('.cab','.zip','.exe')}
        if ($ReadyDriverPack) {
            $PPKGMethod = $true
            Write-Host -ForegroundColor Cyan "$((Get-Date).ToString('yyyy-MM-dd-HHmmss')) DriverPack has been copied to $OSDiskDrivers"
            if ($ReadyDriverPack.Name -like "sp*.exe"){  #Newer HP Softpaqs are native x64 and will allow to be extracted in WinPE
                Write-Host "Found EXE File: $($ReadyDriverPack.FullName)"
                Show-TSActionProgress -Message "Attempting to Extract HP Driver Pack: $($ReadyDriverPack.FullName)" -Step 3 -MaxStep 5 -ErrorAction SilentlyContinue
                try {Start-Process -FilePath $ReadyDriverPack.FullName -ArgumentList "/s /f $OSDiskDrivers\$GetMyDriverPackBaseName" -Wait}
                catch {Write-Output "Failed to Extract"}
                if (Test-Path "$OSDiskDrivers\$GetMyDriverPackBaseName"){
                    Show-TSActionProgress -Message "Applying HP Driver Pack: $($OSDiskDrivers)\$($GetMyDriverPackBaseName)" -Step 4 -MaxStep 5 -ErrorAction SilentlyContinue
                    Write-Output "Starting DISM /image:C:\ /Add-Driver /driver:$($OSDiskDrivers)\$($GetMyDriverPackBaseName) /recurse"
                    $ArgumentList = "/image:C:\ /Add-Driver /driver:`"$OSDiskDrivers\$GetMyDriverPackBaseName`" /recurse"
                    $null = Start-Process -FilePath 'dism.exe' -ArgumentList $ArgumentList -Wait -NoNewWindow
                    $PPKGMethod = $false
                }
                else {
                    Write-Output "Unable to Extract and Apply Driverpack in WinPE, continue to PPKG method"
                }
            }
            else {
                Write-Output "Did not find EXE file to attempt to extract"
            }

            if ($PPKGMethod -eq $true){
                $OSDCloudDriverPackPPKG = Join-Path (Get-Module -Name OSD -ListAvailable | Sort-Object Version -Descending | Select-Object -First 1).ModuleBase "Provisioning\Invoke-OSDCloudDriverPack.ppkg"
        
                if (Test-Path $OSDCloudDriverPackPPKG) {
                    Show-TSActionProgress -Message "Applying first boot Specialize Provisioning Package" -Step 4 -MaxStep 5 -ErrorAction SilentlyContinue
                    Write-Host
                    Write-Host -ForegroundColor Cyan "$((Get-Date).ToString('yyyy-MM-dd-HHmmss')) Applying first boot Specialize Provisioning Package"
                    Write-Host -ForegroundColor DarkGray "dism.exe /Image=$OSDISK\ /Add-ProvisioningPackage /PackagePath:`"$OSDCloudDriverPackPPKG`""
                    $ArgumentList = "/Image=$OSDISK\ /Add-ProvisioningPackage /PackagePath:`"$OSDCloudDriverPackPPKG`""
                    $null = Start-Process -FilePath 'dism.exe' -ArgumentList $ArgumentList -Wait -NoNewWindow
                }
            }
        }
        else {
            Write-Warning "$((Get-Date).ToString('yyyy-MM-dd-HHmmss')) Could not download the DriverPack"
        }
        Stop-Transcript
        Start-Sleep -Seconds 5
    }
}