Public/OSDCloud/OSDCloudUSB.ps1
|
function New-OSDCloudUSB { <# .SYNOPSIS Creates resources by using New-OSDCloudUSB. .DESCRIPTION Provides the implementation for New-OSDCloudUSB. .PARAMETER WorkspacePath Specifies the value for WorkspacePath. .PARAMETER fromIsoFile Specifies the value for fromIsoFile. .PARAMETER fromIsoUrl Specifies the value for fromIsoUrl. .EXAMPLE New-OSDCloudUSB -WorkspacePath <WorkspacePath> -fromIsoFile <fromIsoFile> Runs New-OSDCloudUSB with common parameters. .NOTES Author: David Segura - Recast Software 2026-07-09 - Updated comment-based help .LINK https://github.com/OSDeploy/OSD/tree/master/docs #> [CmdletBinding(DefaultParameterSetName='Workspace')] param ( #Path to the OSDCloud Workspace containing the Media directory #This parameter is not necessary if Get-OSDCloudWorkspace can get a return [Parameter(ParameterSetName='Workspace',ValueFromPipelineByPropertyName)] [System.String]$WorkspacePath, #Path to an OSDCloud ISO #This file will be mounted and the contents will be copied to the OSDCloud USB [Parameter(ParameterSetName='fromIsoFile',Mandatory)] [System.IO.FileInfo]$fromIsoFile, #Path to an OSDCloud ISO saved on the internet #This file will be downloaded and mounted and the contents will be copied to the OSDCloud USB [Parameter(ParameterSetName='fromIsoUrl',Mandatory)] [System.String]$fromIsoUrl ) #================================================= # Block #================================================= $CurrentIdentity = [Security.Principal.WindowsIdentity]::GetCurrent() $CurrentPrincipal = [Security.Principal.WindowsPrincipal]::new($CurrentIdentity) if (-not $CurrentPrincipal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) { Write-Warning "[$(Get-Date -format s)] [$($MyInvocation.MyCommand.Name)] Administrative rights are required" return } Block-WindowsVersionNe10 Block-PowerShellVersionLt5 Block-WindowsReleaseIdLt1703 Block-WinPE #================================================= # Initialize #================================================= $BootLabel = 'WinPE' $DataLabel = 'OSDCloudUSB' $ErrorActionPreference = 'Stop' $WinpeSourcePath = $null #================================================= # Resolve Workspace #================================================= if ($PSCmdlet.ParameterSetName -eq 'Workspace') { if ($PSBoundParameters.ContainsKey('WorkspacePath')) { Set-OSDCloudWorkspace -WorkspacePath $WorkspacePath -ErrorAction Stop | Out-Null } $WorkspacePath = Get-OSDCloudWorkspace -ErrorAction Stop if (-NOT ($WorkspacePath)) { Write-Warning "[$(Get-Date -format s)] Unable to find an OSDCloud Workspace" Break } if (-NOT (Test-Path $WorkspacePath)) { Write-Warning "[$(Get-Date -format s)] Unable to find an OSDCloud Workspace at $WorkspacePath" Break } if (-NOT (Test-Path "$WorkspacePath\Media\sources\boot.wim")) { Write-Warning "[$(Get-Date -format s)] Unable to find an OSDCloud WinPE at $WorkspacePath\Media\sources\boot.wim" Break } $WinpeSourcePath = "$WorkspacePath\Media" } #================================================= # Resolve fromIsoFile #================================================= if ($PSCmdlet.ParameterSetName -eq 'fromIsoFile') { $fromIsoFileGetItem = Get-Item -Path $fromIsoFile -ErrorAction Ignore $fromIsoFileFullName = $fromIsoFileGetItem.FullName if ($fromIsoFileGetItem -and $fromIsoFileGetItem.Extension -eq '.iso') { #Do nothing } else { Write-Warning "[$(Get-Date -format s)] Unable to get the properties of $fromIsoFile" Write-Warning "[$(Get-Date -format s)] Something went very very wrong in this process" Break } #================================================= # Mount fromIsoFile #================================================= $Volumes = (Get-Volume).Where({$_.DriveLetter}).DriveLetter Write-Host -ForegroundColor DarkGray "[$(Get-Date -format s)] Mounting OSDCloudISO at $fromIsoFileFullName" $MountDiskImage = Mount-DiskImage -ImagePath $fromIsoFileFullName Start-Sleep -Seconds 3 $MountDiskImageDriveLetter = (Compare-Object -ReferenceObject $Volumes -DifferenceObject (Get-Volume).Where({$_.DriveLetter}).DriveLetter).InputObject if ($MountDiskImageDriveLetter) { $WinpeSourcePath = "$($MountDiskImageDriveLetter):\" } else { Write-Warning "[$(Get-Date -format s)] Unable to mount $MountDiskImage" Write-Warning "[$(Get-Date -format s)] Something went very very wrong in this process" Break } } #================================================= # Resolve CloudISO #================================================= if ($PSCmdlet.ParameterSetName -eq 'fromIsoUrl') { $ResolveUrl = Invoke-WebRequest -Uri $fromIsoUrl -Method Head -MaximumRedirection 0 -UseBasicParsing -ErrorAction SilentlyContinue if ($ResolveUrl.StatusCode -eq 302) { $fromIsoUrl = $ResolveUrl.Headers.Location } $fromIsoFileGetItem = Save-WebFile -SourceUrl $fromIsoUrl -DestinationDirectory (Join-Path $HOME 'Downloads') $fromIsoFileFullName = $fromIsoFileGetItem.FullName if ($fromIsoFileGetItem -and $fromIsoFileGetItem.Extension -eq '.iso') { Write-Host -ForegroundColor DarkGray "[$(Get-Date -format s)] OSDCloudISO downloaded to $fromIsoFileFullName" } else { Write-Warning "[$(Get-Date -format s)] Unable to download OSDCloudISO" Write-Warning "[$(Get-Date -format s)] Something went very very wrong in this process" Break } #================================================= # Mount OSDCloudISO #================================================= $Volumes = (Get-Volume).Where({$_.DriveLetter}).DriveLetter Write-Host -ForegroundColor DarkGray "[$(Get-Date -format s)] Mounting OSDCloudISO" $MountDiskImage = Mount-DiskImage -ImagePath $fromIsoFileFullName Start-Sleep -Seconds 3 $MountDiskImageDriveLetter = (Compare-Object -ReferenceObject $Volumes -DifferenceObject (Get-Volume).Where({$_.DriveLetter}).DriveLetter).InputObject if ($MountDiskImageDriveLetter) { $WinpeSourcePath = "$($MountDiskImageDriveLetter):\" } else { Write-Warning "[$(Get-Date -format s)] Unable to mount $MountDiskImage" Write-Warning "[$(Get-Date -format s)] Something went very very wrong in this process" Break } } #================================================= # Test WinpeSourcePath #================================================= if (-NOT ($WinpeSourcePath)) { Write-Warning "[$(Get-Date -format s)] Unable to find an OSDCloud Media" Break } if (-NOT (Test-Path $WinpeSourcePath)) { Write-Warning "[$(Get-Date -format s)] Unable to find an OSDCloud Media at $WinpeSourcePath" Break } if (-NOT (Test-Path "$WinpeSourcePath\sources\boot.wim")) { Write-Warning "[$(Get-Date -format s)] Unable to find an OSDCloud WinPE at $WinpeSourcePath\sources\boot.wim" Break } #================================================= # New-BootableUSBDrive #================================================= $BootableUSBDrive = New-BootableUSBDrive -BootLabel $BootLabel -DataLabel $DataLabel $BootableUSBDrive = $BootableUSBDrive | Select-Object -First 1 #================================================= # Test USB Volumes #================================================= $WinPEPartition = Get-USBPartition | Where-Object {($_.DiskNumber -eq $BootableUSBDrive.DiskNumber) -and ($_.PartitionNumber -eq 2)} if (-NOT ($WinPEPartition)) { Write-Warning "[$(Get-Date -format s)] Unable to create OSDCloud WinPE Partition" Write-Warning "[$(Get-Date -format s)] Something went very very wrong in this process" Break } $OSDCloudPartition = Get-USBPartition | Where-Object {($_.DiskNumber -eq $BootableUSBDrive.DiskNumber) -and ($_.PartitionNumber -eq 1)} if (-NOT ($OSDCloudPartition)) { Write-Warning "[$(Get-Date -format s)] Unable to create OSDCloud Data Partition" Write-Warning "[$(Get-Date -format s)] Something went very very wrong in this process" Break } #================================================= # WinpeDestinationPath #================================================= $WinpeDestinationPath = "$($WinPEPartition.DriveLetter):\" if (-NOT ($WinpeDestinationPath)) { Write-Warning "[$(Get-Date -format s)] Unable to find Destination Path at $WinpeDestinationPath" Break } #================================================= # Update WinPE Volume #================================================= if ((Test-Path -Path "$WinpeSourcePath") -and (Test-Path -Path "$WinpeDestinationPath")) { Write-Host -ForegroundColor DarkGray "[$(Get-Date -format s)] Copying $WinpeSourcePath to OSDCloud WinPE partition at $WinpeDestinationPath" robocopy "$WinpeSourcePath" "$WinpeDestinationPath" *.* /e /ndl /njh /njs /np /r:0 /w:0 /b /zb } #================================================= # Remove Read-Only Attribute #================================================= Get-ChildItem -Path $WinpeDestinationPath -File -Recurse -Force | foreach { Set-ItemProperty -Path $_.FullName -Name IsReadOnly -Value $false -Force -ErrorAction Ignore } #================================================= # Dismount OSDCloudISO #================================================= if ($MountDiskImage) { Start-Sleep -Seconds 3 Write-Verbose "[$(Get-Date -format s)] [$($MyInvocation.MyCommand.Name)] Dismounting $($MountDiskImage.ImagePath)" $null = Dismount-DiskImage -ImagePath $MountDiskImage.ImagePath } #================================================= # Complete #================================================= Write-Host -ForegroundColor Cyan "[$(Get-Date -format s)] New-OSDCloudUSB is complete" #================================================= } function New-OSDCloudUSBSetupCompleteTemplate { <# .SYNOPSIS Creates resources by using New-OSDCloudUSBSetupCompleteTemplate. .DESCRIPTION Provides the implementation for New-OSDCloudUSBSetupCompleteTemplate. .EXAMPLE New-OSDCloudUSBSetupCompleteTemplate Runs New-OSDCloudUSBSetupCompleteTemplate with common parameters. .NOTES Author: David Segura - Recast Software 2026-07-09 - Updated comment-based help .LINK https://github.com/OSDeploy/OSD/tree/master/docs #> $OSDCloudUSB = Get-Volume.usb | Where-Object {($_.FileSystemLabel -match 'OSDCloud') -or ($_.FileSystemLabel -match 'BHIMAGE')} | Select-Object -First 1 $SetupCompletePath = "$($OSDCloudUSB.DriveLetter):\OSDCloud\Config\Scripts\SetupComplete" $ScriptsPath = $SetupCompletePath if (!(Test-Path -Path $ScriptsPath)){New-Item -Path $ScriptsPath -ItemType Directory -Force} $RunScript = @(@{ Script = "SetupComplete"; BatFile = 'SetupComplete.cmd'; ps1file = 'SetupComplete.ps1';Type = 'Setup'; Path = "$ScriptsPath"}) Write-Output "Creating $($RunScript.Script) Files" $BatFilePath = "$($RunScript.Path)\$($RunScript.batFile)" $PSFilePath = "$($RunScript.Path)\$($RunScript.ps1File)" #Create Batch File to Call PowerShell File if (Test-Path -Path $PSFilePath){ copy-item $PSFilePath -Destination "$ScriptsPath\SetupComplete.ps1.bak" } New-Item -Path $BatFilePath -ItemType File -Force $CustomActionContent = New-Object system.text.stringbuilder [void]$CustomActionContent.Append('%windir%\System32\WindowsPowerShell\v1.0\powershell.exe -ExecutionPolicy ByPass -File C:\OSDCloud\Scripts\SetupComplete\SetupComplete.ps1') Add-Content -Path $BatFilePath -Value $CustomActionContent.ToString() #Create PowerShell File to do actions New-Item -Path $PSFilePath -ItemType File -Force Add-Content -path $PSFilePath 'Write-Output "========================================================="' Add-Content -path $PSFilePath 'Write-Output "Calling Custom Setup Complete File: $($PSCommandPath)"' Add-Content -path $PSFilePath 'Write-Output ""' Add-Content -path $PSFilePath 'Write-Output "CONFIRMED THIS RAN FROM FILE COPIED VIA FLASH DRIVE"' Add-Content -path $PSFilePath 'Write-Output ""' Add-Content -path $PSFilePath 'Write-Output "Completed Custom Setup Complete File: $($PSCommandPath)"' Add-Content -path $PSFilePath 'Write-Output "========================================================="' } function Update-OSDCloudUSB { <# .SYNOPSIS Updates resources by using Update-OSDCloudUSB. .DESCRIPTION Provides the implementation for Update-OSDCloudUSB. .PARAMETER DriverPack Specifies the value for DriverPack. .PARAMETER PSUpdate Indicates whether to enable PSUpdate. .PARAMETER OS Indicates whether to enable OS. .PARAMETER OSLanguage Specifies the value for OSLanguage. .PARAMETER OSActivation Specifies the value for OSActivation. .PARAMETER OSName Specifies the value for OSName. .EXAMPLE Update-OSDCloudUSB -DriverPack <DriverPack> -PSUpdate Runs Update-OSDCloudUSB with common parameters. .NOTES Author: David Segura - Recast Software 2026-07-09 - Updated comment-based help .LINK https://github.com/OSDeploy/OSD/tree/master/docs #> [CmdletBinding()] param ( #Optional. Select one or more of the following Driver Packs to download [ValidateSet('*','ThisPC','Dell','HP','Lenovo','Microsoft')] [System.String[]]$DriverPack, #Updates the required OSDCloud PowerShell Modules [System.Management.Automation.SwitchParameter]$PSUpdate, #Optional. Allows the selection of an Operating System to add to the USB [System.Management.Automation.SwitchParameter]$OS, #Optional. Allows the selection of Driver Packs to download. If this parameter is not used, any language can be downloaded downloaded [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' )] [System.String]$OSLanguage, #Optional. Selects the proper OS License. If this parameter is not used, Operating Systems with the specified License can be downloaded [Alias('Activation','License','OSLicense')] [ValidateSet('Retail','Volume')] [System.String]$OSActivation, #Optional. Selects an Operating System to download #If this parameter is not used, any Operating Systems can be downloaded #'Windows 11 22H2','Windows 11 21H2','Windows 10 22H2','Windows 10 21H2','Windows 10 21H1','Windows 10 20H2','Windows 10 2004','Windows 10 1909','Windows 10 1903','Windows 10 1809' [ValidateSet( 'Windows 11 26H2','Windows 11 25H2','Windows 11 24H2','Windows 11 23H2','Windows 11 22H2','Windows 11 21H2', 'Windows 10 22H2','Windows 10 21H2','Windows 10 21H1','Windows 10 20H2','Windows 10 2004', 'Windows 10 1909H','Windows 10 1903', 'Windows 10 1809' )] [System.String]$OSName ) #================================================= # Block #================================================= Block-WinPE Block-PowerShellVersionLt5 #================================================= # Initialize #================================================= $UsbVolumes = Get-USBVolume $WorkspacePath = Get-OSDCloudWorkspace $IsAdmin = Get-OSDGather -Property IsAdmin #================================================= # Test USB Volumes # Absolutely need to have USB volumes for this # function to work #================================================= Write-Host -ForegroundColor DarkGray "=========================================================================" if ($UsbVolumes) { Write-Host -ForegroundColor DarkGray "[$(Get-Date -format s)] USB volumes found" Write-Host -ForegroundColor DarkGray "=========================================================================" } else { Write-Warning "[$(Get-Date -format s)] Unable to find any USB volumes" Write-Warning "[$(Get-Date -format s)] Plug in a USB drive first" Write-Host -ForegroundColor DarkGray "=========================================================================" Break } #================================================= # Test OSDCloud Workspace # Not a big deal, but can't robocopy against it #================================================= if (! $WorkspacePath) { Write-Warning "[$(Get-Date -format s)] OSDCloud Workspace is not present on this system" Write-Warning "[$(Get-Date -format s)] You will not be able to update the WinPE volume" Write-Host -ForegroundColor DarkGray "=========================================================================" $RobocopyWorkspace = $false } elseif (! (Test-Path $WorkspacePath)) { Write-Warning "[$(Get-Date -format s)] OSDCloud Workspace is not at the path $WorkspacePath" Write-Warning "[$(Get-Date -format s)] You will not be able to update the WinPE volume" Write-Host -ForegroundColor DarkGray "=========================================================================" $RobocopyWorkspace = $false } elseif (! (Test-Path "$WorkspacePath\Media\sources\boot.wim")) { Write-Warning "[$(Get-Date -format s)] OSDCloud WinPE does not exist at $WorkspacePath\Media\sources\boot.wim" Write-Warning "[$(Get-Date -format s)] You will not be able to update the WinPE volume" Write-Host -ForegroundColor DarkGray "=========================================================================" $RobocopyWorkspace = $false } else { $RobocopyWorkspace = $true } #================================================= # Set WinPE USB Volume Label #================================================= $WinpeVolumes = Get-USBVolume | Where-Object {($_.FileSystemLabel -eq 'USBBOOT') -or ($_.FileSystemLabel -eq 'OSDBOOT') -or ($_.FileSystemLabel -eq 'USB BOOT')} if ($WinpeVolumes) { if ($IsAdmin) { Write-Host -ForegroundColor DarkGray "[$(Get-Date -format s)] Setting OSDCloud USB WinPE volume labels to WinPE" foreach ($volume in $WinpeVolumes) { Set-Volume -DriveLetter $volume.DriveLetter -NewFileSystemLabel 'WinPE' -ErrorAction Ignore } } else { Write-Warning "[$(Get-Date -format s)] Unable to set OSDCloud USB WinPE volume label" Write-Warning "[$(Get-Date -format s)] Run this function again elevated with Admin rights" } } #================================================= # Update all WinPE volumes with Workspace #================================================= $WinpeVolumes = Get-USBVolume | Where-Object {($_.FileSystemLabel -eq 'USBBOOT') -or ($_.FileSystemLabel -eq 'OSDBOOT') -or ($_.FileSystemLabel -eq 'USB BOOT') -or ($_.FileSystemLabel -eq 'WinPE')} if ($WinpeVolumes -and $RobocopyWorkspace) { foreach ($volume in $WinpeVolumes) { if (Test-Path -Path "$($volume.DriveLetter):\") { Write-Host -ForegroundColor DarkGray "[$(Get-Date -format s)] ROBOCOPY $WorkspacePath\Media $($volume.DriveLetter):\" robocopy "$WorkspacePath\Media" "$($volume.DriveLetter):\" *.* /e /ndl /njh /njs /np /r:0 /w:0 /xd "$RECYCLE.BIN" "System Volume Information" Write-Host -ForegroundColor DarkGray "=========================================================================" } } } #================================================= # Update OSDCloud Workspace PowerShell #================================================= if ($RobocopyWorkspace) { if ($PSUpdate -or $DriverPack -or $OS -or $OSName -or $OSActivation -or $OSLanguage) { $PowerShellPath = "$WorkspacePath\PowerShell" if (! (Test-Path "$PowerShellPath")) { Write-Host -ForegroundColor DarkGray "[$(Get-Date -format s)] Creating OSDCloud Workspace PowerShell at $WorkspacePath\PowerShell" $null = New-Item -Path "$PowerShellPath" -ItemType Directory -Force -ErrorAction Ignore $UpdateModules = $true } if (! (Test-Path "$PowerShellPath\Offline\Modules")) { $null = New-Item -Path "$PowerShellPath\Offline\Modules" -ItemType Directory -Force -ErrorAction Ignore $UpdateModules = $true } if (! (Test-Path "$PowerShellPath\Offline\Scripts")) { $null = New-Item -Path "$PowerShellPath\Offline\Scripts" -ItemType Directory -Force -ErrorAction Ignore $UpdateModules = $true } if (! (Test-Path "$PowerShellPath\Required\Modules")) { $null = New-Item -Path "$PowerShellPath\Required\Modules" -ItemType Directory -Force -ErrorAction Ignore } if (! (Test-Path "$PowerShellPath\Required\Scripts")) { $null = New-Item -Path "$PowerShellPath\Required\Scripts" -ItemType Directory -Force -ErrorAction Ignore } } } #================================================= # Update OSDCloud Workspace PowerShell #================================================= if ($RobocopyWorkspace) { if ($UpdateModules -or $PSUpdate) { Write-Host -ForegroundColor DarkGray "[$(Get-Date -format s)] Updating OSDCloud Workspace PowerShell Modules and Scripts at $PowerShellPath" try { Save-Module OSD -Path "$PowerShellPath\Offline\Modules" -ErrorAction Stop } catch { Write-Warning "[$(Get-Date -format s)] There were some issues updating the OSD PowerShell Module at $PowerShellPath\Offline\Modules" Write-Warning "[$(Get-Date -format s)] Make sure you have an Internet connection and can access powershellgallery.com" } try { Save-Module WindowsAutoPilotIntune -Path "$PowerShellPath\Offline\Modules" -ErrorAction Stop } catch { Write-Warning "[$(Get-Date -format s)] There were some issues updating the WindowsAutoPilotIntune PowerShell Module at $PowerShellPath\Offline\Modules" Write-Warning "[$(Get-Date -format s)] Make sure you have an Internet connection and can access powershellgallery.com" } try { Save-Script -Name Get-WindowsAutopilotInfo -Path "$PowerShellPath\Offline\Scripts" -ErrorAction Stop } catch { Write-Warning "[$(Get-Date -format s)] There were some issues updating the Get-WindowsAutopilotInfo PowerShell Script at $PowerShellPath\Offline\Scripts" Write-Warning "[$(Get-Date -format s)] Make sure you have an Internet connection and can access powershellgallery.com" } } } #================================================= # OSDCloudVolumes #================================================= $OSDCloudVolumes = Get-USBVolume | Where-Object {$_.FileSystemLabel -eq 'OSDCloud'} | Where-Object {$_.SizeGB -ge 8} | Sort-Object DriveLetter -Descending if ($OSDCloudVolumes) { if ($IsAdmin) { Write-Host -ForegroundColor DarkGray "[$(Get-Date -format s)] Setting OSDCloud USB volume labels to OSDCloudUSB" foreach ($volume in $OSDCloudVolumes) { Set-Volume -DriveLetter $volume.DriveLetter -NewFileSystemLabel 'OSDCloudUSB' -ErrorAction Ignore } } else { Write-Warning "[$(Get-Date -format s)] Unable to set OSDCloud USB volume label" Write-Warning "[$(Get-Date -format s)] Run this function again elevated with Admin rights" } } #================================================= # IsOfflineReady #================================================= $OSDCloudVolumes = Get-USBVolume | Where-Object {($_.FileSystemLabel -match 'OSDCloud') -or ($_.FileSystemLabel -match 'BHIMAGE')} | Where-Object {$_.SizeGB -ge 8} | Sort-Object DriveLetter -Descending $IsOfflineReady = $false if ($RobocopyWorkspace -and $OSDCloudVolumes) { foreach ($volume in $OSDCloudVolumes) { if (Test-Path "$($volume.DriveLetter):\OSDCloud") { $IsOfflineReady = $true } } } #================================================= # Update OSDCloud Offline #================================================= if ($RobocopyWorkspace -and $OSDCloudVolumes) { foreach ($volume in $OSDCloudVolumes) { if ($IsOfflineReady -or $UpdateModules -or $PSUpdate -or $DriverPack -or $OS -or $OSName -or $OSActivation -or $OSLanguage) { if (Test-Path "$WorkspacePath\Config") { Write-Host -ForegroundColor DarkGray "[$(Get-Date -format s)] ROBOCOPY $WorkspacePath\Config $($volume.DriveLetter):\OSDCloud\Config" robocopy "$WorkspacePath\Config" "$($volume.DriveLetter):\OSDCloud\Config" *.* /e /mt /ndl /njh /njs /r:0 /w:0 /xd "$RECYCLE.BIN" "System Volume Information" Write-Host -ForegroundColor DarkGray "=========================================================================" } if (Test-Path "$WorkspacePath\DriverPacks") { Write-Host -ForegroundColor DarkGray "[$(Get-Date -format s)] ROBOCOPY $WorkspacePath\DriverPacks $($volume.DriveLetter):\OSDCloud\DriverPacks" robocopy "$WorkspacePath\DriverPacks" "$($volume.DriveLetter):\OSDCloud\DriverPacks" *.* /e /mt /ndl /njh /njs /r:0 /w:0 /xd "$RECYCLE.BIN" "System Volume Information" Write-Host -ForegroundColor DarkGray "=========================================================================" } if (Test-Path "$WorkspacePath\OS") { Write-Host -ForegroundColor DarkGray "[$(Get-Date -format s)] ROBOCOPY $WorkspacePath\OS $($volume.DriveLetter):\OSDCloud\OS" robocopy "$WorkspacePath\OS" "$($volume.DriveLetter):\OSDCloud\OS" *.* /e /mt /ndl /njh /njs /r:0 /w:0 /xd "$RECYCLE.BIN" "System Volume Information" Write-Host -ForegroundColor DarkGray "=========================================================================" } if (Test-Path "$WorkspacePath\PowerShell") { Write-Host -ForegroundColor DarkGray "[$(Get-Date -format s)] ROBOCOPY $WorkspacePath\PowerShell $($volume.DriveLetter):\OSDCloud\PowerShell" robocopy "$WorkspacePath\PowerShell" "$($volume.DriveLetter):\OSDCloud\PowerShell" *.* /e /mt /ndl /njh /njs /r:0 /w:0 /xd "$RECYCLE.BIN" "System Volume Information" Write-Host -ForegroundColor DarkGray "=========================================================================" } } } } #================================================= # Single OSDCloudVolume #================================================= if ($OSDCloudVolumes) { if ($DriverPack -or $OS -or $OSName -or $OSActivation -or $OSLanguage) { if (! ($OSDCloudVolumes)) { Write-Warning "[$(Get-Date -format s)] Unable to find an OSDCloud USB volume" Write-Warning "[$(Get-Date -format s)] The USB volume must be labeled OSDCloud and be at least 8GB in size" Write-Host -ForegroundColor DarkGray "=========================================================================" Break } if (($OSDCloudVolumes | Measure-Object).Count -gt 1) { Write-Host -ForegroundColor Yellow "[$(Get-Date -format s)] Select a single OSDCloud USB volume in PowerShell GridView and press OK" $OSDCloudVolumes = $OSDCloudVolumes | Out-GridView -Title 'Select an OSDCloud USB volume and press OK' -OutputMode Single } if (! ($OSDCloudVolumes)) { Write-Warning "[$(Get-Date -format s)] You must select one OSDCloud USB volume" Write-Host -ForegroundColor DarkGray "=========================================================================" Break } } } #================================================= # OSDCloud OSName #================================================= if (($OSDCloudVolumes | Measure-Object).Count -eq 1) { if ($OS -or $OSName -or $OSActivation -or $OSLanguage) { $OSDownloadPath = "$($OSDCloudVolumes.DriveLetter):\OSDCloud\OS" $OSDCloudSavedOS = $null if (Test-Path $OSDownloadPath) { $OSDCloudSavedOS = Get-ChildItem -Path $OSDownloadPath *.esd -Recurse -File | Select-Object -ExpandProperty Name } #$OperatingSystems = Get-WSUSXML -Catalog FeatureUpdate -UpdateArch 'x64' -Silent $OperatingSystems = Get-OSDCloudOperatingSystems if ($OSName) { #$OperatingSystems = $OperatingSystems | Where-Object {$_.Catalog -cmatch $OSName} $OperatingSystems = $OperatingSystems | Where-Object {$_.Name -cmatch $OSName} } if ($OSActivation -eq 'Retail') { #$OperatingSystems = $OperatingSystems | Where-Object {$_.Title -match 'consumer'} $OperatingSystems = $OperatingSystems | Where-Object {$_.Activation -match 'Retail'} } if ($OSActivation -eq 'Volume') { #$OperatingSystems = $OperatingSystems | Where-Object {$_.Title -match 'business'} $OperatingSystems = $OperatingSystems | Where-Object {$_.Activation -match 'Volume'} } if ($OSLanguage){ #$OperatingSystems = $OperatingSystems | Where-Object {$_.Title -match $OSLanguage} $OperatingSystems = $OperatingSystems | Where-Object {$_.Language -match $OSLanguage} } if ($OperatingSystems) { $OperatingSystems = $OperatingSystems | Sort-Object Title foreach ($Item in $OperatingSystems) { #$Item.Catalog = $Item.Catalog -replace 'FeatureUpdate ','' if ($OSDCloudSavedOS) { if ($Item.FileName -in $OSDCloudSavedOS) { $Item.Status = 'Downloaded' } } } #$OperatingSystems = $OperatingSystems | Select-Object -Property OSDVersion,OSDStatus,@{Name='OperatingSystem';Expression={($_.Catalog)}},Title,CreationDate,FileUri,FileName $OperatingSystems = $OperatingSystems | Select-Object -Property Version,ReleaseID,Status,Name,ReleaseDate,Url,FileName Write-Host -ForegroundColor Yellow "[$(Get-Date -format s)] Select one or more Operating Systems to download in PowerShell GridView" #$OperatingSystems = $OperatingSystems | Sort-Object -Property @{Expression='OSDStatus';Descending=$true}, OperatingSystem -Descending | Out-GridView -Title 'Select one or more Operating Systems to download and press OK' -PassThru $OperatingSystems = $OperatingSystems | Sort-Object -Property @{Expression='Status';Descending=$true}, Name -Descending | Out-GridView -Title 'Select one or more Operating Systems to download and press OK' -PassThru foreach ($OperatingSystem in $OperatingSystems) { if ($OperatingSystem.Status -eq 'Downloaded') { Get-ChildItem -Path $OSDownloadPath -Recurse -Include $OperatingSystem.FileName | Select-Object -ExpandProperty FullName } elseif (Test-WebConnection -Uri "$($OperatingSystem.Url)") { #$OSDownloadChildPath = Join-Path $OSDownloadPath (($OperatingSystem.Catalog) -replace 'FeatureUpdate ','') #$OSDownloadChildPath = Join-Path $OSDownloadPath $($OperatingSystem.OperatingSystem) $FolderName = "$($OperatingSystem.Version) $($OperatingSystem.ReleaseID)" $OSDownloadChildPath = Join-Path $OSDownloadPath $FolderName Write-Host -ForegroundColor DarkGray "[$(Get-Date -format s)] Downloading OSDCloud Operating System to $OSDownloadChildPath" #$SaveWebFile = Save-WebFile -SourceUrl $OperatingSystem.FileUri -DestinationDirectory "$OSDownloadChildPath" -DestinationName $OperatingSystem.FileName $SaveWebFile = Save-WebFile -SourceUrl $OperatingSystem.Url -DestinationDirectory "$OSDownloadChildPath" -DestinationName $OperatingSystem.FileName if (Test-Path $SaveWebFile.FullName) { Get-Item $SaveWebFile.FullName } else { Write-Warning "[$(Get-Date -format s)] Could not download the Operating System" } } else { Write-Warning "[$(Get-Date -format s)] Could not verify an Internet connection for the Operating System" } } } else { Write-Warning "[$(Get-Date -format s)] Unable to determine a suitable Operating System" } Write-Host -ForegroundColor DarkGray "=========================================================================" } else { } } #================================================= # OSDCloud DriverPack #================================================= if (($OSDCloudVolumes | Measure-Object).Count -eq 1) { if ($DriverPack) { Write-Host -ForegroundColor DarkGray "[$(Get-Date -format s)] DriverPacks will require up to 2GB each" $DriverPackDownloadPath = "$($OSDCloudVolumes.DriveLetter):\OSDCloud\DriverPacks" $OSDCloudSavedDriverPacks = $null if (Test-Path $DriverPackDownloadPath) { $OSDCloudSavedDriverPacks = Get-ChildItem -Path $DriverPackDownloadPath *.* -Recurse -File | Select-Object -ExpandProperty Name } if ($DriverPack -contains '*') { $DriverPack = 'ThisPC','Dell','HP','Lenovo','Microsoft' } if ($DriverPack -contains 'ThisPC') { $Manufacturer = Get-MyComputerManufacturer -Brief Save-MyDriverPack -DownloadPath "$DriverPackDownloadPath\$Manufacturer" } if ($DriverPack -contains 'Dell') { Get-DellDriverPackCatalog -DownloadPath "$DriverPackDownloadPath\Dell" } if ($DriverPack -contains 'HP') { Get-HPDriverPackCatalog -DownloadPath "$DriverPackDownloadPath\HP" } if ($DriverPack -contains 'Lenovo') { Get-LenovoDriverPackCatalog -DownloadPath "$DriverPackDownloadPath\Lenovo" } if ($DriverPack -contains 'Microsoft') { Get-SurfaceDriverPackCatalog -DownloadPath "$DriverPackDownloadPath\Microsoft" } Write-Host -ForegroundColor DarkGray "=========================================================================" } else { } } #================================================= # PowerShell #================================================= if (($OSDCloudVolumes | Measure-Object).Count -eq 1) { if (Test-Path "$($OSDCloudVolumes.DriveLetter):\OSDCloud") { $PowerShellPath = "$($OSDCloudVolumes.DriveLetter):\OSDCloud\PowerShell" if (-not (Test-Path "$PowerShellPath")) { $null = New-Item -Path "$PowerShellPath" -ItemType Directory -Force -ErrorAction Ignore $UpdateModules = $true } if (-not (Test-Path "$PowerShellPath\Offline\Modules")) { $null = New-Item -Path "$PowerShellPath\Offline\Modules" -ItemType Directory -Force -ErrorAction Ignore $UpdateModules = $true } if (-not (Test-Path "$PowerShellPath\Offline\Scripts")) { $null = New-Item -Path "$PowerShellPath\Offline\Scripts" -ItemType Directory -Force -ErrorAction Ignore $UpdateModules = $true } if (-not (Test-Path "$PowerShellPath\Required\Modules")) { $null = New-Item -Path "$PowerShellPath\Required\Modules" -ItemType Directory -Force -ErrorAction Ignore } if (-not (Test-Path "$PowerShellPath\Required\Scripts")) { $null = New-Item -Path "$PowerShellPath\Required\Scripts" -ItemType Directory -Force -ErrorAction Ignore } } } #================================================= # Online #================================================= if ($OSDCloudVolumes -and $IsOfflineReady) { if ($UpdateModules -or $PSUpdate) { if (($OSDCloudVolumes | Measure-Object).Count -eq 1) { if (Test-Path "$($OSDCloudVolumes.DriveLetter):\OSDCloud") { Write-Host -ForegroundColor DarkGray "[$(Get-Date -format s)] Updating OSD and WindowsAutoPilotIntune PowerShell Modules at $PowerShellPath" try { Save-Module OSD -Path "$PowerShellPath\Offline\Modules" -ErrorAction Stop } catch { Write-Warning "[$(Get-Date -format s)] There were some issues updating the OSD PowerShell Module at $PowerShellPath\Offline\Modules" Write-Warning "[$(Get-Date -format s)] Make sure you have an Internet connection and can access powershellgallery.com" } try { Save-Module WindowsAutoPilotIntune -Path "$PowerShellPath\Offline\Modules" -ErrorAction Stop } catch { Write-Warning "[$(Get-Date -format s)] There were some issues updating the WindowsAutoPilotIntune PowerShell Module at $PowerShellPath\Offline\Modules" Write-Warning "[$(Get-Date -format s)] Make sure you have an Internet connection and can access powershellgallery.com" } try { Save-Script -Name Get-WindowsAutopilotInfo -Path "$PowerShellPath\Offline\Scripts" -ErrorAction Stop } catch { Write-Warning "[$(Get-Date -format s)] There were some issues updating the Get-WindowsAutopilotInfo PowerShell Script at $PowerShellPath\Offline\Scripts" Write-Warning "[$(Get-Date -format s)] Make sure you have an Internet connection and can access powershellgallery.com" } Write-Host -ForegroundColor DarkGray "=========================================================================" } } } else { } } #================================================= # Complete #================================================= Write-Host -ForegroundColor Yellow "Download a Driver Pack to OSDCloud USB:" Write-Host -ForegroundColor Gray "Update-OSDCloudUSB -DriverPack *" Write-Host -ForegroundColor Gray "Update-OSDCloudUSB -DriverPack ThisPC" Write-Host -ForegroundColor Gray "Update-OSDCloudUSB -DriverPack Dell" Write-Host -ForegroundColor Gray "Update-OSDCloudUSB -DriverPack Dell,HP,Lenovo,Microsoft" Write-Host -ForegroundColor DarkGray "=========================================================================" Write-Host -ForegroundColor Yellow "Download an Operating System to OSDCloud USB:" Write-Host -ForegroundColor Gray "Update-OSDCloudUSB -OS" Write-Host -ForegroundColor Gray "Update-OSDCloudUSB -OSName 'Windows 11 26H2'" Write-Host -ForegroundColor Gray "Update-OSDCloudUSB -OSLanguage en-us" Write-Host -ForegroundColor Gray "Update-OSDCloudUSB -OSActivation Volume" Write-Host -ForegroundColor Gray "Update-OSDCloudUSB -OSName 'Windows 11 26H2' -OSLanguage en-us" Write-Host -ForegroundColor Gray "Update-OSDCloudUSB -OSName 'Windows 11 26H2' -OSLanguage de-de -OSActivation Volume" Write-Host -ForegroundColor DarkGray "=========================================================================" Write-Host -ForegroundColor Yellow "Update Offline PowerShell Modules and Scripts:" Write-Host -ForegroundColor Gray "Update-OSDCloudUSB -PSUpdate" Write-Host -ForegroundColor DarkGray "=========================================================================" Write-Host -ForegroundColor Cyan "[$(Get-Date -format s)] Update-OSDCloudUSB is complete" #================================================= } |