Here is how to make a bootable USB using an ISO. Basically, it just formats the USB, writes the boot sector, then copies all of the contents of an ISO file to it. Just a disclaimer here. This seemed not to work on a Surface, because it wanted a FAT formatted volume, not NTFS. So try changing the disk format to FAT32 before running on a Surface.

raw

#
# Make bootable USB
# - use with caution
#
function Make-BootableUsb
{
    [CmdLetBinding()]
    param
    (
        [Parameter(Mandatory=$true)][String]$FileName,
        [Parameter(Mandatory=$true)][String]$DriveLetter
    )
    process
    {
        # Must be admin
        if(-not (Get-IsAdministrator))
        {
            throw 'Please try again as Administrator'
        }

        # Get the full file path
        $FileName = (Get-Item $FileName -ErrorAction SilentlyContinue).FullName

        # sanity check
        if(-not (Test-Path $FileName))
        {
            throw "Could not find file $FileName"
        }

        # More sanity check
        if(-not $DriveLetter)
        {
            throw "Drive letter is not good"
        }

        # Get rid of colon for now
        $DriveLetter = $DriveLetter.TrimEnd(':')

        # Get the MSFT_PARTITION cim instance for the drive letter we want to destroy
	# This just needs to be one of the partitions on our USB. If there are multiple, we will kill them
        # DO NOT EXPECT YOUR STUFF TO LIVE
        $driveVolume = Get-CimInstance msft_partition -Namespace Root\Microsoft\Windows\Storage | Where DriveLetter -Match $DriveLetter

        # Could not find, exit
        if(-not $DriveVolume)
        {
            throw "Could not find disk $DriveLetter"
        }

        # The meat of this thing
        try
        {
            # Mount the disk image
            $MntfileInfo = Mount-DiskImage $FileName -PassThru

            # Get the drive letter of the volume
            $Mntvolume = ($MntfileInfo | Get-Volume).DriveLetter

            # Get the disk number of the USB
            $disk = Get-Disk -Number $driveVolume.DiskNumber
            
            # Destroy the file system on the disk. Remove everything
            $cleaned = $disk | Clear-Disk -RemoveData -PassThru

            # Create a new partition and assign the previous drive letter
            $newPart = $cleaned | New-Partition -DriveLetter $driveVolume.DriveLetter -IsActive -UseMaximumSize
            
            #Create and NTFS filesystem on that disk
            $formatted = $newPart | Format-Volume -FileSystem NTFS
            
            # Make sure we actually made everything
            $dir = "$($driveVolume.DriveLetter):"
            if(-not (Test-Path $dir))
            {
                throw "well, we screwed up your drive"
            }

            # Move onto our empty disk
            pushd $dir
                
                # Write an MBR
                Invoke-Command -ScriptBlock { iex "bootsect.exe /nt60 $dir /force"}

                # Copy the image
                Invoke-Command -ScriptBlock {iex "xcopy /y /e /s $($Mntvolume):\ $dir\"}

            popd

            Write-Output "DONE"
        }
        finally
        {
            # Clean up
            if($MntfileInfo)
            {
                $MntfileInfo | Dismount-DiskImage
            }
        }
    }

}

#
# True if the user is in the admin role
#
function Get-IsAdministrator
{
    [CmdletBinding()]
    param
    (
    )
    process
    {
        foreach($role in Get-UserRoles)
        {
            if($role -match 'Administrator')
            {
                return $true
            }
        }
        return $false
    }
}

##
## Gets all user roles
##
function Get-UserRoles
{
    [CmdletBinding()]
    param
    (
    )
    process
    {
        $principal = [Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent();
        $roles = [System.Enum]::GetValues([Security.Principal.WindowsBuiltInRole])

        $output = @()
        foreach($role in $roles)
        {
            if($principal.IsInRole($role))
            {
                $output += $role
            }
        }

        return $output
    }
}

So what really happens here? There are 3 functions:

  • Get-UserRoles
  • Get-IsAdministrator
  • Make-BootableUsb

The first one Get-UserRoles just asks the OS what roles the current user is in. The second one Get-IsAdministrator is mostly just a wrapper around the first one, which checks to see if the user has the administrator role The last one is the big one. Make-BootableUsb Actually makes a bootable USB. This was a scary one to test... was super afraid that I was going to format my C: drive. Actually funny story, I did accidently format one of my drives while trying to automate something with DISKPART once. Oh that brings me to another point. You can see we don't use DISKPART here. At first I was going to, but why not use the PowerShell functions that are available.

Anyway, I think the code is pretty well documented. So it should be decently simple to understand. Most importantly, this does actually completely clear and format a disk, so use with caution, it is totally possible that it could mess up and delete something important.