Public/OSDCloud/Save-OSDCloud.usb.ps1
<#
.SYNOPSIS Saves Operating System and Driver Pack to an OSDCloud USB Drive .DESCRIPTION Saves Operating System and Driver Pack to an OSDCloud USB Drive .PARAMETER OSVersion Operating System Version to download .PARAMETER OSBuild Operating System Build to download .PARAMETER OSEdition Operating System Edition to download .PARAMETER OSLanguage Operating System Language to download .PARAMETER Manufacturer Computer Manufacturer of the Driver Pack .PARAMETER Product Computer Product of the Driver Pack .LINK https://www.osdcloud.com/build/media/save-osdcloud.usb #> function Save-OSDCloud.usb { [CmdletBinding()] param ( [ValidateSet('Windows 10','Windows 11')] [System.String]$OSVersion, [ValidateSet('21H2','21H1','20H2','2004','1909','1903','1809')] [Alias('Build')] [System.String]$OSBuild, [ValidateSet('Home','Home N','Home Single Language','Education','Education N','Enterprise','Enterprise N','Pro','Pro N')] [Alias('Edition')] [System.String]$OSEdition, [ValidateSet ( 'ar-sa','bg-bg','cs-cz','da-dk','de-de','el-gr', 'en-gb','en-us','es-es','es-mx','et-ee','fi-fi', 'fr-ca','fr-fr','he-il','hr-hr','hu-hu','it-it', 'ja-jp','ko-kr','lt-lt','lv-lv','nb-no','nl-nl', 'pl-pl','pt-br','pt-pt','ro-ro','ru-ru','sk-sk', 'sl-si','sr-latn-rs','sv-se','th-th','tr-tr', 'uk-ua','zh-cn','zh-tw' )] [Alias('Culture','OSCulture')] [System.String]$OSLanguage, [System.String]$Manufacturer = (Get-MyComputerManufacturer -Brief), [System.String]$Product = (Get-MyComputerProduct) ) #================================================= # Start the Clock #================================================= $Global:OSDCloudStartTime = Get-Date #================================================= # Block #================================================= Block-PowerShellVersionLt5 Block-NoCurl Block-WinPE #================================================= # Header #================================================= Write-Host -ForegroundColor DarkGray "=========================================================================" Write-Host -ForegroundColor Cyan "$((Get-Date).ToString('yyyy-MM-dd-HHmmss')) $($MyInvocation.MyCommand.Name)" -NoNewline Write-Host -ForegroundColor Cyan " | Manufacturer: $Manufacturer | Product: $Product" Write-Host -ForegroundColor Cyan "OSDCloud content can be saved to an 8GB+ NTFS USB Volume" Write-Host -ForegroundColor White "Windows 10/11 will require about 4GB, and DriverPacks up to 2GB" #================================================= # Get-Volume.usb #================================================= $GetUSBVolume = Get-Volume.usb | Where-Object {$_.FileSystem -eq 'NTFS'} | Where-Object {$_.SizeGB -ge 8} | Sort-Object DriveLetter -Descending if (-NOT ($GetUSBVolume)) { Write-Warning "Unfortunately, I don't see any USB Volumes that will work" Write-Warning "OSDCloud Failed!" Write-Host -ForegroundColor DarkGray "================================================" Break } Write-Warning "USB Free Space is not verified before downloading yet, so this is on you!" Write-Host -ForegroundColor DarkGray "================================================" if ($GetUSBVolume) { #$GetUSBVolume | Select-Object -Property DriveLetter, FileSystemLabel, SizeGB, SizeRemainingMB, DriveType | Format-Table $SelectUSBVolume = Select-Volume.usb -MinimumSizeGB 8 -FileSystem 'NTFS' $Global:OSDCloudOfflineFullName = "$($SelectUSBVolume.DriveLetter):\OSDCloud" Write-Host -ForegroundColor White "OSDCloud content will be saved to $OSDCloudOfflineFullName" } else { Write-Warning "Save-OSDCloud.usb Requirements:" Write-Warning "8 GB Minimum" Write-Warning "NTFS File System" Break } #================================================= # Autopilot Profiles #================================================= Write-Host -ForegroundColor DarkGray "================================================" Write-Host -ForegroundColor Cyan "Autopilot Profiles" if (-NOT (Test-Path "$OSDCloudOfflineFullName\Config\AutopilotJSON")) { New-Item -Path "$OSDCloudOfflineFullName\Config\AutopilotJSON" -ItemType Directory -Force | Out-Null Write-Host "Autopilot Profiles can be saved to $OSDCloudOfflineFullName\Config\AutopilotJSON" } $FindOSDCloudFile = @() [array]$FindOSDCloudFile = Find-OSDCloudFile -Name $Global:OSDCloudAutopilotJsonName -Path '\OSDCloud\Autopilot\Profiles\' | Sort-Object FullName [array]$FindOSDCloudFile += Find-OSDCloudFile -Name $Global:OSDCloudAutopilotJsonName -Path '\OSDCloud\Config\AutopilotJSON\' | Sort-Object FullName $FindOSDCloudFile = $FindOSDCloudFile | Where-Object {$_.FullName -notlike "C*"} if ($FindOSDCloudFile) { foreach ($Item in $FindOSDCloudFile) { Write-Host -ForegroundColor White "$($Item.FullName)" } } else { Write-Warning "No Autopilot Profiles were found in any <PSDrive>:\OSDCloud\Config\AutopilotJSON" Write-Warning "Autopilot Profiles must be located in a $OSDCloudOfflineFullName\Config\AutopilotJSON direcory" } #================================================= # OSVersion #================================================= Write-Host -ForegroundColor DarkGray "=========================================================================" Write-Host -ForegroundColor Cyan "OSVersion " -NoNewline if ($OSVersion) { Write-Host -ForegroundColor Green $OSVersion } else { Write-Host -ForegroundColor Cyan "Menu" $OSVersionNames = @('Windows 11','Windows 10') $i = $null $OSVersionMenu = foreach ($Item in $OSVersionNames) { $i++ $ObjectProperties = @{ Selection = $i Name = $Item } New-Object -TypeName PSObject -Property $ObjectProperties } $OSVersionMenu | Select-Object -Property Selection, Name | Format-Table | Out-Host do { $SelectReadHost = Read-Host -Prompt "Enter a Selection for the OSVersion" } until (((($SelectReadHost -ge 0) -and ($SelectReadHost -in $OSVersionMenu.Selection)))) $OSVersion = $OSVersionMenu | Where-Object {$_.Selection -eq $SelectReadHost} | Select-Object -ExpandProperty Name Write-Host -ForegroundColor Cyan "OSVersion: " -NoNewline Write-Host -ForegroundColor Green "$OSVersion" } #================================================= # OSBuild #================================================= Write-Host -ForegroundColor DarkGray "=========================================================================" Write-Host -ForegroundColor Cyan "$OSVersion OSBuild " -NoNewline if ($OSVersion -eq 'Windows 11') { $OSBuild = '21H2' } if ($OSBuild) { Write-Host -ForegroundColor Green $OSBuild } else { Write-Host -ForegroundColor Cyan "Menu" $OSBuildNames = @('21H2','21H1','20H2','2004','1909','1903','1809') $i = $null $OSBuildMenu = foreach ($Item in $OSBuildNames) { $i++ $ObjectProperties = @{ Selection = $i Name = $Item } New-Object -TypeName PSObject -Property $ObjectProperties } $OSBuildMenu | Select-Object -Property Selection, Name | Format-Table | Out-Host do { $SelectReadHost = Read-Host -Prompt "Enter a Selection for the $OSVersion OSBuild" } until (((($SelectReadHost -ge 0) -and ($SelectReadHost -in $OSBuildMenu.Selection)))) $OSBuild = $OSBuildMenu | Where-Object {$_.Selection -eq $SelectReadHost} | Select-Object -ExpandProperty Name Write-Host -ForegroundColor Cyan "OSBuild: " -NoNewline Write-Host -ForegroundColor Green "$OSBuild" } #================================================= # OSEdition #================================================= Write-Host -ForegroundColor DarkGray "=========================================================================" Write-Host -ForegroundColor Cyan "$OSVersion $OSBuild OSEdition " -NoNewline if ($PSBoundParameters.ContainsKey('OSEdition')) { Write-Host -ForegroundColor Green $OSEdition } else { Write-Host -ForegroundColor Cyan "Menu" $OSEditionNames = @('Home','Home N','Home Single Language','Education','Education N','Enterprise','Enterprise N','Pro','Pro N') $i = $null $OSEditionMenu = foreach ($Item in $OSEditionNames) { $i++ $ObjectProperties = @{ Selection = $i Name = $Item } New-Object -TypeName PSObject -Property $ObjectProperties } $OSEditionMenu | Select-Object -Property Selection, Name | Format-Table | Out-Host do { $SelectReadHost = Read-Host -Prompt "Enter a Selection for the $OSVersion OSEdition" } until (((($SelectReadHost -ge 0) -and ($SelectReadHost -in $OSEditionMenu.Selection)))) $OSEdition = $OSEditionMenu | Where-Object {$_.Selection -eq $SelectReadHost} | Select-Object -ExpandProperty Name Write-Host -ForegroundColor Cyan "OSEdition: " -NoNewline Write-Host -ForegroundColor Green "$OSEdition" } #================================================= # OSEditionId and OSLicense #================================================= if ($OSEdition -eq 'Home') { $OSEditionId = 'Core' $OSLicense = 'Retail' $ImageIndex = 4 } if ($OSEdition -eq 'Home N') { $OSEditionId = 'CoreN' $OSLicense = 'Retail' $ImageIndex = 5 } if ($OSEdition -eq 'Home Single Language') { $OSEditionId = 'CoreSingleLanguage' $OSLicense = 'Retail' $ImageIndex = 6 } if ($OSEdition -eq 'Enterprise') { $OSEditionId = 'Enterprise' $OSLicense = 'Volume' $ImageIndex = 6 } if ($OSEdition -eq 'Enterprise N') { $OSEditionId = 'EnterpriseN' $OSLicense = 'Volume' $ImageIndex = 7 } #================================================= # OSLicense #================================================= Write-Host -ForegroundColor DarkGray "=========================================================================" Write-Host -ForegroundColor Cyan "$OSVersion $OSBuild $OSEdition OSLicense " -NoNewline if ($OSLicense) { Write-Host -ForegroundColor Green $OSLicense } else { Write-Host -ForegroundColor Cyan "Menu" $OSLicenseNames = @('Retail Windows Consumer Editions','Volume Windows Business Editions') $i = $null $OSLicenseMenu = foreach ($Item in $OSLicenseNames) { $i++ $ObjectProperties = @{ Selection = $i Name = $Item } New-Object -TypeName PSObject -Property $ObjectProperties } $OSLicenseMenu | Select-Object -Property Selection, Name | Format-Table | Out-Host do { $SelectReadHost = Read-Host -Prompt "Enter a Selection for the $OSVersion License" } until (((($SelectReadHost -ge 0) -and ($SelectReadHost -in $OSLicenseMenu.Selection)))) $OSLicenseMenu = $OSLicenseMenu | Where-Object {$_.Selection -eq $SelectReadHost} | Select-Object -ExpandProperty Name if ($OSLicenseMenu -match 'Retail') { $OSLicense = 'Retail' } else { $OSLicense = 'Volume' } Write-Host -ForegroundColor Cyan "OSLicense: " -NoNewline Write-Host -ForegroundColor Green "$OSLicense" } if ($OSEdition -eq 'Education') { $OSEditionId = 'Education' if ($OSLicense -eq 'Retail') {$ImageIndex = 7} if ($OSLicense -eq 'Volume') {$ImageIndex = 4} } if ($OSEdition -eq 'Education N') { $OSEditionId = 'EducationN' if ($OSLicense -eq 'Retail') {$ImageIndex = 8} if ($OSLicense -eq 'Volume') {$ImageIndex = 5} } if ($OSEdition -eq 'Pro') { $OSEditionId = 'Professional' if ($OSLicense -eq 'Retail') {$ImageIndex = 9} if ($OSLicense -eq 'Volume') {$ImageIndex = 8} } if ($OSEdition -eq 'Pro N') { $OSEditionId = 'ProfessionalN' if ($OSLicense -eq 'Retail') {$ImageIndex = 10} if ($OSLicense -eq 'Volume') {$ImageIndex = 9} } Write-Host -ForegroundColor Cyan "OSEditionId: " -NoNewline Write-Host -ForegroundColor Green "$OSEditionId" Write-Host -ForegroundColor Cyan "ImageIndex: " -NoNewline Write-Host -ForegroundColor Green "$ImageIndex" #================================================= # OSLanguage #================================================= Write-Host -ForegroundColor DarkGray "=========================================================================" Write-Host -ForegroundColor Cyan "$OSVersion $OSBuild $OSEdition $OSLicense OSLanguage " -NoNewline if ($PSBoundParameters.ContainsKey('OSLanguage')) { Write-Host -ForegroundColor Green $OSLanguage } else { Write-Host -ForegroundColor Cyan "Menu" $OSLanguageNames = @('ar-sa','bg-bg','cs-cz','da-dk','de-de','el-gr','en-gb','en-us','es-es','es-mx','et-ee','fi-fi','fr-ca','fr-fr','he-il','hr-hr','hu-hu','it-it','ja-jp','ko-kr','lt-lt','lv-lv','nb-no','nl-nl','pl-pl','pt-br','pt-pt','ro-ro','ru-ru','sk-sk','sl-si','sr-latn-rs','sv-se','th-th','tr-tr','uk-ua','zh-cn','zh-tw') $i = $null $OSLanguageMenu = foreach ($Item in $OSLanguageNames) { $i++ $ObjectProperties = @{ Selection = $i Name = $Item } New-Object -TypeName PSObject -Property $ObjectProperties } $OSLanguageMenu | Select-Object -Property Selection, Name | Format-Table | Out-Host do { $SelectReadHost = Read-Host -Prompt "Enter a Selection for the $OSVersion OSLanguage" } until (((($SelectReadHost -ge 0) -and ($SelectReadHost -in $OSLanguageMenu.Selection)))) $OSLanguage = $OSLanguageMenu | Where-Object {$_.Selection -eq $SelectReadHost} | Select-Object -ExpandProperty Name Write-Host -ForegroundColor Cyan "OSLanguage: " -NoNewline Write-Host -ForegroundColor Green "$OSLanguage" } #================================================= # Get-FeatureUpdate #================================================= Write-Host -ForegroundColor DarkGray "=========================================================================" Write-Host -ForegroundColor Cyan "Get-FeatureUpdate" Write-Host -ForegroundColor DarkGray "$OSVersion x64 | OSLicense: $OSLicense | OSBuild: $OSBuild | OSLanguage: $OSLanguage" if ($OSVersion -eq 'Windows 11') { $GetFeatureUpdate = Get-FeatureUpdate -OSVersion 'Windows 11' -OSLicense $OSLicense -OSBuild $OSBuild -OSLanguage $OSLanguage } else { $GetFeatureUpdate = Get-FeatureUpdate -OSLicense $OSLicense -OSBuild $OSBuild -OSLanguage $OSLanguage } if ($GetFeatureUpdate) { $GetFeatureUpdate = $GetFeatureUpdate | Select-Object -Property CreationDate,KBNumber,Title,UpdateOS,UpdateBuild,UpdateArch,FileName, @{Name='SizeMB';Expression={[int]($_.Size /1024/1024)}},FileUri,Hash,AdditionalHash } else { Write-Warning "Unable to locate a $OSVersion Feature Update" Write-Warning "OSDCloud cannot continue" Break } #================================================= # Offline OS #================================================= $OSDCloudOfflineOS = Find-OSDCloudOfflineFile -Name $GetFeatureUpdate.FileName | Select-Object -First 1 if ($OSDCloudOfflineOS) { $OSDCloudOfflineOSFullName = $OSDCloudOfflineOS.FullName Write-Host -ForegroundColor Cyan "Offline: $OSDCloudOfflineOSFullName" } else { if (Test-WebConnection -Uri $GetFeatureUpdate.FileUri) { $SaveFeatureUpdate = Save-FeatureUpdate -OSVersion $OSVersion -OSLicense $OSLicense -OSBuild $OSBuild -OSLanguage $OSLanguage -DownloadPath "$OSDCloudOfflineFullName\OS" | Out-Null } else { Write-Warning "Could not verify an Internet connection for the Windows Feature Update" Write-Warning "OSDCloud cannot continue" Break } } #================================================= # Save-MyDriverPack #================================================= Write-Host -ForegroundColor DarkGray "================================================" Write-Host -ForegroundColor Cyan "Save-MyDriverPack" Save-MyDriverPack -DownloadPath "$OSDCloudOfflineFullName\DriverPacks\$Manufacturer" -Manufacturer $Manufacturer -Product $Product #================================================= # PSGallery Modules #================================================= Write-Host -ForegroundColor DarkGray "================================================" Write-Host -ForegroundColor Cyan "PowerShell Modules and Scripts" #Offline Write-Host "PowerShell Offline Modules and Scripts are located at $OSDCloudOfflineFullName\PowerShell\Offline" Write-Host "This is for Modules and Scripts that OSDCloud needs to add to the Offline OS" Write-Host "" if (-NOT (Test-Path "$OSDCloudOfflineFullName\PowerShell\Offline\Modules")) { New-Item -Path "$OSDCloudOfflineFullName\PowerShell\Offline\Modules" -ItemType Directory -Force | Out-Null } if (-NOT (Test-Path "$OSDCloudOfflineFullName\PowerShell\Offline\Scripts")) { New-Item -Path "$OSDCloudOfflineFullName\PowerShell\Offline\Scripts" -ItemType Directory -Force | Out-Null } #Required Write-Host "PowerShell Required Modules and Scripts are located at $OSDCloudOfflineFullName\PowerShell\Required" Write-Host "This is for Modules and Scripts that you want to add to the Offline OS" Write-Host "" if (-NOT (Test-Path "$OSDCloudOfflineFullName\PowerShell\Required\Modules")) { New-Item -Path "$OSDCloudOfflineFullName\PowerShell\Required\Modules" -ItemType Directory -Force | Out-Null } if (-NOT (Test-Path "$OSDCloudOfflineFullName\PowerShell\Required\Scripts")) { New-Item -Path "$OSDCloudOfflineFullName\PowerShell\Required\Scripts" -ItemType Directory -Force | Out-Null } if (Test-WebConnection -Uri "https://www.powershellgallery.com") { Write-Host -ForegroundColor DarkGray "Save-Module OSD to $OSDCloudOfflineFullName\PowerShell\Offline\Modules" Save-Module -Name OSD -Path "$OSDCloudOfflineFullName\PowerShell\Offline\Modules" Copy-PSModuleToFolder -Name OSD -Destination "$OSDCloudOfflineFullName\PowerShell\Offline\Modules" Write-Host -ForegroundColor DarkGray "Save-Module WindowsAutopilotIntune to $OSDCloudOfflineFullName\PowerShell\Offline\Modules" Save-Module -Name WindowsAutopilotIntune -Path "$OSDCloudOfflineFullName\PowerShell\Offline\Modules" Write-Host -ForegroundColor DarkGray "Save-Module AzureAD to $OSDCloudOfflineFullName\PowerShell\Offline\Modules" Write-Host -ForegroundColor DarkGray "Save-Module Microsoft.Graph.Intune to $OSDCloudOfflineFullName\PowerShell\Offline\Modules" Write-Host -ForegroundColor DarkGray "Save-Script Get-WindowsAutopilotInfo to $OSDCloudOfflineFullName\PowerShell\Offline\Scripts" Save-Script -Name Get-WindowsAutopilotInfo -Path "$OSDCloudOfflineFullName\PowerShell\Offline\Scripts" } else { Write-Warning "Could not validate an Internet connection to the PowerShell Gallery" Write-Warning "OSDCloud cannot continue" Break } #================================================= # Save-OSDCloud.usb Complete #================================================= $Global:OSDCloudEndTime = Get-Date $Global:OSDCloudTimeSpan = New-TimeSpan -Start $Global:OSDCloudStartTime -End $Global:OSDCloudEndTime Write-Host -ForegroundColor DarkGray "================================================" Write-Host -ForegroundColor Yellow "$((Get-Date).ToString('yyyy-MM-dd-HHmmss')) $($MyInvocation.MyCommand.Name) " -NoNewline Write-Host -ForegroundColor Cyan "Completed in $($Global:OSDCloudTimeSpan.ToString("mm' minutes 'ss' seconds'"))!" #================================================= } |