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. freddie-o

    freddie-o MDL Senior Member

    Jul 29, 2009
    449
    441
    10
    #1 freddie-o, Mar 21, 2019
    Last edited: Sep 15, 2019
    This fully automated script creates a custom Windows 10 installation disk.
    • For both Legacy BIOS and the native UEFI boot process.
    • For systems that use UEFI with Secure Boot
    • For Windows ISOs that have Install.WIMs over 4GB -- Due to the 4GB limitation of FAT32.




    What the script does:
    1. Converts your USB disk to MBR scheme -- In case your USB disk was converted to GPT scheme. Otherwise the script will fail in creating the installation disk.
    2. Creates 2 partitions on your USB disk. A FAT32 and an NTFS partition.
    3. Mounts your Windows ISO.
    4. Copies the entire contents of the Windows ISO to the NTFS partition of the installation disk.
    5. Then copies all the boot files (“boot” folder, “efi” folder, “bootmgr”, “bootmgr.efi” and “boot.wim”) from the Windows ISO to the FAT32 partition of the installation disk.
    NOTE: The script adds Legacy BootMenuPolicy to the BCD store to show a progress bar while booting on Legacy BIOS systems.





    Supported Windows 10 versions:

    Only works on Windows 10 v1703 (Build 15063) or higher -- Earlier versions of Windows do not support reading and creating multiple partitions on removable storage devices.





    Thanks to:

    @abbodi1406 and @BAU for their input.





    Version history:

    v1.9.2 (Sep 12, 2019)
    Made some minor modifications to the UI.
    Also some changes to the script on how the ISO is selected.
    The consoles text and background colors are now consistent with one another.

    v1.9.1 (Sep 10, 2019)
    Separated the "Select ISO" and "Create Disk" buttons so you still have opportunity to change your choice of ISO before creating the installation disk.

    v1.9 (Sep 10, 2019)
    Changed the name of script to "Win10 Installation Disk"
    Made corrections and modifications to the script.

    v1.8.2 (Sep 9, 2019)
    Enabled Visual Styles

    v1.8.1 (Sep 8, 2019)
    Cleaned up the script and made some minor changes to the script and UI.

    v1.8 (Sep 6, 2019)
    Reverted to the original design and improved the UI to be more user-friendly.

    v1.7 (Aug 30, 2019)
    More fixes in the elevation of the script.
    More changes to the UI. Updated to a flat design.

    v1.6 (Aug 29, 2019)
    Corrected the script where it aborts when not run as Administrator.
    More changes to the UI.

    v1.5 (Aug 26, 2019)
    New user-friendly GUI.
    Shows a progress bar while booting on Legacy BIOS systems. (Added Legacy BootMenuPolicy to the BCD store.)

    v1.4 (Aug 15, 2019)
    Converts the USB disk to MBR scheme. (In case your USB disk was converted to GPT scheme. Otherwise the script will fail in creating the installation disk.)
    Sets the NTFS partition as Active for Legacy BIOS systems.
    Modified the USB drop down list to show the disk/s and its partitions.

    v1.3 (Aug 7, 2019)
    Did some "housekeeping" to clean the script.
    Modified the script to remove "cosmetics".

    v1.2 (Aug 5, 2019)
    Uses a GUI for creating the Windows installation disk.
    Uses a hybrid batch-powershell format to elevate and run the script

    v1.1 (Aug 2, 2019)
    Modified the script so it runs without echoing to a .ps1 file.
    Uses reg_takeownership to elevate script.

    v1.0 (Mar 13, 2019)
    First automated script.





    Script:

    Code:
    <# : standard way of doing hybrid batch + powershell scripts
    @title Win10 Installation Disk 1.9.2 @ forums.mydigitallife.net &color 3E
    @set "__ARGS__=%*" &powershell -noprofile -c "$ScriptPath='%~f0';iex((Get-Content($ScriptPath))  -join [char[]]10)" &exit/b
    #>
    #
    #   This script must be executed with admin privilege
    #
    #   Test Administrator privileges
    If (-NOT ([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 ($env:__ARGS__ -eq $uac_error) {
       read-host "$uac_error`r`nRight click on the script and select ""Run as administrator""`r`nPress Enter to exit...";exit}
    #   Restart the script to get Administrator privileges and exit
                                                                                          
        Start-Process "$ScriptPath" $uac_error -Verb runAs; exit
    }
    $pswindow = $host.ui.rawui          # create a reference to the console’s UI.RawUI child object
    $pswindow.windowtitle = ([string]($pswindow.windowtitle -split "^.*  ")).trim() ; $ShortTitle=($pswindow.windowtitle -split " @ .*")[0]
    #
    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 # One file can be chosen
        Filter = 'ISO images (*.iso)|*.iso' # Select only iso files
    }
    #
    Function MsgBox {[System.Windows.Forms.MessageBox]::Show($Args[0],$ShortTitle,$Args[1],$Args[2])}
    #
    clear-host
    $USB=$Null
    $Form=New-Object System.Windows.Forms.Form # Create the screen form (window)
    $Form.TopMost = $True
    # Set the title and size of the window:
    $Form.Text=$ShortTitle
    $Form.Width=420 ; $Form.Height=250
    $Form.StartPosition = "CenterScreen"
    $Form.SizeGripStyle = "Hide"
    [System.Windows.Forms.Application]::EnableVisualStyles();
    
    # 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,45)
    $USBDiskList.Size=New-Object System.Drawing.Size(365,20)
    $USBDiskList.Font='Consolas,10'
    $Form.Controls.Add($SelectUSBDiskList)
    $USBDisks=@() # array with USB disk number
    $Disks=Get-Disk | Where-Object {($_.BusType -eq "USB") -and ($_.OperationalStatus -eq "Online")}
    
    While (!$Disks) {
    if((MsgBox "Please plug in your USB disk first then click OK to continue." "OKCancel" "Information") -eq "Cancel") {exit}
        $Disks=Get-Disk | Where-Object {($_.BusType -eq "USB") -and ($_.OperationalStatus -eq "Online")}
    }
    $USBDisk=New-Object System.Windows.Forms.Label # Put the USB Disk label on the form
    $USBDisk.Location=New-Object System.Drawing.Point(20,25)
    $USBDisk.Text="USB Disk"
    $USBDisk.Font='Default Font,9'
    $USBDisk.Size=New-Object System.Drawing.Size(400,20)
    $Form.Controls.Add($USBDisk)
    
    $ISOImage=New-Object System.Windows.Forms.Label # Put the ISO Image label on the form
    $ISOImage.Location=New-Object System.Drawing.Point(20,90)
    $ISOImage.Font='Default Font,9'
    $ISOImage.Size=New-Object System.Drawing.Size(350,20)
    $ISOImage.text="ISO Image"
    $Form.Controls.Add($ISOImage)
    
    $ISOFile=New-Object System.Windows.Forms.Label # Put the ISO file name on the form
    $ISOFile.Location=New-Object System.Drawing.Point(20,110)
    $ISOFile.Text=" "
    $ISOFile.Font='Consolas,10'
    $ISOFile.Size=New-Object System.Drawing.Size(365,23)
    $ISOFile.Backcolor = [System.Drawing.Color]::White
    $ISOFile.BorderStyle = [System.Windows.Forms.BorderStyle]::FixedSingle
    $Form.Controls.Add($ISOFile)
    
    $SelectISOButton=New-Object System.Windows.Forms.Button # Put the Select ISO button on the form
    $SelectISOButton.Location=New-Object System.Drawing.Point(180,170)
    $SelectISOButton.Text="Select ISO"
    $SelectISOButton.Font='Default Font,9'
    $SelectISOButton.Size=New-Object System.Drawing.Size(100,26)
    $Form.Controls.Add($SelectISOButton)
    
    $CancelButton=New-Object System.Windows.Forms.Button # Put the Cancel button on the form
    $CancelButton.Location=New-Object System.Drawing.Point(285,170)
    $CancelButton.Text="Cancel"
    $CancelButton.Font='Default Font,9'
    $CancelButton.Size=New-Object System.Drawing.Size(100,26)
    $Form.Controls.Add($CancelButton)
    $CancelButton.DialogResult = [System.Windows.Forms.DialogResult]::Cancel
    
    $CreateDiskButton=New-Object System.Windows.Forms.Button # Put the Create Disk button on the form
    $CreateDiskButton.Location=New-Object System.Drawing.Point(75,170)
    $CreateDiskButton.Text="Create Disk"
    $CreateDiskButton.Font='Default Font,9'
    $CreateDiskButton.Size=New-Object System.Drawing.Size(100,26)
    $Form.Controls.Add($CreateDiskButton)
    $CreateDiskButton.Enabled = $false
    $CreateDiskButton.DialogResult = [System.Windows.Forms.DialogResult]::OK
    
    $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()}})
    
    Foreach ($USBDisk in $Disks) {
        $FriendlyName=($USBDisk.FriendlyName).PadRight(40," ").substring(0,39)
        $USBDisks+=$USBDisk.DiskNumber
        $USBDiskList.Items.Add(("{0,-39}{1:n2} GB" -f $FriendlyName,($USBDisk.Size/1GB)))|out-null
        $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,-2}({1,1}:){2,-31}[{3:n2} GB]" -f " ", ($Partition.DriveLetter), $Volume.FileSystemLabel.PadRight(25," ").substring(0,25), ($Partition.Size/1GB)))|out-null
                }
            }
        }
    }
    $form.Controls.Add($USBDiskList)
    $USBDiskList.SelectedIndex=0
    #
    if($form.ShowDialog() -eq "Cancel") {MsgBox "The script was cancelled." "OK" "Information"|out-Null;exit}
    #
    # At this point the mounted USB disk and the iso image file path are defined
    #
    $USB=$USBDisks[$USBDiskList.SelectedIndex]
    #
    # Mount the image file if not already mounted and get the drive letter
    #
    #  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 ":") {exit}
    #
    If((MsgBox "WARNING! Your USB disk will be converted to MBR scheme, repartitioned and reformatted.`n`nAll partitions and data stored in the disk will be erased.`r`n`r`nAre you sure you want to continue?" "YESNO" "Warning") -eq "NO"){DisMount-DiskImage -ImagePath $ImagePath|Out-Null;exit}
    Clear-Host
    #    Clear the USB stick
    Clear-Disk $usb -RemoveData -RemoveOEM -Confirm:$false
    set-disk $usb -partitionstyle mbr
    Stop-Service ShellHWDetection -erroraction silentlycontinue|out-null
    #    Create the fat32 boot partition
    $usbfat32=(New-Partition -DiskNumber $usb -Size  1GB -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 -erroraction silentlycontinue|out-null
    #
    robocopy $iso $usbntfs /e /xf $iso\boot\bcd $iso\efi\microsoft\boot\bcd
    robocopy $iso"\" $usbfat32"\" bootmgr bootmgr.efi
    robocopy $iso"\boot" $usbfat32"\boot" /e /xf $iso\boot\bcd
    robocopy $iso"\efi" $usbfat32"\efi" /e /xf $iso\efi\microsoft\boot\bcd
    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
    MsgBox "The installation disk completed successfully." "OK" "Information" |Out-Null;exit
    
    





    Alternatively, you can download the script here:

    Win10 Installation Disk v1.9.2






     
  2. Krager

    Krager MDL Senior Member

    Jan 9, 2017
    395
    227
    10
    That's handy, added to watched threads. I actually enabled TPM and secure boot for the sake of BIOS security so it's nice if I don't have to turn if off for installs. My image is actually still under the limit, but at some point it will exceed it.
     
  3. rpo

    rpo MDL Addicted

    Jan 3, 2010
    947
    718
    30
    1. After statement 30, add :
    Code:
    echo if ^($ISO -eq ":"^) {$wshell.Popup^("No ISO image mounted or operation cancelled",0,"Error"^) ^| Out-Null;exit}
    2. The script elevates itself to run as admin if necessary
     
  4. freddie-o

    freddie-o MDL Senior Member

    Jul 29, 2009
    449
    441
    10
    #4 freddie-o, Mar 22, 2019
    Last edited: Mar 22, 2019
    (OP)
    Like so?

    Code:
    @echo off
    rem    This script must be executed with admin privilege
    (
    echo #    This script must be executed with admin privilege
    echo #    Test Administrator privileges
    echo If ^(-NOT ^([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent^(^)^).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator"^)^)
    echo {
    echo #    Restart the script to get Administrator privileges and exit
    echo     Start-Process 'powershell.exe' -Verb runAs -ArgumentList ^("-NoLogo -WindowStyle Maximized -noprofile -file " + """" + $PSCommandPath + """"^)
    echo     exit
    echo }
    echo #    We have Administrator privileges
    echo [console]::ForegroundColor = "Yellow"
    echo [console]::BackgroundColor = "blue"
    echo clear-host
    echo $wshell=New-Object -ComObject Wscript.Shell
    echo $wshell.Popup^("Plug in the USB stick",0,"USB stick"^) ^| Out-Null
    echo #    Select the USB stick
    echo $usb = ^(Get-Disk ^| Where-Object {^($_.BusType -eq "USB"^) -and ^($_.OperationalStatus -eq "Online"^)} ^| Out-GridView -Title 'Select USB Drive to Format' -OutputMode Single^).number
    echo if ^($usb -eq $null^) {$wshell.Popup^("No USB stick online or operation cancelled",0,"Erro"^) ^| Out-Null;exit}
    echo #    Clear the USB stick
    echo Clear-Disk $usb -RemoveData -RemoveOEM -Confirm:$false
    echo Stop-Service ShellHWDetection
    echo #    Create the fat32 boot partition
    echo $usbfat32=^(New-Partition -DiskNumber $usb -Size 600MB -AssignDriveLetter -IsActive ^| Format-Volume -FileSystem FAT32 -NewFileSystemLabel "BOOT"^).DriveLetter + ":"
    echo #    Create the ntfs intall partition
    echo $usbntfs=^(New-Partition -DiskNumber $usb -UseMaximumSize -AssignDriveLetter ^| Format-Volume -FileSystem NTFS -NewFileSystemLabel "ISO"^).DriveLetter + ":"
    echo Start-Service ShellHWDetection
    echo $wshell.Popup^("Mount the iso image",0,"ISO image"^) ^| Out-Null
    echo $ISO = ^(get-volume^| Where-Object {^($_.DriveType -eq "CD-ROM"^) -and ^($_.filesystemlabel -ne ""^) -and ^($_.OperationalStatus -eq "OK"^)} ^|Out-GridView -Title 'Select Cd-Rom image' -OutputMode Single^).DriveLetter + ":"
    echo if ^($ISO -eq ":"^) {$wshell.Popup^("No ISO image mounted or operation cancelled",0,"Error"^) ^| Out-Null;exit}
    echo robocopy $iso $usbntfs /e
    echo robocopy $iso"\" $usbfat32"\" bootmgr bootmgr.efi
    echo robocopy $iso"\boot" $usbfat32"\boot" /e
    echo robocopy $iso"\efi" $usbfat32"\efi" /e
    echo robocopy $iso"\sources" $usbfat32"\sources" boot.wim
    echo # Eject the mounted iso image
    echo ^(New-Object -ComObject Shell.Application^).Namespace^(17^).ParseName^($ISO^).InvokeVerb^("Eject"^)
    echo Remove-item ^($env:TEMP + "\script.ps1"^)
    )>"%temp%\script.ps1"
    powershell "%temp%\script.ps1" -ExecutionPolicy Bypass

    OK updated the OP script and download link
     
  5. rpo

    rpo MDL Addicted

    Jan 3, 2010
    947
    718
    30
    Yes, that's right.
     
  6. freddie-o

    freddie-o MDL Senior Member

    Jul 29, 2009
    449
    441
    10
  7. freddie-o

    freddie-o MDL Senior Member

    Jul 29, 2009
    449
    441
    10
  8. rpo

    rpo MDL Addicted

    Jan 3, 2010
    947
    718
    30
    Changed the way to select the iso image by introducing a file browser dialog :
    Code:
    @echo off
    (
    echo #
    echo #    This script must be executed with admin privilege
    echo #
    echo #    Test Administrator privileges
    echo If ^(-NOT ^([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent^(^)^).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator"^)^)
    echo {
    echo #    Restart the script to get Administrator privileges and exit
    echo     Start-Process 'powershell.exe' -Verb runAs -ArgumentList ^("-NoLogo -WindowStyle Maximized -noprofile -file " + """" + $PSCommandPath + """"^)
    echo     exit
    echo }
    echo #    We have Administrator privileges
    echo #
    echo [console]::ForegroundColor = "Yellow"
    echo [console]::BackgroundColor = "blue"
    echo #
    echo # Filebrowser dialog
    echo Add-Type -AssemblyName System.Windows.Forms
    echo $FileBrowser = New-Object System.Windows.Forms.OpenFileDialog -Property @{
    echo    Multiselect = $false # One file can be chosen
    echo     Filter = 'ISO images ^(*.iso^)^|*.iso' # Select iso files
    echo }
    echo #
    echo clear-host
    echo $wshell=New-Object -ComObject Wscript.Shell
    echo $wshell.Popup^("Mount the USB stick`r`nand click ""OK"" when ready.",0,"USB stick"^) ^| Out-Null
    echo #    Select the USB stick
    echo $usb = ^(Get-Disk ^| Where-Object {^($_.BusType -eq "USB"^) -and ^($_.OperationalStatus -eq "Online"^)} ^| Out-GridView -Title 'Select USB Drive to Format' -OutputMode Single^).number
    echo if ^($usb -eq $null^) {$wshell.Popup^("No USB stick online or operation cancelled",0,"Error"^) ^| Out-Null;exit}
    echo #    Clear the USB stick
    echo Clear-Disk $usb -RemoveData -RemoveOEM -Confirm:$false
    echo Stop-Service ShellHWDetection
    echo #    Create the fat32 boot partition
    echo $usbfat32=^(New-Partition -DiskNumber $usb -Size 1GB -AssignDriveLetter -IsActive ^| Format-Volume -FileSystem FAT32 -NewFileSystemLabel "BOOTFAT"^).DriveLetter + ":"
    echo #    Create the ntfs intall partition
    echo $usbntfs=^(New-Partition -DiskNumber $usb -UseMaximumSize -AssignDriveLetter ^| Format-Volume -FileSystem NTFS -NewFileSystemLabel "INSTALL"^).DriveLetter + ":"
    echo Start-Service ShellHWDetection
    echo $wshell.Popup^("Select the iso.",0,"ISO image"^) ^| Out-Null
    echo #
    echo [void]$FileBrowser.ShowDialog^(^)
    echo #
    echo $ImagePath = $FileBrowser.FileName;
    echo $ISO=":"
    echo If^($FileBrowser.FileNames -like "*\*"^) {
    echo #  Check if iso already mounted
    echo     $ISO = ^(Get-DiskImage -ImagePath $ImagePath ^| Get-Volume^).DriveLetter
    echo #    Mount iso
    echo     IF ^(!$ISO^) {Mount-DiskImage -ImagePath $ImagePath -StorageType ISO ^|out-null
    echo     $ISO = ^(Get-DiskImage -ImagePath $ImagePath ^| Get-Volume^).DriveLetter}
    echo     $ISO=$ISO+":"
    echo }
    echo if ^($ISO -eq ":"^) {$wshell.Popup^("No ISO image mounted or operation cancelled",0,"Error"^) ^| Out-Null;exit}
    echo robocopy $iso $usbntfs /e
    echo robocopy $iso"\" $usbfat32"\" bootmgr bootmgr.efi
    echo robocopy $iso"\boot" $usbfat32"\boot" /e
    echo robocopy $iso"\efi" $usbfat32"\efi" /e
    echo robocopy $iso"\sources" $usbfat32"\sources" boot.wim
    echo # Eject the mounted iso image
    echo DisMount-DiskImage -ImagePath $ImagePath ^|out-null  
    )>"%temp%\script.ps1"
    powershell "%temp%\script.ps1" -ExecutionPolicy Bypass
    
     
  9. freddie-o

    freddie-o MDL Senior Member

    Jul 29, 2009
    449
    441
    10
    Will the file browser dialog work with selecting the usb stick?
     
  10. rpo

    rpo MDL Addicted

    Jan 3, 2010
    947
    718
    30
    Short answer : no.
     
  11. freddie-o

    freddie-o MDL Senior Member

    Jul 29, 2009
    449
    441
    10
    OK modified it a little bit and updated the OP. Thanks again rpo :thumbsup:
     
  12. rpo

    rpo MDL Addicted

    Jan 3, 2010
    947
    718
    30
    Try this one.
     
  13. freddie-o

    freddie-o MDL Senior Member

    Jul 29, 2009
    449
    441
    10
    #14 freddie-o, Apr 4, 2019
    Last edited: Apr 4, 2019
    (OP)
    Nice :thumbsup: What do you think of this? No more "Mount the USB stick and click "OK" when ready."
    Also what do you think about the "$USBDiskForm" the size of the Windows "Run" window?

    @echo off
    (
    echo #
    echo # This script must be executed with admin privilege
    echo #
    echo # Test Administrator privileges
    echo If ^(-NOT ^([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent^(^)^).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator"^)^)
    echo {
    echo # Restart the script to get Administrator privileges and exit
    echo Start-Process 'powershell.exe' -Verb runAs -ArgumentList ^("-NoLogo -WindowStyle Normal -noprofile -file " + """" + $PSCommandPath + """"^)
    echo exit
    echo }
    echo # We have Administrator privileges
    echo #
    echo [console]::ForegroundColor = "Yellow"
    echo [console]::BackgroundColor = "blue"
    echo #
    echo Add-Type -AssemblyName System.Windows.Forms # Load the class System.Windows.Forms
    echo # Filebrowser dialog
    echo $FileBrowser = New-Object System.Windows.Forms.OpenFileDialog -Property @{
    echo Multiselect = $false # One file can be chosen
    echo Filter = 'ISO images ^(*.iso^)^|*.iso' # Select iso files
    echo }
    echo #
    echo clear-host
    echo # Select the USB stick
    echo $USBDiskForm=New-Object System.Windows.Forms.Form # Create the screen form ^(window^)
    echo # $USBDiskForm ^|gm;pause
    echo # Set the title and size of the window:
    echo $USBDiskForm.Text='Available USB disk^(s^)'
    echo $USBDiskForm.Width=900 ; $USBDiskForm.Height=200
    echo $USBDiskForm.AutoSize=$true # AutoSize property to make the form automatically stretch, if the elements on the form are out of bounds
    echo # Create a drop-down list and fill it
    echo $USB=$Null
    echo $USBDisks=@^(^) # array whith USB disk number
    echo $Disks=Get-Disk ^| Where-Object {^($_.BusType -eq "USB"^) -and ^($_.OperationalStatus -eq "Online"^)}
    echo if ^($Disks.count -eq 0^){"No USB disk available";exit}
    echo $USBDiskList=New-Object System.Windows.Forms.ComboBox
    echo # $USBDiskList^|gm
    echo $USBDiskList.Width=560
    echo Foreach ^($USBDisk in $Disks^) {
    echo $FriendlyName=^($USBDisk.FriendlyName^).PadRight^(30," "^).substring^(0,30^)
    echo $Partitions = Get-Partition ^| Where-Object { $_.DiskNumber -eq $USBDisk.DiskNumber}
    echo If ^($Partitions^) {
    echo Foreach ^($Partition in $Partitions^) {
    echo $Volumes=get-volume ^| Where-Object {$Partition.AccessPaths -contains $_.path }
    echo Foreach ^($Volume in $Volumes^) {
    echo $USBDisks+=$USBDisk.DiskNumber
    echo $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
    echo }
    echo }
    echo } Else {
    echo $USBDisks+=$USBDisk.DiskNumber
    echo $USBDiskList.Items.Add^(^(" {0,-30}| {1,1}| {2,-30}| {3:n2} GB" -f $FriendlyName, " ", " ",^($USBDisk.Size/1GB^)^)^)^|out-null
    echo }
    echo }
    echo $USBDiskList.DropDownStyle=[System.Windows.Forms.ComboBoxStyle]::DropDownList;
    echo $USBDiskList.Location=New-Object System.Drawing.Point^(5,40^)
    echo $USBDiskList.SelectedIndex=0
    echo $USBDiskList.width=950;$USBDiskList.height=20
    echo $USBDiskList.backColor="blue" ; $USBDiskList.ForeColor="White"
    echo $USBDiskList.Font='Courier New,15,style=Bold'
    echo $USBDiskForm.Controls.Add^($USBDiskList^)
    echo $OKButton=New-Object System.Windows.Forms.Button # Put the OK button on the form
    echo $OKButton.Location=New-Object System.Drawing.Size^(890,100^)
    echo $OKButton.Text="OK";$OKButton.Font='Microsoft Sans Serif,10,style=Bold'
    echo $OKButton.width=60;$OKButton.height=30;
    echo $USBDiskForm.Controls.Add^($OKButton^)
    echo $OKButton.Add_Click^({$global:OK=$true;$USBDiskForm.close^(^)}^)
    echo $CancelButton=New-Object System.Windows.Forms.Button # Put the Cancel button on the form
    echo $CancelButton.Location=New-Object System.Drawing.Size^(800,100^)
    echo $CancelButton.Size=New-Object System.Drawing.Size^(120,20^)
    echo $CancelButton.Text="Cancel";$CancelButton.Font='Microsoft Sans Serif,10,style=Bold'
    echo $CancelButton.width=60;$CancelButton.height=30;
    echo $USBDiskForm.Controls.Add^($CancelButton^)
    echo $CancelButton.Add_Click^({$global:OK=$False;$USBDiskForm.close^(^)}^)
    echo [void]$USBDiskForm.ShowDialog^(^) # Display the form on the screen
    echo if ^(!$global:OK^){$wshell.Popup^("Operation cancelled",0,"Error"^) ^| Out-Null;exit}
    echo $USB=$USBDisks[$USBDiskList.SelectedIndex]
    echo # Clear the USB stick
    echo Clear-Disk $usb -RemoveData -RemoveOEM -Confirm:$false
    echo Stop-Service ShellHWDetection
    echo # Create the fat32 boot partition
    echo $usbfat32=^(New-Partition -DiskNumber $usb -Size 1GB -AssignDriveLetter -IsActive ^| Format-Volume -FileSystem FAT32 -NewFileSystemLabel "BOOTFAT"^).DriveLetter + ":"
    echo # Create the ntfs intall partition
    echo $usbntfs=^(New-Partition -DiskNumber $usb -UseMaximumSize -AssignDriveLetter ^| Format-Volume -FileSystem NTFS -NewFileSystemLabel "INSTALL"^).DriveLetter + ":"
    echo Start-Service ShellHWDetection
    echo # Read-Host "Eject the iso if it is mounted. When ready press Enter"
    echo # $Volumes = ^(Get-Volume^).Where^({$_.DriveLetter}^).DriveLetter
    echo # Read-Host "Mount the iso. When ready press Enter"
    echo # $ISO = ^(Compare-Object -ReferenceObject $Volumes -DifferenceObject ^(Get-Volume^).Where^({$_.DriveLetter}^).DriveLetter^).InputObject
    echo # $ISO = ^(get-volume^| Where-Object {^($_.DriveType -eq "CD-ROM"^) -and ^($_.filesystemlabel -ne ""^) -and ^($_.OperationalStatus -eq "OK"^)} ^|Out-GridView -Title 'Select Cd-Rom image' -OutputMode Single^).DriveLetter + ":"
    echo $wshell=New-Object -ComObject Wscript.Shell
    echo $wshell.Popup^("Select the iso.",0,"ISO image"^) ^| Out-Null
    echo #
    echo [void]$FileBrowser.ShowDialog^(^)
    echo #
    echo $ImagePath = $FileBrowser.FileName;
    echo $ISO=":"
    echo If^($FileBrowser.FileNames -like "*\*"^) {
    echo # Check if iso already mounted
    echo $ISO = ^(Get-DiskImage -ImagePath $ImagePath ^| Get-Volume^).DriveLetter
    echo # Mount iso
    echo IF ^(!$ISO^) {Mount-DiskImage -ImagePath $ImagePath -StorageType ISO ^|out-null
    echo $ISO = ^(Get-DiskImage -ImagePath $ImagePath ^| Get-Volume^).DriveLetter}
    echo $ISO=$ISO+":"
    echo }
    echo if ^($ISO -eq ":"^) {$wshell.Popup^("No ISO image mounted or operation cancelled",0,"Error"^) ^| Out-Null;exit}
    echo # Copy-Item -Path $ISO\* -Destination "$($usbntfs)" -Recurse -Verbose
    echo # Copy-Item -Path $ISO"\bootmgr" -Destination $usbfat32"\" -Verbose
    echo # Copy-Item -Path $ISO"\bootmgr.efi" -Destination $usbfat32"\" -Verbose
    echo # Copy-Item -Path $ISO"\boot" -Destination $usbfat32"\boot" -Recurse -Verbose
    echo # Copy-Item -Path $ISO"\efi" -Destination $usbfat32"\efi" -Recurse -Verbose
    echo # new-item $usbfat32"\sources" -itemType Directory
    echo # Copy-Item -Path $ISO"\sources\boot.wim" -Destination $usbfat32"\sources\boot.wim" -Verbose
    echo robocopy $iso $usbntfs /e
    echo robocopy $iso"\" $usbfat32"\" bootmgr bootmgr.efi
    echo robocopy $iso"\boot" $usbfat32"\boot" /e
    echo robocopy $iso"\efi" $usbfat32"\efi" /e
    echo robocopy $iso"\sources" $usbfat32"\sources" boot.wim
    echo # Eject the mounted iso image
    echo # ^(New-Object -ComObject Shell.Application^).Namespace^(17^).ParseName^($ISO^).InvokeVerb^("Eject"^)
    echo DisMount-DiskImage -ImagePath $ImagePath ^|out-null
    echo Remove-item ^($env:TEMP + "\script.ps1"^)
    )>"%temp%\script.ps1"
    powershell "%temp%\script.ps1" -ExecutionPolicy Bypass -WindowStyle Normal
     
  14. rpo

    rpo MDL Addicted

    Jan 3, 2010
    947
    718
    30
    1. 'No more "Mount the USB stick and click "OK" when ready."'
    If no USB stick is mounted, the script will terminate : the popup is just a reminder for the user. Workaround : introduce a wait loop until the stick is mounted.
    2. ' "$USBDiskForm" the size of the Windows "Run" window?" : what do you suggest?
     
  15. freddie-o

    freddie-o MDL Senior Member

    Jul 29, 2009
    449
    441
    10
    #16 freddie-o, Apr 4, 2019
    Last edited: Apr 4, 2019
    (OP)
    No I just took out these lines.

    Code:
    echo $wshell=New-Object -ComObject Wscript.Shell
    echo $wshell.Popup^("Mount the USB stick`r`nand click ""OK"" when ready.",0,"USB stick"^) ^| Out-Null
    So it skips the "Mount the USB stick and click "OK" when ready." pop up window and goes straight to the "$USBDiskForm"

    When you click "Run" in the Start menu... the little run window
     
  16. rpo

    rpo MDL Addicted

    Jan 3, 2010
    947
    718
    30
  17. freddie-o

    freddie-o MDL Senior Member

    Jul 29, 2009
    449
    441
    10
    What do you think about something like this?
    [​IMG]
     
  18. freddie-o

    freddie-o MDL Senior Member

    Jul 29, 2009
    449
    441
    10
    Got this error
    Code:
    Exception setting "windowsize": "Window cannot be taller than 44.
    Parameter name: value.Height
    Actual value was 50."
    At C:\Users\Administrator\AppData\Local\Temp\script.ps1:16 char:77
    + ... ze.height = 50;  $newsize.width = 150;$pswindow.windowsize = $newsize
    +                                           ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        + CategoryInfo          : NotSpecified: (:) [], SetValueInvocationException
        + FullyQualifiedErrorId : ExceptionWhenSetting
     
  19. rpo

    rpo MDL Addicted

    Jan 3, 2010
    947
    718
    30
    Sorry, i can't reproduce this issue on my system. All is working fine here.