@@ -30,29 +30,7 @@ function Invoke-WPFMicroWinRunspace {
3030 param ($MicroWinSettings , $DebugPreference )
3131
3232 # Function to set DISM-compatible permissions on a directory
33- function Set-DismCompatiblePermissions {
34- param ([string ]$Path )
3533
36- try {
37- # Use icacls for reliable permission setting with language-independent SIDs
38- # Grant full control to Administrators (S-1-5-32-544)
39- & icacls " $Path " / grant " *S-1-5-32-544:(OI)(CI)F" / T / C | Out-Null
40-
41- # Grant full control to SYSTEM (S-1-5-18)
42- & icacls " $Path " / grant " *S-1-5-18:(OI)(CI)F" / T / C | Out-Null
43-
44- # Grant full control to current user
45- $currentUser = [System.Security.Principal.WindowsIdentity ]::GetCurrent().Name
46- & icacls " $Path " / grant " ${currentUser} :(OI)(CI)F" / T / C | Out-Null
47-
48- # Grant modify to Authenticated Users (S-1-5-11) for subfolders and files
49- & icacls " $Path " / grant " *S-1-5-11:(OI)(CI)M" / T / C | Out-Null
50-
51- return $true
52- } catch {
53- return $false
54- }
55- }
5634
5735 $sync.ProcessRunning = $true
5836
@@ -117,12 +95,6 @@ function Invoke-WPFMicroWinRunspace {
11795
11896 Write-Host " Target ISO location: $SaveDialogFileName "
11997
120- # Performance optimization: Determine optimal thread count
121- $coreCount = (Get-WmiObject - Class Win32_Processor | Measure-Object - Property NumberOfCores - Sum).Sum
122- $logicalProcessors = (Get-WmiObject - Class Win32_ComputerSystem).NumberOfLogicalProcessors
123- $optimalThreads = [Math ]::Min($logicalProcessors , [Math ]::Max(2 , $coreCount ))
124- Write-Host " System has $coreCount cores, $logicalProcessors logical processors. Using $optimalThreads threads for optimal performance."
125-
12698 # Extract settings from hashtable
12799 $index = $MicroWinSettings.selectedIndex
128100 $mountDir = $MicroWinSettings.mountDir
@@ -213,10 +185,7 @@ function Invoke-WPFMicroWinRunspace {
213185 }
214186
215187 # Check if running as administrator
216- $currentPrincipal = New-Object Security.Principal.WindowsPrincipal([Security.Principal.WindowsIdentity ]::GetCurrent())
217- $isAdmin = $currentPrincipal.IsInRole ([Security.Principal.WindowsBuiltInRole ]::Administrator)
218-
219- if (-not $isAdmin ) {
188+ if (-not (New-Object Security.Principal.WindowsPrincipal([Security.Principal.WindowsIdentity ]::GetCurrent())).IsInRole([Security.Principal.WindowsBuiltInRole ]::Administrator)) {
220189 $msg = " Administrator privileges are required to mount and modify Windows images. Please run WinUtil as Administrator and try again."
221190 Write-Host $msg
222191 $sync.form.Dispatcher.Invoke ([action ]{
@@ -286,12 +255,6 @@ function Invoke-WPFMicroWinRunspace {
286255
287256 # Pre-mount system checks
288257
289- # Check if DISM is available and working
290- try {
291- $dismCheck = & dism / ? 2>&1
292- } catch {
293- }
294-
295258 # Check available disk space
296259 try {
297260 $scratchDrive = Split-Path $scratchDir - Qualifier
@@ -303,23 +266,12 @@ function Invoke-WPFMicroWinRunspace {
303266 } catch {
304267 }
305268
306- # Check if scratch directory is accessible and set proper permissions
269+ # Check if scratch directory is accessible
307270 try {
308271 if (-not (Test-Path $scratchDir )) {
309272 New-Item - Path $scratchDir - ItemType Directory - Force | Out-Null
310273 }
311274
312- # Set proper permissions for DISM operations using the helper function
313- $permissionsSet = Set-DismCompatiblePermissions - Path $scratchDir
314-
315- if ($permissionsSet ) {
316- # Verify permissions were set correctly
317- $newAcl = Get-Acl - Path $scratchDir
318- foreach ($access in $newAcl.Access ) {
319- }
320- } else {
321- }
322-
323275 # Test write access
324276 $testFile = Join-Path $scratchDir " test_access.tmp"
325277 " test" | Out-File - FilePath $testFile - Force
@@ -357,22 +309,14 @@ function Invoke-WPFMicroWinRunspace {
357309 foreach ($wimFilePath in $wimFilePaths ) {
358310 if (Test-Path $wimFilePath ) {
359311 try {
360- $wimItem = Get-Item - Path $wimFilePath - Force
361- if ($wimItem.Attributes -band [System.IO.FileAttributes ]::ReadOnly) {
362- $wimItem.Attributes = $wimItem.Attributes -band (-bnot [System.IO.FileAttributes ]::ReadOnly)
363-
364- # Verify the change was successful
365- $wimItem.Refresh ()
366- if ($wimItem.Attributes -band [System.IO.FileAttributes ]::ReadOnly) {
367- $criticalWimError = $true
368- } else {
369- }
370- } else {
312+ # Remove ReadOnly attribute using attrib command
313+ & attrib - R " $wimFilePath " 2> $null
314+ if ($LASTEXITCODE -ne 0 ) {
315+ $criticalWimError = $true
371316 }
372317 } catch {
373318 $criticalWimError = $true
374319 }
375- } else {
376320 }
377321 }
378322
@@ -899,14 +843,25 @@ function Invoke-WPFMicroWinRunspace {
899843
900844 # Last attempt - try multiple fallback strategies
901845
902- # Try DISM discard
846+
847+ # First, commit the image
903848 try {
904- $dismResult = & dism / english / unmount- image / mountdir:" $scratchDir " / discard / loglevel:1
905- if ($LASTEXITCODE -eq 0 ) {
906- $dismountSuccess = $true
907- } else {
908- }
909- } catch {
849+ & dism / english / commit- image / mountdir:" $scratchDir " / loglevel:1
850+ } catch {}
851+
852+ # Now, keep discarding the image in a loop
853+ $discardAttempts = 0
854+ $maxDiscardAttempts = 6
855+ while (-not $dismountSuccess -and $discardAttempts -lt $maxDiscardAttempts ) {
856+ try {
857+ $dismResult = & dism / english / unmount- image / mountdir:" $scratchDir " / discard / loglevel:1
858+ if ($LASTEXITCODE -eq 0 ) {
859+ $dismountSuccess = $true
860+ break
861+ }
862+ } catch {}
863+ $discardAttempts ++
864+ Start-Sleep - Seconds 5
910865 }
911866
912867 # Try PowerShell discard if DISM failed
@@ -942,9 +897,8 @@ function Invoke-WPFMicroWinRunspace {
942897 try {
943898 Write-Host " Exporting image into $mountDir \sources\install2.wim with optimized settings..."
944899 try {
945- # Use Fast compression for better performance, especially during development/testing
946- # Users can change this to "Max" if they prefer smaller file size over speed
947- Export-WindowsImage - SourceImagePath " $mountDir \sources\install.wim" - SourceIndex $index - DestinationImagePath " $mountDir \sources\install2.wim" - CompressionType " Fast"
900+ # Use Max compression for smaller file size (slower, but more efficient)
901+ Export-WindowsImage - SourceImagePath " $mountDir \sources\install.wim" - SourceIndex $index - DestinationImagePath " $mountDir \sources\install2.wim" - CompressionType " Max"
948902 } catch {
949903 # Fall back to DISM with optimized settings
950904 dism / english / export-image / sourceimagefile= " $mountDir \sources\install.wim" / sourceindex= $index / destinationimagefile= " $mountDir \sources\install2.wim" / compress:fast / checkintegrity / verify / loglevel:1
0 commit comments