Skip to content

Commit 2a4d645

Browse files
DISMTools 0.7 Preview 5 (#263)
* Update assembly information * [PE Helper] WDSH Server: Add Web Dashboard * [Refactor] Added more LINQ queries for volumes * [Enhance] Several enhancements - Renewed PMIP now uses accent colors for border - The ISO creator now offers the ability to download and install the required ADK components automatically - In doing this, a new progress reporter panel has been implemented. This is planned to be used in more components of DISMTools * [ISO Creator] Bump default resolution * [PE Helper] WDSH Server: Many improvements - Dashboard location is now "/api/wdshome" - Logging is now performed in the user's %TEMP% directory - Buttons were added to refresh information and view server logs - If there are multiple network adapters, they now appear as separate entries - A field has been added for NIC Teaming * [PE Helper] Add packages from the Storage module * [PE Helper] Detect drive letters in conflict Attempt 1 of tackling #262 * [PE Helper] More consistency for ESP references * [ISO Creator] Close if request was declined * [Refactor] Remove redundant blocks with specific methods * [PE Helper] Slightly improve disk conflict detection - We now make sure volume info is output to host console - Redundant code was removed * [Library] Update Markdig to 0.41.3 * [PE Helper] Add option for command console, add admin scripts * [DynaLog] Add process ID to event logs * [PE Helper] Add new admin script, fix cmdcons issue * [PE Helper] Fixed WDSHS issue with image pre-deployment * [REL] Update What's New section
1 parent bdf85bd commit 2a4d645

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

63 files changed

+1043
-818
lines changed

DISMTools.vbproj

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@
8181
<HintPath>packages\ini-parser.2.5.2\lib\net20\INIFileParser.dll</HintPath>
8282
</Reference>
8383
<Reference Include="Markdig, Version=0.41.0.0, Culture=neutral, processorArchitecture=MSIL">
84-
<HintPath>packages\Markdig.0.41.2\lib\net462\Markdig.dll</HintPath>
84+
<HintPath>packages\Markdig.0.41.3\lib\net462\Markdig.dll</HintPath>
8585
</Reference>
8686
<Reference Include="Microsoft.Dism, Version=1.0.0.0, Culture=neutral, PublicKeyToken=5bba90053b345501, processorArchitecture=MSIL">
8787
<HintPath>packages\Microsoft.Dism.3.3.12\lib\net40\Microsoft.Dism.dll</HintPath>
@@ -299,6 +299,7 @@
299299
<Compile Include="Panels\DoWork\ProgressPanel.vb">
300300
<SubType>Form</SubType>
301301
</Compile>
302+
<Compile Include="Panels\DoWork\ProgressReporter.vb" />
302303
<Compile Include="Panels\Exceptions\ExceptionForm.Designer.vb">
303304
<DependentUpon>ExceptionForm.vb</DependentUpon>
304305
</Compile>
@@ -1196,6 +1197,15 @@
11961197
<None Include="Helpers\extps1\PE_Helper\files\HotInstall.zip">
11971198
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
11981199
</None>
1200+
<None Include="Helpers\extps1\PE_Helper\files\scripts\fullcopy.bat">
1201+
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
1202+
</None>
1203+
<None Include="Helpers\extps1\PE_Helper\files\scripts\imagecapture.bat">
1204+
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
1205+
</None>
1206+
<None Include="Helpers\extps1\PE_Helper\files\scripts\initializenetwork.bat">
1207+
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
1208+
</None>
11991209
<None Include="Helpers\extps1\PE_Helper\files\startup\menu.ps1">
12001210
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
12011211
</None>

Helpers/extps1/PE_Helper/PE_Helper.ps1

Lines changed: 137 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,18 @@ class TargetImage {
5858
}
5959
}
6060

61+
class DiskLayout {
62+
[string]$espVolume
63+
[string]$bootVolume
64+
[string]$recoveryVolume
65+
66+
DiskLayout([string]$esp, [string]$boot, [string]$recovery) {
67+
$this.espVolume = $esp
68+
$this.bootVolume = $boot
69+
$this.recoveryVolume = $recovery
70+
}
71+
}
72+
6173
if (([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator) -eq $false)
6274
{
6375
Write-Host "You need to run this script as an administrator"
@@ -464,6 +476,8 @@ function Add-PEPackages {
464476
$pkgs.Add("$((Get-Location).Path)\ISOTEMP\OCs\en-US\WinPE-SecureStartup_en-us.cab")
465477
$pkgs.Add("$((Get-Location).Path)\ISOTEMP\OCs\WinPE-EnhancedStorage.cab")
466478
$pkgs.Add("$((Get-Location).Path)\ISOTEMP\OCs\en-US\WinPE-EnhancedStorage_en-us.cab")
479+
$pkgs.Add("$((Get-Location).Path)\ISOTEMP\OCs\WinPE-StorageWMI.cab")
480+
$pkgs.Add("$((Get-Location).Path)\ISOTEMP\OCs\en-US\WinPE-StorageWMI_en-us.cab")
467481
# Add ARM64EC packages
468482
if ($architecture -eq 'arm64') {
469483
$pkgs.Add("$((Get-Location).Path)\ISOTEMP\OCs\WinPE-x64-Support.cab")
@@ -634,6 +648,8 @@ function Start-PECustomization
634648
Copy-Item -Path "$((Get-Location).Path)\files\startup\StartInstall.ps1" -Destination "$imagePath\StartInstall.ps1" -Force
635649
Copy-Item -Path "$((Get-Location).Path)\files\dim_start\dimstart.bat" -Destination "$imagePath\dimstart.bat" -Force
636650
Copy-Item -Path "$((Get-Location).Path)\files\startup\menu.ps1" -Destination "$imagePath\menu.ps1" -Force
651+
New-Item -Path "$imagePath\scripts" -ItemType Directory | Out-Null
652+
Copy-Item -Path "$((Get-Location).Path)\files\scripts\*" -Destination "$imagePath\scripts" -Verbose -Force -Recurse -Container -ErrorAction SilentlyContinue
637653
Write-Host "Startup commands changed"
638654
}
639655
catch
@@ -917,11 +933,20 @@ function Start-OSApplication
917933
} until ($choice -eq "Y")
918934
}
919935
$driveLetter = ""
936+
$bootLetter = ""
920937
if ($partition -eq 0)
921938
{
922-
$driveLetter = "C"
923939
# Proceed with default disk configuration
924-
Write-DiskConfiguration $drive $true $partition
940+
$diskLayout = Write-DiskConfiguration $drive $true $partition
941+
if ($diskLayout -ne $null) {
942+
# Get the volume letter that was stored in the function
943+
$driveLetter = $diskLayout.bootVolume
944+
$bootLetter = $diskLayout.espVolume
945+
} else {
946+
# Assume boot drive is C and ESP is W
947+
$driveLetter = "C"
948+
$bootLetter = "W"
949+
}
925950
}
926951
else
927952
{
@@ -942,6 +967,7 @@ function Start-OSApplication
942967
$driveLetter = Read-Host "Specify a drive letter"
943968
} until ($driveLetter -ne "")
944969
}
970+
$bootLetter = "W"
945971
}
946972
Write-Host "Creating page file for Windows PE..."
947973
wpeutil createpagefile /path="$($driveLetter):\WinPEpge.sys" /size=256
@@ -1020,7 +1046,7 @@ function Start-OSApplication
10201046
{
10211047
Remove-Item -Path "$($driveLetter):\`$DISMTOOLS.~LS" -Recurse -Force -ErrorAction SilentlyContinue | Out-Null
10221048
}
1023-
New-BootFiles -drLetter $driveLetter -bootPart "auto" -diskId $drive -cleanDrive $($partition -eq 0)
1049+
New-BootFiles -drLetter $driveLetter -bootPart "auto" -diskId $drive -cleanDrive $($partition -eq 0) -espLetter $bootLetter
10241050
Start-Sleep -Milliseconds 250
10251051
Clear-Host
10261052
Write-Host "`n`n`n`n`n`n`n`n`n`n"
@@ -1216,46 +1242,118 @@ function Write-DiskConfiguration
12161242
Write-Host "Writing disk configuration. Please wait..."
12171243
if ($cleanDrive)
12181244
{
1219-
$formatter = @'
1245+
$preFormatter = @"
12201246
sel dis #DISKID#
12211247
cle
1248+
exit
1249+
"@
1250+
$preFormatter = $preFormatter.Replace("#DISKID#", $diskId).Trim()
1251+
$preFormatter | Out-File "$env:SYSTEMDRIVE\files\diskpart\dp_preformat.dp" -Force -Encoding utf8
1252+
$dpProc = Start-Process -FilePath "$env:SYSTEMROOT\system32\diskpart.exe" -ArgumentList "/s `"$env:SYSTEMDRIVE\files\diskpart\dp_preformat.dp`"" -Wait -PassThru -NoNewWindow
1253+
1254+
$espLetter = "W"
1255+
$bootLetter = "C"
1256+
$recoveryLetter = "R"
1257+
$usedLetters = 0
1258+
$espUsed = $false
1259+
$bootUsed = $false
1260+
$recoveryUsed = $false
1261+
1262+
Write-Host "Checking letters of mounted drives for conflicts..."
1263+
1264+
# One of the three letters mentioned above may be already in use. Check these before assuming they're our targets.
1265+
# This is more the case when you boot the ISO with Ventoy
1266+
if ((Get-Volume | Where-Object { $_.DriveLetter -eq $espLetter }).Count -gt 0) {
1267+
Write-Host "The default letter for the EFI System Partition is already in use."
1268+
$usedLetters++
1269+
$espUsed = $true
1270+
}
1271+
1272+
if ((Get-Volume | Where-Object { $_.DriveLetter -eq $bootLetter }).Count -gt 0) {
1273+
Write-Host "The default letter for the boot partition is already in use."
1274+
$usedLetters++
1275+
$bootUsed = $true
1276+
}
1277+
1278+
if ((Get-Volume | Where-Object { $_.DriveLetter -eq $recoveryLetter }).Count -gt 0) {
1279+
Write-Host "The default letter for the Windows Recovery Environment partition is already in use."
1280+
$usedLetters++
1281+
$recoveryUsed = $true
1282+
}
1283+
1284+
if ($usedLetters -gt 0) {
1285+
Write-Host "After clearing the partitions of disk $diskId, some of the drive letters are still in use by, possibly, external disks. This may cause undesired behavior."
1286+
Write-Host "You will now be shown a list of disks, and you will be given the opportunity to reassign disk letters."
1287+
Write-Host "These settings only apply to the disk changes in the Preinstallation Environment."
1288+
1289+
Get-Volume | Out-Host # let's make sure we are outputting this info
1290+
1291+
# Ask for all the letters that are producing conflicts
1292+
1293+
if ($espUsed) {
1294+
$newEspLetter = Read-Host -Prompt "Provide a volume letter for the EFI System Partition, or press ENTER to use the default letter [$($espLetter)]"
1295+
if ($newEspLetter -ne "") {
1296+
$espLetter = $newEspLetter
1297+
}
1298+
}
1299+
1300+
if ($bootUsed) {
1301+
$newBootLetter = Read-Host -Prompt "Provide a volume letter for the boot partition, or press ENTER to use the default letter [$($bootLetter)]"
1302+
if ($newBootLetter -ne "") {
1303+
$bootLetter = $newBootLetter
1304+
}
1305+
}
1306+
1307+
if ($recoveryUsed) {
1308+
$newRecoveryLetter = Read-Host -Prompt "Provide a volume letter for the Windows Recovery Environment partition, or press ENTER to use the default letter [$($recoveryLetter)]"
1309+
if ($newRecoveryLetter -ne "") {
1310+
$recoveryLetter = $newRecoveryLetter
1311+
}
1312+
}
1313+
1314+
} else {
1315+
Write-Host "No conflicts were detected after clearing the partitions of disk $diskId. Continuing with disk configuration..."
1316+
}
1317+
1318+
$formatter = @'
1319+
sel dis #DISKID#
12221320
#GPTPART#
12231321
#MBRPART#
12241322
exit
12251323
'@
1226-
$formatter_gpt = @'
1324+
$formatter_gpt = @"
12271325
conv gpt
12281326
cre par efi size=512
12291327
for fs=fat32 quick label="System"
1230-
ass letter W
1328+
ass letter $espLetter
12311329
cre par msr size=16
12321330
cre par pri
12331331
REM Prevent updates from failing to update WinRE
12341332
shrink minimum=1024
12351333
for quick label="Windows"
1236-
ass letter C
1334+
ass letter $bootLetter
12371335
cre par pri
12381336
for quick label="Recovery"
1239-
ass letter R
1337+
ass letter $recoveryLetter
12401338
set id="de94bba4-06d1-4d40-a16a-bfd50179d6ac"
12411339
gpt attributes=0x8000000000000001
1242-
'@
1243-
$formatter_mbr = @'
1340+
"@
1341+
$formatter_mbr = @"
12441342
cre par pri size=100
12451343
for quick label="System"
1246-
ass letter W
1344+
ass letter $espLetter
12471345
REM Important for MBR configurations
12481346
active
12491347
cre par pri
12501348
REM Prevent updates from failing to update WinRE
12511349
shrink minimum=1024
12521350
for quick label="Windows"
1253-
ass letter C
1351+
ass letter $bootLetter
12541352
cre par pri
12551353
for quick label="Recovery"
1256-
ass letter R
1354+
ass letter $recoveryLetter
12571355
set id=27
1258-
'@
1356+
"@
12591357
$uefiMode = ($env:firmware_type -eq "UEFI")
12601358
$formatter = $formatter.Replace("#DISKID#", $diskId).Trim()
12611359
if ($uefiMode)
@@ -1270,6 +1368,7 @@ function Write-DiskConfiguration
12701368
}
12711369
$formatter | Out-File "$env:SYSTEMDRIVE\files\diskpart\dp_format.dp" -Force -Encoding utf8
12721370
$dpProc = Start-Process -FilePath "$env:SYSTEMROOT\system32\diskpart.exe" -ArgumentList "/s `"$env:SYSTEMDRIVE\files\diskpart\dp_format.dp`"" -Wait -PassThru -NoNewWindow
1371+
$finalLayout = [DiskLayout]::new($espLetter, $bootLetter, $recoveryLetter)
12731372
}
12741373
else
12751374
{
@@ -1285,6 +1384,9 @@ function Write-DiskConfiguration
12851384
$dpProc = Start-Process -FilePath "$env:SYSTEMROOT\system32\diskpart.exe" -ArgumentList "/s `"$env:SYSTEMDRIVE\files\diskpart\dp_format.dp`"" -Wait -PassThru -NoNewWindow
12861385
}
12871386
Write-Host "Disk configuration has been written successfully."
1387+
if ($finalLayout -ne $null) {
1388+
return $finalLayout
1389+
}
12881390
}
12891391

12901392
function Get-WimIndexes
@@ -1668,14 +1770,19 @@ function New-BootFiles
16681770
The index of a disk
16691771
.PARAMETER cleanDrive
16701772
Determine whether to run detections for specific boot scenarios
1773+
.PARAMETER espLetter
1774+
The letter of the EFI System Partition volume. By default, it's W if not specified
16711775
.EXAMPLE
16721776
New-BootFiles -drLetter "C:" -bootPart "auto" -diskId 0 -cleanDrive $false
1777+
.EXAMPLE
1778+
New-BootFiles -drLetter "C:" -bootPart "auto" -diskId 0 -cleanDrive $false -espLetter "V"
16731779
#>
16741780
param (
16751781
[Parameter(Mandatory = $true, Position = 0)] [string]$drLetter,
16761782
[Parameter(Mandatory = $true, Position = 1)] [string]$bootPart,
16771783
[Parameter(Mandatory = $true, Position = 2)] [int]$diskId,
1678-
[Parameter(Mandatory = $true, Position = 3)] [bool]$cleanDrive
1784+
[Parameter(Mandatory = $true, Position = 3)] [bool]$cleanDrive,
1785+
[Parameter(Position = 4)] [string]$espLetter = "W"
16791786
)
16801787
if ($env:firmware_type -eq "UEFI")
16811788
{
@@ -1688,12 +1795,12 @@ function New-BootFiles
16881795
{
16891796
if (($disk.DiskIndex -eq $diskId) -and ($disk.BootPartition))
16901797
{
1691-
$MSRAssign = @'
1798+
$MSRAssign = @"
16921799
sel dis #DISKID#
16931800
sel par #VOLNUM#
1694-
ass letter w
1801+
ass letter $espLetter
16951802
exit
1696-
'@
1803+
"@
16971804
$MSRAssign = $MSRAssign.Replace("#DISKID#", $diskId).Trim()
16981805
$MSRAssign = $MSRAssign.Replace("#VOLNUM#", $($disk.Index + 1)).Trim()
16991806
$MSRAssign | Out-File "$env:SYSTEMDRIVE\files\diskpart\dp_bootassign.dp" -Force -Encoding utf8
@@ -1709,11 +1816,11 @@ function New-BootFiles
17091816
}
17101817
}
17111818
}
1712-
bcdboot "$($drLetter):\Windows" /s "W:" /f ALL
1819+
bcdboot "$($drLetter):\Windows" /s "$($espLetter):" /f ALL
17131820
}
17141821
else
17151822
{
1716-
bcdboot "$($drLetter):\Windows" /s "W:" /f ALL
1823+
bcdboot "$($drLetter):\Windows" /s "$($espLetter):" /f ALL
17171824
}
17181825
}
17191826
else
@@ -1727,12 +1834,12 @@ function New-BootFiles
17271834
{
17281835
if (($disk.DiskIndex -eq $diskId) -and ($disk.BootPartition))
17291836
{
1730-
$MSRAssign = @'
1837+
$MSRAssign = @"
17311838
sel dis #DISKID#
17321839
sel par #VOLNUM#
1733-
ass letter w
1840+
ass letter $espLetter
17341841
exit
1735-
'@
1842+
"@
17361843
$MSRAssign = $MSRAssign.Replace("#DISKID#", $diskId).Trim()
17371844
$MSRAssign = $MSRAssign.Replace("#VOLNUM#", $($disk.Index + 1)).Trim()
17381845
$MSRAssign | Out-File "$env:SYSTEMDRIVE\files\diskpart\dp_bootassign.dp" -Force -Encoding utf8
@@ -1748,15 +1855,16 @@ function New-BootFiles
17481855
}
17491856
}
17501857
}
1751-
bootsect /nt60 W:
1752-
bootsect /nt60 W: /mbr
1753-
bcdboot "$($drLetter):\Windows" /s "W:" /f BIOS
1858+
# We have to do this stupid thing to coax bootsect to work for BIOS
1859+
bootsect /nt60 "$espLetter`:"
1860+
bootsect /nt60 "$espLetter`:" /mbr
1861+
bcdboot "$($drLetter):\Windows" /s "$($espLetter):" /f BIOS
17541862
}
17551863
else
17561864
{
1757-
bootsect /nt60 W:
1758-
bootsect /nt60 W: /mbr
1759-
bcdboot "$($drLetter):\Windows" /s "W:" /f BIOS
1865+
bootsect /nt60 "$espLetter`:"
1866+
bootsect /nt60 "$espLetter`:" /mbr
1867+
bcdboot "$($drLetter):\Windows" /s "$($espLetter):" /f BIOS
17601868
}
17611869
}
17621870
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
@echo off
2+
3+
REM set this to a value higher than 0 to manually specify the number of threads for robocopy. 0 or lesser will default to 8
4+
set manualthreads=0
5+
REM set this value to customize the wait time between retries. Value of 0: no wait time
6+
set waittime=5
7+
REM set this value to customize the number of retries on failed copies. Value of 0: no retries
8+
set numberofretries=2
9+
REM set this value to customize what to copy when copying files. Refer to robocopy documentation
10+
set filecopy_operation=DATSOU
11+
REM set this value to customize what to copy when copying directories. Refer to robocopy documentation
12+
set dircopy_operation=DAT
13+
14+
if not exist "%windir%\system32\robocopy.exe" (
15+
echo Robocopy is a requirement.
16+
exit 1
17+
)
18+
19+
if %manualthreads% leq 0 (
20+
set manualthreads=8
21+
)
22+
23+
echo Full Disk Copy Utility -- this will copy the full contents of a drive to another drive. Make sure destination drive is blank
24+
set /p sourcedrive=Please enter the drive letter for the source drive:
25+
set /p destdrive=Please enter the drive letter for the destination drive:
26+
27+
echo The copy operation can take a while, depending on the speed of both disks.
28+
29+
robocopy %sourcedrive%:\ %destdrive%:\ /e /w:%waittime% /r:%numberofretries% /copy:%filecopy_operation% /dcopy:%dircopy_operation% /mt:%manualthreads%

0 commit comments

Comments
 (0)