Public/OSDCloudSetup/OSDCloudUSB.ps1
function New-OSDCloudUSB { <# .SYNOPSIS Creates an OSDCloud USB Drive and copies the contents of the OSDCloud Workspace Media directory Clear, Initialize, Partition (WinPE and OSDCloudUSB), and Format a USB Disk Requires Admin Rights .DESCRIPTION Creates an OSDCloud USB Drive and copies the contents of the OSDCloud Workspace Media directory Clear, Initialize, Partition (WinPE and OSDCloud), and Format a USB Disk Requires Admin Rights .EXAMPLE New-OSDCloudUSB -WorkspacePath C:\OSDCloud .EXAMPLE New-OSDCloudUSB -fromIsoFile D:\osdcloud.iso .EXAMPLE New-OSDCloudUSB -fromIsoUrl https://contoso.blob.core.windows.net/public/osdcloud.iso .LINK https://www.osdcloud.com/setup/osdcloud-usb #> [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 #================================================= Block-StandardUser 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).ToString('yyyy-MM-dd-HHmmss')) Unable to find an OSDCloud Workspace" Break } if (-NOT (Test-Path $WorkspacePath)) { Write-Warning "$((Get-Date).ToString('yyyy-MM-dd-HHmmss')) Unable to find an OSDCloud Workspace at $WorkspacePath" Break } if (-NOT (Test-Path "$WorkspacePath\Media\sources\boot.wim")) { Write-Warning "$((Get-Date).ToString('yyyy-MM-dd-HHmmss')) 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).ToString('yyyy-MM-dd-HHmmss')) Unable to get the properties of $fromIsoFile" Write-Warning "$((Get-Date).ToString('yyyy-MM-dd-HHmmss')) Something went very very wrong in this process" Break } #================================================= # Mount fromIsoFile #================================================= $Volumes = (Get-Volume).Where({$_.DriveLetter}).DriveLetter Write-Host -ForegroundColor DarkGray "$((Get-Date).ToString('yyyy-MM-dd-HHmmss')) 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).ToString('yyyy-MM-dd-HHmmss')) Unable to mount $MountDiskImage" Write-Warning "$((Get-Date).ToString('yyyy-MM-dd-HHmmss')) 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).ToString('yyyy-MM-dd-HHmmss')) OSDCloudISO downloaded to $fromIsoFileFullName" } else { Write-Warning "$((Get-Date).ToString('yyyy-MM-dd-HHmmss')) Unable to download OSDCloudISO" Write-Warning "$((Get-Date).ToString('yyyy-MM-dd-HHmmss')) Something went very very wrong in this process" Break } #================================================= # Mount OSDCloudISO #================================================= $Volumes = (Get-Volume).Where({$_.DriveLetter}).DriveLetter Write-Host -ForegroundColor DarkGray "$((Get-Date).ToString('yyyy-MM-dd-HHmmss')) 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).ToString('yyyy-MM-dd-HHmmss')) Unable to mount $MountDiskImage" Write-Warning "$((Get-Date).ToString('yyyy-MM-dd-HHmmss')) Something went very very wrong in this process" Break } } #================================================= # Test WinpeSourcePath #================================================= if (-NOT ($WinpeSourcePath)) { Write-Warning "$((Get-Date).ToString('yyyy-MM-dd-HHmmss')) Unable to find an OSDCloud Media" Break } if (-NOT (Test-Path $WinpeSourcePath)) { Write-Warning "$((Get-Date).ToString('yyyy-MM-dd-HHmmss')) Unable to find an OSDCloud Media at $WinpeSourcePath" Break } if (-NOT (Test-Path "$WinpeSourcePath\sources\boot.wim")) { Write-Warning "$((Get-Date).ToString('yyyy-MM-dd-HHmmss')) 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).ToString('yyyy-MM-dd-HHmmss')) Unable to create OSDCloud WinPE Partition" Write-Warning "$((Get-Date).ToString('yyyy-MM-dd-HHmmss')) 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).ToString('yyyy-MM-dd-HHmmss')) Unable to create OSDCloud Data Partition" Write-Warning "$((Get-Date).ToString('yyyy-MM-dd-HHmmss')) Something went very very wrong in this process" Break } #================================================= # WinpeDestinationPath #================================================= $WinpeDestinationPath = "$($WinPEPartition.DriveLetter):\" if (-NOT ($WinpeDestinationPath)) { Write-Warning "$((Get-Date).ToString('yyyy-MM-dd-HHmmss')) 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).ToString('yyyy-MM-dd-HHmmss')) 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).ToString('yyyy-MM-dd-HHmmss')) Dismounting $($MountDiskImage.ImagePath)" $null = Dismount-DiskImage -ImagePath $MountDiskImage.ImagePath } #================================================= # Complete #================================================= Write-Host -ForegroundColor Cyan "$((Get-Date).ToString('yyyy-MM-dd-HHmmss')) New-OSDCloudUSB is complete" #================================================= } function New-OSDCloudUSBSetupCompleteTemplate { $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} $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 an OSDCloud USB by downloading OS and Driver Packs from the internet .DESCRIPTION Updates an OSDCloud USB by downloading OS and Driver Packs from the internet .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 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).ToString('yyyy-MM-dd-HHmmss')) USB volumes found" Write-Host -ForegroundColor DarkGray "=========================================================================" } else { Write-Warning "$((Get-Date).ToString('yyyy-MM-dd-HHmmss')) Unable to find any USB volumes" Write-Warning "$((Get-Date).ToString('yyyy-MM-dd-HHmmss')) 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).ToString('yyyy-MM-dd-HHmmss')) OSDCloud Workspace is not present on this system" Write-Warning "$((Get-Date).ToString('yyyy-MM-dd-HHmmss')) You will not be able to update the WinPE volume" Write-Host -ForegroundColor DarkGray "=========================================================================" $RobocopyWorkspace = $false } elseif (! (Test-Path $WorkspacePath)) { Write-Warning "$((Get-Date).ToString('yyyy-MM-dd-HHmmss')) OSDCloud Workspace is not at the path $WorkspacePath" Write-Warning "$((Get-Date).ToString('yyyy-MM-dd-HHmmss')) 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).ToString('yyyy-MM-dd-HHmmss')) OSDCloud WinPE does not exist at $WorkspacePath\Media\sources\boot.wim" Write-Warning "$((Get-Date).ToString('yyyy-MM-dd-HHmmss')) 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).ToString('yyyy-MM-dd-HHmmss')) 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).ToString('yyyy-MM-dd-HHmmss')) Unable to set OSDCloud USB WinPE volume label" Write-Warning "$((Get-Date).ToString('yyyy-MM-dd-HHmmss')) 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).ToString('yyyy-MM-dd-HHmmss')) 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).ToString('yyyy-MM-dd-HHmmss')) 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).ToString('yyyy-MM-dd-HHmmss')) Updating OSDCloud Workspace PowerShell Modules and Scripts at $PowerShellPath" try { Save-Module OSD -Path "$PowerShellPath\Offline\Modules" -ErrorAction Stop } catch { Write-Warning "$((Get-Date).ToString('yyyy-MM-dd-HHmmss')) There were some issues updating the OSD PowerShell Module at $PowerShellPath\Offline\Modules" Write-Warning "$((Get-Date).ToString('yyyy-MM-dd-HHmmss')) 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).ToString('yyyy-MM-dd-HHmmss')) There were some issues updating the WindowsAutoPilotIntune PowerShell Module at $PowerShellPath\Offline\Modules" Write-Warning "$((Get-Date).ToString('yyyy-MM-dd-HHmmss')) 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).ToString('yyyy-MM-dd-HHmmss')) There were some issues updating the Get-WindowsAutopilotInfo PowerShell Script at $PowerShellPath\Offline\Scripts" Write-Warning "$((Get-Date).ToString('yyyy-MM-dd-HHmmss')) 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).ToString('yyyy-MM-dd-HHmmss')) 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).ToString('yyyy-MM-dd-HHmmss')) Unable to set OSDCloud USB volume label" Write-Warning "$((Get-Date).ToString('yyyy-MM-dd-HHmmss')) 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).ToString('yyyy-MM-dd-HHmmss')) 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).ToString('yyyy-MM-dd-HHmmss')) 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).ToString('yyyy-MM-dd-HHmmss')) 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).ToString('yyyy-MM-dd-HHmmss')) 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).ToString('yyyy-MM-dd-HHmmss')) Unable to find an OSDCloud USB volume" Write-Warning "$((Get-Date).ToString('yyyy-MM-dd-HHmmss')) 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).ToString('yyyy-MM-dd-HHmmss')) 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).ToString('yyyy-MM-dd-HHmmss')) 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).ToString('yyyy-MM-dd-HHmmss')) 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).ToString('yyyy-MM-dd-HHmmss')) 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).ToString('yyyy-MM-dd-HHmmss')) Could not download the Operating System" } } else { Write-Warning "$((Get-Date).ToString('yyyy-MM-dd-HHmmss')) Could not verify an Internet connection for the Operating System" } } } else { Write-Warning "$((Get-Date).ToString('yyyy-MM-dd-HHmmss')) 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).ToString('yyyy-MM-dd-HHmmss')) 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-DellDriverPack -DownloadPath "$DriverPackDownloadPath\Dell" } if ($DriverPack -contains 'HP') { Get-HPDriverPack -DownloadPath "$DriverPackDownloadPath\HP" } if ($DriverPack -contains 'Lenovo') { Get-LenovoDriverPack -DownloadPath "$DriverPackDownloadPath\Lenovo" } if ($DriverPack -contains 'Microsoft') { Get-MicrosoftDriverPack -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).ToString('yyyy-MM-dd-HHmmss')) Updating OSD and WindowsAutoPilotIntune PowerShell Modules at $PowerShellPath" try { Save-Module OSD -Path "$PowerShellPath\Offline\Modules" -ErrorAction Stop } catch { Write-Warning "$((Get-Date).ToString('yyyy-MM-dd-HHmmss')) There were some issues updating the OSD PowerShell Module at $PowerShellPath\Offline\Modules" Write-Warning "$((Get-Date).ToString('yyyy-MM-dd-HHmmss')) 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).ToString('yyyy-MM-dd-HHmmss')) There were some issues updating the WindowsAutoPilotIntune PowerShell Module at $PowerShellPath\Offline\Modules" Write-Warning "$((Get-Date).ToString('yyyy-MM-dd-HHmmss')) 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).ToString('yyyy-MM-dd-HHmmss')) There were some issues updating the Get-WindowsAutopilotInfo PowerShell Script at $PowerShellPath\Offline\Scripts" Write-Warning "$((Get-Date).ToString('yyyy-MM-dd-HHmmss')) 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 22H2'" 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 10 21H2' -OSLanguage en-us" Write-Host -ForegroundColor Gray "Update-OSDCloudUSB -OSName 'Windows 10 20H2' -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).ToString('yyyy-MM-dd-HHmmss')) Update-OSDCloudUSB is complete" #================================================= } |