Public/Functions/split/Copy-IsoToUsb.ps1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
<#
.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 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: 18.9.4
             
    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,
        [System.Management.Automation.SwitchParameter]$MakeBootable,
        [System.Management.Automation.SwitchParameter]$NTFS,
        [System.Management.Automation.SwitchParameter]$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"
        #=================================================
    }
}