Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
5 changes: 4 additions & 1 deletion .gitattributes
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
# Auto detect text files and perform LF normalization
* text=auto
*.sh text eol=lf
/pkgsrc.zip filter=lfs diff=lfs merge=lfs -text

# Bundled NuGet package archive must stay as a normal repository file.
# Do not store it through Git LFS, because CI must be able to restore packages during checkout.
tools/build/pkgsrc.bundle -filter -diff -merge -text
2 changes: 1 addition & 1 deletion .github/ISSUE_TEMPLATE/bug.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ Add any other context about the problem here.

DISMTools 0.6.1 and later use DynaLog as a means to write diagnostic information to a log file that you can send to the developers. The log is stored in `<program directory>\Logs`:

- If you are using an installed copy, go to `\Program Files\DISMTools\<Stable or Preview>\logs`
- If you are using an installed copy, go to `\Program Files\DISMTools\logs` for stable builds or `\Program Files\DISMTools\Preview\logs` for preview builds
- If you are using a portable copy, go to `<startup location>\logs`

The file in question is `DT_DynaLog.log`. Attach this log by dropping it below:
Expand Down
2 changes: 1 addition & 1 deletion .github/ISSUE_TEMPLATE/program-exception.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ If you have run into an internal error (program exception), we would like to lea

DISMTools 0.6.1 and later use DynaLog as a means to write diagnostic information to a log file that you can send to the developers. The log is stored in `<program directory>\Logs`:

- If you are using an installed copy, go to `\Program Files\DISMTools\<Stable or Preview>\logs`
- If you are using an installed copy, go to `\Program Files\DISMTools\logs` for stable builds or `\Program Files\DISMTools\Preview\logs` for preview builds
- If you are using a portable copy, go to `<startup location>\logs`

The file in question is `DT_DynaLog.log`. Attach this log by dropping it below:
Expand Down
73 changes: 0 additions & 73 deletions .github/workflows/create-nightly-installer.yaml

This file was deleted.

120 changes: 120 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
name: Build and publish release

on:
push:
branches:
- dt_prerel_*
- dt_rel*
paths-ignore:
- '**/README.md'
- 'res/**'
workflow_dispatch:
inputs:
release_channel:
description: Release channel
required: true
default: stable
type: choice
options:
- stable
- preview
prerelease:
description: Mark the GitHub Release as prerelease
required: true
default: false
type: boolean
draft:
description: Create the GitHub Release as draft
required: true
default: false
type: boolean

permissions:
contents: write

env:
ACTIONS_ALLOW_UNSECURE_COMMANDS: true

jobs:
build-release:
runs-on: windows-latest
steps:
- uses: actions/checkout@v4
with:
submodules: 'true'
lfs: false
fetch-depth: 0

- name: Set up MSBuild
uses: microsoft/Setup-MSBuild@v2

- name: Prepare NuGet packages
shell: pwsh
run: |
if (Test-Path .\tools\build\pkgsrc.bundle) { Get-Item .\tools\build\pkgsrc.bundle | Select-Object FullName, Length }
.\nugetpkgprep.bat

- name: Build application output
shell: pwsh
run: |
$ghAction = "yes"
$solutionDir = "$((Get-Location).Path)\"
$projectDir = "$((Get-Location).Path)\"
$targetDir = (Get-Location).Path + "\bin\Debug\"
iex "$($solutionDir)CheckMissingDlls.ps1"
msbuild DISMTools.vbproj /p:Configuration=Debug /p:DeployOnBuild=true /p:SolutionDir=$solutionDir /p:ProjectDir=$projectDir /p:TargetDir=$targetDir

- name: Build installer output
shell: pwsh
run: |
.\tools\build\BuildInstaller.ps1 `
-BuildOutputPath "${{ github.workspace }}\bin\Debug" `
-CleanFilesDirectory

- name: Verify installer localization payload
shell: pwsh
run: .\tools\build\VerifyInstallerLocalization.ps1

- name: Publish GitHub Release
shell: pwsh
env:
GH_TOKEN: ${{ github.token }}
run: |
$releaseChannel = "${{ github.event.inputs.release_channel }}"
if ([string]::IsNullOrWhiteSpace($releaseChannel)) {
if ("${{ github.ref_name }}" -like "dt_prerel_*") {
$releaseChannel = "preview"
} else {
$releaseChannel = "stable"
}
}

$prereleaseInput = "${{ github.event.inputs.prerelease }}"
$isPrerelease = $false
if ($releaseChannel -eq "preview" -or $prereleaseInput -eq "true") {
$isPrerelease = $true
}

$draftInput = "${{ github.event.inputs.draft }}"
$isDraft = $false
if ($draftInput -eq "true") {
$isDraft = $true
}

.\tools\build\PublishReleaseAsset.ps1 `
-InstallerPath "${{ github.workspace }}\Installer\Output\dt_setup.exe" `
-PortableSourcePath "${{ github.workspace }}\bin\Debug" `
-BranchName "${{ github.ref_name }}" `
-RunNumber "${{ github.run_number }}" `
-RunAttempt "${{ github.run_attempt }}" `
-Sha "${{ github.sha }}" `
-ReleaseChannel $releaseChannel `
-AssetOutputDirectory "${{ github.workspace }}\artifacts\release" `
-Prerelease:$isPrerelease `
-Draft:$isDraft

- name: Upload workflow artifacts
uses: actions/upload-artifact@v4
with:
name: release-assets
path: ${{ github.workspace }}\artifacts\release\*
2 changes: 1 addition & 1 deletion ApplicationEvents.vb
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ Namespace My
Private debounceInterval As TimeSpan = TimeSpan.FromSeconds(2)

Private Sub Start(sender As Object, e As EventArgs) Handles Me.Startup
LocalizationService.Initialize()
DynaLog.LogMessage("Adding startup event handlers...")
AddHandler Microsoft.Win32.SystemEvents.UserPreferenceChanged, AddressOf SysEvts_UserPreferenceChanged
AddHandler Microsoft.Win32.SystemEvents.DisplaySettingsChanging, AddressOf SysEvts_DisplaySettingsChanging
Expand Down Expand Up @@ -184,4 +185,3 @@ Namespace My


End Namespace

15 changes: 15 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -110,3 +110,18 @@ You can work on the following:
## Conclusion

If you follow all these steps and rules, you'll achieve good pull requests, so go on and make your changes!

## Installer language files

Edit installer translations in `Installer\Languages`. Do not edit `Installer\Compiler\Default.isl` for DISMTools text. That file belongs to the bundled Inno Setup compiler runtime.

## Application language files

Application translations are edited in the root `language` folder. The application discovers available languages by reading all `*.ini` files in that folder.

When adding a new language, copy an existing INI file and update `[LanguageFileInformation]` with `LanguageCode` and `LanguageName`. The file name can be chosen freely because the application identifies the language from the metadata inside the file. The application and every utility must keep using the shared `Utilities\Language\LocalizationService.vb` source file. Do not create project specific copies of the localization service.
Keep utility interface sections scoped to the utility, for example `DynaViewer.Designer.Main` or `Updater.Designer.Main`. Do not place unrelated utility windows in the main application section `Designer.Main`.

Keep section names and key names in English. Translate only the values after `=`.

PE Helper localization is exported into a generated Windows installation ISO as one minimal INI for the selected `LanguageCode`. Keep `Helpers\extps1\PE_Helper\PE_Helper.ps1` in sync with the actual localization calls in `PEHelperMainMenu`. The localization validator checks this automatically. Do not copy a complete application language file into the ISO. HotInstall uses its own language files and must not reuse the application INI files.
81 changes: 63 additions & 18 deletions CheckMissingDLLs.ps1
Original file line number Diff line number Diff line change
@@ -1,30 +1,75 @@
if ($ghAction -ne "yes")
{
$SolutionDir = "$((Get-Location).Path)\..\.."
$TargetDir = "$((Get-Location).Path)"
$ErrorActionPreference = "Stop"

function Get-NormalizedDirectoryPath {
param(
[Parameter(Mandatory = $true)]
[string]$Path
)

$fullPath = [System.IO.Path]::GetFullPath($Path)
if (-not $fullPath.EndsWith([System.IO.Path]::DirectorySeparatorChar)) {
$fullPath += [System.IO.Path]::DirectorySeparatorChar
}
return $fullPath
}

if ($ghAction -ne "yes") {
$SolutionDir = "$((Get-Location).Path)\..\.."
$TargetDir = "$((Get-Location).Path)"
}

if (-not (Test-Path ".\bin\Debug"))
{
New-Item "$($SolutionDir)bin\Debug" -ItemType Directory -Force
if ([string]::IsNullOrWhiteSpace($SolutionDir)) {
$SolutionDir = (Get-Location).Path
}

if (-not (Test-Path ".\bin\Debug\System.IO.dll" -PathType Leaf)) {
Copy-Item "$($SolutionDir)\packages\System.IO.4.3.0\lib\net462\System.IO.dll" "$($TargetDir)\System.IO.dll"
if ([string]::IsNullOrWhiteSpace($TargetDir)) {
$TargetDir = Join-Path $SolutionDir "bin\Debug"
}

if (-not (Test-Path ".\bin\Debug\System.Net.Http.dll" -PathType Leaf)) {
Copy-Item "$($SolutionDir)\packages\System.Net.Http.4.3.4\lib\net46\System.Net.Http.dll" "$($TargetDir)\System.Net.Http.dll"
$SolutionDir = Get-NormalizedDirectoryPath -Path $SolutionDir
$TargetDir = [System.IO.Path]::GetFullPath($TargetDir)
$projectFile = Join-Path $SolutionDir "DISMTools.vbproj"

if (-not (Test-Path -LiteralPath $projectFile)) {
throw "DISMTools.vbproj was not found: $projectFile"
}

if (-not (Test-Path ".\bin\Debug\System.Runtime.dll" -PathType Leaf)) {
Copy-Item "$($SolutionDir)\packages\System.Runtime.4.3.0\lib\net462\System.Runtime.dll" "$($TargetDir)\System.Runtime.dll"
New-Item -Path $TargetDir -ItemType Directory -Force | Out-Null

[xml]$projectXml = Get-Content -LiteralPath $projectFile
$namespaceManager = New-Object System.Xml.XmlNamespaceManager($projectXml.NameTable)
$namespaceManager.AddNamespace("msb", "http://schemas.microsoft.com/developer/msbuild/2003")

$hintPathNodes = $projectXml.SelectNodes("//msb:Reference/msb:HintPath", $namespaceManager)
$missingFiles = New-Object System.Collections.Generic.List[string]
$copiedFiles = New-Object System.Collections.Generic.List[string]

foreach ($hintPathNode in $hintPathNodes) {
$relativeHintPath = $hintPathNode.InnerText.Trim()
if ([string]::IsNullOrWhiteSpace($relativeHintPath)) {
continue
}

if (-not $relativeHintPath.EndsWith(".dll", [System.StringComparison]::OrdinalIgnoreCase)) {
continue
}

$sourcePath = Join-Path $SolutionDir $relativeHintPath
if (-not (Test-Path -LiteralPath $sourcePath -PathType Leaf)) {
$missingFiles.Add($relativeHintPath) | Out-Null
continue
}

$targetPath = Join-Path $TargetDir ([System.IO.Path]::GetFileName($sourcePath))
if (-not (Test-Path -LiteralPath $targetPath -PathType Leaf)) {
Copy-Item -LiteralPath $sourcePath -Destination $targetPath -Force
$copiedFiles.Add([System.IO.Path]::GetFileName($sourcePath)) | Out-Null
}
}

if ((-not (Test-Path ".\bin\Debug\System.Security*.dll" -PathType Leaf)) -or ((Get-ChildItem ".\bin\Debug\System.Security*.dll").Count -lt 4)) {
Copy-Item "$($SolutionDir)\packages\System.Security.Cryptography.Algorithms.4.3.0\lib\net463\System.Security.Cryptography.Algorithms.dll" "$($TargetDir)\System.Security.Cryptography.Algorithms.dll"
Copy-Item "$($SolutionDir)\packages\System.Security.Cryptography.Encoding.4.3.0\lib\net46\System.Security.Cryptography.Encoding.dll" "$($TargetDir)\System.Security.Cryptography.Encoding.dll"
Copy-Item "$($SolutionDir)\packages\System.Security.Cryptography.Primitives.4.3.0\lib\net46\System.Security.Cryptography.Primitives.dll" "$($TargetDir)\System.Security.Cryptography.Primitives.dll"
Copy-Item "$($SolutionDir)\packages\System.Security.Cryptography.X509Certificates.4.3.0\lib\net461\System.Security.Cryptography.X509Certificates.dll" "$($TargetDir)\System.Security.Cryptography.X509Certificates.dll"
if ($missingFiles.Count -gt 0) {
$message = "The following referenced DLL files are missing after NuGet restore:" + [Environment]::NewLine + ($missingFiles -join [Environment]::NewLine)
throw $message
}

Write-Host "Checked referenced NuGet DLL files. Copied $($copiedFiles.Count) file(s) to $TargetDir"
Loading