Win10 Installation Disk [UEFI or BIOS / UEFI with Secure Boot / Install.wim over 4GB]

Discussion in 'Scripting' started by freddie-o, Mar 21, 2019.

  1. rpo

    rpo MDL Addicted

    Jan 3, 2010
    944
    710
    30
    Can't reproduce the error when starting the script. Perhaps a problem witl the directory name?
    Code:
    <# : standard way of doing hybrid batch + powershell scripts
    @set "__CMD__=%~f0" &set "__ARGS__=%*" &powershell -noprofile -c "iex([io.file]::ReadAllText(\"%~f0\"))" &exit/b
    #>
    #
    #    This script must be executed with admin privilege
    #
    #    Test Administrator privileges
    If (-NOT ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole(544))
    {
    #    Restart the script to get Administrator privileges and exit
         Start-Process cmd -ArgumentList ("/c call `"$Env:__CMD__`" $Env:__ARGS__") -Verb runAs
         exit
    }
    #    We have Administrator privileges
    #
    $pswindow = $host.ui.rawui          # create a reference to the console’s UI.RawUI child object
    $pswindow.windowtitle = "Windows Installation Disk v1.3 by: rpo/abbodi1406/BAU/freddie-o [forums.mydigitallife.net]"
    [console]::ForegroundColor = "Yellow"
    [console]::BackgroundColor = "blue"
    #
    Add-Type -AssemblyName System.Windows.Forms # Load the class System.Windows.Forms
    # Filebrowser dialog
    $FileBrowser = New-Object System.Windows.Forms.OpenFileDialog -Property @{
       Multiselect = $false # One file can be chosen
        Filter = 'ISO images (*.iso)|*.iso' # Select iso files
    }
    $wshell=New-Object -ComObject Wscript.Shell
    #
    clear-host
    #
    $Form=New-Object System.Windows.Forms.Form # Create the screen form (window)
    # Set the size of the window:
    $Form.FormBorderStyle = "none"
    $Form.Width=450 ; $Form.Height=120
    $Form.AutoSize=$true # AutoSize property to make the form automatically stretch, if the elements on the form are out of bounds
    $Form.KeyPreview = $True
    $Form.Add_KeyDown({if ($_.KeyCode -eq "Enter"){$SelectISOButton.PerformClick()}})
    $Form.Add_KeyDown({if ($_.KeyCode -eq "Escape"){$CancelButton.PerformClick()}})
    #
    #    Select the USB disk
    # Create a 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(30,35)
    $USBDiskList.Width=380;$USBDiskList.height=20
    $Form.Controls.Add($SelectUSBDiskList)
    $USB=$Null
    $USBDisks=@() # array with USB disk number
    $Disks=Get-Disk | Where-Object {($_.BusType -eq "USB") -and ($_.OperationalStatus -eq "Online")}
    While (!$Disks) {
        $Result=$wshell.Popup("No USB disk was detected. `r`n`r`Plug in your USB disk first. Click ""OK"" after you have plugged in your disk or ""Cancel"" to exit.",0,"Plug in the USB",1+64)
            if ($result -eq 2) {$wshell.Popup("The script was cancelled.",0,"Cancel script",0+64) | Out-Null;exit}
        $Disks=Get-Disk | Where-Object {($_.BusType -eq "USB") -and ($_.OperationalStatus -eq "Online")}
    }
    Foreach ($USBDisk in $Disks) {
        $FriendlyName=($USBDisk.FriendlyName).PadRight(30," ").substring(0,30)
        $Partitions = Get-Partition | Where-Object { $_.DiskNumber -eq $USBDisk.DiskNumber}
        If ($Partitions) {
            Foreach ($Partition in $Partitions) {
            $Volumes=get-volume | Where-Object {$Partition.AccessPaths -contains  $_.path }
            Foreach ($Volume in $Volumes) {
                $USBDisks+=$USBDisk.DiskNumber
                $USBDiskList.Items.Add((" {0,-30}|{1,1}:| {2,-30}| {3:n2} GB" -f $FriendlyName, ($Partition.DriveLetter), $Volume.FileSystemLabel.PadRight(30," ").substring(0,30), ($Partition.Size/1GB)))|out-null
                }     
            }
        } Else {
            $USBDisks+=$USBDisk.DiskNumber
            $USBDiskList.Items.Add((" {0,-30}| {1,1}| {2,-30}| {3:n2} GB" -f $FriendlyName, " ", " ",($USBDisk.Size/1GB)))|out-null
        }
    }
    $form.Controls.Add($USBDiskList)
    $USBDiskList.SelectedIndex=0
    
    $SelectUSBDisk=New-Object System.Windows.Forms.Label # Put the SelectUSBDisk label on the form
    $SelectUSBDisk.Location=New-Object System.Drawing.Size(30,15)
    $SelectUSBDisk.Text="Select the USB disk";$SelectUSBDisk.Font='Consolas,10'
    $SelectUSBDisk.width=150;$SelectUSBDisk.height=15;
    $Form.Controls.Add($SelectUSBDisk)
    
    $SelectISOButton=New-Object System.Windows.Forms.Button # Put the SelectISO button on the form
    $SelectISOButton.Location=New-Object System.Drawing.Size(300,70)
    $SelectISOButton.Text="Select ISO";$SelectISOButton.Font='Consolas,10'
    $SelectISOButton.Size=New-Object System.Drawing.Size(120,20)
    $SelectISOButton.width=110;$SelectISOButton.height=30;
    $Form.Controls.Add($SelectISOButton)
    $SelectISOButton.DialogResult = [System.Windows.Forms.DialogResult]::OK
    
    $CancelButton=New-Object System.Windows.Forms.Button # Put the Cancel button on the form
    $CancelButton.Location=New-Object System.Drawing.Size(180,70)
    $CancelButton.Text="Cancel";$CancelButton.Font='Consolas,10'
    $CancelButton.Size=New-Object System.Drawing.Size(120,20)
    $CancelButton.width=110;$CancelButton.height=30;
    $Form.Controls.Add($CancelButton)
    $CancelButton.DialogResult = [System.Windows.Forms.DialogResult]::Cancel
    #
    $result = $form.ShowDialog()
    if ($result -eq "Cancel"){$wshell.Popup("The script was cancelled.",0,"Cancel script",0+64) | Out-Null;exit}
    #
    $USB=$USBDisks[$USBDiskList.SelectedIndex]
    #
    [void]$FileBrowser.ShowDialog()
    #
    $ImagePath = $FileBrowser.FileName;
    if ($ImagePath -eq ""){$wshell.Popup("The script was cancelled.",0,"Cancel script",0+64) | Out-Null;exit}
    $ISO=":"
    If($FileBrowser.FileNames -like "*\*") {
    #  Check if iso already mounted
        $ISO = (Get-DiskImage -ImagePath $ImagePath | Get-Volume).DriveLetter
    #    Mount iso
        IF (!$ISO) {Mount-DiskImage -ImagePath $ImagePath -StorageType ISO |out-null
        $ISO = (Get-DiskImage -ImagePath $ImagePath | Get-Volume).DriveLetter}
        $ISO=$ISO+":"
    }
    if ($ISO -eq ":") {$wshell.Popup("The script was cancelled.",0,"Cancel operation",0+64) | Out-Null;exit}
    #
    $Result=$wshell.Popup("All partitions and data on the USB disk will be lost. `r`n`r`nAre you sure you want to start creating the Windows installation disk?",0,"Warning",1+48)
    if ($result -eq 2) {DisMount-DiskImage -ImagePath $ImagePath |out-null;exit}
    #    Clear the USB stick
    Clear-Disk $usb -RemoveData -RemoveOEM -Confirm:$false
    Stop-Service ShellHWDetection
    #    Create the fat32 boot partition
    $usbfat32=(New-Partition -DiskNumber $usb -Size 700MB -AssignDriveLetter | Format-Volume -FileSystem FAT32 -NewFileSystemLabel "BOOT").DriveLetter + ":"
    #    Create the ntfs intall partition
    $usbntfs=(New-Partition -DiskNumber $usb -UseMaximumSize -AssignDriveLetter -IsActive | Format-Volume -FileSystem NTFS -NewFileSystemLabel "INSTALL").DriveLetter + ":"
    Start-Service ShellHWDetection
    #
    robocopy $iso $usbntfs /e
    robocopy $iso"\" $usbfat32"\" bootmgr bootmgr.efi
    robocopy $iso"\boot" $usbfat32"\boot" /e
    robocopy $iso"\efi" $usbfat32"\efi" /e
    robocopy $iso"\sources" $usbfat32"\sources" boot.wim
    
    Copy-Item $ISO"\boot\bcd" $env:temp -Force
    & bcdedit /store ($env:temp + "\bcd") /set '{default}' bootmenupolicy Legacy
    Set-ItemProperty -Path ($env:temp + "\bcd") -Name IsReadOnly -Value $true
    Copy-Item ($env:temp + "\bcd") $usbfat32"\boot\bcd" -Force
    Copy-Item ($env:temp + "\bcd") $usbntfs"\boot\bcd" -Force
    Copy-Item $ISO"\EFI\Microsoft\boot\bcd" $env:temp -Force
    & bcdedit /store ($env:temp + "\bcd") /set '{default}' bootmenupolicy Legacy
    Set-ItemProperty -Path ($env:temp + "\bcd") -Name IsReadOnly -Value $true
    Copy-Item ($env:temp + "\bcd") $usbfat32"\EFI\Microsoft\boot\bcd" -Force
    Copy-Item ($env:temp + "\bcd") $usbntfs"\EFI\Microsoft\boot\bcd" -Force
    remove-item ($env:temp + "\bcd") -force
    remove-item ($env:temp + "\bcd.*") -force
    
    # Eject the mounted iso image
    DisMount-DiskImage -ImagePath $ImagePath |out-null
    #done - keep a comment on the last line so the previous useful crlf never gets eaten
    

    With UEFI/GPTE systems the fat32 partition is used and the partition doesn't need to be activated. With legacy bios MBR systems you can boot with an ntfs partition, the fat32 partition isn't needed, but on older computers (all my systems) the partition has to be set as active.
    AFAIK, you have no progress bar if you don't modify the BCD whatever windows boot disk you use.
     
  2. freddie-o

    freddie-o MDL Senior Member

    Jul 29, 2009
    448
    437
    10
    Still shows
    Code:
    H:\> : standard way of doing hybrid batch + powershell scripts 0<#
    The system cannot find the file specified.
    Renamed the file without spaces and put it in the root of the partition but still the same... never had to do this with past scripts.

    So when booting on an MBR system, the installation disk doesn't use the FAT32 partition but goes straight to the NTFS partition? You mean you couldn't boot into the installation disk?

    All my Windows 10 ISOs have a progress bar when loading into the boot.wim. Maybe it's just on older PCs and/or versions of Windows?
     
  3. freddie-o

    freddie-o MDL Senior Member

    Jul 29, 2009
    448
    437
    10
    Not so sure about the System.Windows.Forms window not having a title bar so you cannot move it around.
     
  4. BAU

    BAU MDL Senior Member

    Feb 10, 2009
    376
    589
    10
    That's just your fault for saving the batch file in an incompatible format.
    Make sure you always use a 7-8 bit format such as OEM(DOS) / ANSI ( Windows 1250 ) / ISO-8859 etc and NOT unicode or utf with bom
     
  5. freddie-o

    freddie-o MDL Senior Member

    Jul 29, 2009
    448
    437
    10
    I use Notepad++ to edit and save it as Batch file (*.bat, *.cmd)
     
  6. rpo

    rpo MDL Addicted

    Jan 3, 2010
    944
    710
    30
    On a MBR system, the boot process searchs for an active partition : if the ntfs partition is set active (the fat32 partition is not active : only one partition can be set active on a volume), it will be used. If no partition is set active your system may not boot (depends on the bios).
     
  7. rpo

    rpo MDL Addicted

    Jan 3, 2010
    944
    710
    30
    I too use notepad++, downloaded the uploaded file and executed the script without issue.
     
  8. freddie-o

    freddie-o MDL Senior Member

    Jul 29, 2009
    448
    437
    10
    The problem went away after I restarted my computer. :)
     
  9. freddie-o

    freddie-o MDL Senior Member

    Jul 29, 2009
    448
    437
    10
    I was thinking though. The script was originally meant just to automate the job of formatting and copying the ISO to the USB disk. So now I'm not sure about modifying the bcd store to add bootmenupolicy legacy.
     
  10. freddie-o

    freddie-o MDL Senior Member

    Jul 29, 2009
    448
    437
    10
    This won't cause a problem with some UEFI (with Secure Boot) systems that boot into FAT32?
     
  11. rpo

    rpo MDL Addicted

    Jan 3, 2010
    944
    710
    30
    Just delete the instructions modifying the bcd store.
    If you prefer, you can set the fat32 partition active as in the original script :
    # Create the fat32 boot partition
    $usbfat32=(New-Partition -DiskNumber $usb -Size 1GB -AssignDriveLetter -IsActive | Format-Volume -FileSystem FAT32 -NewFileSystemLabel "BOOTFAT").DriveLetter + ":"
    # Create the ntfs intall partition
    $usbntfs=(New-Partition -DiskNumber $usb -UseMaximumSize -AssignDriveLetter | Format-Volume -FileSystem NTFS -NewFileSystemLabel "INSTALL").DriveLetter + ":"
     
  12. drew84

    drew84 MDL Addicted

    Mar 13, 2014
    526
    978
    30
    .. guys freddie-o, rpo
    I have been following this thread for a while now, and am enjoying the banter/conversation between you two..
    looking forward to the continued conversation and each update of this project
     
    Stop hovering to collapse... Click to collapse... Hover to expand... Click to expand...
  13. freddie-o

    freddie-o MDL Senior Member

    Jul 29, 2009
    448
    437
    10
    #113 freddie-o, Aug 8, 2019
    Last edited: Aug 8, 2019
    (OP)
    EDIT:

    The script so far with no errors...
    Code:
    <# : standard way of doing hybrid batch + powershell scripts
    @set "__CMD__=%~f0" &set "__ARGS__=%*" &powershell -noprofile -c "iex([io.file]::ReadAllText(\"%~f0\"))" &exit/b
    #>
    #
    #    This script must be executed with admin privilege
    #
    #    Test Administrator privileges
    If (-NOT ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole(544))
    {
    #    Restart the script to get Administrator privileges and exit
         Start-Process cmd -ArgumentList ("/c call `"$Env:__CMD__`" $Env:__ARGS__") -Verb runAs
         exit
    }
    #    We have Administrator privileges
    #
    $pswindow = $host.ui.rawui          # create a reference to the console’s UI.RawUI child object
    $pswindow.windowtitle ="Script by: rpo/abbodi1406/BAU/freddie-o [forums.mydigitallife.net]"
    [console]::ForegroundColor = "Yellow"
    [console]::BackgroundColor = "Blue"
    #
    Add-Type -AssemblyName System.Windows.Forms # Load the class System.Windows.Forms
    # Filebrowser dialog
    $FileBrowser = New-Object System.Windows.Forms.OpenFileDialog -Property @{
       Multiselect = $false # One file can be chosen
        Filter = 'ISO images (*.iso)|*.iso' # Select iso files
    }
    $wshell=New-Object -ComObject Wscript.Shell
    #
    $global:SelectISO=$False
    $global:Cancel=$False
    #
    clear-host
    $Form=New-Object System.Windows.Forms.Form # Create the screen form (window)
    # Set the title and size of the window:
    $Form.Text='Windows Installation Disk v1.3'
    $Form.Width=450 ; $Form.Height=200
    $Form.AutoSize=$true # AutoSize property to make the form automatically stretch, if the elements on the form are out of bounds
    #    Select the USB disk
    # Create a drop-down list and fill it
    $Combobox=New-Object System.Windows.Forms.ComboBox
    $Combobox.DropDownStyle=[System.Windows.Forms.ComboBoxStyle]::DropDownList;
    $Combobox.Location=New-Object System.Drawing.Point(30,35)
    $Combobox.Width=380;$Combobox.height=20
    $USB=$Null
    $USBDisks=@() # array with USB disk number
    $Disks=Get-Disk | Where-Object {($_.BusType -eq "USB") -and ($_.OperationalStatus -eq "Online")}
    While (!$Disks) {
        $Result=$wshell.Popup("Plug in your USB disk first, then click ""OK"" to continue. `r`n`r`nTo close this script, click ""Cancel"".",0,"Plug in USB disk",1+64)
        if ($result -eq 2) {exit}
        $Disks=Get-Disk | Where-Object {($_.BusType -eq "USB") -and ($_.OperationalStatus -eq "Online")}
    }
    $USBDiskList=New-Object System.Windows.Forms.ComboBox
    # $USBDiskList|gm
    $USBDiskList.Width=450
    Foreach ($USBDisk in $Disks) {
        $FriendlyName=($USBDisk.FriendlyName).PadRight(30," ").substring(0,30)  
        $Partitions = Get-Partition | Where-Object { $_.DiskNumber -eq $USBDisk.DiskNumber}
        If ($Partitions) {
            Foreach ($Partition in $Partitions) {
            $Volumes=get-volume | Where-Object {$Partition.AccessPaths -contains  $_.path }
            Foreach ($Volume in $Volumes) {
                $USBDisks+=$USBDisk.DiskNumber
                $Combobox.Items.Add((" {0,-30}|{1,1}:| {2,-30}| {3:n2} GB" -f $FriendlyName, ($Partition.DriveLetter), $Volume.FileSystemLabel.PadRight(30," ").substring(0,30), ($Partition.Size/1GB)))|out-null
                }      
            }  
        } Else {
            $USBDisks+=$USBDisk.DiskNumber
            $USBDiskList.Items.Add((" {0,-30}| {1,1}| {2,-30}| {3:n2} GB" -f $FriendlyName, " ", " ",($USBDisk.Size/1GB)))|out-null
        }
    }
    $SelectUSBDisk=New-Object System.Windows.Forms.Label # Put the SelectUSBDisk label on the form
    $SelectUSBDisk.Location=New-Object System.Drawing.Size(30,15)
    $SelectUSBDisk.Text="Select the USB disk";$SelectUSBDisk.Font='Consolas,10'
    $SelectUSBDisk.width=150;$SelectUSBDisk.height=15;
    $Form.Controls.Add($SelectUSBDisk)
    $form.Controls.Add($Combobox)
    $Combobox.SelectedIndex=0
    
    
    
    $SelectISOButton=New-Object System.Windows.Forms.Button # Put the SelectISO button on the form
    $SelectISOButton.Location=New-Object System.Drawing.Size(300,110)
    $SelectISOButton.Text="Select ISO";$SelectISOButton.Font='Consolas,10'
    $SelectISOButton.width=110;$SelectISOButton.height=30;
    $Form.Controls.Add($SelectISOButton)
    $SelectISOButton.Add_Click({$global:SelectISO=$true;[void]$FileBrowser.ShowDialog()})
    $Form.Controls.Add($SelectISOButton)
    $SelectISOButton.Add_Click({$Form.close()})
    
    $CancelButton=New-Object System.Windows.Forms.Button # Put the Cancel button on the form
    $CancelButton.Location=New-Object System.Drawing.Size(180,110)
    $CancelButton.Size=New-Object System.Drawing.Size(120,20)
    $CancelButton.Text="Cancel";$CancelButton.Font='Consolas,10'
    $CancelButton.width=110;$CancelButton.height=30;
    $Form.Controls.Add($CancelButton)
    $CancelButton.Add_Click({$global:Cancel=$True;$Form.close()})
    #
    [void]$Form.ShowDialog()
    #
    $USB=$USBDisks[$USBDiskList.SelectedIndex]
    #
    $ImagePath = $FileBrowser.FileName;
    $ISO=":"
    If($FileBrowser.FileNames -like "*\*") {
    #  Check if iso already mounted
        $ISO = (Get-DiskImage -ImagePath $ImagePath | Get-Volume).DriveLetter
    #    Mount iso
        IF (!$ISO) {Mount-DiskImage -ImagePath $ImagePath -StorageType ISO |out-null
        $ISO = (Get-DiskImage -ImagePath $ImagePath | Get-Volume).DriveLetter}
        $ISO=$ISO+":"
    }
    if ($ISO -eq ":") {$wshell.Popup("The script was cancelled.",0,"Cancel script",0+64) | Out-Null;exit}
    #
    $Result=$wshell.Popup("Warning! All partitions and data on the USB disk will be lost. `r`n`r`nTo create the Windows installation disk, click ""OK"". `r`n`r`nTo close this script, click ""Cancel"".",0,"Create Windows installation disk",1+48)
    if ($result -eq 2) {DisMount-DiskImage -ImagePath $ImagePath |out-null;exit}
    #    Clear the USB stick
    Clear-Disk $usb -RemoveData -RemoveOEM -Confirm:$false
    Stop-Service ShellHWDetection
    #    Create the fat32 boot partition
    $usbfat32=(New-Partition -DiskNumber $usb -Size 700MB -AssignDriveLetter -IsActive | Format-Volume -FileSystem FAT32 -NewFileSystemLabel "BOOT").DriveLetter + ":"
    #    Create the ntfs intall partition
    $usbntfs=(New-Partition -DiskNumber $usb -UseMaximumSize -AssignDriveLetter | Format-Volume -FileSystem NTFS -NewFileSystemLabel "INSTALL").DriveLetter + ":"
    Start-Service ShellHWDetection
    #
    robocopy $iso $usbntfs /e
    robocopy $iso"\" $usbfat32"\" bootmgr bootmgr.efi
    robocopy $iso"\boot" $usbfat32"\boot" /e
    robocopy $iso"\efi" $usbfat32"\efi" /e
    robocopy $iso"\sources" $usbfat32"\sources" boot.wim
    # Eject the mounted iso image
    DisMount-DiskImage -ImagePath $ImagePath |out-null
    #done - keep a comment on the last line so the previous useful crlf never gets eaten
     
  14. rpo

    rpo MDL Addicted

    Jan 3, 2010
    944
    710
    30
    Your script is confusing : you have 2 combobox objects : $Combobox and $UsbDiskList. The script should be adapted to use only $UsbDiskList.
     
  15. freddie-o

    freddie-o MDL Senior Member

    Jul 29, 2009
    448
    437
    10
  16. freddie-o

    freddie-o MDL Senior Member

    Jul 29, 2009
    448
    437
    10
    #116 freddie-o, Aug 9, 2019
    Last edited: Aug 9, 2019
    (OP)
    Fixed
    Code:
    <# : standard way of doing hybrid batch + powershell scripts
    @set "__CMD__=%~f0" &set "__ARGS__=%*" &powershell -noprofile -c "iex([io.file]::ReadAllText(\"%~f0\"))" &exit/b
    #>
    #
    #    This script must be executed with admin privilege
    #
    #    Test Administrator privileges
    If (-NOT ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole(544))
    {
    #    Restart the script to get Administrator privileges and exit
         Start-Process cmd -ArgumentList ("/c call `"$Env:__CMD__`" $Env:__ARGS__") -Verb runAs
         exit
    }
    #    We have Administrator privileges
    #
    $pswindow = $host.ui.rawui          # create a reference to the console’s UI.RawUI child object
    $pswindow.windowtitle = "Script by: rpo/abbodi1406/BAU/freddie-o [forums.mydigitallife.net]"
    [console]::ForegroundColor = "yellow"
    [console]::BackgroundColor = "blue"
    #
    Add-Type -AssemblyName System.Windows.Forms # Load the class System.Windows.Forms
    # Filebrowser dialog
    $FileBrowser = New-Object System.Windows.Forms.OpenFileDialog -Property @{
       Multiselect = $false # One file can be chosen
        Filter = 'ISO images (*.iso)|*.iso' # Select iso files
    }
    $wshell=New-Object -ComObject Wscript.Shell
    #
    clear-host
    #
    $Form=New-Object System.Windows.Forms.Form # Create the screen form (window)
    # Set the title and size of the window:
    $Form.Text='Windows Installation Disk v1.3'
    $Form.Width=455 ; $Form.Height=220
    $Form.AutoSize=$true # AutoSize property to make the form automatically stretch, if the elements on the form are out of bounds
    #
    #    Select the USB disk
    # Create a 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,35)
    $USBDiskList.Width=400;$USBDiskList.height=20
    $Form.Controls.Add($SelectUSBDisk)
    $USB=$Null
    $USBDisks=@() # array with USB disk number
    $Disks=Get-Disk | Where-Object {($_.BusType -eq "USB") -and ($_.OperationalStatus -eq "Online")}
    While (!$Disks) {
        $Result=$wshell.Popup("Plug in your USB disk first, then click ""OK"" to continue. `r`n`r`nTo close this script, click ""Cancel"".",0,"Plug in USB disk",1+64)
            if ($result -eq 2) {$wshell.Popup("The script was cancelled.",0,"Cancel script",0+64) | Out-Null;exit}
        $Disks=Get-Disk | Where-Object {($_.BusType -eq "USB") -and ($_.OperationalStatus -eq "Online")}
    }
    Foreach ($USBDisk in $Disks) {
        $FriendlyName=($USBDisk.FriendlyName).PadRight(30," ").substring(0,30)
        $Partitions = Get-Partition | Where-Object { $_.DiskNumber -eq $USBDisk.DiskNumber}
        If ($Partitions) {
            Foreach ($Partition in $Partitions) {
            $Volumes=get-volume | Where-Object {$Partition.AccessPaths -contains  $_.path }
            Foreach ($Volume in $Volumes) {
                $USBDisks+=$USBDisk.DiskNumber
                $USBDiskList.Items.Add((" {0,-30}|{1,1}:| {2,-30}| {3:n2} GB" -f $FriendlyName, ($Partition.DriveLetter), $Volume.FileSystemLabel.PadRight(30," ").substring(0,30), ($Partition.Size/1GB)))|out-null
                }     
            }
        } Else {
            $USBDisks+=$USBDisk.DiskNumber
            $USBDiskList.Items.Add((" {0,-30}| {1,1}| {2,-30}| {3:n2} GB" -f $FriendlyName, " ", " ",($USBDisk.Size/1GB)))|out-null
        }
    }
    
    $form.Controls.Add($USBDiskList)
    $USBDiskList.SelectedIndex=0
    
    $SelectUSB=New-Object System.Windows.Forms.Label # Put the SelectUSB label on the form
    $SelectUSB.Location=New-Object System.Drawing.Size(20,15)
    $SelectUSB.Text="Select USB disk";$SelectUSB.Font='Consolas,10'
    $SelectUSB.width=380;$SelectUSB.height=15;
    $Form.Controls.Add($SelectUSB)
    
    $SelectISOButton=New-Object System.Windows.Forms.Button # Put the SelectISO button on the form
    $SelectISOButton.Location=New-Object System.Drawing.Size(310,130)
    $SelectISOButton.Text="Select ISO";$SelectISOButton.Font='Consolas,10'
    $SelectISOButton.Size=New-Object System.Drawing.Size(120,20)
    $SelectISOButton.width=110;$SelectISOButton.height=30;
    $Form.Controls.Add($SelectISOButton)
    $SelectISOButton.DialogResult = [System.Windows.Forms.DialogResult]::OK
    
    $CancelButton=New-Object System.Windows.Forms.Button # Put the Cancel button on the form
    $CancelButton.Location=New-Object System.Drawing.Size(190,130)
    $CancelButton.Text="Cancel";$CancelButton.Font='Consolas,10'
    $CancelButton.Size=New-Object System.Drawing.Size(120,20)
    $CancelButton.width=110;$CancelButton.height=30;
    $Form.Controls.Add($CancelButton)
    $CancelButton.DialogResult = [System.Windows.Forms.DialogResult]::Cancel
    #
    $result = $form.ShowDialog()
    if ($result -eq "Cancel"){$wshell.Popup("The script was cancelled.",0,"Cancel script",0+64) | Out-Null;exit}
    #
    $USB=$USBDisks[$USBDiskList.SelectedIndex]
    #
    [void]$FileBrowser.ShowDialog()
    #
    $ImagePath = $FileBrowser.FileName;
    if ($ImagePath -eq ""){$wshell.Popup("The script was cancelled.",0,"Cancel script",0+64) | Out-Null;exit}
    $ISO=":"
    If($FileBrowser.FileNames -like "*\*") {
    #  Check if iso already mounted
        $ISO = (Get-DiskImage -ImagePath $ImagePath | Get-Volume).DriveLetter
    #    Mount iso
        IF (!$ISO) {Mount-DiskImage -ImagePath $ImagePath -StorageType ISO |out-null
        $ISO = (Get-DiskImage -ImagePath $ImagePath | Get-Volume).DriveLetter}
        $ISO=$ISO+":"
    }
    if ($ISO -eq ":") {$wshell.Popup("The script was cancelled.",0,"Cancel script",0+64) | Out-Null;exit}
    #
    $Result=$wshell.Popup("Warning! All partitions and data on the USB disk will be lost. `r`n`r`nTo continue creating the installation disk, click ""OK"". `r`n`r`nTo close this script, click ""Cancel"".",0,"Create Windows installation disk",1+48)
    if ($result -eq 2) {DisMount-DiskImage -ImagePath $ImagePath |out-null;exit}
    #    Clear the USB stick
    Clear-Disk $usb -RemoveData -RemoveOEM -Confirm:$false
    Stop-Service ShellHWDetection
    #    Create the fat32 boot partition
    $usbfat32=(New-Partition -DiskNumber $usb -Size 700MB -AssignDriveLetter -IsActive | Format-Volume -FileSystem FAT32 -NewFileSystemLabel "BOOT").DriveLetter + ":"
    #    Create the ntfs intall partition
    $usbntfs=(New-Partition -DiskNumber $usb -UseMaximumSize -AssignDriveLetter | Format-Volume -FileSystem NTFS -NewFileSystemLabel "INSTALL").DriveLetter + ":"
    Start-Service ShellHWDetection
    #
    robocopy $iso $usbntfs /e
    robocopy $iso"\" $usbfat32"\" bootmgr bootmgr.efi
    robocopy $iso"\boot" $usbfat32"\boot" /e
    robocopy $iso"\efi" $usbfat32"\efi" /e
    robocopy $iso"\sources" $usbfat32"\sources" boot.wim
    
    # Eject the mounted iso image
    DisMount-DiskImage -ImagePath $ImagePath |out-null
    #done - keep a comment on the last line so the previous useful crlf never gets eaten
    

    Edit:
    Updated the script (which had errors) in the OP.
     
  17. rpo

    rpo MDL Addicted

    Jan 3, 2010
    944
    710
    30
    For me it's OK!
     
  18. rpo

    rpo MDL Addicted

    Jan 3, 2010
    944
    710
    30
    @BAU
    Your original (modified) coding to get admin privilege :
    Code:
    <# : standard way of doing hybrid batch + powershell scripts
    @echo off
    ::AveYo: self-elevate passing args and preventing loop
    set "args="%~f0" %*" & call set "args=%%args:"=\"%%"
    fsutil dirty query %systemdrive%>nul||(if "%?%" neq "y" powershell -c "start cmd -ArgumentList '/c set ?=y&call %args%' -verb runas" &exit)
    powershell -NoLogo -NoProfile -WindowStyle Normal -ExecutionPolicy Bypass -c "iex([io.file]::ReadAllText(\"%~f0\"))" &exit/b
    #>
    has the advantage to prevent loop, but this is not the case with :
    Code:
    <# : standard way of doing hybrid batch + powershell scripts
    @set "__CMD__=%~f0" &set "__ARGS__=%*" &powershell -noprofile -c "iex([io.file]::ReadAllText(\"%~f0\"))" &exit/b
    #>
    #
    #    This script must be executed with admin privilege
    #
    #    Test Administrator privileges
    If (-NOT ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole(544))
    {
    #    Restart the script to get Administrator privileges and exit
         Start-Process cmd -ArgumentList ("/c call `"$Env:__CMD__`" $Env:__ARGS__") -Verb runAs
         exit
    }
    How is this to be modified to prevent loop? I suppose we have to deal with argument passing...
     
  19. BAU

    BAU MDL Senior Member

    Feb 10, 2009
    376
    589
    10
    there should be no loop since the check is in powershell - IsInRole(544) takes care of that ( if not admin - restart as admin, if already admin, do nothing )
     
  20. rpo

    rpo MDL Addicted

    Jan 3, 2010
    944
    710
    30
    Thanks. Efficient, as usual.