PoshCode Logo PowerShell Code Repository

WindowsInstallPoint by Rich Kusak 10 months ago
embed code: <script type="text/javascript" src="http://PoshCode.org/embed/2609"></script>download | new post

Initialize-WindowsInstallPoint
This function was developed to automate the process required to make a USB drive a device from which Windows can be installed. Many posts are available on the internet about the manual steps required by searching: “install windows 7 from usb”.

  1. function Initialize-WindowsInstallPoint {
  2. <#
  3.         .SYNOPSIS
  4.                 Initializes a drive to become a Windows OS install point.
  5.                
  6.         .DESCRIPTION
  7.                 The Initialize-WindowsInstallPoint function uses the "diskpart" utility to wipe, partition, and format a local or removable drive.
  8.                 The "bootsect" tool processes the bootmgr allowing the drive to become a bootable device from which Windows can be installed.
  9.                 Once the drive is initialized, copy the entire contents of the Windows install media to the drive.
  10.                 Windows Vista, 7, Server 2008, and Server 2008 R2 are supported.
  11.        
  12.         .PARAMETER Drive
  13.                 Specifies the drive to initialize as a Windows install point.
  14.                 <DriveLetter:>
  15.        
  16.         .PARAMETER BootsectPath
  17.                 The full file path to the "bootsect.exe" tool. For Windows versions 6.x, it's located on the installation media in the "boot" folder.
  18.        
  19.         .PARAMETER DiskpartPath
  20.                 The full file path to the "diskpart.exe" tool. Default parameter value: $env:SystemRoot\System32\diskpart.exe
  21.  
  22.         .EXAMPLE
  23.                 Initialize-WindowsInstallPoint X: D:\boot\bootsect.exe
  24.                 Initializes drive X: using the bootsect.exe tool located in the boot folder of drive D:
  25.        
  26.         .INPUTS
  27.                 System.String
  28.        
  29.         .OUTPUTS
  30.                 None
  31.        
  32.         .NOTES
  33.                 Name: Initialize-WindowsInstallPoint
  34.                 Author: Rich Kusak (rkusak@cbcag.edu)
  35.                 Created: 2009-10-24
  36.                 Last Edit: 2011-04-07 18:48
  37.                 Version: 1.7.0.0
  38.                
  39.                 #Requires Version 2.0
  40.  
  41.         .LINK
  42.                 bootsect.exe
  43.  
  44.         .LINK
  45.                 diskpart.exe
  46. #>
  47.  
  48.         [CmdletBinding(ConfirmImpact='High', SupportsShouldProcess=$true)]
  49.         param (
  50.                 [Parameter(Position=0, Mandatory=$true, ValueFromPipelineByPropertyName=$true,
  51.                         HelpMessage='The drive qualifier of the device to become a Windows install point.'
  52.                 )]
  53.                 [ValidateScript({
  54.                         switch ($_) {
  55.                                 $env:SystemDrive {throw 'This operation cannot be performed on the system drive.'}
  56.                                 {$_ -match '^[a-z]:$'} {$true}
  57.                                 default {throw "The argument '$_' is not a valid drive designation. Supply an argument that matches '<DriveLetter>:' and try the command again."}
  58.                         }
  59.                 })]
  60.                 [string]$Drive,
  61.                
  62.                 [Parameter(Position=1, Mandatory=$true, ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true,
  63.                         HelpMessage='The full path to the bootsect.exe tool.'
  64.                 )]
  65.                 [Alias('FullName')]
  66.                 [ValidateScript({
  67.                         if (Test-Path $_ -Include '*bootsect.exe') {$true} else {
  68.                                 throw "The argument '$_' is not a real path to the bootsect.exe tool."
  69.                         }
  70.                 })]
  71.                 [string]$BootsectPath,
  72.                
  73.                 [Parameter(ValueFromPipelineByPropertyName=$true,
  74.                         HelpMessage='The full path to the diskpart.exe tool.'
  75.                 )]
  76.                 [ValidateScript({
  77.                         if (Test-Path $_ -Include '*diskpart.exe') {$true} else {
  78.                                 throw "The arguments '$_' is not a real path to the diskpart.exe tool."
  79.                         }
  80.                 })]
  81.                 [string]$DiskpartPath = "$env:SystemRoot\System32\diskpart.exe"
  82.         )
  83.  
  84.         begin {
  85.                
  86.                 function Test-Elevation {
  87.                         $admin = [System.Security.Principal.WindowsBuiltInRole]::Administrator
  88.                         $identity  = [System.Security.Principal.WindowsIdentity]::GetCurrent()
  89.                         $principal = New-Object System.Security.Principal.WindowsPrincipal($identity)
  90.  
  91.                         $principal.IsInRole($admin)
  92.                 }
  93.                
  94.                 # Test that PowerShell is running as an administrator
  95.                 if (-not (Test-Elevation)) {
  96.                         throw 'Administrator privileges are required. PowerShell is not running as an administrator.'
  97.                 }
  98.                
  99.                 $dpExitCodes = @{
  100.                         0 = 'No error occurred. The entire script ran without failure.'
  101.                         1 = 'A fatal exception occurred. There may be a serious problem.'
  102.                         2 = 'The arguments specified on a Diskpart command line were incorrect.'
  103.                         3 = 'Diskpart was unable to open the specified script or output file.'
  104.                         4 = 'One of the services Diskpart uses returned a failure.'
  105.                         5 = 'A command syntax error occurred. The script failed because an object was improperly selected or was invalid for use with that command.'
  106.                 }
  107.                
  108.                 # Temporary files for the diskpart script and redirect standard output
  109.                 $dpScript = [System.IO.Path]::GetTempFileName()
  110.                 $rso = [System.IO.Path]::GetTempFileName()
  111.                
  112.                 # Set the initial instance of the variable used to control the flow of $psCmdlet
  113.                 $psc = $null
  114.         } # end begin
  115.        
  116.         process {
  117.                
  118.                 # Capitalize drive letter for display
  119.                 $Drive = $Drive.ToUpper()
  120.                
  121.                 # Detrimine if the drive meets the requirements to become a Windows install point
  122.                 Write-Debug 'Getting WMI object Win32_LogicalDisk'
  123.                 $logicalDisk = Get-WmiObject Win32_LogicalDisk -Filter "DeviceID = '$Drive' "
  124.  
  125.                 if ($logicalDisk.DriveType -notmatch '^(2|3)$') {
  126.                         return Write-Error "Drive '$Drive' is not a local or removable drive." -TargetObject $Drive
  127.                 } elseif ($logicalDisk.Size -lt 3.5GB) {
  128.                         # Different Windows editions vary in size but a drive 3.5GB or greater should accomidate all editions
  129.                         Write-Warning "Drive '$Drive' may not be large enough for Windows installation files."
  130.                 }
  131.  
  132.                 if ($psc -eq $null) {$psc = $psCmdlet}
  133.                 if ($psc.ShouldProcess($Drive, "Initialize Windows install point. Any existing data will be DESTROYED")) {
  134.                         Write-Progress -Activity 'Initialize Windows Install Point' -Status "Drive $Drive" -CurrentOperation 'Preparing disk volume' -PercentComplete 0
  135.                        
  136.                         # Diskpart script content
  137.                         @"
  138.                                 Select Volume $($Drive[0])
  139.                                 Clean
  140.                                 Create Partition Primary
  141.                                 Select Partition 1
  142.                                 Active
  143.                                 Format Quick FS=NTFS Label=WindowsInstallPoint
  144.                                 Assign Letter $Drive
  145.                                 Exit
  146. "@ | Out-File $dpScript -Encoding ASCII -Force
  147.  
  148.                         Write-Debug 'Starting process diskpart.exe'
  149.                         # Using Start-Process allows the exit code to be processed from either the console or ISE.
  150.                         $diskpart = Start-Process $DiskpartPath "/s $dpScript" -NoNewWindow -Wait -PassThru -RedirectStandardOutput $rso
  151.  
  152.                         1..45 | ForEach {
  153.                                 Write-Progress -Activity 'Initialize Windows Install Point' -Status "Drive $Drive" -CurrentOperation 'Preparing disk volume' -PercentComplete $_
  154.                                 Sleep -Milliseconds 20
  155.                         }
  156.                        
  157.                         # Removes empty lines from the original diskpart.exe output and sends it to the verbose stream
  158.                         Get-Content $rso | Select-String '.' | ForEach {Write-Verbose $_}
  159.                        
  160.                         # Diskpart error handling
  161.                         if ($diskpart.ExitCode -eq 0) {
  162.                                 Write-Verbose "Drive '$Drive' has been successfully processed by the diskpart.exe tool."
  163.                         } elseif ($diskpart.ExitCode -gt 0) {
  164.                                 return Write-Error $dpExitCodes.($diskpart.ExitCode)
  165.                         } else {
  166.                                 return Write-Error 'An unknown error occured.'
  167.                         }
  168.                        
  169.                         Write-Debug 'Starting process bootsect.exe'
  170.                         # Using Start-Process allows the exit code to be processed from either the console or ISE.
  171.                         $bootsect = Start-Process $BootsectPath "/NT60 $Drive" -NoNewWindow -Wait -PassThru -RedirectStandardOutput $rso
  172.  
  173.                         46..90 | ForEach {
  174.                                 Write-Progress -Activity 'Initialize Windows Install Point' -Status "Drive $Drive" -CurrentOperation 'Setting boot code' -PercentComplete $_
  175.                                 Sleep -Milliseconds 20
  176.                         }
  177.  
  178.                         # Removes empty lines from the original bootsect.exe output and sends it to the verbose stream
  179.                         Get-Content $rso | Select-String '.' | ForEach {Write-Verbose $_}
  180.  
  181.                         # Bootsect error handling
  182.                         if ($bootsect.ExitCode -eq 0) {
  183.                                 Write-Verbose "Drive '$Drive' has been successfully processed by the bootsect.exe tool."
  184.                                 Write-Progress -Activity 'Initialize Windows Install Point' -Status "Drive $Drive" -CurrentOperation 'Complete' -PercentComplete 100
  185.                                 Sleep -Seconds 1
  186.                         } else {
  187.                                 return Write-Error "$bootsect"
  188.                         }
  189.                 } # end ShouldProcess
  190.                
  191.                 Write-Verbose "Drive '$Drive' has been successfully initialized as a Windows install point."
  192.         } # end process
  193.  
  194.         end {
  195.                
  196.                 # Cleanup temporary files
  197.                 Remove-Item $dpScript, $rso -Force -WhatIf:$false
  198.         }
  199. } # end function Initialize-WindowsInstallPoint

Submit a correction or amendment below (
click here to make a fresh posting)
After submitting an amendment, you'll be able to view the differences between the old and new posts easily.

Syntax highlighting:


Remember me