-
Notifications
You must be signed in to change notification settings - Fork 1
/
WTG.ps1
181 lines (155 loc) · 7.49 KB
/
WTG.ps1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
<#
.Synopsis
Automates the creation of Windows To Go USB sticks.
.DESCRIPTION
This script will automate the creation of Windows To Go USB sticks and
leverage PowerShell jobs to queue them and write an image sequentially.
BitLocker is automatically enabled and a PIN is randomly generated. The PIN
is recorded along with the Recovery Key on the root of the workstation
executing the script.
.EXAMPLE
.\WTG.ps1 -ImagePath C:\image.wim -Domain test.local -Unattend C:\Unattend.xml -ComputerName TEST01 -Suffix 1000
.EXAMPLE
.\WTG.ps1 -ImagePath C:\image.wim -Unattend C:\Unattend.xml -ComputerName TEST01
.INPUTS
None.
.OUTPUTS
None.
.NOTES
This script requires the WinToGo.psm1 module.
Due to a restriction of DISM, Windows cannot write multiple WIM files at the
same time. The script will iterate through each USB stick and execute them
sequentially.
#>
Param (
[Parameter(Mandatory=$true,
Position=0)]
[ValidateNotNull()]
[ValidateNotNullOrEmpty()]
[String]$ImagePath,
[Parameter(Mandatory=$true)]
[ValidateNotNull()]
[ValidateNotNullOrEmpty()]
[String]$Unattend,
[Parameter(Mandatory=$true)]
[String]$ComputerName,
[Parameter(Mandatory=$false)]
[String]$Domain,
[Parameter(Mandatory=$false)]
[String]$Suffix,
[Parameter(Mandatory=$false)]
[String]$BitLockerPIN,
[Parameter(Mandatory=$false)]
[Switch]$VMTest
)
#$ConfirmPreference = 'Low'
Write-Debug 'Checking for administrative privileges'
$myWindowsID= [System.Security.Principal.WindowsIdentity]::GetCurrent()
$myWindowsPrincipal= New-Object System.Security.Principal.WindowsPrincipal($myWindowsID)
$adminRole = [System.Security.Principal.WindowsBuiltInRole]::Administrator
If ($myWindowsPrincipal.IsInRole($adminRole)) {
Write-Debug -Message 'Currently running with administrative privileges'
}
Else {
Write-Debug -Message 'Currently running with limited user rights.'
Write-Verbose -Message 'You need to execute this script with administrative privileges. Exiting.'
Exit
}
Write-Verbose -Message 'Loading dependencies.'
If (Get-Module -Name WinToGo) {
Write-Debug -Message 'WinToGo is currently loaded'
}
Else {
Write-Debug -Message 'WinToGo is not currently loaded. Attemping to load it.'
If (Test-Path .\WinToGo) {
Write-Debug -Message 'Found WinToGo module folder in working directory'
If (Test-Path "$env:USERPROFILE\Documents\WindowsPowerShell\Modules") {
Write-Debug -Message "PowerShell Module folder exists in user profile. Copying the WinToGo PowerShell Module to $env:USERPROFILE\Documents\WindowsPowerShell\Modules"
Copy-Item -Path .\WinToGo -Destination "$env:USERPROFILE\Documents\WindowsPowerShell\Modules" -Force -Recurse
Write-Debug -Message 'Importing the WinToGo PowerShell Module'
Import-Module -Name WinToGo
}
Else {
Write-Debug -Message "Creating the PowerShell Modules folder at $env:USERPROFILE\Documents\WindowsPowerShell\Modules"
New-Item -ItemType Directory -Path "$env:USERPROFILE\Documents\WindowsPowerShell\Modules" | Out-Null
Write-Debug -Message "Copying the WinToGo PowerShell Module to $env:USERPROFILE\Documents\WindowsPowerShell\Modules"
Copy-Item -Path .\WinToGo -Destination "$env:USERPROFILE\Documents\WindowsPowerShell\Modules" -Force -Recurse
Write-Debug -Message 'Importing the WinToGo PowerShell Module'
Import-Module -Name WinToGo
}
}
Else {
Write-Verbose -Message 'Cannot find/load a needed dependency (WinToGo.psm1). Exiting.'
Write-Debug -Message 'WinToGo module not loaded.'
Exit
}
}
Write-Debug -Message 'Defining drive letters'
$DriveLetters = 68..90 | ForEach-Object {"$([char]$_):"} | Where-Object {(New-Object System.IO.DriveInfo $_).DriveType -eq 'noRootdirectory'}
$DriveIndex = 2
Write-Debug -Message 'Grabing disk objects'
If ($VMTest.IsPresent -eq $true) {
Write-Debug 'VMTest variable is true, removing the USB filter'
$Disks = Get-Disk | Where-Object {$_.Size -gt 20Gb -and -not $_.IsBoot}
}
Else {
Write-Debug 'VMTest is false, only using USB based volumes'
$Disks = Get-Disk | Where-Object {$_.Path -match "USBSTOR" -and $_.Size -gt 20Gb -and -not $_.IsBoot}
}
Write-Debug -Message "The value of ImagePath is: $ImagePath"
Write-Debug -Message "The value of BitLockerPIN is: $BitLockerPIN"
Write-Debug -Message "The value of Domain outside the job is $Domain"
Write-Debug -Message "The value of Unattend is: $Unattend"
Write-Debug -Message "The value of ComputerName outside the job is: $ComputerName"
Write-Debug -Message "Stopping the Windows Hardware Detection service"
Try {
Stop-Service -Name ShellHWDetection
}
Catch {
Write-Debug -Message "Error in stopping ShellHWDetection. May have already been stopped or does not exist."
}
If ($Disks.Path) {
Write-Debug -Message 'Beginning If Statement for each disk'
ForEach ($Disk in $Disks) {
Write-Debug -Message 'Launching PowerShell Job'
Start-Job -InitializationScript {Import-Module -Name WinToGo} -ScriptBlock {
$DebugPreference = 'Continue'
$Disk = $args[0]
Write-Debug -Message "The value of Disk is: $Disk"
$ImagePath = $args[1]
Write-Debug -Message "The value of ImagePath is: $ImagePath"
$BitLockerPIN = $args[2]
Write-Debug -Message "The value of BitLockerPIN is: $BitLockerPIN"
$Domain = $args[3]
Write-Debug -Message "The value of Domain is: $Domain"
$ComputerName = $args[4]
Write-Debug -Message "The value of ComputerName is: $ComputerName"
$Suffix = $args[5]
Write-Debug -Message "The value of Suffix is: $Suffix"
$Unattend = $args[6]
Write-Debug -Message "The value of Unattend is: $Unattend"
$ComputerName = $ComputerName + "-" + $Suffix
Write-Debug -Message "Calling Initialize-WTGStick function"
$OSVolume = Initialize-WTGStick -Disk $Disk -BitLockerPIN $BitLockerPIN -ComputerName $ComputerName
Write-Debug -Message 'Calling Write-WTGStick function'
Write-WTGStick -DriveLetter $OSVolume.DriveLetter -Image $ImagePath -ComputerName $ComputerName -Unattend $Unattend
$Unattend = $OSVolume.DriveLetter + ":\Windows\System32\Sysprep\Unattend.xml"
If ($Domain) {
Write-Debug -Message 'Calling Join-WTGDomain function'
Join-WTGDomain -OSDriveLetter ($OSVolume.DriveLetter) -Unattend $Unattend -Domain $Domain -ComputerName $ComputerName
}
Write-Debug -Message 'Calling BCDBoot.exe to write BCD Store to the stick'
$SystemDriveLetter = ($Disk | Get-Partition | Where-Object {$_.Size -eq 350MB -and $_.Type -eq "FAT32"}).DriveLetter.ToString()
Write-Debug -Message "The value of SystemDriveLetter is: $SystemDriveLetter"
Start-Process -FilePath "$($OSVolume.DriveLetter):\Windows\System32\bcdboot.exe" -WorkingDirectory "$($OSVolume.DriveLetter):\Windows\System32" -ArgumentList "$($OSVolume.DriveLetter):\Windows /f ALL /s ${SystemDriveLetter}:" -WindowStyle Hidden -Wait
} -ArgumentList $Disk,$ImagePath,$BitLockerPIN,$Domain,$ComputerName,$Suffix,$Unattend | Wait-Job
Write-Debug -Message "Current drive index is $DriveIndex"
$DriveIndex = $DriveIndex + 2
$Suffix = [String]([Int]$Suffix + 1)
Write-Debug -Message "Updated drive index is $DriveIndex"
}
}
Else {
Write-Debug -Message "No USB sticks detected in the Disk variable."
Write-Verbose -Message 'No USB sticks detected.'
}