YES Can it be added to the main GUI? (It's on a separate "Windows.Form") Question... Why are there 2 progress bars? Same with the console here https://forums.mydigitallife.net/th...tall-wim-over-4-gb.79268/page-22#post-1873349 Can it be combined to just show one progress bar?
As @Carlos Detweiller said, the upper bar is for the global stats and the lower for the current file. The same form is used do display the screens. The -Window parameter on the powershell command line can be changed. The bar for the current file is not significant for small files because the bar are updated after 4Mbytes are processed. Here is my script : Spoiler Code: <# : standard way of doing hybrid batch + powershell scripts @title Win10+ Setup Disk 3.4 &color 3E @powershell -noprofile -Window max -c "$param='%*';$ScriptPath='%~f0';iex((Get-Content('%~f0') -Raw))"&exit/b #> $OnlyUSBsticks="NO" # $host.ui.rawui.windowtitle = ($title=$host.ui.rawui.windowtitle -replace "^.* ") # # # Homepage: https://forums.mydigitallife.net/threads/win10-setup-disk-works-with-uefi-secure-boot-bios-install-wim-over-4-gb.79268/ # Credits: @rpo, @freddie-o, @BAU & @abbodi1406 # Add-Type -AssemblyName Microsoft.VisualBasic Function MsgBox { # learn.microsoft.com/en-us/office/vba/language/reference/user-interface-help/msgbox-function [Microsoft.VisualBasic.Interaction]::MsgBox( $Args[0],"$($Args[1]),$($Args[2]),SystemModal",$title)} # # This script must be executed with admin privilege # # Test Administrator privileges If (!([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator")) { $uac_error="Elevating UAC for Administrator Privileges failed" # The following test is to avoid infinite looping if elevating UAC for Administrator Privileges failed If($param -eq $uac_error){ $msg="$uac_error.`r`nRight click on the script and select ""Run as administrator""." MsgBox $msg "OKOnly" "Critical" >$Null;exit} # Restart the script to get Administrator privileges and exit Start-Process "$ScriptPath" $uac_error -Verb runAs; exit } # Add-Type -AssemblyName System.Windows.Forms # Load the class System.Windows.Forms # # Filebrowser dialog object $FileBrowser = New-Object System.Windows.Forms.OpenFileDialog -Property @{ Multiselect = $false # Only one file can be chosen Filter = 'ISO images (*.iso)|*.iso' # Select only iso files } # Function Update_bcd ($partition){ # Set bootmenupolicy Legacy for $partition bcdedit /store "$partition\boot\bcd" /set '{default}' bootmenupolicy Legacy >$Null bcdedit /store "$partition\EFI\Microsoft\boot\bcd" /set '{default}' bootmenupolicy Legacy >$Null remove-item "$partition\boot\bcd.*" -force remove-item "$partition\EFI\Microsoft\boot\bcd.*" -force } # ************************************************** $msg="Would you like to show only USB sticks and hide external hard disks?" $filter="Status='OK' and (InterfaceType='usb'and MediaType='Removable Media')" # YES : show only usb sticks # NO : show usb sticks and external hard disks $OnlyUSBsticks=MsgBox $msg "YESNO" "Question" If($OnlyUSBsticks -eq "NO"){$filter="$filter or MediaType='External hard disk media'"} # ************************************************** $delay=15 While(!($Disks=Get-CimInstance -ClassName Win32_DiskDrive -Filter $filter)){ $msg="No USB sticks were detected. Plug in your USB stick first and retry after $delay seconds or Cancel to exit." If((MsgBox $msg "RetryCancel" "Question") -eq "Cancel"){exit} Start-Sleep $delay >$Null} # #winform dimensions $height=270 $width=420 $Form=New-Object System.Windows.Forms.Form # Create the screen form (window) $Form.TopMost = $True $Form.ShowIcon=$False $Form.ControlBox=$False # Set the title and size of the window: $Form.Text="$Title" $Form.Font='Consolas,10' $Form.Width=$width ; $Form.Height=$height $Form.StartPosition = "CenterScreen" $Form.KeyPreview = $True $Form.Add_KeyDown({if ($_.KeyCode -eq "Enter"){$OKButton.PerformClick()}}) # Enter = click OK button $Form.Add_KeyDown({if ($_.KeyCode -eq "Escape"){$CancelButton.PerformClick()}}) # Escape = click on Cancel button $Form.SizeGripStyle = "Hide" $form.ShowInTaskbar = $False $form.MaximizeBox = $False $form.MinimizeBox = $False [System.Windows.Forms.Application]::EnableVisualStyles(); # Add a Source Windows ISO label on the form $SourceISO=New-Object System.Windows.Forms.Label $SourceISO.Location=New-Object System.Drawing.Point(20,30) $SourceISO.Size=New-Object System.Drawing.Size(200,20) $SourceISO.text="Source Windows ISO" $Form.Controls.Add($SourceISO) # # Add the ISO file name on the form $ISOFile=New-Object System.Windows.Forms.Label $ISOFile.Location=New-Object System.Drawing.Point(20,50) $ISOFile.Text=" " $ISOFile.Size=New-Object System.Drawing.Size(364,24) $ISOFile.Backcolor = "White" $ISOFile.BorderStyle = "FixedSingle" $Form.Controls.Add($ISOFile) # # Add a Target USB Disk label on the form $TargetUSB=New-Object System.Windows.Forms.Label $TargetUSB.Location=New-Object System.Drawing.Point(20,100) $TargetUSB.Text="Target USB Disk" $TargetUSB.Size=New-Object System.Drawing.Size(200,20) $Form.Controls.Add($TargetUSB) # # Create a USB Disk drop-down list and fill it $USBDiskList=New-Object System.Windows.Forms.ComboBox $USBDiskList.DropDownStyle=[System.Windows.Forms.ComboBoxStyle]::DropDownList $USBDiskList.Location=New-Object System.Drawing.Point(20,120) $USBDiskList.Size=New-Object System.Drawing.Size(363,22) $Form.Controls.Add($SelectUSBDiskList) # # Add a Select ISO button on the form $SelectISOButton=New-Object System.Windows.Forms.Button $SelectISOButton.Location=New-Object System.Drawing.Point(20,185) $SelectISOButton.Text="Select ISO" $SelectISOButton.Size=New-Object System.Drawing.Size(110,26) $Form.Controls.Add($SelectISOButton) # # Add a Create Setup Disk button on the form $CreateDiskButton=New-Object System.Windows.Forms.Button $CreateDiskButton.Location=New-Object System.Drawing.Point(140,185) $CreateDiskButton.Text="Create Setup Disk" $CreateDiskButton.Size=New-Object System.Drawing.Size(155,26) $Form.Controls.Add($CreateDiskButton) $CreateDiskButton.Enabled = $false $CreateDiskButton.DialogResult = "OK" # # Add a Cancel button on the form $CancelButton=New-Object System.Windows.Forms.Button $CancelButton.Location=New-Object System.Drawing.Point(305,185) $CancelButton.Text="Cancel" $CancelButton.Size=New-Object System.Drawing.Size(80,26) $Form.Controls.Add($CancelButton) $CancelButton.DialogResult = "Cancel" # $SelectISOButton.Add_Click({ If ($FileBrowser.ShowDialog() -ne "Cancel"){ # if Cancel, just ignore $Global:ImagePath=$FileBrowser.filename # return the file name $ISOFile.Text=Split-Path -Path $ImagePath -leaf # extract filename and extension (iso) if(($ISOFile.Text).length -gt 44){ $ISOFile.Text=$ImagePath.PadRight(100).substring(0,43)+"..."} $CreateDiskButton.Enabled = $true $CreateDiskButton.Focus()}}) # $USBDisks=@() # array with USB disk number Foreach ($Disk in $Disks){ $FriendlyName=($Disk.Caption).PadRight(40).substring(0,35) $USBDisks+=$Disk.Index $USBDiskList.Items.Add(("{0,-30}{1,10:n2} GB" -f $FriendlyName,($Disk.Size/1GB))) >$Null <# Foreach ($Partition in (Get-Partition $Disk.Index)) { If(!$Partition.DriveLetter){$AccessPath=" "}Else{$AccessPath=$Partition.DriveLetter+":"} $USBDisks+=$Disk.Index $USBDiskList.Items.Add((" ({0,2}){1,-30}{2,10:n2} GB" -f $AccessPath,($Partition| Get-Volume).FileSystemLabel.PadRight(25).substring(0,25),($Partition.Size/1GB))) >$Null } #> } $form.Controls.Add($USBDiskList) $USBDiskList.SelectedIndex=0 # $Groupbox=New-Object System.Windows.Forms.Groupbox # Add a group box on the form $Groupbox.Location=New-Object System.Drawing.Point(7,0) $Groupbox.Text="" $Groupbox.Size=New-Object System.Drawing.Size(390,225) $Form.Controls.Add($Groupbox) # # create label $label1 = New-Object system.Windows.Forms.Label $label1.Left=5 $label1.Top= 10 $label1.Width= $width - 20 #adjusted height to accommodate progress $label1.Height=150 $label1.Font= "Verdana" #optional to show border #$label1.BorderStyle=1 $msg=@" 1.) Click "Select ISO" to select your source Windows ISO 2.) Select your "Target USB disk" from the drop-down menu 3.) Click "Create Setup Disk" to start creating your Windows setup disk "@ MsgBox "$msg" "OKOnly" "Information" >$Null # if($form.ShowDialog() -eq "Cancel") {exit} # $Form.Controls.Remove($SourceISO) $Form.Controls.Remove($ISOFile) $Form.Controls.Remove($TargetUSB) $Form.Controls.Remove($SelectUSBDiskList) $Form.Controls.Remove($SelectISOButton) $Form.Controls.Remove($CreateDiskButton) $Form.Controls.Remove($CancelButton) $Form.Controls.Remove($USBDiskList) $Form.Controls.Remove($Groupbox) # # At this point the mounted USB disk and the iso image file path are defined # $USB=$USBDisks[$USBDiskList.SelectedIndex] # $msg=@" WARNING!`r`n Your USB disk will be converted to MBR scheme, repartitioned and reformatted.`r`n All partitions and data currently stored in the USB disk will be erased.`r`n Are you sure you want to continue? "@ If((MsgBox $msg "YESNO" "Exclamation") -eq "NO"){exit} Clear-Host #add the label to the form $form.controls.add($label1) # #"Mounting and checking to see if the ISO image was mounted" # Check if iso already mounted by getting driveletter If($ISO=(Get-DiskImage $ImagePath|Get-Volume).DriveLetter){$Mounted=$True}Else # Mount iso and get drive letter {$Mounted=$False;If(!($ISO=(Mount-DiskImage $ImagePath|Get-Volume).DriveLetter)){Exit}} $ISO=$ISO+":" # Stop-Service ShellHWDetection -ErrorAction SilentlyContinue >$Null $ProgressPreference="SilentlyContinue" $label1.Text = "Cleaning the USB disk and converting it to MBR partition scheme" $form.Show() # "Select disk $USB`nclean`nconvert MBR`nexit"|diskpart >$Null If($LASTEXITCODE -ne 0){ $msg="Diskpart operations failed with error code $LASTEXITCODE." $msg;pause } $label1.Text = $label1.Text+"`r`n`r`nCreating the FAT32 boot partition" $form.Refresh() $usbfat32=(New-Partition -DiskNumber $usb -Size 1GB -AssignDriveLetter| Format-Volume -FileSystem FAT32 -NewFileSystemLabel "BOOT").DriveLetter + ":" $label1.Text = $label1.Text+"`r`n`r`nCreating the NTFS setup partition & marking partition as active" $form.Refresh() $usbntfs=(New-Partition -DiskNumber $usb -UseMaximumSize -AssignDriveLetter -IsActive| Format-Volume -FileSystem NTFS -NewFileSystemLabel "SETUP").DriveLetter + ":" Start-Service ShellHWDetection -erroraction silentlycontinue >$Null # ********************************************************************* $form.controls.Remove($label1) # $label1 = New-Object system.Windows.Forms.Label $label1.Text = "not started" $label1.Left=5 $label1.Top= 10 $label1.Width= $width - 20 $label1.Height=65 $label1.Font= "Verdana" #$label1.BorderStyle=1 $form.controls.add($label1) # $label2 = New-Object system.Windows.Forms.Label $label2.Text = "not started" $label2.Left=5 $label2.Top= 130 $label2.Width= $width - 20 $label2.Height=65 $label2.Font= "Verdana" #$label2.BorderStyle=1 $form.controls.add($label2) $progressBar1 = New-Object System.Windows.Forms.ProgressBar $progressBar1.Value = 0 $progressBar1.Style="Continuous" # $System_Drawing_Size = New-Object System.Drawing.Size $System_Drawing_Size.Width = $width - 30 $System_Drawing_Size.Height = 20 $progressBar1.Size = $System_Drawing_Size $progressBar1.Left = 5 $progressBar1.Top = 70 $form.Controls.Add($progressBar1) # $progressBar2 = New-Object System.Windows.Forms.ProgressBar $progressBar2.Name = 'progressBar2' $progressBar2.Value = 0 $progressBar2.Style="Continuous" $System_Drawing_Size = New-Object System.Drawing.Size $System_Drawing_Size.Width = $width - 30 $System_Drawing_Size.Height = 20 $progressBar2.Size = $System_Drawing_Size $progressBar2.Left = 5 $progressBar2.Top = 200 $form.Controls.Add($progressBar2) $form.Show()| out-null $form.Focus() | out-null # # ***************************************************************************** # Function Copy_With_Progression { # suffix 1 : variables for global process # suffix 2 : variables for one file process [long]$allbytes = ($files | measure -Sum length).Sum [long]$total1 = 0 # bytes done $index = 0 $filescount = $files.Count $sw1 = [Diagnostics.Stopwatch]::StartNew() $Buffer = New-Object Byte[] (4MB) # 4MB buffer ForEach ($file in $files) { $filefullname = $file.fullname $index++ # build destination path for this file (for example H:\sources\boot.wim) $destfile = "$Dest_device$((Split-Path $filefullname -NoQualifier))" $destdir= Split-Path $destfile -Parent # if it doesn't exist, create it if (!(Test-Path $destdir)){New-Item -ItemType Directory "$destdir" -Force >$Null} $SourceFile = [io.file]::OpenRead($filefullname) $DestinationFile = [io.file]::Create($destfile) $Filelength=$File.Length $sw2 = [Diagnostics.Stopwatch]::StartNew() [long]$total2 = [long]$count = 0 do { # copy 4MB of src file to dst file $count = $SourceFile.Read($buffer, 0, $buffer.Length) $DestinationFile.Write($buffer, 0, $count) # this is just write-progress # uses stopwatch to determine how long is left $total2 += $count $total1 += $count # Statistics for current file if ($Filelength -gt 1){ $pctcomp2 = $total2 * 100 / $FileLength}else{$pctcomp2 = 100} [int]$secselapsed2 = $sw2.Elapsed.TotalSeconds if ($secselapsed2 -ne 0){ [single]$xferrate = $total2 / $secselapsed2 / 1mb}else{[single]$xferrate = 0.0} if ($total2 -gt 0) { [int]$secsleft2=$secselapsed2/$total2*$Filelength -$secselapsed2}else{[int]$secsleft2=0} # Global statistics $pctcomp1 = $total1 * 100/ $allbytes [int]$secselapsed1 = $sw1.Elapsed.TotalSeconds if ($total1 -gt 0) { [int]$secsleft1=$secselapsed1/$total1*$Filelength -$secselapsed1}else{[int]$secsleft1=0} # Global $Form.Text="Copying $destfile" $progressBar1.Value = $pctcomp1 $label1.text="{0,5} of $filescount files - {1,5} left" -f $index,($filescount - $index) $label1.text="$($label1.text){0,20:0} MB of {1,6:0} MB" -f ($total1/1MB),($allbytes/1MB) $label1.text="$($label1.text)`r`n`r`nPercent complete = {0,3:0}% {1,4} minutes {2,2} seconds remaining" -f $pctcomp1,[math]::Truncate($secsleft1/60),($secsleft1%60) # Current file $progressBar2.Value = $pctcomp2 $label2.text="Copying file @ {0,6:n2} MB/s" -f $xferrate $label2.text="$($label2.text){0,16:0} MB of {1,6:0} MB" -f ($total2/1MB),($filelength/1MB) $label2.text="$($label2.text)`r`n`r`nPercent complete = {0,3:0}% {1,4} minutes {2,2} seconds remaining" -f $pctcomp2,[math]::Truncate($secsleft2/60),($secsleft2%60) $form.Refresh() } while ($count -gt 0) $sw2.Stop() $sw2.Reset() $SourceFile.Close() $DestinationFile.Close() } $sw1.Stop() $sw1.Reset() $Buffer=$Null # }# End Function Copy_With_Progression # #"`r`nCopying boot files to the fat32 boot partition $usbfat32" $files = Get-ChildItem $iso\boot, $iso\efi, $iso\sources\boot.wim, $iso\bootmgr.*, $iso\bootmgr -Recurse -File -Force $Dest_device="$usbfat32" Copy_With_Progression # Update_BCD $usbfat32 #"`r`nRemoving the drive letter to hide the fat32 boot partition" Get-Volume ($usbfat32 -replace ".$")|Get-Partition| Remove-PartitionAccessPath -accesspath $usbfat32 # #"`r`nCopying contents of the ISO to the NTFS setup partition $usbntfs" $files = Get-ChildItem $iso -Recurse -File -Force $Dest_device="$usbntfs" Copy_With_Progression # $form.Close() # Update_BCD $usbntfs bootsect /nt60 $usbntfs /force /mbr >$Null # Eject the mounted iso image if it was loaded by the script If(!$Mounted){DisMount-DiskImage $ImagePath >$Null} MsgBox "$Title was created successfully." "OKOnly" "Information" >$Null Update : my bad, the code is now ok
Temporarily closed for maintenance. Will be re-opened very soon. Edit: Reopened under new management. @rpo Edit: Oh, and while we are at it, would you like to have this topic moved to the "MDL Projects and Applications" forum? @rpo
Why not, it appears that prominent people of the community approve your suggestion. PS : caveat concerning the gui draft : the gui may freeze (because Powershells support for multithreading is limited).
A candidate for next release : Spoiler Code: <# : hybrid batch + powershell script @title Win10+ Setup Disk 3.3 &color 3E @powershell -noprofile -Window hidden -c "$param='%*';$ScriptPath='%~f0';iex((Get-Content('%~f0') -Raw))"&exit/b #> $OnlyUSBsticks="NO" # # Homepage: https://forums.mydigitallife.net/threads/win10-setup-disk-works-with-uefi-secure-boot-bios-install-wim-over-4-gb.79268/ # Credits: @rpo, @freddie-o, @BAU & @abbodi1406 # #****************************************************************************** $Copy_with_progress= { Param ($iso,$usbfat32,$usbntfs,$title) $ProgressPreference='Continue' # $Host.ui.rawui.windowtitle = $Title # Function Copy_With_Progress ($partition,$Files,$fs) { [long]$allbytes = ($Files | measure -Sum length).Sum [long]$Total1 = 0 # bytes done $index = 0 $FilesCount = $Files.Count $StopWatch1 = [System.Diagnostics.Stopwatch]::StartNew() $Buffer = New-Object Byte[] (4096 * 1024) # 4MB buffer # ForEach ($File in $Files) { $FileFullName = $File.FullName [long]$FileLength = $File.Length $index++ # build destination path for this file (for example H:\sources\boot.wim) $DestFile = \"$partition$((Split-Path $filefullname -NoQualifier))\" $DestDir = Split-Path $DestFile -Parent # if dir doesn't exist, create it if (!(Test-Path $DestDir)){New-Item -ItemType Directory \"$DestDir\" -Force >$Null} $SourceFile = [io.file]::OpenRead($FileFullName) $DestinationFile = [io.file]::Create($DestFile) $StopWatch2 = [System.Diagnostics.Stopwatch]::StartNew() [long]$Total2 = [long]$Count = 0 do { # copy source file to destination file, 4MB at a time $Count = $SourceFile.Read($Buffer, 0, $Buffer.Length) $DestinationFile.Write($Buffer, 0, $Count) # this is just write-progress # uses stopwatch to determine how long is left $Total1 += $Count $Total2 += $Count # # Global statistics # $CompletionRate1 = $Total1 / $allbytes * 100 [int]$MSElapsed = [int]$StopWatch1.ElapsedMilliseconds if (($Total1 -ne $allbytes) -and ($Total1 -ne 0)) { [int]$RemainingSeconds1 = $MSElapsed * ($allbytes / $Total1 - 1) / 1000 } else {[int]$RemainingSeconds1 = 0} $mbytes=$allbytes/1MB $ProgressParameters = @{ Activity = \"$fs $partition partition\" Status = \"{0,3:0}% of {1:n2} MBytes, $index of $Filescount files ($($Filescount - $index) left)\" -f $CompletionRate1,$mbytes PercentComplete = $CompletionRate1 SecondsRemaining = $RemainingSeconds1} Write-Progress @ProgressParameters # # Statistics for current file # [int]$MSElapsed = [int]$StopWatch2.ElapsedMilliseconds if ($Count -ne 0) { $CompletionRate2 = $Total2 / $FileLength * 100 [int]$RemainingSeconds2 = $MSElapsed * ($FileLength / $Total2 - 1) / 1000 if ($MSElapsed -ge 1000) { [single]$xferrate = $Total2 / $MSElapsed / 1mb * 1000} else{[single]$xferrate = 0.0} }else { $CompletionRate2 = 100 [int]$RemainingSeconds2 = 0 } $mbytes=$FileLength/1MB $ProgressParameters = @{ Id = 1 Activity = \"$($DestFile -Replace '^...')\" Status = \"{0,3:0}% of {1:n2} MBytes, copying file @ {2:n2} MB/s\" -f $CompletionRate2,$mbytes,$xferrate PercentComplete = $CompletionRate2 SecondsRemaining = $RemainingSeconds2} Write-Progress @ProgressParameters # } while ($Count -gt 0) $StopWatch2.Stop() $StopWatch2.Reset() $SourceFile.Close() $DestinationFile.Close() } # end for each file $StopWatch1.Stop() $StopWatch1.Reset() } # End Function # $Files=Get-ChildItem $iso\boot, $iso\efi, ` $iso\sources\boot.wim, $iso\bootmgr.*, $iso\bootmgr -Recurse -File -Force Copy_With_Progress $usbfat32 $Files 'FAT32' # $Files=Get-ChildItem $iso -Recurse -File -Force Copy_With_Progress $usbntfs $Files 'NTFS' # } # end of scriptblock #****************************************************************************** $host.ui.rawui.windowtitle = ($title=$host.ui.rawui.windowtitle -replace "^.* ") Add-Type -AssemblyName System.Windows.Forms # Load the class System.Windows.Forms [System.Windows.Forms.Application]::EnableVisualStyles() # $Form = New-Object System.Windows.Forms.Form -Property @{ # Create the screen form (window) TopMost = $True ShowIcon = $False ControlBox = $False ForeColor = "White" BackColor = "Black" Text = "$Title" Font = 'Consolas,10' Width = 420 Height = 270 StartPosition = "CenterScreen" SizeGripStyle = "Hide" ShowInTaskbar = $False MaximizeBox = $False MinimizeBox = $False KeyPreview = $True #Add_KeyDown({if ($_.KeyCode -eq "Escape"){$CancelButton.PerformClick()}}) } # # Add a OK button on the form $OKButton = New-Object System.Windows.Forms.Button -Property @{ Location = New-Object System.Drawing.Point(25,185) Size = New-Object System.Drawing.Size(80,26) DialogResult = "OK" } $Form.Controls.Add($OKButton) # # Add a Cancel button on the form $CancelButton = New-Object System.Windows.Forms.Button -Property @{ Location = New-Object System.Drawing.Point(300,185) Size = New-Object System.Drawing.Size(80,26) DialogResult = "Cancel" } # # create label $Label0 = New-Object system.Windows.Forms.Label -Property @{ Location = New-Object System.Drawing.Point(20,10) Size = New-Object System.Drawing.Size(365,25) Font = "Arial,12" ForeColor = "Red" BackColor = "White" } # $Label1 = New-Object system.Windows.Forms.Label -Property @{ Location = New-Object System.Drawing.Point(60,70) Size = New-Object System.Drawing.Size(380,150) } $Form.Controls.Add($Label1) # # # This script must be executed with admin privilege # # Test Administrator privileges $uac_error="Elevating UAC for Administrator Privileges failed" $Label1.Text = @" $uac_error!`r`n`r`nRight click on the script. Select "Run as administrator". "@ If (!([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator")) { # The following test is to avoid infinite looping if elevating UAC for Administrator Privileges failed If($param -eq $uac_error){ $Form.ForeColor = "Red" $Form.BackColor = "White" $Label1.Location = New-Object System.Drawing.Point(20,50) $Label1.Size = New-Object System.Drawing.Size(380,120) $OKButton.Location = New-Object System.Drawing.Point(170,185) $OKButton.Text = "Exit" $Form.Controls.Add($OKButton) [void]$Form.Showdialog() exit} # Restart the script to get Administrator privileges and exit Start-Process "$ScriptPath" $uac_error -Verb runAs; exit } # # Filebrowser dialog object $FileBrowser = New-Object System.Windows.Forms.OpenFileDialog -Property @{ Multiselect = $false # Only one file can be chosen Filter = 'ISO images (*.iso)|*.iso' # Select only iso files } # Function Update_bcd ($partition){ # Set bootmenupolicy Legacy for $partition bcdedit /store "$partition\boot\bcd" /set '{default}' bootmenupolicy Legacy >$Null bcdedit /store "$partition\EFI\Microsoft\boot\bcd" /set '{default}' bootmenupolicy Legacy >$Null remove-item "$partition\boot\bcd.*" -force remove-item "$partition\EFI\Microsoft\boot\bcd.*" -force } # $Label1.Location = New-Object System.Drawing.Point(40,60) $Label1.Size = New-Object System.Drawing.Size(380,100) $Label1.Text = @" Would you like to show only USB sticks and hide external hard disks? "@ $filter = "Status='OK' and (InterfaceType='usb'and MediaType='Removable Media')" # YES : show only usb sticks # NO : show usb sticks and external hard disks $Form.Controls.Add($CancelButton) $CancelButton.Text = "No" $OKButton.Text = "Yes" $OnlyUSBsticks=$Form.ShowDialog() If($OnlyUSBsticks -eq "Cancel"){$filter = "$filter or MediaType='External hard disk media'"} # $Label0.Text = "No USB device were detected." $Label1.Text = @" Plug in your USB device first.`n Retry or Cancel. "@ $OKButton.Text = "Retry" $CancelButton.Text = "Cancel" While(!($Disks=Get-CimInstance -ClassName Win32_DiskDrive -Filter $filter)){ $Form.Controls.Add($Label0) If($Form.ShowDialog() -eq "Cancel"){exit} $Form.Controls.Remove($Label0) } # $Label1.Location = New-Object System.Drawing.Point(10,20) $Label1.Size = New-Object System.Drawing.Size(380,150) $Label1.Text = @" 1. Click "Select ISO" to select your source Windows ISO`n 2. Select your "Target USB disk" from the drop-down menu`n 3. Click "Create Setup Disk" to start creating your Windows setup disk "@ $OKButton.Location = New-Object System.Drawing.Point(25,185) $OKButton.Text = "Next" $CancelButton.Text = "Abort" If($Form.Showdialog() -eq "Cancel"){exit} # # Add a Source Windows ISO label on the form $Label1.Location = New-Object System.Drawing.Point(20,30) $Label1.Size = New-Object System.Drawing.Size(200,20) $Label1.Text = "Source Windows ISO" # # Add the ISO file name on the form $ISOFile = New-Object System.Windows.Forms.Label -Property @{ Location = New-Object System.Drawing.Point(20,50) Size = New-Object System.Drawing.Size(364,24) Backcolor = "White" ForeColor = "Black" BorderStyle = "FixedSingle" } # # Add a Target USB Disk label on the form $TargetUSB = New-Object System.Windows.Forms.Label -Property @{ Location = New-Object System.Drawing.Point(20,100) Text = "Target USB Disk" Size = New-Object System.Drawing.Size(200,20) } # # Create a USB Disk drop-down list and fill it $USBDiskList = New-Object System.Windows.Forms.ComboBox -Property @{ DropDownStyle = [System.Windows.Forms.ComboBoxStyle]::DropDownList Location = New-Object System.Drawing.Point(20,120) Size = New-Object System.Drawing.Size(363,22) } # # Add a Select ISO button on the form $SelectISOButton = New-Object System.Windows.Forms.Button -Property @{ Location = New-Object System.Drawing.Point(20,185) Text = "Select ISO" Size = New-Object System.Drawing.Size(110,26) } # # Add a Create Setup Disk button on the form $OKButton.Location = New-Object System.Drawing.Point(140,185) $OKButton.Size = New-Object System.Drawing.Size(155,26) $OKButton.Text="" $OKButton.Enabled = $false # # Add a Cancel button on the form $CancelButton.Text = "Cancel" # $SelectISOButton.Add_Click({ If ($FileBrowser.ShowDialog() -ne "Cancel"){ # if Cancel, just ignore $Global:ImagePath=$FileBrowser.filename # return the file name $ISOFile.Text = Split-Path -Path $ImagePath -leaf # extract filename and extension (iso) if(($ISOFile.Text).length -gt 44){ $ISOFile.Text = $ImagePath.PadRight(100).substring(0,43)+"..."} $OKButton.Text = "Create Setup Disk" $OKButton.Enabled = $true $OKButton.Focus()}}) # $USBDisks=@() # array with USB disk number Foreach ($Disk in $Disks){ $FriendlyName = ($Disk.Caption).PadRight(40).substring(0,35) $USBDisks+=$Disk.Index $USBDiskList.Items.Add(("{0,-30}{1,10:n2} GB" -f $FriendlyName,($Disk.Size/1GB))) >$Null <# Foreach ($Partition in (Get-Partition $Disk.Index)) { If(!$Partition.DriveLetter){$AccessPath=" "}Else{$AccessPath=$Partition.DriveLetter+":"} $USBDisks+=$Disk.Index $USBDiskList.Items.Add((" ({0,2}){1,-30}{2,10:n2} GB" -f $AccessPath,($Partition| Get-Volume).FileSystemLabel.PadRight(25).substring(0,25),($Partition.Size/1GB))) >$Null } #> } # $GroupBox = New-Object System.Windows.Forms.GroupBox # Add a group box on the form $GroupBox.Location = New-Object System.Drawing.Point(7,0) $GroupBox.Size = New-Object System.Drawing.Size(390,225) $Form.Controls.AddRange(@($ISOFile, $TargetUSB, $SelectISOButton, $USBDiskList, $GroupBox)) # $USBDiskList.SelectedIndex=0 # if($Form.ShowDialog() -eq "Cancel") {exit} # # At this point the mounted USB disk and the iso image file path are defined # $USB=$USBDisks[$USBDiskList.SelectedIndex] # $Form.Controls.Clear() $Form.Controls.AddRange(@($OKButton, $CancelButton, $Label1, $Label0)) $OKButton.Location = New-Object System.Drawing.Point(25,185) $OKButton.Text = "Yes" $CancelButton.Text = "No" $OKButton.Size = New-Object System.Drawing.Size(80,26) $Label1.Location = New-Object System.Drawing.Point(20,50) $Label1.Size = New-Object System.Drawing.Size(380,180) $Label0.Text = "WARNING!`n" $Label1.Text = @" Your USB device will be converted to MBR scheme, repartitioned and reformatted.`n All partitions and data currently stored in the USB device will be erased.`n Are you sure you want to continue? "@ if($Form.ShowDialog() -eq "Cancel") {exit} # $Label1.Location = New-Object System.Drawing.Point(10,20) $Label1.Size = New-Object System.Drawing.Size(380,160) $Label1.Text = "Mounting and checking to see if the ISO image was mounted`n" $Form.Controls.Clear() $Form.Controls.Add($Label1) $Form.Show() $Form.Refresh() # # Check if iso already mounted by getting driveletter If($ISO = (Get-DiskImage $ImagePath|Get-Volume).DriveLetter){$Mounted = $True}Else # Mount iso and get drive letter {$Mounted = $False;If(!($ISO = (Mount-DiskImage $ImagePath|Get-Volume).DriveLetter)){Exit}} $ISO=$ISO+":" # Stop-Service ShellHWDetection -ErrorAction SilentlyContinue >$Null $ProgressPreference="SilentlyContinue" # $Label1.Text = $Label1.Text+"`nCleaning the USB disk and converting it to MBR partition scheme`n" $Form.Refresh() "Select disk $USB`nclean`nconvert MBR`nexit"|diskpart >$Null If($LASTEXITCODE -ne 0){ $Form.Hide() $Label1.Location=New-Object System.Drawing.Point(20,80) $Label1.Size=New-Object System.Drawing.Size(380,100) $Label1.Text = "Diskpart operations failed with error code $LASTEXITCODE." $OKButton.Location=New-Object System.Drawing.Point(170,185) $OKButton.Text = "Exit" $Form.Controls.Add($OKButton) [void]$Form.Showdialog() exit} # $Label1.Text = $Label1.Text+"`nCreating the FAT32 boot partition`n" $Form.Refresh() $usbfat32 = (New-Partition -DiskNumber $usb -Size 1GB -AssignDriveLetter| Format-Volume -FileSystem FAT32 -NewFileSystemLabel "BOOT").DriveLetter + ":" $Files = Get-ChildItem $iso\boot, $iso\efi, ` $iso\sources\boot.wim, $iso\bootmgr.*, $iso\bootmgr -Recurse -File -Force $FilesSize = ($Files | measure -Sum Length).Sum/1GB $msg = @" Fat32 1 GB partition too small. $("{0,1:n2}" -f $FilesSize) GB needed" "@ If ($FilesSize -gt 1GB){ $Form.Hide() $Label1.Text = $msg $Label1.ForeColor = "Red" $Label1.BackColor = "White" $Label1.Location=New-Object System.Drawing.Point(20,80) $Label1.AutoSize = $True $OKButton.Text = "Exit" $OKButton.Location=New-Object System.Drawing.Point(170,185) $Form.Controls.Add($OKButton) [void]$Form.Showdialog() exit } $Label1.Text = $Label1.Text+"`nCreating the NTFS setup partition and marking partition active" $Form.Refresh() $usbntfs = (New-Partition -DiskNumber $usb -UseMaximumSize -AssignDriveLetter -IsActive| Format-Volume -FileSystem NTFS -NewFileSystemLabel "SETUP").DriveLetter + ":" $Files = Get-ChildItem $iso -Recurse -File -Force $FilesSize = ($Files | measure -Sum Length).Sum/1GB $PartitionSize = (Get-Volume ($usbntfs -Replace ".$")).Size/1GB $msg = @" NTFS partition $("{0,1:n2}" -f $PartitionSize) too small. $("{0,1:n2}" -f $FilesSize) GB needed" "@ If($FilesSize -gt $PartitionSize){ $Form.Hide() $Label1.Text = $msg $Label1.ForeColor = "Red" $Label1.BackColor = "White" $Label1.Location=New-Object System.Drawing.Point(10,80) $Label1.AutoSize = $True $OKButton.Text = "Exit" $OKButton.Location=New-Object System.Drawing.Point(170,185) $Form.Controls.Add($OKButton) [void]$Form.Showdialog() exit } # $Form.Hide() Start-Service ShellHWDetection -erroraction silentlycontinue >$Null # #****************************************************************************** Try{ Pwsh -c "$PsVersionTable" -ErrorAction Stop >$Null $ps = "pwsh"} Catch{$ps = "powershell"} #"`r`nStarting copy process and waiting for completion`r`n" $Process = Start-Process $ps -ArgumentList ` "-Command & {$Copy_with_progress} '$iso' '$usbfat32' '$usbntfs' '$title'" -Wait -PassThru #****************************************************************************** # $Label1.Location=New-Object System.Drawing.Point(20,80) $Label1.Size=New-Object System.Drawing.Size(380,100) $OKButton.Location=New-Object System.Drawing.Point(170,185) $Form.Controls.Add($OKButton) If($process.ExitCode -ne 0){ $Label1.Text = "Copying files to the USB device failed." $OKButton.Text = "Exit" [void]$Form.Showdialog() exit} # $OKButton.Location = New-Object System.Drawing.Point(25,185) $OKButton.Text = "Next" $CancelButton.Text = "Abort" $Form.Controls.Add($CancelButton) $Label1.Text = "All folders and files copyed." If($Form.Showdialog() -eq "Cancel"){exit} # $Form.Controls.Remove($OKButton) $Form.Controls.Remove($CancelButton) $Label1.Location = New-Object System.Drawing.Point(10,20) $Label1.Size = New-Object System.Drawing.Size(380,160) $Label1.Text = "Updating BCD`n" $Form.Show() $Form.Refresh() Update_BCD $usbfat32 Update_BCD $usbntfs # $Label1.Text = $Label1.Text+"`nRemoving the drive letter to hide the FAT32 boot partition`n" $Form.Refresh() Get-Volume ($usbfat32 -replace ".$")|Get-Partition| Remove-PartitionAccessPath -accesspath $usbfat32 # $Label1.Text = $Label1.Text+"`nEject the mounted ISO image if it was loaded by the script" $Form.Refresh() # Eject the mounted iso image if it was loaded by the script If(!$Mounted){DisMount-DiskImage $ImagePath >$Null} # bootsect /nt60 $usbntfs /force /mbr >$Nul # $Form.Hide() $Form.Controls.Add($OKButton) $OKButton.Location=New-Object System.Drawing.Point(170,185) $Label1.Location=New-Object System.Drawing.Point(20,80) $Label1.AutoSize = $True $Label1.Text = "$Title was created successfully." $OKButton.Text = "Exit" [void]$Form.ShowDialog() Progression bar output with Powershell 5.1 : Progression bar output with pwsh 7 :
The OP was updated The download includes versions 3.2 and 3.3, they differ only by cosmetic changes; the created disk has the same content for the two versions. Update : Re-uploaded today (April, 22th) to correct a bug while performing a test to ensure that no created partition of the USB device is too small (concerns only version 3.3 since version 3.2 doesn't perform this test).
Re-upload due to a small UI update. Reminder : if you NEVER want to use usb connected external hdd/ssd, edit the script : 1. Search the string $OnlyUSBsticks="NO" and replace by $OnlyUSBsticks="YES" 2. Search the statement : Code: If($Form.ShowDialog() -eq "Cancel"){$OnlyUSBsticks="No"}Else{$OnlyUSBsticks="Yes"} and delete it.
Hey @rpo, just wondering—would it be possible to add support for a source Windows folder in a future release as well? It’d be super helpful for those of us who usually work with extracted installation files instead of full ISOs. Thanks for considering it!
This was asked many years ago. The short anwer was "no", but i could reconsider this demand. Instead of searching a iso file, it could be possible to search for a install.wim or install.esd file. Is this acceptable?
New version adding the possibility to select source windows folder; select install.wim/esd in the extracted dolders. Spoiler Code: <# : hybrid batch + powershell script @title Win10+ Setup Disk 3.4 &color 3E @powershell -noprofile -Window hidden -c "$param='%*';$ScriptPath='%~f0';iex((Get-Content('%~f0') -Raw))"&exit/b #> $OnlyUSBsticks="NO" # # Homepage: https://forums.mydigitallife.net/threads/win10-setup-disk-works-with-uefi-secure-boot-bios-install-wim-over-4-gb.79268/ # Credits: @rpo, @freddie-o, @BAU & @abbodi1406 # #****************************************************************************** $Copy_with_progress= { Param ($iso,$usbfat32,$usbntfs,$title) # $Host.ui.rawui.windowtitle = $Title # Function Copy_With_Progress ($partition,$Files,$fs) { [long]$allbytes = ($Files | measure -Sum length).Sum [long]$Total1 = 0 # bytes done $index = 0 $FilesCount = $Files.Count $StopWatch1 = [System.Diagnostics.Stopwatch]::StartNew() $Buffer = New-Object Byte[] (4096 * 1024) # 4MB buffer # ForEach ($File in $Files) { $FileFullName = $File.FullName [long]$FileLength = $File.Length $index++ # build destination path for this file (for example H:\sources\boot.wim) $DestFile = $partition+$FileFullName.Substring($iso.length) $DestDir = Split-Path $DestFile -Parent # if dir doesn't exist, create it if (!(Test-Path $DestDir)){New-Item -ItemType Directory \"$DestDir\" -Force >$Null} $SourceFile = [io.file]::OpenRead($FileFullName) $DestinationFile = [io.file]::Create($DestFile) $StopWatch2 = [System.Diagnostics.Stopwatch]::StartNew() [long]$Total2 = [long]$Count = 0 do { # copy source file to destination file, 4MB at a time $Count = $SourceFile.Read($Buffer, 0, $Buffer.Length) $DestinationFile.Write($Buffer, 0, $Count) # this is just write-progress # uses stopwatch to determine how long is left $Total1 += $Count $Total2 += $Count # # Global statistics # $CompletionRate1 = $Total1 / $allbytes * 100 [int]$MSElapsed = [int]$StopWatch1.ElapsedMilliseconds if (($Total1 -ne $allbytes) -and ($Total1 -ne 0)) { [int]$RemainingSeconds1 = $MSElapsed * ($allbytes / $Total1 - 1) / 1000 } else {[int]$RemainingSeconds1 = 0} $mbytes=$allbytes/1MB $ProgressParameters = @{ Activity = \"$fs $partition partition\" Status = \"{0,3:0}% of {1:n2} MBytes, $index of $Filescount files ($($Filescount - $index) left)\" -f $CompletionRate1,$mbytes PercentComplete = $CompletionRate1 SecondsRemaining = $RemainingSeconds1} Write-Progress @ProgressParameters # # Statistics for current file # [int]$MSElapsed = [int]$StopWatch2.ElapsedMilliseconds if ($Count -ne 0) { $CompletionRate2 = $Total2 / $FileLength * 100 [int]$RemainingSeconds2 = $MSElapsed * ($FileLength / $Total2 - 1) / 1000 if ($MSElapsed -ge 1000) { [single]$xferrate = $Total2 / $MSElapsed / 1mb * 1000} else{[single]$xferrate = 0.0} }else { $CompletionRate2 = 100 [int]$RemainingSeconds2 = 0 } $mbytes=$FileLength/1MB $ProgressParameters = @{ Id = 1 Activity = \"$($DestFile -Replace '^...')\" Status = \"{0,3:0}% of {1:n2} MBytes, copying file @ {2:n2} MB/s\" -f $CompletionRate2,$mbytes,$xferrate PercentComplete = $CompletionRate2 SecondsRemaining = $RemainingSeconds2} Write-Progress @ProgressParameters # } while ($Count -gt 0) $StopWatch2.Stop() $StopWatch2.Reset() $SourceFile.Close() $DestinationFile.Close() } # end for each file $StopWatch1.Stop() $StopWatch1.Reset() } # End Function # $Files=Get-ChildItem $iso\boot, $iso\efi, ` $iso\sources\boot.wim, $iso\bootmgr.*, $iso\bootmgr -Recurse -File -Force Copy_With_Progress $usbfat32 $Files 'FAT32' # $Files=Get-ChildItem $iso -Recurse -File -Force Copy_With_Progress $usbntfs $Files 'NTFS' # } # end of scriptblock #****************************************************************************** $host.ui.rawui.windowtitle = ($title=$host.ui.rawui.windowtitle -replace "^.* ") Add-Type -AssemblyName System.Windows.Forms # Load the class System.Windows.Forms [System.Windows.Forms.Application]::EnableVisualStyles() # $Form = New-Object System.Windows.Forms.Form -Property @{ # Create the screen form (window) TopMost = $True ShowIcon = $False ControlBox = $False ForeColor = "White" BackColor = "Black" Text = "$Title" Font = 'Consolas,10' Width = 420 Height = 270 StartPosition = "CenterScreen" SizeGripStyle = "Hide" ShowInTaskbar = $False MaximizeBox = $False MinimizeBox = $False KeyPreview = $True} # # Add a OK button on the form $OKButton = New-Object System.Windows.Forms.Button -Property @{ Location = New-Object System.Drawing.Point(25,185) Size = New-Object System.Drawing.Size(80,26) DialogResult = "OK" } $Form.Controls.Add($OKButton) # # Add a Cancel button on the form $CancelButton = New-Object System.Windows.Forms.Button -Property @{ Location = New-Object System.Drawing.Point(300,185) Size = New-Object System.Drawing.Size(80,26) DialogResult = "Cancel"} # # create label $Label0 = New-Object system.Windows.Forms.Label -Property @{ Location = New-Object System.Drawing.Point(20,10) Size = New-Object System.Drawing.Size(365,25) Font = "Arial,12" ForeColor = "Red" BackColor = "White"} # $Label1 = New-Object system.Windows.Forms.Label -Property @{ Location = New-Object System.Drawing.Point(60,70) Size = New-Object System.Drawing.Size(380,150)} # # How to # $HowTo= New-Object system.Windows.Forms.Form -Property @{ TopMost = $True ShowIcon = $False ControlBox = $False ShowInTaskbar = $False Width = 420 Height = 270 Font = "Arial,12"} # $HowToText = New-Object system.Windows.Forms.RichTextBox -Property @{ Location = New-Object System.Drawing.Point(10,30) Dock = "Fill" BackColor = 'Blue' ForeColor = 'White' Anchor = 'top, left'} $HowTo.Controls.Add($HowToText) # # Display information # $Information= New-Object system.Windows.Forms.Form -Property @{ TopMost = $True ShowIcon = $False ControlBox = $False ShowInTaskbar = $False StartPosition = 'CenterScreen' Width = 420 Height = 270 Font = "Arial,12"} # $InformationText = New-Object system.Windows.Forms.RichTextBox -Property @{ Location = New-Object System.Drawing.Point(10,30) Dock = "Fill" BackColor = 'Blue' ForeColor = 'White' Anchor = 'top, left'} $Information.Controls.Add($InformationText) # # # This script must be executed with admin privilege # # Test Administrator privileges $uac_error="Elevating UAC for Administrator Privileges failed" $Label1.Text = @" $uac_error!`r`n`r`nRight click on the script. Select "Run as administrator". "@ If (!([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator")) { # The following test is to avoid infinite looping if elevating UAC for Administrator Privileges failed If($param -eq $uac_error){ $Form.ForeColor = "Red" $Form.BackColor = "White" $Label1.Location = New-Object System.Drawing.Point(20,50) $Label1.Size = New-Object System.Drawing.Size(380,120) $OKButton.Location = New-Object System.Drawing.Point(170,185) $OKButton.Text = "Exit" $Form.Controls.AddRange(@($OKButton, $Label1)) [void]$Form.Showdialog() exit} # Restart the script to get Administrator privileges and exit Start-Process "$ScriptPath" $uac_error -Verb runAs; exit } # # Filebrowser dialog object $FileBrowser = New-Object System.Windows.Forms.OpenFileDialog -Property @{ Title="Select ISO image or intall.wim/esd in extracted source folder" Multiselect = $false # Only one file can be chosen Filter = 'ISO images (*.iso;*install.wim;*install.esd)|*.iso;*install.wim;*install.esd' # Select only iso files } # Function Update_bcd ($partition){ # Set bootmenupolicy Legacy for $partition bcdedit /store "$partition\boot\bcd" /set '{default}' bootmenupolicy Legacy >$Null bcdedit /store "$partition\EFI\Microsoft\boot\bcd" /set '{default}' bootmenupolicy Legacy >$Null remove-item "$partition\boot\bcd.*" -force remove-item "$partition\EFI\Microsoft\boot\bcd.*" -force } # $Form.Controls.Clear() $Label1.Location = New-Object System.Drawing.Point(40,60) $Label1.Size = New-Object System.Drawing.Size(380,100) $Label1.Text = @" Would you like to show only USB sticks and hide external hdd/ssd disks? "@ $filter = "Status='OK' and (InterfaceType='usb'and MediaType='Removable Media')" # YES : show only usb sticks # NO : show usb sticks and external hard disks $Form.Controls.AddRange(@($OKButton, $Label1, $CancelButton)) $CancelButton.Text = "No" $OKButton.Text = "Yes" If($Form.ShowDialog() -eq "Cancel"){$OnlyUSBsticks="No"}Else{$OnlyUSBsticks="Yes"} If($OnlyUSBsticks -eq "No") {$filter = "$filter or MediaType='External hard disk media'"} # $Form.Controls.Clear() $Label0.Text = "No USB device were detected." $Label1.Text = @" Plug in your USB device first.`n Retry or Cancel. "@ $OKButton.Text = "Retry" $CancelButton.Text = "Cancel" While(!($Disks=Get-CimInstance -ClassName Win32_DiskDrive -Filter $filter)){ $Form.Controls.AddRange(@($OKButton, $CancelButton, $Label0, $Label1)) If($Form.ShowDialog() -eq "Cancel"){exit}} # # Add a Source Windows ISO label on the form $Label1.Location = New-Object System.Drawing.Point(20,25) $Label1.Size = New-Object System.Drawing.Size(400,20) $Label1.Text = "Windows source (ISO or extracted source folder)" # # Add the ISO file name on the form $ISOFile = New-Object System.Windows.Forms.TextBox -Property @{ Location = New-Object System.Drawing.Point(20,45) Size = New-Object System.Drawing.Size(364,24) Backcolor = "White" ForeColor = "Black" ReadOnly = $True BorderStyle = "FixedSingle"} # # Add a Target USB Disk label on the form $TargetUSB = New-Object System.Windows.Forms.Label -Property @{ Location = New-Object System.Drawing.Point(20,100) Text = "Target USB Disk" Size = New-Object System.Drawing.Size(200,20)} # # Create a USB Disk drop-down list and fill it $USBDiskList = New-Object System.Windows.Forms.ComboBox -Property @{ DropDownStyle = [System.Windows.Forms.ComboBoxStyle]::DropDownList Location = New-Object System.Drawing.Point(20,120) Size = New-Object System.Drawing.Size(363,22)} # # Add a Select ISO button on the form $SelectISOButton = New-Object System.Windows.Forms.Button -Property @{ Location = New-Object System.Drawing.Point(20,185) Text = "Source" Size = New-Object System.Drawing.Size(110,26)} # # Add a Create Setup Disk button on the form $OKButton.Location = New-Object System.Drawing.Point(140,185) $OKButton.Size = New-Object System.Drawing.Size(155,26) $OKButton.Text="" $OKButton.Enabled = $false # # Add a Cancel button on the form $CancelButton.Text = "Cancel" # $SelectISOButton.Add_Click({ If ($FileBrowser.ShowDialog() -ne "Cancel"){ # if Cancel, just ignore $Global:ImagePath=$FileBrowser.filename # return the file name If($ImagePath.Split(".") -eq "Iso"){ $Global:dvd = $True $ISOFile.Text = Split-Path -Path $ImagePath -leaf # filename (.iso) }Else{ $Global:dvd = $False $Global:ImagePath=Split-Path $ImagePath -Parent|Split-Path -Parent $ISOFile.Text = $ImagePath } if(($ISOFile.Text).length -gt 44){ $ISOFile.Text = $ImagePath.PadRight(100).substring(0,43)+"..."} $OKButton.Text = "Create Setup Disk" $OKButton.Enabled = $true $OKButton.Focus()}}) # $USBDisks=@() # array with USB disk number Foreach ($Disk in $Disks){ $FriendlyName = ($Disk.Caption).PadRight(40).substring(0,35) $USBDisks+=$Disk.Index $USBDiskList.Items.Add(("{0,-30}{1,10:n2} GB" -f $FriendlyName,($Disk.Size/1GB))) >$Null <# Foreach ($Partition in (Get-Partition $Disk.Index)) { If(!$Partition.DriveLetter){$AccessPath=" "}Else{$AccessPath=$Partition.DriveLetter+":"} $USBDisks+=$Disk.Index $USBDiskList.Items.Add((" ({0,2}){1,-30}{2,10:n2} GB" -f $AccessPath,($Partition| Get-Volume).FileSystemLabel.PadRight(25).substring(0,25),($Partition.Size/1GB))) >$Null } #> } # $GroupBox = New-Object System.Windows.Forms.GroupBox # Add a group box on the form $GroupBox.Location = New-Object System.Drawing.Point(7,0) $GroupBox.Size = New-Object System.Drawing.Size(390,225) # $Form.Controls.Clear() $Form.Controls.AddRange(@($Label1, $OKbutton, $CancelButton, $ISOFile)) $Form.Controls.AddRange(@($TargetUSB, $SelectISOButton, $USBDiskList, $GroupBox)) # $USBDiskList.SelectedIndex=0 # $HowToText.Text = @" `nPlugin your usb device `n`nClick "Select ISO" or install.wim/esd in extracted folders `n`nSelect your "Target USB disk" from the drop-down menu `n`nClick "Create Setup Disk" to start creating your Windows setup disk "@ $HowTo.Show() $HowTo.Refresh() $Result= $Form.ShowDialog() $HowTo.Dispose() $HowTo.Close() If($Result -eq "Cancel") {exit} # # At this point the mounted USB disk and the iso image file path are defined # $USB=$USBDisks[$USBDiskList.SelectedIndex] # $Form.Controls.Clear() $Form.Controls.AddRange(@($OKButton, $CancelButton, $Label1, $Label0)) $OKButton.Location = New-Object System.Drawing.Point(25,185) $OKButton.Text = "Yes" $CancelButton.Text = "No" $OKButton.Size = New-Object System.Drawing.Size(80,26) $Label1.Location = New-Object System.Drawing.Point(20,50) $Label1.Size = New-Object System.Drawing.Size(380,180) $Label0.Text = "WARNING!`n" $Label1.Text = @" Your USB device will be converted to MBR scheme, repartitioned and reformatted.`n All partitions and data currently stored in the USB device will be erased.`n Are you sure you want to continue? "@ if($Form.ShowDialog() -eq "Cancel") {exit} # $Information.Show() If($dvd){ $InformationText.AppendText("`nMounting and checking to see if the ISO image was mounted`n") $Information.Refresh() # # Check if iso already mounted by getting driveletter If($ISO = (Get-DiskImage $ImagePath|Get-Volume).DriveLetter){$Mounted = $True}Else # Mount iso and get drive letter {$Mounted = $False;If(!($ISO = (Mount-DiskImage $ImagePath|Get-Volume).DriveLetter)){Exit}} $ISO=$ISO+":" }Else{ $ISO = $ImagePath } # Stop-Service ShellHWDetection -ErrorAction SilentlyContinue >$Null $ProgressPreference="SilentlyContinue" # $InformationText.AppendText("`nCleaning the USB disk and converting it to MBR partition scheme`n") $Information.Refresh() "Select disk $USB`nclean`nconvert MBR`nexit"|diskpart >$Null If($LASTEXITCODE -ne 0){ $Information.Hide() $Form.Controls.Clear() $Form.Controls.AddRange(@($OKButton, $Label1)) $Label1.Location=New-Object System.Drawing.Point(20,80) $Label1.Size=New-Object System.Drawing.Size(380,100) $Label1.Text = "Diskpart operations failed with error code $LASTEXITCODE." $OKButton.Location=New-Object System.Drawing.Point(170,185) $OKButton.Text = "Exit" $Form.Controls.Add($OKButton) [void]$Form.Showdialog() exit} # $InformationText.AppendText("`nCreating the FAT32 boot partition`n") $Information.Refresh() $usbfat32 = (New-Partition -DiskNumber $usb -Size 1GB -AssignDriveLetter| Format-Volume -FileSystem FAT32 -NewFileSystemLabel "BOOT").DriveLetter + ":" $Files = Get-ChildItem $iso\boot, $iso\efi, ` $iso\sources\boot.wim, $iso\bootmgr.*, $iso\bootmgr -Recurse -File -Force $FilesSize = ($Files | measure -Sum Length).Sum/1GB $msg = @" Fat32 1 GB partition too small. $("{0,1:n2}" -f $FilesSize) GB needed" "@ If ($FilesSize -gt 1GB){ $Information.Hide() $Form.Controls.Clear() $Label1.Text = $msg $Label1.ForeColor = "Red" $Label1.BackColor = "White" $Label1.Location=New-Object System.Drawing.Point(20,80) $Label1.AutoSize = $True $OKButton.Text = "Exit" $OKButton.Location=New-Object System.Drawing.Point(170,185) $Form.Controls.AddRange(@($OKButton, $Label1)) [void]$Form.Showdialog() exit } $InformationText.AppendText("`nCreating the NTFS setup partition and marking partition active") $Information.Refresh() $usbntfs = (New-Partition -DiskNumber $usb -UseMaximumSize -AssignDriveLetter -IsActive| Format-Volume -FileSystem NTFS -NewFileSystemLabel "SETUP").DriveLetter + ":" $Files = Get-ChildItem $iso -Recurse -File -Force $FilesSize = ($Files | measure -Sum Length).Sum/1GB $PartitionSize = (Get-Volume ($usbntfs -Replace ".$")).Size/1GB $msg = @" NTFS partition $("{0,1:n2}" -f $PartitionSize) too small. $("{0,1:n2}" -f $FilesSize) GB needed" "@ If($FilesSize -gt $PartitionSize){ $Information.Hide() $Form.Controls.Clear() $Label1.Text = $msg $Label1.ForeColor = "Red" $Label1.BackColor = "White" $Label1.Location=New-Object System.Drawing.Point(10,80) $Label1.AutoSize = $True $OKButton.Text = "Exit" $OKButton.Location=New-Object System.Drawing.Point(170,185) $Form.Controls.AddRange(@($OKButton, $Label1)) [void]$Form.Showdialog() exit } # $InformationText.Text = "" $Information.Hide() Start-Service ShellHWDetection -erroraction silentlycontinue >$Null # #****************************************************************************** Try{ Pwsh -c "$PsVersionTable" -ErrorAction Stop >$Null $ps = "pwsh"} Catch{$ps = "powershell"} #"`r`nStarting copy process and waiting for completion`r`n" $Process = Start-Process $ps -ArgumentList ` "-Command & {$Copy_with_progress} '$iso' '$usbfat32' '$usbntfs' '$title'" -Wait -PassThru #****************************************************************************** # $Form.Controls.Clear() $Label1.Location=New-Object System.Drawing.Point(20,80) $Label1.Size=New-Object System.Drawing.Size(380,100) $OKButton.Location=New-Object System.Drawing.Point(170,185) $Form.Controls.AddRange(@($OKButton, $Label1)) If($process.ExitCode -ne 0){ $Label1.Text = "Copying files to the USB device failed." $OKButton.Text = "Exit" [void]$Form.Showdialog() exit} # $Form.Controls.Clear $OKButton.Location = New-Object System.Drawing.Point(25,185) $OKButton.Text = "Next" $CancelButton.Text = "Abort" $Label1.Text = "All folders and files copyed." $Form.Controls.AddRange(@($OKButton, $Label1, $CancelButton)) If($Form.Showdialog() -eq "Cancel"){exit} # $InformationText.AppendText("`nUpdating BCD`n") $Information.Show() $Information.Refresh() Update_BCD $usbfat32 Update_BCD $usbntfs # $InformationText.AppendText("`nRemoving the drive letter to hide the FAT32 boot partition`n") $Information.Refresh() Get-Volume ($usbfat32 -replace ".$")|Get-Partition| Remove-PartitionAccessPath -accesspath $usbfat32 # If(DVD){ $InformationText.AppendText("`nEject the mounted ISO image if it was loaded by the script") $Information.Refresh() # Eject the mounted iso image if it was loaded by the script If(!$Mounted){DisMount-DiskImage $ImagePath >$Null} } # bootsect /nt60 $usbntfs /force /mbr >$Null # $Information.Dispose() $Information.Close() $Form.Controls.Clear() $Form.Controls.AddRange(@($OKButton, $Label1)) $OKButton.Location=New-Object System.Drawing.Point(170,185) $Label1.Location=New-Object System.Drawing.Point(20,80) $Label1.AutoSize = $True $Label1.Text = "$Title was created successfully." $OKButton.Text = "Exit" [void]$Form.ShowDialog()
Experimental version introducing progress bars Spoiler Code: <# : hybrid batch + powershell script @title Win10+ Setup Disk 3.5 &color 3E @powershell -noprofile -Window hidden -c "$param='%*';$ScriptPath='%~f0';iex((Get-Content('%~f0') -Raw))"&exit/b #> $OnlyUSBsticks="NO" # # Homepage: https://forums.mydigitallife.net/threads/win10-setup-disk-works-with-uefi-secure-boot-bios-install-wim-over-4-gb.79268/ # Credits: @rpo, @freddie-o, @BAU & @abbodi1406 # #****************************************************************************** $host.ui.rawui.windowtitle = ($title=$host.ui.rawui.windowtitle -replace "^.* ") Add-Type -AssemblyName System.Windows.Forms # Load the class System.Windows.Forms [System.Windows.Forms.Application]::EnableVisualStyles() $Width = 420; $Height = 270 # #****************************************************************************** Function Copy_Progression ($Files,$Partition,$fs) { # # suffix 1 : variables for global process # suffix 2 : variables for one file process [long]$allbytes = ($Files | measure -Sum length).Sum [long]$Total1 = 0 # bytes done $index = 0 $FilesCount = $Files.Count $StopWatch1 = [Diagnostics.Stopwatch]::StartNew() $Buffer = New-Object Byte[] (4MB) # 4MB buffer # ForEach ($File in $Files) { $FileFullName = $File.fullname [long]$FileLength = $File.Length $index++ # build destination path for this file (for example H:\sources\boot.wim) $DestFile = $partition+$FileFullName.Substring($iso.length) $DestDir= Split-Path $DestFile -Parent # if it doesn't exist, create it if (!(Test-Path $DestDir)){New-Item -ItemType Directory "$DestDir" -Force >$Null} $SourceFile = [io.file]::OpenRead($FileFullName) $DestinationFile = [io.file]::Create($DestFile) $FileLength=$File.Length $Sync.FileName="$($DestFile -Replace '^...')" $StopWatch2 = [Diagnostics.Stopwatch]::StartNew() [long]$Total2 = [long]$Count = 0 $LastStopWatch = 0 do { # copy 4MB of src file to dst file $Count = $SourceFile.Read($buffer, 0, $buffer.Length) $DestinationFile.Write($buffer, 0, $Count) # this is just write-progress # uses stopwatch to determine how long is left $Total2 += $Count $Total1 += $Count # # Global statistics # $CompletionRate1 = $Total1 / $allbytes * 100 [int]$MSElapsed = [int]$StopWatch1.ElapsedMilliseconds if (($Total1 -ne $allbytes) -and ($Total1 -ne 0)) { [int]$RemainingSeconds1 = $MSElapsed * ($allbytes / $Total1 - 1) / 1000 } else {[int]$RemainingSeconds1 = 0} $Label1="$Partition $FS {0,5} of {1,5} files - {2,5} left" -f $index,$FilesCount,($FilesCount - $index) $Label1="$Label1{0,10:0} MB of {1,6:0} MB" -f ($Total1/1MB),($allbytes/1MB) $Label1="$Label1`r`n`r`nPercent complete = {0,3:0}% {1,4} minutes {2,2} seconds remaining" -f $CompletionRate1,[math]::Truncate($RemainingSeconds1/60),($RemainingSeconds1%60) $Sync.Label1=$Label1 $Sync.CompletionRate1 = $CompletionRate1 # # Statistics for current file # [int]$MSElapsed = [int]$StopWatch2.ElapsedMilliseconds if ($Count -ne 0) { $CompletionRate2 = $Total2 / $FileLength * 100 [int]$RemainingSeconds2 = $MSElapsed * ($FileLength / $Total2 - 1) / 1000 if ($MSElapsed -ge 1000) { [single]$xferrate = $Total2 / $MSElapsed / 1mb * 1000} else{[single]$xferrate = 0.0} }else { $CompletionRate2 = 100 [int]$RemainingSeconds2 = 0 } $Label2="Copying file @ {0,6:n2} MB/s" -f $xferrate $Label2="$Label2{0,16:0} MB of {1,6:0} MB" -f ($Total2/1MB),($filelength/1MB) $Label2="$Label2`r`n`r`nPercent complete = {0,3:0}% {1,4} minutes {2,2} seconds remaining" -f $CompletionRate2,[math]::Truncate($RemainingSeconds2/60),($RemainingSeconds2%60) If (($CompletionRate2 -eq 100) -or (($MSElapsed - $LastStopWatch) -gt 1000)){ $LastStopWatch = $MSElapsed } $Sync.Label2=$Label2 $Sync.CompletionRate2 = $CompletionRate2 $Sync.Flag = 1 } while ($Count -gt 0) $StopWatch2.Stop() $StopWatch2.Reset() $SourceFile.Close() $DestinationFile.Close() } If($fs -eq "NTFS"){$Sync.Flag = -1} $StopWatch1.Stop() $StopWatch1.Reset() $Buffer=$Null # }# End Function Copy_With_Progression #****************************************************************************** # $Form = New-Object System.Windows.Forms.Form -Property @{ # Create the screen form (window) TopMost = $True ShowIcon = $False ControlBox = $False ForeColor = "White" BackColor = "Black" Text = "$Title" Font = 'Consolas,10' Width = $Width;Height = $Height StartPosition = "CenterScreen" SizeGripStyle = "Hide" ShowInTaskbar = $False MaximizeBox = $False MinimizeBox = $False KeyPreview = $True} # # Add a OK button on the form $OKButton = New-Object System.Windows.Forms.Button -Property @{ Location = New-Object System.Drawing.Point(25,185) Size = New-Object System.Drawing.Size(80,26) DialogResult = "OK" } $Form.Controls.Add($OKButton) # # Add a Cancel button on the form $CancelButton = New-Object System.Windows.Forms.Button -Property @{ Location = New-Object System.Drawing.Point(300,185) Size = New-Object System.Drawing.Size(80,26) DialogResult = "Cancel"} # # create label $Label0 = New-Object system.Windows.Forms.Label -Property @{ Location = New-Object System.Drawing.Point(20,10) Size = New-Object System.Drawing.Size(365,25) Font = "Arial,12" ForeColor = "Red" BackColor = "White"} # $Label1 = New-Object system.Windows.Forms.Label -Property @{ Location = New-Object System.Drawing.Point(60,70) Size = New-Object System.Drawing.Size(380,150)} # # How to # $HowTo= New-Object system.Windows.Forms.Form -Property @{ TopMost = $True ShowIcon = $False ControlBox = $False ShowInTaskbar = $False Width = $Width;Height = $Height Font = "Arial,12"} # $HowToText = New-Object system.Windows.Forms.RichTextBox -Property @{ Location = New-Object System.Drawing.Point(10,30) Dock = "Fill" BackColor = 'Blue' ForeColor = 'White' Anchor = 'top, left'} $HowTo.Controls.Add($HowToText) # # Display information # $Information= New-Object system.Windows.Forms.Form -Property @{ TopMost = $True ShowIcon = $False ControlBox = $False ShowInTaskbar = $False StartPosition = 'CenterScreen' Width = $Width;Height = $Height BackColor = 'Blue' ForeColor = 'White' Font = "Arial,12"} # $InformationText = New-Object system.Windows.Forms.RichTextBox -Property @{ Location = New-Object System.Drawing.Point(10,30) Dock = "Fill" BackColor = 'Blue' ForeColor = 'White' Anchor = 'top, left'} $Information.Controls.Add($InformationText) # # # This script must be executed with admin privilege # # Test Administrator privileges $uac_error="Elevating UAC for Administrator Privileges failed" $Label1.Text = @" $uac_error!`r`n`r`nRight click on the script. Select "Run as administrator". "@ If (!([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator")) { # The following test is to avoid infinite looping if elevating UAC for Administrator Privileges failed If($param -eq $uac_error){ $Form.ForeColor = "Red" $Form.BackColor = "White" $Label1.Location = New-Object System.Drawing.Point(20,50) $Label1.Size = New-Object System.Drawing.Size(380,120) $OKButton.Location = New-Object System.Drawing.Point(170,185) $OKButton.Text = "Exit" $Form.Controls.AddRange(@($OKButton, $Label1)) [void]$Form.Showdialog() exit} # Restart the script to get Administrator privileges and exit Start-Process "$ScriptPath" $uac_error -Verb runAs; exit } # # Filebrowser dialog object $FileBrowser = New-Object System.Windows.Forms.OpenFileDialog -Property @{ Title="Select ISO image or intall.wim/esd in extracted source folder" Multiselect = $false # Only one file can be chosen Filter = 'ISO images (*.iso;*install.wim;*install.esd)|*.iso;*install.wim;*install.esd' # Select only iso files } # Function Update_bcd ($partition){ # Set bootmenupolicy Legacy for $partition bcdedit /store "$partition\boot\bcd" /set '{default}' bootmenupolicy Legacy >$Null bcdedit /store "$partition\EFI\Microsoft\boot\bcd" /set '{default}' bootmenupolicy Legacy >$Null remove-item "$partition\boot\bcd.*" -force remove-item "$partition\EFI\Microsoft\boot\bcd.*" -force } # $Form.Controls.Clear() $Label1.Location = New-Object System.Drawing.Point(40,60) $Label1.Size = New-Object System.Drawing.Size(380,100) $Label1.Text = @" Would you like to show only USB sticks and hide external hdd/ssd disks? "@ $filter = "Status='OK' and (InterfaceType='usb'and MediaType='Removable Media')" # YES : show only usb sticks # NO : show usb sticks and external hard disks $Form.Controls.AddRange(@($OKButton, $Label1, $CancelButton)) $CancelButton.Text = "No" $OKButton.Text = "Yes" If($Form.ShowDialog() -eq "Cancel"){$OnlyUSBsticks="No"}Else{$OnlyUSBsticks="Yes"} If($OnlyUSBsticks -eq "No") {$filter = "$filter or MediaType='External hard disk media'"} # $Form.Controls.Clear() $Label0.Text = "No USB device were detected." $Label1.Text = @" Plug in your USB device first.`n Retry or Cancel. "@ $OKButton.Text = "Retry" $CancelButton.Text = "Cancel" While(!($Disks=Get-CimInstance -ClassName Win32_DiskDrive -Filter $filter)){ $Form.Controls.AddRange(@($OKButton, $CancelButton, $Label0, $Label1)) If($Form.ShowDialog() -eq "Cancel"){exit}} # # Add a Source Windows ISO label on the form $Label1.Location = New-Object System.Drawing.Point(20,25) $Label1.Size = New-Object System.Drawing.Size(400,20) $Label1.Text = "Windows source (ISO or extracted source folder)" # # Add the ISO file name on the form $ISOFile = New-Object System.Windows.Forms.TextBox -Property @{ Location = New-Object System.Drawing.Point(20,45) Size = New-Object System.Drawing.Size(364,24) Backcolor = "White" ForeColor = "Black" ReadOnly = $True BorderStyle = "FixedSingle"} # # Add a Target USB Disk label on the form $TargetUSB = New-Object System.Windows.Forms.Label -Property @{ Location = New-Object System.Drawing.Point(20,100) Text = "Target USB Disk" Size = New-Object System.Drawing.Size(200,20)} # # Create a USB Disk drop-down list and fill it $USBDiskList = New-Object System.Windows.Forms.ComboBox -Property @{ DropDownStyle = [System.Windows.Forms.ComboBoxStyle]::DropDownList Location = New-Object System.Drawing.Point(20,120) Size = New-Object System.Drawing.Size(363,22)} # # Add a Select ISO button on the form $SelectISOButton = New-Object System.Windows.Forms.Button -Property @{ Location = New-Object System.Drawing.Point(20,185) Text = "Source" Size = New-Object System.Drawing.Size(110,26)} # # Add a Create Setup Disk button on the form $OKButton.Location = New-Object System.Drawing.Point(140,185) $OKButton.Size = New-Object System.Drawing.Size(155,26) $OKButton.Text="" $OKButton.Enabled = $false # # Add a Cancel button on the form $CancelButton.Text = "Cancel" # $SelectISOButton.Add_Click({ If ($FileBrowser.ShowDialog() -ne "Cancel"){ # if Cancel, just ignore $Global:ImagePath=$FileBrowser.filename # return the file name If($ImagePath.Split(".") -eq "Iso"){ $Global:dvd = $True $ISOFile.Text = Split-Path -Path $ImagePath -leaf # filename (.iso) }Else{ $Global:dvd = $False $Global:ImagePath=Split-Path $ImagePath -Parent|Split-Path -Parent $ISOFile.Text = $ImagePath } if(($ISOFile.Text).length -gt 44){ $ISOFile.Text = $ImagePath.PadRight(100).substring(0,43)+"..."} $OKButton.Text = "Create Setup Disk" $OKButton.Enabled = $true $OKButton.Focus()}}) # $USBDisks=@() # array with USB disk number Foreach ($Disk in $Disks){ $FriendlyName = ($Disk.Caption).PadRight(40).substring(0,35) $USBDisks+=$Disk.Index $USBDiskList.Items.Add(("{0,-30}{1,10:n2} GB" -f $FriendlyName,($Disk.Size/1GB))) >$Null <# Foreach ($Partition in (Get-Partition $Disk.Index)) { If(!$Partition.DriveLetter){$AccessPath=" "}Else{$AccessPath=$Partition.DriveLetter+":"} $USBDisks+=$Disk.Index $USBDiskList.Items.Add((" ({0,2}){1,-30}{2,10:n2} GB" -f $AccessPath,($Partition| Get-Volume).FileSystemLabel.PadRight(25).substring(0,25),($Partition.Size/1GB))) >$Null } #> } # $GroupBox = New-Object System.Windows.Forms.GroupBox # Add a group box on the form $GroupBox.Location = New-Object System.Drawing.Point(7,0) $GroupBox.Size = New-Object System.Drawing.Size(390,225) # $Form.Controls.Clear() $Form.Controls.AddRange(@($Label1, $OKbutton, $CancelButton, $ISOFile)) $Form.Controls.AddRange(@($TargetUSB, $SelectISOButton, $USBDiskList, $GroupBox)) # $USBDiskList.SelectedIndex=0 # $HowToText.Text = @" `nPlugin your usb device `n`nClick "Select ISO" or install.wim/esd in extracted folders `n`nSelect your "Target USB disk" from the drop-down menu `n`nClick "Create Setup Disk" to start creating your Windows setup disk "@ $HowTo.Show() $HowTo.Refresh() $Result= $Form.ShowDialog() $HowTo.Dispose() $HowTo.Close() If($Result -eq "Cancel") {exit} # # At this point the mounted USB disk and the iso image file path are defined # $USB=$USBDisks[$USBDiskList.SelectedIndex] # $Form.Controls.Clear() $Form.Controls.AddRange(@($OKButton, $CancelButton, $Label1, $Label0)) $OKButton.Location = New-Object System.Drawing.Point(25,185) $OKButton.Text = "Yes" $CancelButton.Text = "No" $OKButton.Size = New-Object System.Drawing.Size(80,26) $Label1.Location = New-Object System.Drawing.Point(20,50) $Label1.Size = New-Object System.Drawing.Size(380,180) $Label0.Text = "WARNING!`n" $Label1.Text = @" Your USB device will be converted to MBR scheme, repartitioned and reformatted.`n All partitions and data currently stored in the USB device will be erased.`n Are you sure you want to continue? "@ if($Form.ShowDialog() -eq "Cancel") {exit} # $Information.Show() If($dvd){ $InformationText.AppendText("`nMounting and checking to see if the ISO image was mounted`n") $Information.Refresh() # # Check if iso already mounted by getting driveletter If($ISO = (Get-DiskImage $ImagePath|Get-Volume).DriveLetter){$Mounted = $True}Else # Mount iso and get drive letter {$Mounted = $False;If(!($ISO = (Mount-DiskImage $ImagePath|Get-Volume).DriveLetter)){Exit}} $ISO=$ISO+":" }Else{ $ISO = $ImagePath } # Stop-Service ShellHWDetection -ErrorAction SilentlyContinue >$Null $ProgressPreference="SilentlyContinue" # $InformationText.AppendText("`nCleaning the USB disk and converting it to MBR partition scheme`n") $Information.Refresh() "Select disk $USB`nclean`nconvert MBR`nexit"|diskpart >$Null If($LASTEXITCODE -ne 0){ $Information.Hide() $Form.Controls.Clear() $Form.Controls.AddRange(@($OKButton, $Label1)) $Label1.Location=New-Object System.Drawing.Point(20,80) $Label1.Size=New-Object System.Drawing.Size(380,100) $Label1.Text = "Diskpart operations failed with error code $LASTEXITCODE." $OKButton.Location=New-Object System.Drawing.Point(170,185) $OKButton.Text = "Exit" $Form.Controls.Add($OKButton) [void]$Form.Showdialog() exit} # $InformationText.AppendText("`nCreating the FAT32 boot partition`n") $Information.Refresh() $usbfat32 = (New-Partition -DiskNumber $usb -Size 1GB -AssignDriveLetter| Format-Volume -FileSystem FAT32 -NewFileSystemLabel "BOOT").DriveLetter + ":" $Files32 = Get-ChildItem $iso\boot, $iso\efi, ` $iso\sources\boot.wim, $iso\bootmgr.*, $iso\bootmgr -Recurse -File -Force $FilesSize = ($Files32 | measure -Sum Length).Sum/1GB $msg = @" Fat32 1 GB partition too small. $("{0,1:n2}" -f $FilesSize) GB needed" "@ If ($FilesSize -gt 1GB){ $Information.Hide() $Form.Controls.Clear() $Label1.Text = $msg $Label1.ForeColor = "Red" $Label1.BackColor = "White" $Label1.Location=New-Object System.Drawing.Point(20,80) $Label1.AutoSize = $True $OKButton.Text = "Exit" $OKButton.Location=New-Object System.Drawing.Point(170,185) $Form.Controls.AddRange(@($OKButton, $Label1)) [void]$Form.Showdialog() exit } $InformationText.AppendText("`nCreating the NTFS setup partition and marking partition active") $Information.Refresh() $usbntfs = (New-Partition -DiskNumber $usb -UseMaximumSize -AssignDriveLetter -IsActive| Format-Volume -FileSystem NTFS -NewFileSystemLabel "SETUP").DriveLetter + ":" $FilesNTFS = Get-ChildItem $iso -Recurse -File -Force $FilesSize = ($FilesNTFS | measure -Sum Length).Sum/1GB $PartitionSize = (Get-Volume ($usbntfs -Replace ".$")).Size/1GB $msg = @" NTFS partition $("{0,1:n2}" -f $PartitionSize) too small. $("{0,1:n2}" -f $FilesSize) GB needed" "@ If($FilesSize -gt $PartitionSize){ $Information.Hide() $Form.Controls.Clear() $Label1.Text = $msg $Label1.ForeColor = "Red" $Label1.BackColor = "White" $Label1.Location=New-Object System.Drawing.Point(10,80) $Label1.AutoSize = $True $OKButton.Text = "Exit" $OKButton.Location=New-Object System.Drawing.Point(170,185) $Form.Controls.AddRange(@($OKButton, $Label1)) [void]$Form.Showdialog() exit } # $InformationText.Text = "" $Information.Hide() Start-Service ShellHWDetection -erroraction silentlycontinue >$Null # #****************************************************************************** # $Sync = [hashtable]::Synchronized(@{}) $Sync.Host = $host $Sync.Flag = 0 # $runspace = [runspacefactory]::CreateRunspace() $runspace.Open() $runspace.SessionStateProxy.SetVariable('Sync',$Sync) $powershell = [powershell]::Create() $powershell.Runspace = $runspace $powershell.AddScript({ # $Width = 420; $Height = 270 $Form = New-Object System.Windows.Forms.Form -Property @{ # Create the screen form (window) TopMost = $True ShowIcon = $False ControlBox = $True Text = " " Font = 'Consolas,10' Width = $Width; Height = $Height StartPosition = "CenterScreen" SizeGripStyle = "Hide" ShowInTaskbar = $False MaximizeBox = $False MinimizeBox = $False ForeColor = "White" BackColor = "Blue"} # $form.Add_Closing({param($sender,$e) $Sync.Flag =-2 [environment]::exit(1)}) $Label1 = New-Object system.Windows.Forms.Label -Property @{ Location = New-Object System.Drawing.Point(5, 30) Size = New-Object System.Drawing.Size(($Width-20),65) Font= "Verdana"} # $ProgressBar1 = New-Object System.Windows.Forms.ProgressBar -Property @{ Value = 0 Minimum = 0 Maximum = 100 Style="Continuous" Location = New-Object System.Drawing.Point(5, 90) Size = New-Object System.Drawing.Size(($Width-25),20)} # $Label2 = New-Object system.Windows.Forms.Label -Property @{ Location = New-Object System.Drawing.Point(0, 130) Size = New-Object System.Drawing.Size(($Width-20),65) Font= "Verdana"} # $ProgressBar2 = New-Object System.Windows.Forms.ProgressBar -Property @{ Value = 0 Minimum = 0 Maximum = 100 Style="Continuous" Location = New-Object System.Drawing.Point(5, 190) Size = New-Object System.Drawing.Size(($Width-25),20)} $Form.Show() $Form.Controls.AddRange(@($Label1, $Label2, $ProgressBar1, $ProgressBar2)) # While ($Sync.Flag -eq 0){Start-Sleep -Milliseconds 100|Out-Null} While ($Sync.Flag -gt 0) { $Form.Text = $Sync.FileName $Label1.Text = $Sync.Label1 $Label2.Text = $Sync.Label2 $ProgressBar1.Value = $Sync.CompletionRate1 $ProgressBar2.Value = $Sync.CompletionRate2 $Form.Refresh() [System.Windows.Forms.Application]::DoEvents() # $Sync.host.ui.WriteVerboseLine($Sync.label1) $Null = (Start-Sleep -MilliSeconds 100) }Else{$form.Close();$Form.Dispose()} })|Out-Null $handle = $powershell.BeginInvoke() # Copy_Progression $Files32 $usbfat32 "FAT32" Copy_Progression $Filesntfs $usbntfs "NTFS" $Sync.Flag = -1 #****************************************************************************** # $Form.Controls.Clear() $OKButton.Location = New-Object System.Drawing.Point(25,185) $OKButton.Text = "Next" $CancelButton.Location = New-Object System.Drawing.Point(300,185) $CancelButton.Text = "Abort" $Label1.Text = "All folders and files copyed." $Label1.Location=New-Object System.Drawing.Point(30,80) $Label1.Size = New-Object System.Drawing.Size(380,20) $Form.Controls.AddRange(@($OKButton, $Label1, $CancelButton)) If($Form.Showdialog() -eq "Cancel"){exit} # $InformationText.AppendText("`nUpdating BCD`n") $Information.Show() $Information.Refresh() Update_BCD $usbfat32 Update_BCD $usbntfs # $InformationText.AppendText("`nRemoving the drive letter to hide the FAT32 boot partition`n") $Information.Refresh() Get-Volume ($usbfat32 -replace ".$")|Get-Partition| Remove-PartitionAccessPath -accesspath $usbfat32 # If(DVD){ $InformationText.AppendText("`nEject the mounted ISO image if it was loaded by the script") $Information.Refresh() # Eject the mounted iso image if it was loaded by the script If(!$Mounted){DisMount-DiskImage $ImagePath >$Null} } # bootsect /nt60 $usbntfs /force /mbr >$Null # $Information.Dispose() $Information.Close() $Form.Controls.Clear() $Form.Controls.AddRange(@($OKButton, $Label1)) $OKButton.Location=New-Object System.Drawing.Point(170,185) $Label1.Location=New-Object System.Drawing.Point(20,80) $Label1.AutoSize = $True $Label1.Text = "$Title was created successfully." $OKButton.Text = "Exit" [void]$Form.ShowDialog()