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).