Copy-IsoToUsb.ps1

<#
.LINK
    https://www.osdeploy.com
.SYNOPSIS
    Creates a Bootable FAT32 USB (32GB or smaller) and copies a Mounted ISO.
.DESCRIPTION
    Creates a Bootable FAT32 USB (32GB or smaller) and copies a Mounted ISO.
.PARAMETER ISOFile
    Full path to the ISO file to Mount
.PARAMETER MakeBootable
    Uses Bootsect to make the USB Bootable
.PARAMETER SplitWim
    Splits an Install.wim into 500MB swm files. Automatic for FAT32
.PARAMETER USBDriveLabel
    USB Drive Label (no spaces)
.EXAMPLE
    Copy-IsoToUsb -ISOFile "C:\Temp\SW_DVD5_Win_Pro_Ent_Edu_N_10_1709_64BIT_English_MLF_X21-50143.ISO" -MakeBootable -USBDriveLabel WIN10X64
    You will be prompted to select a USB Drive in GridView
.NOTES
    NAME: Copy-IsoToUsb.ps1
    AUTHOR: David Segura, david@segura.org
    BLOG: http://www.osdeploy.com
    VERSION: 19.1.15
             
    Original credit to Mike Robbins
    http://mikefrobbins.com/2018/01/18/use-powershell-to-create-a-bootable-usb-drive-from-a-windows-10-or-windows-server-2016-iso/
     
    Additional credit to Sergey Tkachenko
    https://winaero.com/blog/powershell-windows-10-bootable-usb/
#>


function Copy-IsoToUsb {
    [CmdletBinding()]
    Param (
        [Parameter(Mandatory)]
        [ValidateNotNullOrEmpty()]
        [ValidateScript({(Test-Path $_) -and ((Get-Item $_).Extension -eq '.iso')})]
        [string]$ISOFile,
        [switch]$MakeBootable,
        [switch]$NTFS,
        [switch]$SplitWim,
        [string]$USBLabel
    )
    BEGIN {
        #======================================================================================
        Write-Verbose "Validating Elevated Permissions ..."
        #======================================================================================
        $Elevated = ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)
        if ( -not $Elevated ) {
            Throw "This Function requires Elevation"
        }
    }
    
    PROCESS {
        #======================================================================================
        Write-Verbose "Selecting USB Drive ..."
        #======================================================================================
        if ($NTFS) {
            $Results = Get-Disk | Where-Object {$_.Size/1GB -lt 33 -and $_.BusType -eq 'USB'} | Out-GridView -Title 'Select USB Drive to Format' -OutputMode Single | Clear-Disk -RemoveData -RemoveOEM -Confirm:$false -PassThru | New-Partition -UseMaximumSize -IsActive -AssignDriveLetter | Format-Volume -FileSystem NTFS -NewFileSystemLabel $USBLabel
        } else {
            $Results = Get-Disk | Where-Object {$_.Size/1GB -lt 33 -and $_.BusType -eq 'USB'} | Out-GridView -Title 'Select USB Drive to Format' -OutputMode Single | Clear-Disk -RemoveData -RemoveOEM -Confirm:$false -PassThru | New-Partition -UseMaximumSize -IsActive -AssignDriveLetter | Format-Volume -FileSystem FAT32 -NewFileSystemLabel $USBLabel
        }
        
        #======================================================================================
        Write-Verbose "Validating a USB Drive was Selected ..."
        #======================================================================================
        if($null -eq $Results) {
            Throw "No USB Driver was Found or Selected"
        }

        #======================================================================================
        Write-Verbose "Getting Volumes ..."
        #======================================================================================
        $Volumes = (Get-Volume).Where({$_.DriveLetter}).DriveLetter
        
        #======================================================================================
        Write-Verbose "Mounting the ISO ..."
        #======================================================================================
        Mount-DiskImage -ImagePath $ISOFile
        
        #======================================================================================
        Write-Verbose "Waiting 5 Seconds ..."
        #======================================================================================
        Start-Sleep -s 5
        
        #======================================================================================
        Write-Verbose "Detemrining the Drive Letter of the Mounted ISO ..."
        #======================================================================================
        $ISO = (Compare-Object -ReferenceObject $Volumes -DifferenceObject (Get-Volume).Where({$_.DriveLetter}).DriveLetter).InputObject
        
        #======================================================================================
        Write-Verbose "Making the USB Drive Botoable ..."
        #======================================================================================
        if ($MakeBootable.IsPresent) {
            Set-Location -Path "$($ISO):\boot"
            bootsect.exe /nt60 "$($Results.DriveLetter):"    
        }
        
        #======================================================================================
        Write-Verbose "Set SplitWim"
        #======================================================================================
        if (! ($NTFS.IsPresent)) {
            if (Test-Path "$($ISO):\sources\install.wim") {
                if ((Get-Item "$($ISO):\sources\install.wim").length -gt 4gb) {
                    Write-Verbose "Split-WindowsImage: True"
                    $SplitWim = $true
                }
            }
        }

        #======================================================================================
        Write-Verbose "Copying Files ..."
        #======================================================================================
        if ($SplitWim.IsPresent) {
            Copy-Item -Path "$($ISO):\*" -Exclude install.wim -Destination "$($Results.DriveLetter):" -Recurse -Verbose

            if (Test-Path "$($ISO):\sources\install.wim") {
                $WimTemp = "$((Get-Date).ToString('HHmmss'))"

                if (Test-Path "$env:TEMP\$WimTemp") {Remove-Item -Path "$env:TEMP\$WimTemp" -Force | Out-Null}
                New-Item -Path "$env:TEMP\$WimTemp" -ItemType Directory -Force | Out-Null

                Write-Host "Copying $($ISO):\sources\install.wim to $env:TEMP\$WimTemp\install.wim" -ForegroundColor Green
                Copy-Item -Path "$($ISO):\sources\install.wim" -Destination "$env:TEMP\$WimTemp\install.wim" -Verbose

                Set-ItemProperty -Path "$env:TEMP\$WimTemp\install.wim" -Name IsReadOnly -Value $false | Out-Null
                
                Write-Host "Splitting install.wim to $env:TEMP\$WimTemp\install*.swm" -ForegroundColor Green
                Split-WindowsImage -FileSize 500 -ImagePath "$env:TEMP\$WimTemp\install.wim" -SplitImagePath "$env:TEMP\$WimTemp\install.swm" | Out-Null
                
                Write-Host "Copying install*.swm to $($Results.DriveLetter):\sources" -ForegroundColor Green
                Copy-Item -Path "$env:TEMP\$WimTemp\*" -Exclude install.wim -Destination "$($Results.DriveLetter):\sources" -Recurse -Verbose
            }
        } else {
            Copy-Item -Path "$($ISO):\*" -Destination "$($Results.DriveLetter):" -Recurse -Verbose
        }

        #======================================================================================
        Write-Verbose "Dismounting Disk Image ..."
        #======================================================================================
        Dismount-DiskImage -ImagePath $ISOFile
    }
    END {
        #======================================================================================
        Write-Verbose "Complete"
        #======================================================================================
    }
}