diff --git a/7z/amd64/7z.dll b/7z/amd64/7z.dll index 2ba9f270..94c4f834 100644 Binary files a/7z/amd64/7z.dll and b/7z/amd64/7z.dll differ diff --git a/7z/amd64/7z.exe b/7z/amd64/7z.exe index a739ca0f..7a101940 100644 Binary files a/7z/amd64/7z.exe and b/7z/amd64/7z.exe differ diff --git a/7z/i386/7z.dll b/7z/i386/7z.dll index 7c1527a0..d768ded7 100644 Binary files a/7z/i386/7z.dll and b/7z/i386/7z.dll differ diff --git a/7z/i386/7z.exe b/7z/i386/7z.exe index a8e8480b..c388be1b 100644 Binary files a/7z/i386/7z.exe and b/7z/i386/7z.exe differ diff --git a/Helpers/extps1/PE_Helper/PE_Helper.ps1 b/Helpers/extps1/PE_Helper/PE_Helper.ps1 index 63f37baf..bd628d40 100644 --- a/Helpers/extps1/PE_Helper/PE_Helper.ps1 +++ b/Helpers/extps1/PE_Helper/PE_Helper.ps1 @@ -612,7 +612,7 @@ function Start-OSApplication } until ($driveLetter -ne "") } } - wpeutil createpagefile /path="$($driveLetter):\pagefile.sys" /size=256 + wpeutil createpagefile /path="$($driveLetter):\WinPEpge.sys" /size=256 $wimFile = Get-WimIndexes $serviceableArchitecture = (((Get-CimInstance -Class Win32_Processor | Where-Object { $_.DeviceID -eq "CPU0" }).Architecture) -eq (Get-WindowsImage -ImagePath "$($wimFile.wimPath)" -Index $wimFile.index).Architecture) Write-Host "Applying Windows image. This can take some time..." @@ -1038,8 +1038,28 @@ function Set-Serviceability [Parameter(Mandatory = $true, Position = 0)] [string] $ImagePath ) Write-Host "Starting serviceability tests..." - # Bit of a mouthful, but good for PowerShell verbs - dism /image=$ImagePath /is-serviceable + # Follow Panther engine steps (https://github.com/CodingWonders/Panther-Diagram) + Write-Host "Creating temporary directory for serviceability operations..." + $scratchDir = "" + $driveLetter = "" + try + { + $folderPath = $ImagePath.Replace("\", "").Trim() + $driveLetter = $folderPath + if (-not (Test-Path "$folderPath\`$DISMTOOLS.~LS")) { New-Item -Path "$folderPath\`$DISMTOOLS.~LS" -ItemType Directory | Out-Null } + $guidStr = [System.Guid]::NewGuid().Guid + New-Item -Path "$folderPath\`$DISMTOOLS.~LS\PackageTemp\$guidStr" -ItemType Directory | Out-Null + Write-Host "Successfully created the scratch directory." + $scratchDir = "$folderPath\`$DISMTOOLS.~LS\PackageTemp\$guidStr" + # Bit of a mouthful, but good for PowerShell verbs (+ scratch dir support) + dism /image=$ImagePath /scratchdir="$scratchDir" /is-serviceable + } + catch + { + Write-Host "Could not create temporary directory. Continuing without one. Do note that the serviceability tests might fail." + # Bit of a mouthful, but good for PowerShell verbs + dism /image=$ImagePath /is-serviceable + } if ($?) { Write-Host "Serviceability tests have succeeded. The image is valid." @@ -1048,6 +1068,12 @@ function Set-Serviceability { Write-Host "Serviceability tests have failed. The image is not valid." } + if (($scratchDir -ne "") -and (Test-Path -Path "$scratchDir")) + { + Write-Host "Removing temporary directory..." + Remove-Item -Path "$scratchDir" -Recurse -Force -ErrorAction SilentlyContinue | Out-Null + Remove-Item -Path "$driveLetter\`$DISMTOOLS.~LS" -Recurse -Force -ErrorAction SilentlyContinue | Out-Null + } } function New-BootFiles @@ -1081,7 +1107,7 @@ function New-BootFiles { foreach ($disk in $(Get-CimInstance -ClassName Win32_DiskPartition)) { - if ($disk.BootPartition) + if (($disk.DiskIndex -eq $diskId) -and ($disk.BootPartition)) { $MSRAssign = @' sel dis #DISKID# @@ -1112,7 +1138,7 @@ function New-BootFiles { foreach ($disk in $(Get-CimInstance -ClassName Win32_DiskPartition)) { - if ($disk.BootPartition) + if (($disk.DiskIndex -eq $diskId) -and ($disk.BootPartition)) { $MSRAssign = @' sel dis #DISKID# diff --git a/Helpers/extps1/mImgMgr.ps1 b/Helpers/extps1/mImgMgr.ps1 index e67529d6..065a06e4 100644 --- a/Helpers/extps1/mImgMgr.ps1 +++ b/Helpers/extps1/mImgMgr.ps1 @@ -63,7 +63,7 @@ function Get-MenuItems #> param ( [Parameter(Mandatory = $true, Position = 0)] [int] $selImage, - [Parameter(Mandatory = $true, Position = 1)] [Object[]] $mountedImages + [Parameter(Position = 1)] [Object[]] $mountedImages ) try { diff --git a/Installer/Nightly/dt_setup.exe b/Installer/Nightly/dt_setup.exe index a24b297b..2822594e 100644 Binary files a/Installer/Nightly/dt_setup.exe and b/Installer/Nightly/dt_setup.exe differ diff --git a/MainForm.vb b/MainForm.vb index 993a0a77..7e4faa32 100644 --- a/MainForm.vb +++ b/MainForm.vb @@ -3633,6 +3633,20 @@ Public Class MainForm Return False End Function + Public Event APIExceptionThrown(errorEx As Exception) + + Private Sub APIExceptionHandler(errorEx As Exception) Handles Me.APIExceptionThrown + MsgBox(errorEx.Message, vbOKOnly + vbExclamation, "API error") + End Sub + + Sub ThrowAPIException(APIException As DismException) + Dim errorEx As New Exception("An error occurred while getting information with the DISM API. Consider reading the message below for more information:" & CrLf & CrLf & + APIException.Message & CrLf & CrLf & + "This does not indicate a program error, but it implies that you will not be able to perform some operations unless the issue is resolved." & CrLf & CrLf & + "Error code: " & Hex(APIException.HResult), APIException) + RaiseEvent APIExceptionThrown(errorEx) + End Sub + ''' ''' Gets installed packages in an image and puts them in separate arrays ''' @@ -3664,6 +3678,8 @@ Public Class MainForm imgPackageRelType = imgPackageRelTypeList.ToArray() imgPackageInstTime = imgPackageInstTimeList.ToArray() End Using + Catch ex As DismException + ThrowAPIException(ex) Finally DismApi.Shutdown() End Try @@ -3827,6 +3843,8 @@ Public Class MainForm imgFeatureNames = imgFeatureNameList.ToArray() imgFeatureState = imgFeatureStateList.ToArray() End Using + Catch ex As DismException + ThrowAPIException(ex) Finally DismApi.Shutdown() End Try @@ -4011,6 +4029,8 @@ Public Class MainForm imgAppxResourceIds = imgAppxResourceIdList.ToArray() imgAppxVersions = imgAppxVersionList.ToArray() End Using + Catch ex As DismException + ThrowAPIException(ex) Finally DismApi.Shutdown() End Try @@ -4246,6 +4266,8 @@ Public Class MainForm imgCapabilityIds = imgCapabilityNameList.ToArray() imgCapabilityState = imgCapabilityStateList.ToArray() End Using + Catch ex As DismException + ThrowAPIException(ex) Finally DismApi.Shutdown() End Try @@ -4413,6 +4435,8 @@ Public Class MainForm imgDrvVersions = imgDrvVersionList.ToArray() imgDrvBootCriticalStatus = imgDrvBootCriticalStatusList.ToArray() End Using + Catch ex As DismException + ThrowAPIException(ex) Finally DismApi.Shutdown() End Try diff --git a/My Project/AssemblyInfo.vb b/My Project/AssemblyInfo.vb index 267f2076..d0d5f285 100644 --- a/My Project/AssemblyInfo.vb +++ b/My Project/AssemblyInfo.vb @@ -31,5 +31,5 @@ Imports System.Runtime.InteropServices ' mediante el asterisco ('*'), como se muestra a continuación: ' - - + + diff --git a/My Project/Resources.Designer.vb b/My Project/Resources.Designer.vb index 752f6ad7..9cd936ac 100644 --- a/My Project/Resources.Designer.vb +++ b/My Project/Resources.Designer.vb @@ -2178,13 +2178,14 @@ Namespace My.Resources ''' ''' Busca una cadena traducida similar a Bugfixes: ''' - '''- Fixed some splash screen issues if the program is run on Windows 7/Server 2008 R2 or if the program is run without administrative privileges (thanks liliactr on the My Digital Life forums for spotting) + '''- Fixed an issue in the CLI version of the mounted image manager that would throw an error at startup if no images were mounted + '''- If the download or install sizes of capabilities are less than 1024 bytes, the program will no longer show "(~)" + '''- Fixed a critical issue where all DISM commands would fail for offline installations if the mount directory were a drive (thanks @Xhib-ba for spotting) ''' '''New features: ''' - '''- Existing PowerShell tooling (excluding the PE Helper) has been refactored and cleaned up for increased code readability and quality - '''- If you were to add multiple installation images to your customized ISO files, the PE helper will now ask you what image to apply - '''- You ca [resto de la cadena truncado]";. + '''- The program update system has had some improvements: + ''' - A minimum version thr [resto de la cadena truncado]";. ''' Friend ReadOnly Property WhatsNew() As String Get diff --git a/My Project/Resources.resx b/My Project/Resources.resx index 1545bb8c..0d24c583 100644 --- a/My Project/Resources.resx +++ b/My Project/Resources.resx @@ -1119,15 +1119,21 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI Bugfixes: -- Fixed some splash screen issues if the program is run on Windows 7/Server 2008 R2 or if the program is run without administrative privileges (thanks liliactr on the My Digital Life forums for spotting) +- Fixed an issue in the CLI version of the mounted image manager that would throw an error at startup if no images were mounted +- If the download or install sizes of capabilities are less than 1024 bytes, the program will no longer show "(~)" +- Fixed a critical issue where all DISM commands would fail for offline installations if the mount directory were a drive (thanks @Xhib-ba for spotting) New features: -- Existing PowerShell tooling (excluding the PE Helper) has been refactored and cleaned up for increased code readability and quality -- If you were to add multiple installation images to your customized ISO files, the PE helper will now ask you what image to apply -- You can now get who signed a driver when saving installed driver information to a file -- The way custom properties of packages and features are viewed has been improved, better showing the hierarchy of these properties -- The Scintilla.NET library has been updated to version 5.5.1 +- The program update system has had some improvements: + - A minimum version threshold has been added to update information files. The currently running version is compared with this threshold to determine if settings should be migrated +- The 7-Zip component has been updated to version 24.06 +- The Preinstallation Environment (PE) helper has had some improvements: + - The OS installer now creates a scratch directory on the target drive to avoid any DISM serviceability warnings + - Disk volume checks have been improved to ensure that the correct boot volume is selected when creating boot files +- The App Installer downloader now informs of download errors and saves target files using the extension in the URL +- The custom property viewer can now prompt you to select a property if you haven't done so +- The program can now detect and inform about DISM API errors to you ..\Resources\split_img.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a diff --git a/Panels/DoWork/ProgressPanel.vb b/Panels/DoWork/ProgressPanel.vb index 0c0635d5..42afa907 100644 --- a/Panels/DoWork/ProgressPanel.vb +++ b/Panels/DoWork/ProgressPanel.vb @@ -758,6 +758,12 @@ Public Class ProgressPanel PkgErrorText.RichTextBox1.Clear() FeatErrorText.RichTextBox1.Clear() DismApi.Initialize(DismLogLevel.LogErrors) + Dim OperationUseQuotes As Boolean + Dim targetImage As String = "" + If MountDir <> "" Then + OperationUseQuotes = Not Path.GetPathRoot(MountDir) = MountDir + targetImage = If(OperationUseQuotes, Quote & MountDir & Quote, MountDir) + End If If opNum = 0 Then Select Case Language Case 0 @@ -2185,7 +2191,7 @@ Public Class ProgressPanel "Processing " & pkgCount & " packages..." & CrLf) If pkgAdditionOp = 0 Then DISMProc.StartInfo.FileName = DismProgram - CommandArgs &= If(OnlineMgmt, " /online", " /image=" & Quote & MountDir & Quote) & " /norestart /add-package /packagepath=" & Quote & pkgSource & Quote + CommandArgs &= If(OnlineMgmt, " /online", " /image=" & targetImage) & " /norestart /add-package /packagepath=" & Quote & pkgSource & Quote If pkgIgnoreApplicabilityChecks Then CommandArgs &= " /ignorecheck" End If @@ -2303,7 +2309,7 @@ Public Class ProgressPanel If Not pkgIsApplicable Or pkgIsInstalled Then Continue For LogView.AppendText(CrLf & "Processing package...") DISMProc.StartInfo.FileName = DismProgram - CommandArgs &= If(OnlineMgmt, " /online", " /image=" & Quote & MountDir & Quote) & " /norestart /add-package /packagepath=" & Quote & pkgs(x) & Quote + CommandArgs &= If(OnlineMgmt, " /online", " /image=" & targetImage) & " /norestart /add-package /packagepath=" & Quote & pkgs(x) & Quote If pkgIgnoreApplicabilityChecks Then CommandArgs &= " /ignorecheck" End If @@ -2492,7 +2498,7 @@ Public Class ProgressPanel If pkgIsReadyForRemoval Then LogView.AppendText(CrLf & "Processing package removal...") DISMProc.StartInfo.FileName = DismProgram - CommandArgs &= If(OnlineMgmt, " /online", " /image=" & Quote & MountDir & Quote) & " /norestart /remove-package /packagename=" & pkgRemovalNames(x) + CommandArgs &= If(OnlineMgmt, " /online", " /image=" & targetImage) & " /norestart /remove-package /packagename=" & pkgRemovalNames(x) DISMProc.StartInfo.Arguments = CommandArgs DISMProc.Start() DISMProc.WaitForExit() @@ -2594,7 +2600,7 @@ Public Class ProgressPanel If pkgIsReadyForRemoval Then LogView.AppendText(CrLf & "Processing package removal...") DISMProc.StartInfo.FileName = DismProgram - CommandArgs &= If(OnlineMgmt, " /online", " /image=" & Quote & MountDir & Quote) & " /norestart /remove-package /packagepath=" & pkgRemovalFiles(x) + CommandArgs &= If(OnlineMgmt, " /online", " /image=" & targetImage) & " /norestart /remove-package /packagepath=" & pkgRemovalFiles(x) DISMProc.StartInfo.Arguments = CommandArgs DISMProc.Start() DISMProc.WaitForExit() @@ -2783,7 +2789,7 @@ Public Class ProgressPanel Finally DismApi.Shutdown() End Try - CommandArgs &= If(OnlineMgmt, " /online", " /image=" & Quote & MountDir & Quote) & " /norestart /enable-feature /featurename=" & featEnablementNames(x).Replace("ListViewItem: ", "").Trim().Replace("{", "").Trim().Replace("}", "").Trim() + CommandArgs &= If(OnlineMgmt, " /online", " /image=" & targetImage) & " /norestart /enable-feature /featurename=" & featEnablementNames(x).Replace("ListViewItem: ", "").Trim().Replace("{", "").Trim().Replace("}", "").Trim() If featisParentPkgNameUsed And featParentPkgName <> "" Then CommandArgs &= " /packagename=" & featParentPkgName End If @@ -2975,7 +2981,7 @@ Public Class ProgressPanel Finally DismApi.Shutdown() End Try - CommandArgs &= If(OnlineMgmt, " /online", " /image=" & Quote & MountDir & Quote) & " /norestart /disable-feature /featurename=" & featDisablementNames(x).Replace("ListViewItem: ", "").Trim().Replace("{", "").Trim().Replace("}", "").Trim() + CommandArgs &= If(OnlineMgmt, " /online", " /image=" & targetImage) & " /norestart /disable-feature /featurename=" & featDisablementNames(x).Replace("ListViewItem: ", "").Trim().Replace("{", "").Trim().Replace("}", "").Trim() If featDisablementParentPkgUsed And featDisablementParentPkg <> "" Then CommandArgs &= " /packagename=" & featParentPkgName End If @@ -3050,7 +3056,7 @@ Public Class ProgressPanel End Select ' Initialize command DISMProc.StartInfo.FileName = DismProgram - CommandArgs &= If(OnlineMgmt, " /online", " /image=" & Quote & MountDir & Quote) & " /cleanup-image" + CommandArgs &= If(OnlineMgmt, " /online", " /image=" & targetImage) & " /cleanup-image" Select Case CleanupTask Case 0 Select Case Language @@ -3305,7 +3311,7 @@ Public Class ProgressPanel "- Catalog file: " & If(ppkgAdditionCatalogPath = "", "none specified", Quote & ppkgAdditionCatalogPath & Quote) & CrLf & _ "- Commit image after adding provisioning package? " & If(ppkgAdditionCommit, "Yes", "No")) DISMProc.StartInfo.FileName = DismProgram - CommandArgs &= If(OnlineMgmt, " /online", " /image=" & Quote & MountDir & Quote) & " /add-provisioningpackage /packagepath=" & Quote & ppkgAdditionPackagePath & Quote & If(ppkgAdditionCatalogPath <> "" And File.Exists(ppkgAdditionCatalogPath), " /catalogpath=" & Quote & ppkgAdditionCatalogPath & Quote, "") + CommandArgs &= If(OnlineMgmt, " /online", " /image=" & targetImage) & " /add-provisioningpackage /packagepath=" & Quote & ppkgAdditionPackagePath & Quote & If(ppkgAdditionCatalogPath <> "" And File.Exists(ppkgAdditionCatalogPath), " /catalogpath=" & Quote & ppkgAdditionCatalogPath & Quote, "") DISMProc.StartInfo.Arguments = CommandArgs DISMProc.Start() DISMProc.WaitForExit() @@ -3511,7 +3517,7 @@ Public Class ProgressPanel Else ' Initialize command DISMProc.StartInfo.FileName = DismProgram - CommandArgs &= If(OnlineMgmt, " /online", " /image=" & Quote & MountDir & Quote) & " /add-provisionedappxpackage " + CommandArgs &= If(OnlineMgmt, " /online", " /image=" & targetImage) & " /add-provisionedappxpackage " If File.GetAttributes(appxAdditionPackageList(x).PackageFile) = FileAttributes.Directory Then CommandArgs &= "/folderpath=" & Quote & appxAdditionPackageList(x).PackageFile & Quote Else @@ -3739,7 +3745,7 @@ Public Class ProgressPanel LogView.AppendText(CrLf & CrLf & _ "Processing package...") DISMProc.StartInfo.FileName = DismProgram - CommandArgs &= If(OnlineMgmt, " /online", " /image=" & Quote & MountDir & Quote) & " /remove-provisionedappxpackage /packagename=" & appxRemovalPackages(x) + CommandArgs &= If(OnlineMgmt, " /online", " /image=" & targetImage) & " /remove-provisionedappxpackage /packagename=" & appxRemovalPackages(x) DISMProc.StartInfo.Arguments = CommandArgs DISMProc.Start() DISMProc.WaitForExit() @@ -3890,7 +3896,7 @@ Public Class ProgressPanel Finally DismApi.Shutdown() End Try - CommandArgs &= If(OnlineMgmt, " /online", " /image=" & Quote & MountDir & Quote) & " /norestart /add-capability /capabilityname=" & capAdditionIds(x) + CommandArgs &= If(OnlineMgmt, " /online", " /image=" & targetImage) & " /norestart /add-capability /capabilityname=" & capAdditionIds(x) If capAdditionUseSource And Directory.Exists(capAdditionSource) Then CommandArgs &= " /source=" & Quote & capAdditionSource & Quote End If @@ -4059,7 +4065,7 @@ Public Class ProgressPanel DismApi.Shutdown() End Try DISMProc.StartInfo.FileName = DismProgram - CommandArgs &= If(OnlineMgmt, " /online", " /image=" & Quote & MountDir & Quote) & " /norestart /remove-capability /capabilityname=" & capRemovalIds(x) + CommandArgs &= If(OnlineMgmt, " /online", " /image=" & targetImage) & " /norestart /remove-capability /capabilityname=" & capRemovalIds(x) DISMProc.StartInfo.Arguments = CommandArgs DISMProc.Start() DISMProc.WaitForExit() @@ -4227,7 +4233,7 @@ Public Class ProgressPanel "The driver package currently about to be processed is a folder, so information about it can't be obtained. Proceeding anyway...") End If DISMProc.StartInfo.FileName = DismProgram - CommandArgs &= If(OnlineMgmt, " /online", " /image=" & Quote & MountDir & Quote) & " /add-driver /driver=" & Quote & drvAdditionPkgs(x) & Quote + CommandArgs &= If(OnlineMgmt, " /online", " /image=" & targetImage) & " /add-driver /driver=" & Quote & drvAdditionPkgs(x) & Quote If drvAdditionForceUnsigned Then CommandArgs &= " /forceunsigned" End If @@ -4424,7 +4430,7 @@ Public Class ProgressPanel DismApi.Shutdown() End Try DISMProc.StartInfo.FileName = DismProgram - CommandArgs &= If(OnlineMgmt, " /online", " /image=" & Quote & MountDir & Quote) & " /remove-driver /driver=" & Quote & drvRemovalPkgs(x) & Quote + CommandArgs &= If(OnlineMgmt, " /online", " /image=" & targetImage) & " /remove-driver /driver=" & Quote & drvRemovalPkgs(x) & Quote DISMProc.StartInfo.Arguments = CommandArgs DISMProc.Start() DISMProc.WaitForExit() @@ -4505,10 +4511,10 @@ Public Class ProgressPanel Case 1 ' Not supported Case Is >= 2 - CommandArgs &= If(OnlineMgmt, " /online", " /image=" & Quote & MountDir & Quote) & " /export-driver /destination=" & Quote & drvExportTarget & Quote + CommandArgs &= If(OnlineMgmt, " /online", " /image=" & targetImage) & " /export-driver /destination=" & Quote & drvExportTarget & Quote End Select Case 10 - CommandArgs &= If(OnlineMgmt, " /online", " /image=" & Quote & MountDir & Quote) & " /export-driver /destination=" & Quote & drvExportTarget & Quote + CommandArgs &= If(OnlineMgmt, " /online", " /image=" & targetImage) & " /export-driver /destination=" & Quote & drvExportTarget & Quote End Select DISMProc.StartInfo.Arguments = CommandArgs DISMProc.Start() @@ -4594,7 +4600,7 @@ Public Class ProgressPanel End Try If Directory.Exists(Application.StartupPath & "\export_temp") Then LogView.AppendText(CrLf & "Exporting third-party drivers from import source..." & CrLf) - CommandArgs &= If(ImportSourceInt = 1, " /online", " /image=" & Quote & MountDir & Quote) & " /export-driver /destination=" & Quote & Application.StartupPath & "\export_temp" & Quote + CommandArgs &= If(ImportSourceInt = 1, " /online", " /image=" & targetImage) & " /export-driver /destination=" & Quote & Application.StartupPath & "\export_temp" & Quote DISMProc.StartInfo.FileName = DismProgram DISMProc.StartInfo.Arguments = CommandArgs DISMProc.Start() @@ -4636,7 +4642,7 @@ Public Class ProgressPanel End Select LogView.AppendText(CrLf & "Importing third-party drivers from the temporary export directory to the destination image...") CommandArgs = BckArgs - CommandArgs &= If(OnlineMgmt, " /online", " /image=" & Quote & MountDir & Quote) & " /add-driver /driver=" & Quote & Application.StartupPath & "\export_temp" & Quote & " /recurse" + CommandArgs &= If(OnlineMgmt, " /online", " /image=" & targetImage) & " /add-driver /driver=" & Quote & Application.StartupPath & "\export_temp" & Quote & " /recurse" DISMProc.StartInfo.Arguments = CommandArgs DISMProc.Start() DISMProc.WaitForExit() @@ -4691,7 +4697,7 @@ Public Class ProgressPanel End Select LogView.AppendText(CrLf & "Setting the Windows PE scratch space..." & CrLf & _ "- New scratch space amount: " & peNewScratchSpace & " MB") - CommandArgs &= " /image=" & Quote & MountDir & Quote & " /set-scratchspace=" & peNewScratchSpace + CommandArgs &= " /image=" & targetImage & " /set-scratchspace=" & peNewScratchSpace DISMProc.StartInfo.FileName = DismProgram DISMProc.StartInfo.Arguments = CommandArgs DISMProc.Start() @@ -4740,7 +4746,7 @@ Public Class ProgressPanel End Select LogView.AppendText(CrLf & "Setting the Windows PE target path..." & CrLf & _ "- New target path: " & Quote & peNewTargetPath & Quote) - CommandArgs &= " /image=" & Quote & MountDir & Quote & " /set-targetpath=" & peNewTargetPath + CommandArgs &= " /image=" & targetImage & " /set-targetpath=" & peNewTargetPath DISMProc.StartInfo.FileName = DismProgram DISMProc.StartInfo.Arguments = CommandArgs DISMProc.Start() diff --git a/Panels/Get_Ops/Capabilities/GetCapabilityInfo.vb b/Panels/Get_Ops/Capabilities/GetCapabilityInfo.vb index d50d2c61..ec84a9ff 100644 --- a/Panels/Get_Ops/Capabilities/GetCapabilityInfo.vb +++ b/Panels/Get_Ops/Capabilities/GetCapabilityInfo.vb @@ -297,30 +297,30 @@ Public Class GetCapabilityInfoDlg Case 0 Select Case My.Computer.Info.InstalledUICulture.ThreeLetterWindowsLanguageName Case "ENU", "ENG" - Label42.Text = "Download size: " & capInfo.DownloadSize & " bytes (~" & Converters.BytesToReadableSize(capInfo.DownloadSize) & ")" & CrLf & _ - "Install size: " & capInfo.InstallSize & " bytes (~" & Converters.BytesToReadableSize(capInfo.InstallSize) & ")" + Label42.Text = "Download size: " & capInfo.DownloadSize & " bytes" & If(capInfo.DownloadSize >= 1024, " (~" & Converters.BytesToReadableSize(capInfo.DownloadSize) & ")", "") & CrLf & _ + "Install size: " & capInfo.InstallSize & " bytes" & If(capInfo.InstallSize >= 1024, " (~" & Converters.BytesToReadableSize(capInfo.InstallSize) & ")", "") Case "ESN" - Label42.Text = "Tamaño de descarga: " & capInfo.DownloadSize & " bytes (~" & Converters.BytesToReadableSize(capInfo.DownloadSize) & ")" & CrLf & _ - "Tamaño de instalación: " & capInfo.InstallSize & " bytes (~" & Converters.BytesToReadableSize(capInfo.InstallSize) & ")" + Label42.Text = "Tamaño de descarga: " & capInfo.DownloadSize & " bytes" & If(capInfo.DownloadSize >= 1024, " (~" & Converters.BytesToReadableSize(capInfo.DownloadSize) & ")", "") & CrLf & _ + "Tamaño de instalación: " & capInfo.InstallSize & " bytes" & If(capInfo.InstallSize >= 1024, " (~" & Converters.BytesToReadableSize(capInfo.InstallSize) & ")", "") Case "FRA" - Label42.Text = "Taille du téléchargement : " & capInfo.DownloadSize & " octets (~" & Converters.BytesToReadableSize(capInfo.DownloadSize, True) & ")" & CrLf & _ - "Taille d'installation : " & capInfo.InstallSize & " octets (~" & Converters.BytesToReadableSize(capInfo.InstallSize, True) & ")" + Label42.Text = "Taille du téléchargement : " & capInfo.DownloadSize & " octets" & If(capInfo.DownloadSize >= 1024, " (~" & Converters.BytesToReadableSize(capInfo.DownloadSize, True) & ")", "") & CrLf & _ + "Taille d'installation : " & capInfo.InstallSize & " octets" & If(capInfo.InstallSize >= 1024, " (~" & Converters.BytesToReadableSize(capInfo.InstallSize, True) & ")", "") Case "PTB", "PTG" - Label42.Text = "Tamanho do descarregamento: " & capInfo.DownloadSize & " bytes (~" & Converters.BytesToReadableSize(capInfo.DownloadSize) & ")" & CrLf & _ - "Tamanho da instalação: " & capInfo.InstallSize & " bytes (~" & Converters.BytesToReadableSize(capInfo.InstallSize) & ")" + Label42.Text = "Tamanho do descarregamento: " & capInfo.DownloadSize & " bytes" & If(capInfo.DownloadSize >= 1024, " (~" & Converters.BytesToReadableSize(capInfo.DownloadSize) & ")", "") & CrLf & _ + "Tamanho da instalação: " & capInfo.InstallSize & " bytes" & If(capInfo.InstallSize >= 1024, " (~" & Converters.BytesToReadableSize(capInfo.InstallSize) & ")", "") End Select Case 1 - Label42.Text = "Download size: " & capInfo.DownloadSize & " bytes (~" & Converters.BytesToReadableSize(capInfo.DownloadSize) & ")" & CrLf & _ - "Install size: " & capInfo.InstallSize & " bytes (~" & Converters.BytesToReadableSize(capInfo.InstallSize) & ")" + Label42.Text = "Download size: " & capInfo.DownloadSize & " bytes" & If(capInfo.DownloadSize >= 1024, " (~" & Converters.BytesToReadableSize(capInfo.DownloadSize) & ")", "") & CrLf & _ + "Install size: " & capInfo.InstallSize & " bytes" & If(capInfo.InstallSize >= 1024, " (~" & Converters.BytesToReadableSize(capInfo.InstallSize) & ")", "") Case 2 - Label42.Text = "Tamaño de descarga: " & capInfo.DownloadSize & " bytes (~" & Converters.BytesToReadableSize(capInfo.DownloadSize) & ")" & CrLf & _ - "Tamaño de instalación: " & capInfo.InstallSize & " bytes (~" & Converters.BytesToReadableSize(capInfo.InstallSize) & ")" + Label42.Text = "Tamaño de descarga: " & capInfo.DownloadSize & " bytes" & If(capInfo.DownloadSize >= 1024, " (~" & Converters.BytesToReadableSize(capInfo.DownloadSize) & ")", "") & CrLf & _ + "Tamaño de instalación: " & capInfo.InstallSize & " bytes" & If(capInfo.InstallSize >= 1024, " (~" & Converters.BytesToReadableSize(capInfo.InstallSize) & ")", "") Case 3 - Label42.Text = "Taille du téléchargement : " & capInfo.DownloadSize & " octets (~" & Converters.BytesToReadableSize(capInfo.DownloadSize, True) & ")" & CrLf & _ - "Taille d'installation : " & capInfo.InstallSize & " octets (~" & Converters.BytesToReadableSize(capInfo.InstallSize, True) & ")" + Label42.Text = "Taille du téléchargement : " & capInfo.DownloadSize & " octets" & If(capInfo.DownloadSize >= 1024, " (~" & Converters.BytesToReadableSize(capInfo.DownloadSize, True) & ")", "") & CrLf & _ + "Taille d'installation : " & capInfo.InstallSize & " octets" & If(capInfo.InstallSize >= 1024, " (~" & Converters.BytesToReadableSize(capInfo.InstallSize, True) & ")", "") Case 4 - Label42.Text = "Tamanho do descarregamento: " & capInfo.DownloadSize & " bytes (~" & Converters.BytesToReadableSize(capInfo.DownloadSize) & ")" & CrLf & _ - "Tamanho da instalação: " & capInfo.InstallSize & " bytes (~" & Converters.BytesToReadableSize(capInfo.InstallSize) & ")" + Label42.Text = "Tamanho do descarregamento: " & capInfo.DownloadSize & " bytes" & If(capInfo.DownloadSize >= 1024, " (~" & Converters.BytesToReadableSize(capInfo.DownloadSize) & ")", "") & CrLf & _ + "Tamanho da instalação: " & capInfo.InstallSize & " bytes" & If(capInfo.InstallSize >= 1024, " (~" & Converters.BytesToReadableSize(capInfo.InstallSize) & ")", "") End Select End Using Catch NRE As NullReferenceException diff --git a/Panels/Get_Ops/Features/GetFeatureInfo.vb b/Panels/Get_Ops/Features/GetFeatureInfo.vb index f1814bbf..2250155a 100644 --- a/Panels/Get_Ops/Features/GetFeatureInfo.vb +++ b/Panels/Get_Ops/Features/GetFeatureInfo.vb @@ -311,6 +311,27 @@ Public Class GetFeatureInfoDlg cPropContents &= "- " & If(cProp.Path <> "", cProp.Path & "\", "") & cProp.Name & ": " & cProp.Value & CrLf Next PopulateTreeView(cPropPathView, cPropContents.Replace("- ", "").Trim()) + Select Case MainForm.Language + Case 0 + Select Case My.Computer.Info.InstalledUICulture.ThreeLetterWindowsLanguageName + Case "ENU", "ENG" + cPropValue.Text = "Please select or expand an entry." + Case "ESN" + cPropValue.Text = "Por favor, seleccione o expanda una entrada." + Case "FRA" + cPropValue.Text = "Veuillez sélectionner ou étendre une entrée." + Case "PTB", "PTG" + cPropValue.Text = "Por favor, seleccione ou expanda uma entrada." + End Select + Case 1 + cPropValue.Text = "Please select or expand an entry." + Case 2 + cPropValue.Text = "Por favor, seleccione o expanda una entrada." + Case 3 + cPropValue.Text = "Veuillez sélectionner ou étendre une entrée." + Case 4 + cPropValue.Text = "Por favor, seleccione ou expanda uma entrada." + End Select Else Select Case MainForm.Language Case 0 diff --git a/Panels/Get_Ops/InfoSave/ImgInfoSaveDlg.vb b/Panels/Get_Ops/InfoSave/ImgInfoSaveDlg.vb index d3744e71..174d34e2 100644 --- a/Panels/Get_Ops/InfoSave/ImgInfoSaveDlg.vb +++ b/Panels/Get_Ops/InfoSave/ImgInfoSaveDlg.vb @@ -1717,8 +1717,8 @@ Public Class ImgInfoSaveDlg " - Display name: " & capInfo.DisplayName & CrLf & _ " - Capability description: " & capInfo.Description & CrLf & _ " - Sizes:" & CrLf & _ - " - Download size: " & capInfo.DownloadSize & " bytes (~" & Converters.BytesToReadableSize(capInfo.DownloadSize) & ")" & CrLf & _ - " - Install size: " & capInfo.InstallSize & " bytes (~" & Converters.BytesToReadableSize(capInfo.InstallSize) & ")" & CrLf & CrLf + " - Download size: " & capInfo.DownloadSize & " bytes" & If(capInfo.DownloadSize >= 1024, " (~" & Converters.BytesToReadableSize(capInfo.DownloadSize) & ")", "") & CrLf & _ + " - Install size: " & capInfo.InstallSize & " bytes" & If(capInfo.InstallSize >= 1024, " (~" & Converters.BytesToReadableSize(capInfo.InstallSize) & ")", "") & CrLf & CrLf Next Contents &= " - Complete capability information has been gathered" & CrLf & CrLf ElseIf (Not SkipQuestions Or Not AutoCompleteInfo(3)) And MsgBox(msg(1), vbYesNo + vbQuestion, msg(2)) = MsgBoxResult.Yes Then diff --git a/Panels/Get_Ops/Pkgs/GetPkgInfo.vb b/Panels/Get_Ops/Pkgs/GetPkgInfo.vb index 5b00220b..0389683e 100644 --- a/Panels/Get_Ops/Pkgs/GetPkgInfo.vb +++ b/Panels/Get_Ops/Pkgs/GetPkgInfo.vb @@ -732,6 +732,27 @@ Public Class GetPkgInfoDlg cPropContents &= "- " & If(cProp.Path <> "", cProp.Path & "\", "") & cProp.Name & ": " & cProp.Value & CrLf Next PopulateTreeView(cPropPathView, cPropContents.Replace("- ", "").Trim()) + Select Case MainForm.Language + Case 0 + Select Case My.Computer.Info.InstalledUICulture.ThreeLetterWindowsLanguageName + Case "ENU", "ENG" + cPropValue.Text = "Please select or expand an entry." + Case "ESN" + cPropValue.Text = "Por favor, seleccione o expanda una entrada." + Case "FRA" + cPropValue.Text = "Veuillez sélectionner ou étendre une entrée." + Case "PTB", "PTG" + cPropValue.Text = "Por favor, seleccione ou expanda uma entrada." + End Select + Case 1 + cPropValue.Text = "Please select or expand an entry." + Case 2 + cPropValue.Text = "Por favor, seleccione o expanda una entrada." + Case 3 + cPropValue.Text = "Veuillez sélectionner ou étendre une entrée." + Case 4 + cPropValue.Text = "Por favor, seleccione ou expanda uma entrada." + End Select Else Select Case MainForm.Language Case 0 diff --git a/Panels/Img_Ops/AppxPkgs/AddProvAppxPackage.vb b/Panels/Img_Ops/AppxPkgs/AddProvAppxPackage.vb index 2e47b3a8..75411561 100644 --- a/Panels/Img_Ops/AppxPkgs/AddProvAppxPackage.vb +++ b/Panels/Img_Ops/AppxPkgs/AddProvAppxPackage.vb @@ -1882,6 +1882,19 @@ Public Class AddProvAppxPackage End If End Sub + Function GetDownloadedPackageExtensionFromAppInstaller(PkgFile As String) As String + Dim appExtensions() As String = New String(7) {".appx", ".appxbundle", ".msix", ".msixbundle", ".eappx", ".eappxbundle", ".emsix", ".emsixbundle"} + Try + For Each appExtension In appExtensions + Dim targetFile As String = PkgFile.Replace(Path.GetExtension(PkgFile), appExtension) + If File.Exists(targetFile) Then Return appExtension + Next + Catch ex As Exception + Return Nothing + End Try + Return Nothing + End Function + Private Sub ListView1_DragDrop(sender As Object, e As DragEventArgs) Handles ListView1.DragDrop Dim PackageFiles() As String = e.Data.GetData(DataFormats.FileDrop) Cursor = Cursors.WaitCursor @@ -1894,9 +1907,10 @@ Public Class AddProvAppxPackage ElseIf Path.GetExtension(PackageFile).Equals(".appinstaller", StringComparison.OrdinalIgnoreCase) Then If Not AppInstallerDownloader.IsDisposed Then AppInstallerDownloader.Dispose() AppInstallerDownloader.AppInstallerFile = PackageFile - If Not File.Exists(PackageFile.Replace(".appinstaller", ".appxbundle").Trim()) Then AppInstallerDownloader.ShowDialog(Me) - If File.Exists(PackageFile.Replace(".appinstaller", ".appxbundle").Trim()) Then ScanAppxPackage(False, PackageFile.Replace(".appinstaller", ".appxbundle").Trim()) + If Not File.Exists(PackageFile.Replace(".appinstaller", GetDownloadedPackageExtensionFromAppInstaller(PackageFile))) Then AppInstallerDownloader.ShowDialog(Me) + If File.Exists(PackageFile.Replace(".appinstaller", GetDownloadedPackageExtensionFromAppInstaller(PackageFile)).Trim()) Then ScanAppxPackage(False, PackageFile.Replace(".appinstaller", GetDownloadedPackageExtensionFromAppInstaller(PackageFile)).Trim()) ElseIf File.GetAttributes(PackageFile) = FileAttributes.Directory Then + Dim msg As String = "" ' Temporary support for directories If File.Exists(PackageFile & "\AppxSignature.p7x") And File.Exists(PackageFile & "\AppxMetadata\AppxBundleManifest.xml") Or File.Exists(PackageFile & "\AppxManifest.xml") Then ScanAppxPackage(True, PackageFile) @@ -1906,151 +1920,40 @@ Public Class AddProvAppxPackage Case 0 Select Case My.Computer.Info.InstalledUICulture.ThreeLetterWindowsLanguageName Case "ENU", "ENG" - If MsgBox("The following directory:" & CrLf & Quote & PackageFile & Quote & CrLf & "contains application packages. Do you want to process them as well?" & CrLf & CrLf & "NOTE: this will scan this directory recursively, so it may take longer for this operation to complete", vbYesNo + vbQuestion, "Add provisioned AppX packages") = MsgBoxResult.Yes Then - For Each AppPkg In My.Computer.FileSystem.GetFiles(PackageFile, FileIO.SearchOption.SearchAllSubDirectories) - If Path.GetExtension(AppPkg).Equals(".appx", StringComparison.OrdinalIgnoreCase) Or Path.GetExtension(AppPkg).Equals(".appxbundle", StringComparison.OrdinalIgnoreCase) Or _ - Path.GetExtension(AppPkg).Equals(".msix", StringComparison.OrdinalIgnoreCase) Or Path.GetExtension(AppPkg).Equals(".msixbundle", StringComparison.OrdinalIgnoreCase) Then - ScanAppxPackage(False, AppPkg) - ElseIf Path.GetExtension(AppPkg).Equals(".appinstaller", StringComparison.OrdinalIgnoreCase) Then - If Not AppInstallerDownloader.IsDisposed Then AppInstallerDownloader.Dispose() - AppInstallerDownloader.AppInstallerFile = AppPkg - If Not File.Exists(AppPkg.Replace(".appinstaller", ".appxbundle").Trim()) Then AppInstallerDownloader.ShowDialog(Me) - If File.Exists(AppPkg.Replace(".appinstaller", ".appxbundle").Trim()) Then ScanAppxPackage(False, AppPkg.Replace(".appinstaller", ".appxbundle").Trim()) - Else - Continue For - End If - Next - Else - Continue For - End If + msg = "The following directory:" & CrLf & Quote & PackageFile & Quote & CrLf & "contains application packages. Do you want to process them as well?" & CrLf & CrLf & "NOTE: this will scan this directory recursively, so it may take longer for this operation to complete" Case "ESN" - If MsgBox("El siguiente directorio:" & CrLf & Quote & PackageFile & Quote & CrLf & "contiene paquetes de aplicación. ¿Desea procesarlos también?" & CrLf & CrLf & "NOTA: esto escaneará este directorio de una forma recursiva, así que esta operación podría tardar más tiempo en completar", vbYesNo + vbQuestion, "Añadir paquetes aprovisionados AppX") = MsgBoxResult.Yes Then - For Each AppPkg In My.Computer.FileSystem.GetFiles(PackageFile, FileIO.SearchOption.SearchAllSubDirectories) - If Path.GetExtension(AppPkg).Equals(".appx", StringComparison.OrdinalIgnoreCase) Or Path.GetExtension(AppPkg).Equals(".appxbundle", StringComparison.OrdinalIgnoreCase) Or _ - Path.GetExtension(AppPkg).Equals(".msix", StringComparison.OrdinalIgnoreCase) Or Path.GetExtension(AppPkg).Equals(".msixbundle", StringComparison.OrdinalIgnoreCase) Then - ScanAppxPackage(False, AppPkg) - ElseIf Path.GetExtension(AppPkg).Equals(".appinstaller", StringComparison.OrdinalIgnoreCase) Then - If Not AppInstallerDownloader.IsDisposed Then AppInstallerDownloader.Dispose() - AppInstallerDownloader.AppInstallerFile = AppPkg - If Not File.Exists(AppPkg.Replace(".appinstaller", ".appxbundle").Trim()) Then AppInstallerDownloader.ShowDialog(Me) - If File.Exists(AppPkg.Replace(".appinstaller", ".appxbundle").Trim()) Then ScanAppxPackage(False, AppPkg.Replace(".appinstaller", ".appxbundle").Trim()) - Else - Continue For - End If - Next - Else - Continue For - End If + msg = "El siguiente directorio:" & CrLf & Quote & PackageFile & Quote & CrLf & "contiene paquetes de aplicación. ¿Desea procesarlos también?" & CrLf & CrLf & "NOTA: esto escaneará este directorio de una forma recursiva, así que esta operación podría tardar más tiempo en completar" Case "FRA" - If MsgBox("Le répertoire suivant :" & CrLf & Quote & PackageFile & Quote & CrLf & "contient des paquets d'application. Voulez-vous les traiter également ?" & CrLf & CrLf & "REMARQUE : l'analyse de ce répertoire se fera de manière récursive, ce qui peut prolonger la durée de l'opération.", vbYesNo + vbQuestion, "Ajouter des paquets AppX provisionnés") = MsgBoxResult.Yes Then - For Each AppPkg In My.Computer.FileSystem.GetFiles(PackageFile, FileIO.SearchOption.SearchAllSubDirectories) - If Path.GetExtension(AppPkg).Equals(".appx", StringComparison.OrdinalIgnoreCase) Or Path.GetExtension(AppPkg).Equals(".appxbundle", StringComparison.OrdinalIgnoreCase) Or _ - Path.GetExtension(AppPkg).Equals(".msix", StringComparison.OrdinalIgnoreCase) Or Path.GetExtension(AppPkg).Equals(".msixbundle", StringComparison.OrdinalIgnoreCase) Then - ScanAppxPackage(False, AppPkg) - ElseIf Path.GetExtension(AppPkg).Equals(".appinstaller", StringComparison.OrdinalIgnoreCase) Then - If Not AppInstallerDownloader.IsDisposed Then AppInstallerDownloader.Dispose() - AppInstallerDownloader.AppInstallerFile = AppPkg - If Not File.Exists(AppPkg.Replace(".appinstaller", ".appxbundle").Trim()) Then AppInstallerDownloader.ShowDialog(Me) - If File.Exists(AppPkg.Replace(".appinstaller", ".appxbundle").Trim()) Then ScanAppxPackage(False, AppPkg.Replace(".appinstaller", ".appxbundle").Trim()) - Else - Continue For - End If - Next - Else - Continue For - End If + msg = "Le répertoire suivant :" & CrLf & Quote & PackageFile & Quote & CrLf & "contient des paquets d'application. Voulez-vous les traiter également ?" & CrLf & CrLf & "REMARQUE : l'analyse de ce répertoire se fera de manière récursive, ce qui peut prolonger la durée de l'opération." Case "PTB", "PTG" - If MsgBox("O seguinte diretório:" & CrLf & Quote & PackageFile & Quote & CrLf & "contém pacotes de aplicações. Deseja processá-los também?" & CrLf & CrLf & "NOTA: esta operação irá analisar este diretório recursivamente, pelo que poderá demorar mais tempo a ser concluída", vbYesNo + vbQuestion, "Adicionar pacotes AppX provisionados") = MsgBoxResult.Yes Then - For Each AppPkg In My.Computer.FileSystem.GetFiles(PackageFile, FileIO.SearchOption.SearchAllSubDirectories) - If Path.GetExtension(AppPkg).Equals(".appx", StringComparison.OrdinalIgnoreCase) Or Path.GetExtension(AppPkg).Equals(".appxbundle", StringComparison.OrdinalIgnoreCase) Or _ - Path.GetExtension(AppPkg).Equals(".msix", StringComparison.OrdinalIgnoreCase) Or Path.GetExtension(AppPkg).Equals(".msixbundle", StringComparison.OrdinalIgnoreCase) Then - ScanAppxPackage(False, AppPkg) - ElseIf Path.GetExtension(AppPkg).Equals(".appinstaller", StringComparison.OrdinalIgnoreCase) Then - If Not AppInstallerDownloader.IsDisposed Then AppInstallerDownloader.Dispose() - AppInstallerDownloader.AppInstallerFile = AppPkg - If Not File.Exists(AppPkg.Replace(".appinstaller", ".appxbundle").Trim()) Then AppInstallerDownloader.ShowDialog(Me) - If File.Exists(AppPkg.Replace(".appinstaller", ".appxbundle").Trim()) Then ScanAppxPackage(False, AppPkg.Replace(".appinstaller", ".appxbundle").Trim()) - Else - Continue For - End If - Next - Else - Continue For - End If + msg = "O seguinte diretório:" & CrLf & Quote & PackageFile & Quote & CrLf & "contém pacotes de aplicações. Deseja processá-los também?" & CrLf & CrLf & "NOTA: esta operação irá analisar este diretório recursivamente, pelo que poderá demorar mais tempo a ser concluída" End Select Case 1 - If MsgBox("The following directory:" & CrLf & Quote & PackageFile & Quote & CrLf & "contains application packages. Do you want to process them as well?" & CrLf & CrLf & "NOTE: this will scan this directory recursively, so it may take longer for this operation to complete", vbYesNo + vbQuestion, "Add provisioned AppX packages") = MsgBoxResult.Yes Then - For Each AppPkg In My.Computer.FileSystem.GetFiles(PackageFile, FileIO.SearchOption.SearchAllSubDirectories) - If Path.GetExtension(AppPkg).Equals(".appx", StringComparison.OrdinalIgnoreCase) Or Path.GetExtension(AppPkg).Equals(".appxbundle", StringComparison.OrdinalIgnoreCase) Or _ - Path.GetExtension(AppPkg).Equals(".msix", StringComparison.OrdinalIgnoreCase) Or Path.GetExtension(AppPkg).Equals(".msixbundle", StringComparison.OrdinalIgnoreCase) Then - ScanAppxPackage(False, AppPkg) - ElseIf Path.GetExtension(AppPkg).Equals(".appinstaller", StringComparison.OrdinalIgnoreCase) Then - If Not AppInstallerDownloader.IsDisposed Then AppInstallerDownloader.Dispose() - AppInstallerDownloader.AppInstallerFile = AppPkg - If Not File.Exists(AppPkg.Replace(".appinstaller", ".appxbundle").Trim()) Then AppInstallerDownloader.ShowDialog(Me) - If File.Exists(AppPkg.Replace(".appinstaller", ".appxbundle").Trim()) Then ScanAppxPackage(False, AppPkg.Replace(".appinstaller", ".appxbundle").Trim()) - Else - Continue For - End If - Next - Else - Continue For - End If + msg = "The following directory:" & CrLf & Quote & PackageFile & Quote & CrLf & "contains application packages. Do you want to process them as well?" & CrLf & CrLf & "NOTE: this will scan this directory recursively, so it may take longer for this operation to complete" Case 2 - If MsgBox("El siguiente directorio:" & CrLf & Quote & PackageFile & Quote & CrLf & "contiene paquetes de aplicación. ¿Desea procesarlos también?" & CrLf & CrLf & "NOTA: esto escaneará este directorio de una forma recursiva, así que esta operación podría tardar más tiempo en completar", vbYesNo + vbQuestion, "Añadir paquetes aprovisionados AppX") = MsgBoxResult.Yes Then - For Each AppPkg In My.Computer.FileSystem.GetFiles(PackageFile, FileIO.SearchOption.SearchAllSubDirectories) - If Path.GetExtension(AppPkg).Equals(".appx", StringComparison.OrdinalIgnoreCase) Or Path.GetExtension(AppPkg).Equals(".appxbundle", StringComparison.OrdinalIgnoreCase) Or _ - Path.GetExtension(AppPkg).Equals(".msix", StringComparison.OrdinalIgnoreCase) Or Path.GetExtension(AppPkg).Equals(".msixbundle", StringComparison.OrdinalIgnoreCase) Then - ScanAppxPackage(False, AppPkg) - ElseIf Path.GetExtension(AppPkg).Equals(".appinstaller", StringComparison.OrdinalIgnoreCase) Then - If Not AppInstallerDownloader.IsDisposed Then AppInstallerDownloader.Dispose() - AppInstallerDownloader.AppInstallerFile = AppPkg - If Not File.Exists(AppPkg.Replace(".appinstaller", ".appxbundle").Trim()) Then AppInstallerDownloader.ShowDialog(Me) - If File.Exists(AppPkg.Replace(".appinstaller", ".appxbundle").Trim()) Then ScanAppxPackage(False, AppPkg.Replace(".appinstaller", ".appxbundle").Trim()) - Else - Continue For - End If - Next - Else - Continue For - End If + msg = "El siguiente directorio:" & CrLf & Quote & PackageFile & Quote & CrLf & "contiene paquetes de aplicación. ¿Desea procesarlos también?" & CrLf & CrLf & "NOTA: esto escaneará este directorio de una forma recursiva, así que esta operación podría tardar más tiempo en completar" Case 3 - If MsgBox("Le répertoire suivant :" & CrLf & Quote & PackageFile & Quote & CrLf & "contient des paquets d'application. Voulez-vous les traiter également ?" & CrLf & CrLf & "REMARQUE : l'analyse de ce répertoire se fera de manière récursive, ce qui peut prolonger la durée de l'opération.", vbYesNo + vbQuestion, "Ajouter des paquets AppX provisionnés") = MsgBoxResult.Yes Then - For Each AppPkg In My.Computer.FileSystem.GetFiles(PackageFile, FileIO.SearchOption.SearchAllSubDirectories) - If Path.GetExtension(AppPkg).Equals(".appx", StringComparison.OrdinalIgnoreCase) Or Path.GetExtension(AppPkg).Equals(".appxbundle", StringComparison.OrdinalIgnoreCase) Or _ - Path.GetExtension(AppPkg).Equals(".msix", StringComparison.OrdinalIgnoreCase) Or Path.GetExtension(AppPkg).Equals(".msixbundle", StringComparison.OrdinalIgnoreCase) Then - ScanAppxPackage(False, AppPkg) - ElseIf Path.GetExtension(AppPkg).Equals(".appinstaller", StringComparison.OrdinalIgnoreCase) Then - If Not AppInstallerDownloader.IsDisposed Then AppInstallerDownloader.Dispose() - AppInstallerDownloader.AppInstallerFile = AppPkg - If Not File.Exists(AppPkg.Replace(".appinstaller", ".appxbundle").Trim()) Then AppInstallerDownloader.ShowDialog(Me) - If File.Exists(AppPkg.Replace(".appinstaller", ".appxbundle").Trim()) Then ScanAppxPackage(False, AppPkg.Replace(".appinstaller", ".appxbundle").Trim()) - Else - Continue For - End If - Next - Else - Continue For - End If + msg = "Le répertoire suivant :" & CrLf & Quote & PackageFile & Quote & CrLf & "contient des paquets d'application. Voulez-vous les traiter également ?" & CrLf & CrLf & "REMARQUE : l'analyse de ce répertoire se fera de manière récursive, ce qui peut prolonger la durée de l'opération." Case 4 - If MsgBox("O seguinte diretório:" & CrLf & Quote & PackageFile & Quote & CrLf & "contém pacotes de aplicações. Deseja processá-los também?" & CrLf & CrLf & "NOTA: esta operação irá analisar este diretório recursivamente, pelo que poderá demorar mais tempo a ser concluída", vbYesNo + vbQuestion, "Adicionar pacotes AppX provisionados") = MsgBoxResult.Yes Then - For Each AppPkg In My.Computer.FileSystem.GetFiles(PackageFile, FileIO.SearchOption.SearchAllSubDirectories) - If Path.GetExtension(AppPkg).Equals(".appx", StringComparison.OrdinalIgnoreCase) Or Path.GetExtension(AppPkg).Equals(".appxbundle", StringComparison.OrdinalIgnoreCase) Or _ - Path.GetExtension(AppPkg).Equals(".msix", StringComparison.OrdinalIgnoreCase) Or Path.GetExtension(AppPkg).Equals(".msixbundle", StringComparison.OrdinalIgnoreCase) Then - ScanAppxPackage(False, AppPkg) - ElseIf Path.GetExtension(AppPkg).Equals(".appinstaller", StringComparison.OrdinalIgnoreCase) Then - If Not AppInstallerDownloader.IsDisposed Then AppInstallerDownloader.Dispose() - AppInstallerDownloader.AppInstallerFile = AppPkg - If Not File.Exists(AppPkg.Replace(".appinstaller", ".appxbundle").Trim()) Then AppInstallerDownloader.ShowDialog(Me) - If File.Exists(AppPkg.Replace(".appinstaller", ".appxbundle").Trim()) Then ScanAppxPackage(False, AppPkg.Replace(".appinstaller", ".appxbundle").Trim()) - Else - Continue For - End If - Next + msg = "O seguinte diretório:" & CrLf & Quote & PackageFile & Quote & CrLf & "contém pacotes de aplicações. Deseja processá-los também?" & CrLf & CrLf & "NOTA: esta operação irá analisar este diretório recursivamente, pelo que poderá demorar mais tempo a ser concluída" + End Select + If MsgBox(msg, vbYesNo + vbQuestion, Label1.Text) = MsgBoxResult.Yes Then + For Each AppPkg In My.Computer.FileSystem.GetFiles(PackageFile, FileIO.SearchOption.SearchAllSubDirectories) + If Path.GetExtension(AppPkg).Equals(".appx", StringComparison.OrdinalIgnoreCase) Or Path.GetExtension(AppPkg).Equals(".appxbundle", StringComparison.OrdinalIgnoreCase) Or _ + Path.GetExtension(AppPkg).Equals(".msix", StringComparison.OrdinalIgnoreCase) Or Path.GetExtension(AppPkg).Equals(".msixbundle", StringComparison.OrdinalIgnoreCase) Then + ScanAppxPackage(False, AppPkg) + ElseIf Path.GetExtension(AppPkg).Equals(".appinstaller", StringComparison.OrdinalIgnoreCase) Then + If Not AppInstallerDownloader.IsDisposed Then AppInstallerDownloader.Dispose() + AppInstallerDownloader.AppInstallerFile = AppPkg + If Not File.Exists(AppPkg.Replace(".appinstaller", GetDownloadedPackageExtensionFromAppInstaller(AppPkg))) Then AppInstallerDownloader.ShowDialog(Me) + If File.Exists(AppPkg.Replace(".appinstaller", GetDownloadedPackageExtensionFromAppInstaller(AppPkg))) Then ScanAppxPackage(False, AppPkg.Replace(".appinstaller", GetDownloadedPackageExtensionFromAppInstaller(AppPkg))) Else Continue For End If - End Select + Next + Else + Continue For + End If End If Else Select Case MainForm.Language diff --git a/Panels/Img_Ops/AppxPkgs/AppInstallerDownloader.vb b/Panels/Img_Ops/AppxPkgs/AppInstallerDownloader.vb index 70600627..e929c221 100644 --- a/Panels/Img_Ops/AppxPkgs/AppInstallerDownloader.vb +++ b/Panels/Img_Ops/AppxPkgs/AppInstallerDownloader.vb @@ -162,7 +162,7 @@ Public Class AppInstallerDownloader ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 AddHandler Downloader.DownloadProgressChanged, AddressOf WebClient_DownloadProgressChanged AddHandler Downloader.DownloadFileCompleted, AddressOf WebClient_DownloadFileCompleted - Downloader.DownloadFileAsync(New Uri(AppInstallerUri), Path.GetDirectoryName(AppInstallerFile) & "\" & Path.GetFileNameWithoutExtension(AppInstallerFile) & ".appxbundle") + Downloader.DownloadFileAsync(New Uri(AppInstallerUri), Path.GetDirectoryName(AppInstallerFile) & "\" & Path.GetFileNameWithoutExtension(AppInstallerFile) & Path.GetExtension(AppInstallerUri)) End Sub #Region "WebClient event handlers" @@ -197,6 +197,34 @@ Public Class AppInstallerDownloader End Sub Private Sub WebClient_DownloadFileCompleted(sender As Object, e As AsyncCompletedEventArgs) + If e.Error IsNot Nothing Then + Dim msg As String = "" + Select Case Language + Case 0 + Select Case My.Computer.Info.InstalledUICulture.ThreeLetterWindowsLanguageName + Case "ENU", "ENG" + msg = "An error occurred while downloading the file: " & e.Error.Message + Case "ESN" + msg = "Se produjo un error al descargar el archivo: " & e.Error.Message + Case "FRA" + msg = "Une erreur s'est produite lors du téléchargement du fichier : " & e.Error.Message + Case "PTB", "PTG" + msg = "Ocorreu um erro ao baixar o arquivo: " & e.Error.Message + End Select + Case 1 + msg = "An error occurred while downloading the file: " & e.Error.Message + Case 2 + msg = "Se produjo un error al descargar el archivo: " & e.Error.Message + Case 3 + msg = "Une erreur s'est produite lors du téléchargement du fichier : " & e.Error.Message + Case 4 + msg = "Ocorreu um erro ao baixar o arquivo: " & e.Error.Message + End Select + MsgBox(msg, vbOKOnly + vbCritical, "DISMTools") + If File.Exists(Path.GetDirectoryName(AppInstallerFile) & "\" & Path.GetFileNameWithoutExtension(AppInstallerFile) & Path.GetExtension(AppInstallerUri)) Then + File.Delete(Path.GetDirectoryName(AppInstallerFile) & "\" & Path.GetFileNameWithoutExtension(AppInstallerFile) & Path.GetExtension(AppInstallerUri)) + End If + End If Thread.Sleep(500) Close() End Sub diff --git a/README.md b/README.md index 25c8a1c6..9802a315 100644 --- a/README.md +++ b/README.md @@ -14,6 +14,17 @@ DISMTools is a front-end for DISM that lets you manage your Windows Imaging (WIM) files and a whole lot more. +## About this project + +This project was created simply because of the lack of free, open-source, and updated graphical interfaces for DISM. Before this tool was started, these popular UIs were available: + +- [NTLite](https://www.ntlite.com/), which is the most popular offering. This software is free, but puts certain features (like downloading OS and program updates) behind a paywall, so it may not be for you if you are looking for a free, fully-featured program +- [MSMG Toolkit](https://forums.mydigitallife.net/threads/msmg-toolkit.50572/), which is one popular alternative. This is free and open-source (given that it is a script), but it may not be easily accessible for download, and may not be intuitive given its command-line user interface (TUI) +- [DISM GUI](https://github.com/mikecel79/DISMGUI), the first popular, .NET powered GUI that lets you perform a couple of actions with your Windows images. While it is open-source (with its source code available on GitHub), it has not been updated since 2017 +- [DISM++](https://github.com/Chuyu-Team/Dism-Multi-language), another fully-featured, CBS-powered GUI. However, it has not been updated since 2023 and it is not open-source (even though there is a GitHub repository, it is only meant for the website and language translations) + +There are also more GUIs for DISM, but they are way less known, so they are not mentioned here. Given this situation, this project was created to be a viable alternative to NTLite that was free, open-source, easily accessible, and constantly updated. + ## Key features ### Working with projects @@ -32,6 +43,10 @@ The program also supports setting and removing file associations for projects wi With the **online** and **offline installation management modes**, you can easily manage any installation of a modern Windows version. +### Compatibility and performance go hand in hand + +Unlike other user interfaces for DISM that use either the DISM API or the DISM executable, DISMTools uses both, providing great performance to get the information you want from your images and installations quickly, and compatibility, allowing you to use any version of the DISM program, ranging from the Windows 7 version all the way up to the latest versions in Windows 10 and 11, so that your existing command-line workflows are not affected when you move to the graphical interface. + ### An advanced front-end DISMTools isn't just a front-end for DISM, but an advanced one. As you perform tasks with your images and installations, you're presented with rich information and functionality. Here are some examples: @@ -176,7 +191,8 @@ If you want to grab a copy straight from the source code, follow these instructi 1. Begin by either cloning the project or downloading a ZIP of the source code. Go to "Code", and select an option from there 2. Prepare the NuGet packages by running `nugetpkgprep.bat` in the location you cloned the repository to 3. Open the solution in Visual Studio 2012 or later -4. Finally, go to "Build > Build solution", or press CTRL-Shift-B +4. Scroll down on the Solution Explorer until you find `UnpEax`, right-click it and select Build +5. Finally, go to "Build > Build solution", or press CTRL-Shift-B ### Additional startup flags diff --git a/Updater/DISMTools-UCS/MainForm.vb b/Updater/DISMTools-UCS/MainForm.vb index cc4f66e8..92de8ef0 100644 --- a/Updater/DISMTools-UCS/MainForm.vb +++ b/Updater/DISMTools-UCS/MainForm.vb @@ -22,6 +22,7 @@ Public Class MainForm Dim latestVer As String Dim relTag As String Dim needsMigration As Boolean + Dim minNoMig As Version Dim ReleaseDownloader As New WebClient() @@ -209,7 +210,7 @@ Public Class MainForm Using client As New WebClient() ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 Try - client.DownloadFile("https://raw.githubusercontent.com/CodingWonders/DISMTools/" & branch & "/Updater/DISMTools-UCS/update-bin/" & If(branch.Contains("preview"), "preview.ini", "stable.ini"), Application.StartupPath & "\info.ini") + client.DownloadFile("https://raw.githubusercontent.com/CodingWonders/DISMTools/" & branch & "/Updater/DISMTools-UCS/update-bin/" & If(branch.Contains("pre"), "preview.ini", "stable.ini"), Application.StartupPath & "\info.ini") Catch ex As WebException MsgBox("We couldn't fetch the necessary update information. Reason:" & CrLf & ex.Status.ToString(), vbOKOnly + vbCritical, Text) Environment.Exit(1) @@ -225,6 +226,15 @@ Public Class MainForm relTag = Line.Replace("ReleaseTag = ", "").Trim() ElseIf Line.StartsWith("MigrateSettings") Then needsMigration = If(Line.Replace("MigrateSettings = ", "").Trim() = "True", True, False) + ElseIf Line.StartsWith("MinNoMig") Then + Try + Dim minNoMigStr As String = Line.Replace("MinNoMig = ", "").Trim() + minNoMig = New Version(minNoMigStr) + Dim fv As String = FileVersionInfo.GetVersionInfo(Application.StartupPath & "\DISMTools.exe").ProductVersion.ToString() + needsMigration = Not (New Version(fv) >= minNoMig) + Catch ex As Exception + Debug.WriteLine("Could not get minimum version for no migrations") + End Try End If Next Label17.Visible = needsMigration diff --git a/Updater/DISMTools-UCS/update-bin/preview.ini b/Updater/DISMTools-UCS/update-bin/preview.ini index 2d120a0e..f556de21 100644 --- a/Updater/DISMTools-UCS/update-bin/preview.ini +++ b/Updater/DISMTools-UCS/update-bin/preview.ini @@ -1,6 +1,7 @@ [Version] -LatestVer = 0.5.0.2452 -ReleaseTag = v0.5_pre_2452 +LatestVer = 0.5.0.2461 +ReleaseTag = v0.5_pre_2461 [Options] -MigrateSettings = False \ No newline at end of file +MigrateSettings = False +MinNoMig = 0.5.0.2433 \ No newline at end of file diff --git a/Updater/DISMTools-UCS/update-bin/stable.ini b/Updater/DISMTools-UCS/update-bin/stable.ini index 94eaeab4..810df654 100644 --- a/Updater/DISMTools-UCS/update-bin/stable.ini +++ b/Updater/DISMTools-UCS/update-bin/stable.ini @@ -1,6 +1,7 @@ [Version] -LatestVer = 0.4.2.2424 -ReleaseTag = v0.4.2_stable +LatestVer = 0.5.0.2462 +ReleaseTag = v0.5_stable [Options] -MigrateSettings = False \ No newline at end of file +MigrateSettings = False +MinNoMig = 0.5.0.2462 \ No newline at end of file diff --git a/Updater/DISMTools-UCS/update-bin/update.exe b/Updater/DISMTools-UCS/update-bin/update.exe index ea58e037..8e9efd5b 100644 Binary files a/Updater/DISMTools-UCS/update-bin/update.exe and b/Updater/DISMTools-UCS/update-bin/update.exe differ diff --git a/Updater/DISMTools-UCS/verinfo/preview.ini b/Updater/DISMTools-UCS/verinfo/preview.ini index 2d120a0e..f556de21 100644 --- a/Updater/DISMTools-UCS/verinfo/preview.ini +++ b/Updater/DISMTools-UCS/verinfo/preview.ini @@ -1,6 +1,7 @@ [Version] -LatestVer = 0.5.0.2452 -ReleaseTag = v0.5_pre_2452 +LatestVer = 0.5.0.2461 +ReleaseTag = v0.5_pre_2461 [Options] -MigrateSettings = False \ No newline at end of file +MigrateSettings = False +MinNoMig = 0.5.0.2433 \ No newline at end of file diff --git a/Updater/DISMTools-UCS/verinfo/stable.ini b/Updater/DISMTools-UCS/verinfo/stable.ini index 94eaeab4..810df654 100644 --- a/Updater/DISMTools-UCS/verinfo/stable.ini +++ b/Updater/DISMTools-UCS/verinfo/stable.ini @@ -1,6 +1,7 @@ [Version] -LatestVer = 0.4.2.2424 -ReleaseTag = v0.4.2_stable +LatestVer = 0.5.0.2462 +ReleaseTag = v0.5_stable [Options] -MigrateSettings = False \ No newline at end of file +MigrateSettings = False +MinNoMig = 0.5.0.2462 \ No newline at end of file