-
Notifications
You must be signed in to change notification settings - Fork 10
/
Import-OSBuild.ps1
449 lines (390 loc) · 18.9 KB
/
Import-OSBuild.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
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
<#
.NOTES
===========================================================================
Created on: 1/10/2019
Author: Andrew Jimenez (asjimene) - https://github.com/asjimene/
Filename: Import-OSBuild.ps1
Version: 2020.02.19
===========================================================================
.SYNOPSIS
Imports Image File Builds created using the OSDBuilder tool by David Segura (http://www.osdbuilder.com)
.DESCRIPTION
## OSDBuilder Import Tool
The purpose of this tool is to import OSBuilds and OSMedia created using David Segura's OSDBuilder module into SCCM. It's primary functions are as follows:
1. Copy the OSBuild/OSMedia into the correct content shares (wim file and optionally OS Upgrade Packages)
2. Import the OSBuild/OSMedia into SCCM Operating System Images (Optionally import OS Upgrade Package)
3. Distribute Content to a specified Distribution Point Group
4. Optionally update a specified task sequence step with the new OS Image
.EXAMPLE
.\Import-OSBuild.ps1
Imports an OSBuild wim file only
.EXAMPLE
.\Import-OSBuild.ps1 -ImportOSUpgrade
Import an OSBuild wim file and the cooresponding OS Upgrade Package
.EXAMPLE
.\Import-OSBuild.ps1 -OSUploadName "Windows 10 Enterprise x64 1809" -ImportOSUpgrade
Import the latest OSBuild with the name like "Windows 10 Enterprise x64 1809", and import the cooresponding OSUpgrade package. This flag is helpful for automating the upload process, say... after an OSBuild is completed.
.EXAMPLE
.\Import-OSBuild.ps1 -OSUploadMedia -OSUploadName "Windows 10 Enterprise x64 1809" -UpdateTS -TaskSequenceName "DEV Task Sequence" -TaskSequenceStepName "Install Windows 10 x64"
Import the latest OSMedia with the name like "Windows 10 Enterprise x64 1809", then update the step "Install Windows 10 x64" in the task sequence "DEV Task Sequence" with the newly uploaded media
.EXAMPLE
.\Import-OSBuild -Import-OSMedia -ImportOSUpgrade
Import an OSMedia wim file and the cooresponding OS Upgrade Package
.EXAMPLE
.\Import-OSBuild -UseExistingPackages
Import an OSBuild, but do not create a new wim on the content share, instead update an exising wim
NOTE: This flag cannot be used silently
.EXAMPLE
.\Import-OSBuild -UseExistingPackages -ImportOSUpgrade
Import an OSBuild wim file, and the cooresponding OS Upgrade Package but use an exising wim and Upgrade Package
#>
param (
# Also import the associated OSUpgrade package
[Parameter(Mandatory = $false)]
[switch]$ImportOSUpgrade = $false,
# Import OSMedia instead of OSBuild
[Parameter(Mandatory = $false)]
[switch]$ImportOSMedia = $false,
# Upgrade an existing Image and (optionally) Upgrade Package
[Parameter(Mandatory = $false)]
[switch]$UseExistingPackages = $false,
# Build/Media Name to upload (Uses '-like "*$OSUploadName*"' to choose the latest OSBuild or OSMedia with the provided name)
[Parameter(Mandatory = $false)]
[string]$OSUploadName,
# Update an Operating System image in a task sequence with the newly uploaded Operating System
[Parameter(ParameterSetName = 'TSUpdate', Mandatory = $false)]
[switch]$UpdateTS = $false,
# Specify the Name of the Task Sequence to Update (Requires UpdateTS switch)
[Parameter(ParameterSetName = 'TSUpdate', Mandatory = $true)]
[string]$TaskSequenceName,
# Specify the Name of the Operating System Step to Update (Requires UpdateTS switch)
[Parameter(ParameterSetName = 'TSUpdate', Mandatory = $true)]
[string]$TaskSequenceStepName
)
## Global Variables
# SCCM Variables
$Global:ContentShare = "\\Path\to\Content\share"
$Global:OSUpgradeContentShare = "\\Path\to\OSUpgrades\share"
$Global:SCCMSite = "SITE:"
$Global:PreferredDistributionLoc = "PreferredGroupName" #Must be a distribution point group at this time
# Logging Variables
$Global:LogPath = "$PSScriptRoot\OSDBuilder-Import.log"
$Global:MaxLogSize = 1000kb
# Other Variables
$Global:rCpyThreads = 4 # Number of threads for Robocopy to use during OSUpgrade Copy
## Functions
function Add-LogContent {
param
(
[parameter(Mandatory = $false)]
[switch]$Load,
[parameter(Mandatory = $true)]
$Content
)
if ($Load) {
if ((Get-Item $LogPath -ErrorAction SilentlyContinue).length -gt $MaxLogSize) {
Write-Output "$(Get-Date -Format G) - $Content" > $LogPath
}
else {
Write-Output "$(Get-Date -Format G) - $Content" >> $LogPath
}
}
else {
Write-Output "$(Get-Date -Format G) - $Content" >> $LogPath
}
}
function copy-OSDBuilderObject {
param (
[ValidateSet('Image','UpgradePackage')][string]$Type,
[string]$name,
[string]$source,
[string]$destination
)
If ($Type -eq "Image"){
# Copy the selected install.wim to the ContentShare using the build name
Add-LogContent "Attempting to Copy $source to $destination"
try {
Copy-Item -Path $source -Destination $destination -Force
Add-LogContent "Copy Completed Successfully"
}
catch {
$ErrorMessage = $_.Exception.Message
Add-LogContent "ERROR: Copying $source to $destination failed! Skipping import for $name"
Add-LogContent "ERROR: $ErrorMessage"
}
}
Else {
# Copy the selected Upgrade Package to the ContentShare using the build name
Add-LogContent "Attempting to Copy OS Upgrade Files from $source to $destination"
try {
#Copy-Item -Path "$($source)\OS" -Destination "$destination" -Recurse -Force
$rcpyArguments = "`"$source`" `"$destination`" /MIR /Z /MT:$Global:rCpyThreads"
Add-LogContent "Copy Command: robocopy.exe $rcpyArguments"
Start-Process "robocopy.exe" -ArgumentList $rcpyArguments -Wait -NoNewWindow
Add-LogContent "Copy Completed Successfully"
}
catch {
$ErrorMessage = $_.Exception.Message
Add-LogContent "ERROR: Copying $source to $destination failed! Skipping import for $name"
Add-LogContent "ERROR: $ErrorMessage"
}
}
}
function import-OSDBuilderObject {
param (
[ValidateSet('Image','UpgradePackage')][string]$Type,
[string]$Name,
[string]$Path,
[string]$version,
[string]$Description
)
# Import the Copied wim into SCCM
Add-LogContent "Importing $Name"
Push-Location
Set-Location $Global:SCCMSite
try {
if ($Type -eq "Image"){
New-CMOperatingSystemImage -Name "$Name" -Path "$Path" -Version "$version" -Description "$Description"
Add-LogContent "Successfully Imported the Operating System as $Name"
}
Else {
New-CMOperatingSystemInstaller -Name "$Name" -Path "$Path" -Version "$version" -Description "$Description"
Add-LogContent "Successfully Imported the Operating System as $Name"
}
}
catch {
$ErrorMessage = $_.Exception.Message
Add-LogContent "ERROR: Importing wim into SCCM from $Path failed! Skipping import for $Name"
Add-LogContent "ERROR: $ErrorMessage"
}
Pop-Location
}
function Update-OSContent {
param (
[ValidateSet('Image','UpgradePackage')][string]$Type,
[string]$Name
)
# Distribute the new OSImage to the Specified Distribution Point Group
Add-LogContent "Distributing $Name to $($Global:PreferredDistributionLoc)"
Push-Location
Set-Location $Global:SCCMSite
if ($updateExistingImage){
try {
if ($Type -eq "Image"){
Invoke-CMContentRedistribution -InputObject $(Get-CMOperatingSystemImage -Name "$Name") -DistributionPointGroupName $Global:PreferredDistributionLoc
(Get-CMOperatingSystemImage -Name "$Name").ExecuteMethod("ReloadImageProperties", $null)
Add-LogContent "Successfully Completed Copy, and Re-Distribution of OSBuild: $Name"
}
else {
Invoke-CMContentRedistribution -InputObject $(Get-CMOperatingSystemInstaller -Name "$Name") -DistributionPointGroupName $Global:PreferredDistributionLoc
Add-LogContent "Successfully Completed Copy, and Re-Distribution of OSUpgrade: $Name"
}
}
catch {
$ErrorMessage = $_.Exception.Message
Add-LogContent "ERROR: Distributing OSImage $Name Failed!"
Add-LogContent "ERROR: $ErrorMessage"
}
}
else {
try {
if ($Type -eq "Image"){
Start-CMContentDistribution -OperatingSystemImageName "$Name" -DistributionPointGroupName $Global:PreferredDistributionLoc
(Get-CMOperatingSystemImage -Name "$Name").ExecuteMethod("ReloadImageProperties", $null)
Add-LogContent "Successfully Completed Copy, Import, and Distribution of OSBuild: $Name"
}
else {
Start-CMContentDistribution -OperatingSystemInstallerName "$Name" -DistributionPointGroupName $Global:PreferredDistributionLoc
Add-LogContent "Successfully Completed Copy, Import, and Distribution of OSUpgrade: $Name"
}
}
catch {
$ErrorMessage = $_.Exception.Message
Add-LogContent "ERROR: Distributing OSImage $Name Failed!"
Add-LogContent "ERROR: $ErrorMessage"
}
}
Pop-Location
}
## Main
Add-LogContent -Content "Starting Import-OSBuild" -Load
# Import ConfigurationManager Cmdlets
if (-not (Get-Module ConfigurationManager)) {
try {
Add-LogContent "Importing ConfigurationManager Module"
Import-Module (Join-Path $(Split-Path $env:SMS_ADMIN_UI_PATH) ConfigurationManager.psd1) -ErrorAction SilentlyContinue -WarningAction SilentlyContinue
}
catch {
$ErrorMessage = $_.Exception.Message
Add-LogContent "ERROR: Importing ConfigurationManager Module Failed! Exiting!"
Add-LogContent "ERROR: $ErrorMessage"
Exit
}
}
# Import OSDBuilder Module Cmdlets
if (-not (Get-Module OSDBuilder)) {
try {
Add-LogContent "Importing OSDBuilder Module"
Import-Module OSDBuilder
}
catch {
$ErrorMessage = $_.Exception.Message
Add-LogContent "ERROR: Importing OSDBuilder Module Failed! Exiting!"
Add-LogContent "ERROR: $ErrorMessage"
Exit
}
}
# Check OSDBuilder Version
if ((Get-Module OSDBuilder).Version -lt "19.6.3.0") {
Write-Host "OSDBuilder Version is out-of-date, please upgrade to the latest version"
Add-LogContent "OSDBuilder Version is out-of-date, please upgrade to the latest version"
Exit
}
# Search the OSDBuilder Path for new Wim Files to import, loop if none are selected
$selectedBuilds = $null
while ([System.String]::IsNullOrEmpty($selectedBuilds)) {
if ($ImportOSMedia) {
if ([System.String]::IsNullOrEmpty($OSUploadName)) {
$selectedBuilds = Get-OSMedia -GridView
}
else {
$selectedBuilds = Get-OSMedia | Where-Object -Property Name -like "$OSUploadName*" | Sort-Object ModifiedTime | Select-Object -Last 1
}
Add-LogContent "Selected the Following Media to import: $($SelectedBuilds.Name -join " ; ")"
}
Else {
if ([System.String]::IsNullOrEmpty($OSUploadName)) {
$selectedBuilds = Get-OSBuilds -GridView
}
else {
$selectedBuilds = Get-OSBuilds | Where-Object -Property Name -like "$OSUploadName*" | Sort-Object ModifiedTime | Select-Object -Last 1
}
Add-LogContent "Selected the Following Builds to import: $($SelectedBuilds.Name -join " ; ")"
}
}
if ($UseExistingPackages){
# Get the OSImage name and the OSUpgradePackage name from SCCM
Push-Location
Set-Location $Global:SCCMSite
$OSImageSelection = Get-CMOperatingSystemImage | Select-Object Name,ImageOSVersion,SourceDate,PkgSourcePath | Out-GridView -Title "Select the OS Image to Upgrade" -OutputMode Single
$Global:ContentShare = $OSImageSelection.PkgSourcePath
if ($ImportOSUpgrade) {
$OSUpgradeSelection = Get-CMOperatingSystemInstaller | Select-Object Name,ImageOSVersion,SourceDate,PkgSourcePath | Out-Gridview -Title "Select the Upgrade Package to Update" -OutputMode Single
$Global:OSUpgradeContentShare = $OSUpgradeSelection.PkgSourcePath
}
Pop-Location
}
ForEach ($Build in $SelectedBuilds){
# Set Build Variables
$BuildName = $Build.Name
$BuildVersion = $Build.UBR
$BuildDescription = $Build.Imagename + " Version $BuildVersion - Imported from OSDBuilder on: $(Get-Date -Format G)"
$wimLocation = Join-Path -Path $Build.FullName -ChildPath "OS\sources\install.wim"
$OSLocation = Join-Path -Path $Build.FullName -ChildPath "OS"
if ($Global:ContentShare -like "*.wim") {
Add-LogContent "Specified content location is a wim, will update existing wim, and use existing Upgrade Content Share"
$updateExistingImage = $true
$BuildName = $OSImageSelection.Name
$destinationPath = "$Global:ContentShare"
$osUpgradePath = "$Global:OSUpgradeContentShare"
# Backup the Existing image File (as long as it exists)
try {
Add-LogContent "Backing up: $destinationPath to: $($destinationPath.Replace(".wim","-$((Get-Date).ToString(`"yyyyMMdd`")).wim"))"
Move-Item -path "$destinationPath" -Destination $destinationPath.Replace(".wim","-$((Get-Date).ToString(`"yyyyMMdd`")).wim") -ErrorAction Stop
Add-LogContent "Backed up: $destinationPath to: $($destinationPath.Replace(".wim","-$((Get-Date).ToString(`"yyyyMMdd`")).wim"))"
}
catch {
$ErrorMessage = $_.Exception.Message
Add-LogContent "ERROR: Unable to backup $destinationPath"
Add-LogContent "ERROR: $ErrorMessage"
}
# Backup the Existing Upgrade Content Path
if ($ImportOSUpgrade) {
try {
Add-LogContent "Backing Up $OSUpgradePath to: $OSUpgradePath-$((Get-Date).ToString(`"yyyyMMdd`"))"
Move-Item -path "$OSUpgradePath" -Destination "$OSUpgradePath-$((Get-Date).ToString(`"yyyyMMdd`"))" -ErrorAction Stop
Add-LogContent "Backed Up $OSUpgradePath to: $OSUpgradePath-$((Get-Date).ToString(`"yyyyMMdd`"))"
}
catch {
$ErrorMessage = $_.Exception.Message
Add-LogContent "ERROR: Unable to backup $destinationPath"
Add-LogContent "ERROR: $ErrorMessage"
}
}
} else {
$destinationPath = "$Global:ContentShare\$($Build.Name).wim"
$osUpgradePath = "$Global:OSUpgradeContentShare\$($Build.Name)"
}
# Upgrade and Import OS Item
if ((Test-Path $wimLocation) -and (-not (Test-Path $destinationPath)) -and (-not $updateExistingImage)){
Add-LogContent "Pre-Check Complete - Import can continue"
# Copy the selected install.wim to the ContentShare using the build name
copy-OSDBuilderObject -Type Image -name $BuildName -source $wimLocation -destination $destinationPath
# Import the newly Copied wim
import-OSDBuilderObject -Type Image -Name $BuildName -Path $destinationPath -version $BuildVersion -Description $BuildDescription
# Distribute the new OSImage to the Specified Distribution Point Group
Update-OSContent -Type Image -Name $BuildName
}
elseif ((Test-Path $OSLocation) -and $updateExistingImage) {
Add-LogContent "Pre-Check Complete - Updating Existing OSImage Item - Import can continue"
# Copy the install.wim to the same location as the original
copy-OSDBuilderObject -Type Image -name $BuildName -source $wimLocation -destination $destinationPath
# Redistribute the Content
Update-OSContent -Type Image -Name $BuildName
}
else {
if (-not (Test-Path $wimLocation)){
Add-LogContent "ERROR: install.wim not found at $wimLocation - Skipping import for $($Build.Name)"
}
if (Test-Path $destinationPath){
Add-LogContent "ERROR: $destinationPath already exists! Skipping import for $($Build.Name)"
}
}
# Import OSUpgradePackage
if ($ImportOSUpgrade) {
if ((Test-Path $OSLocation) -and (-not (Test-Path $osUpgradePath)) -and (-not $updateExistingImage)){
Add-LogContent "Pre-Check Complete - Creating New OSUpgrade Item - Import can continue"
# Copy the Upgrade package to the Content Share
copy-OSDBuilderObject -Type UpgradePackage -name $BuildName -source $OSLocation -destination $osUpgradePath
# Import the OS Upgrade Package
import-OSDBuilderObject -Type UpgradePackage -Name $BuildName -Path $osUpgradePath -version $BuildVersion -Description $BuildDescription
# Distribute the Content
Start-Sleep 10 ## Should help with failed content distribution
Update-OSContent -Type UpgradePackage -Name $BuildName
}
elseif ((Test-Path $OSLocation) -and $updateExistingImage) {
Add-LogContent "Pre-Check Complete - Updating Existing OSUpgrade Item - Import can continue"
# Copy the Upgrade package to the Content Share
$OSUpgradeName =$OSUpgradeSelection.Name
copy-OSDBuilderObject -Type UpgradePackage -name $OSUpgradeName -source $OSLocation -destination $osUpgradePath
# Distribute the Content
Start-Sleep 10 ## Should help with failed content distribution
Update-OSContent -Type UpgradePackage -Name $OSUpgradeName
}
Else {
if (-not (Test-Path $wimLocation)){
Add-LogContent "ERROR: install.wim not found at $wimLocation - Skipping import for $($Build.Name)"
}
if (Test-Path $destinationPath){
Add-LogContent "ERROR: $osUpgradePath already exists! Skipping import for $($Build.Name)"
}
}
}
}
if ($UpdateTS) {
Push-Location
Set-Location $Global:SCCMSite
Add-LogContent "Waiting 60 Seconds before updating task sequence (This hopefully prevents some issues)"
Start-Sleep 60
Add-LogContent "Updating Task Sequence Step $TaskSequenceStepName on $TaskSequenceName with new package $BuildName"
Add-LogContent "Set-CMTaskSequenceStepApplyOperatingSystem -ImagePackage (Get-CMOperatingSystemImage -Name `"$BuildName`") -ImagePackageIndex 1 -TaskSequenceName $TaskSequenceName -StepName $TaskSequenceStepName"
try {
Set-CMTaskSequenceStepApplyOperatingSystem -ImagePackage (Get-CMOperatingSystemImage -Name "$BuildName") -ImagePackageIndex 1 -TaskSequenceName $TaskSequenceName -StepName $TaskSequenceStepName -ErrorAction Stop
} catch {
$ErrorMessage = $_.Exception.Message
Add-LogContent "ERROR: Failed to Update Task Sequence"
Add-LogContent $ErrorMessage
}
Pop-Location
}
Add-LogContent "Import-OSBuild has Completed!"