Skip to content

Commit 7a173ff

Browse files
committed
added windows app sdk fetching and bundling into the installer
1 parent da29411 commit 7a173ff

File tree

4 files changed

+74
-8
lines changed

4 files changed

+74
-8
lines changed

Installer/Program.cs

+34-8
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,9 @@ public class BootstrapperOptions : SharedOptions
116116
[Option('m', "msi-path", Required = true, HelpText = "Path to the MSI package to embed")]
117117
public string MsiPath { get; set; }
118118

119+
[Option('w', "windows-app-sdk-path", Required = true, HelpText = "Path to the Windows App Sdk package to embed")]
120+
public string WindowsAppSdkPath { get; set; }
121+
119122
public new void Validate()
120123
{
121124
base.Validate();
@@ -124,6 +127,8 @@ public class BootstrapperOptions : SharedOptions
124127
throw new ArgumentException($"Logo PNG file not found at '{LogoPng}'", nameof(LogoPng));
125128
if (!SystemFile.Exists(MsiPath))
126129
throw new ArgumentException($"MSI package not found at '{MsiPath}'", nameof(MsiPath));
130+
if (!SystemFile.Exists(WindowsAppSdkPath))
131+
throw new ArgumentException($"Windows App Sdk package not found at '{WindowsAppSdkPath}'", nameof(WindowsAppSdkPath));
127132
}
128133
}
129134

@@ -337,16 +342,16 @@ private static int BuildBundle(BootstrapperOptions opts)
337342
{
338343
opts.Validate();
339344

340-
if (!DotNetRuntimePackagePayloads.TryGetValue(opts.Platform, out var payload))
345+
if (!DotNetRuntimePackagePayloads.TryGetValue(opts.Platform, out var dotNetRuntimePayload))
341346
throw new ArgumentException($"Invalid architecture '{opts.Platform}' specified", nameof(opts.Platform));
342347

343-
// TODO: it would be nice to include the WindowsAppRuntime but
344-
// Microsoft makes it difficult to check from a regular
345-
// installer:
346-
// https://learn.microsoft.com/en-us/windows/apps/windows-app-sdk/check-windows-app-sdk-versions
347-
// https://github.com/microsoft/WindowsAppSDK/discussions/2437
348+
var windowsAppSdkPaylod = new ExePackagePayload
349+
{
350+
SourceFile = opts.WindowsAppSdkPath
351+
};
352+
348353
var bundle = new Bundle(ProductName,
349-
new ExePackage
354+
new ExePackage // .NET Runtime
350355
{
351356
PerMachine = true,
352357
// Don't uninstall the runtime when the bundle is uninstalled.
@@ -362,7 +367,28 @@ private static int BuildBundle(BootstrapperOptions opts)
362367
// anyway. The MSI will fatally exit if the runtime really isn't
363368
// available, and the user can install it themselves.
364369
Vital = false,
365-
Payloads = [payload],
370+
Payloads = [dotNetRuntimePayload],
371+
},
372+
// TODO: right now we are including the Windows App Sdk in the bundle
373+
// and always install it
374+
// Microsoft makes it difficult to check if it exists from a regular installer:
375+
// https://learn.microsoft.com/en-us/windows/apps/windows-app-sdk/check-windows-app-sdk-versions
376+
// https://github.com/microsoft/WindowsAppSDK/discussions/2437
377+
new ExePackage // Windows App Sdk
378+
{
379+
PerMachine = true,
380+
Permanent = true,
381+
Cache = PackageCacheAction.remove,
382+
// There is no license agreement for this SDK.
383+
InstallArguments = "--quiet",
384+
Vital = false,
385+
Payloads =
386+
[
387+
new ExePackagePayload
388+
{
389+
SourceFile = opts.WindowsAppSdkPath
390+
}
391+
],
366392
},
367393
new MsiPackage(opts.MsiPath)
368394
{

scripts/Get-WindowsAppSdk.ps1

+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
# Usage: Get-WindowsAppSdk.ps1 -arch <x64|arm64>
2+
param (
3+
[ValidateSet("x64", "arm64")]
4+
[Parameter(Mandatory = $true)]
5+
[string] $arch
6+
)
7+
8+
function Download-File([string] $url, [string] $outputPath, [string] $etagFile) {
9+
Write-Host "Downloading '$url' to '$outputPath'"
10+
# We use `curl.exe` here because `Invoke-WebRequest` is notoriously slow.
11+
& curl.exe `
12+
--progress-bar `
13+
-v `
14+
--show-error `
15+
--fail `
16+
--location `
17+
--etag-compare $etagFile `
18+
--etag-save $etagFile `
19+
--output $outputPath `
20+
$url
21+
if ($LASTEXITCODE -ne 0) { throw "Failed to download $url" }
22+
if (!(Test-Path $outputPath) -or (Get-Item $outputPath).Length -eq 0) {
23+
throw "Failed to download '$url', output file '$outputPath' is missing or empty"
24+
}
25+
}
26+
27+
# Download the Windows App Sdk binary from Microsoft for this platform if we don't have
28+
# it yet (or it's different).
29+
$windowsAppSdkMajorVersion = "1.6"
30+
$windowsAppSdkFullVersion = "1.6.250228001"
31+
$windowsAppSdkPath = Join-Path $PSScriptRoot "files\windows-app-sdk-$($arch).exe"
32+
$windowsAppSdkUri = "https://aka.ms/windowsappsdk/$($windowsAppSdkMajorVersion)/$($windowsAppSdkFullVersion)/windowsappruntimeinstall-$($arch).exe"
33+
$windowsAppSdkEtagFile = $windowsAppSdkPath + ".etag"
34+
Download-File $windowsAppSdkUri $windowsAppSdkPath $windowsAppSdkEtagFile

scripts/Publish.ps1

+5
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,10 @@ Copy-Item $mutagenAgentsSrcPath $mutagenAgentsDestPath
175175
if ($LASTEXITCODE -ne 0) { throw "Failed to build MSI" }
176176
Add-CoderSignature $msiOutputPath
177177

178+
$getWindowsAppSdk = Join-Path $scriptRoot "Get-WindowsAppSdk.ps1"
179+
& $getWindowsAppSdk -arch $arch
180+
$windowsAppSdkPath = Join-Path $scriptRoot "files\windows-app-sdk-$($arch).exe"
181+
178182
# Build the bootstrapper
179183
& dotnet.exe run --project .\Installer\Installer.csproj -c Release -- `
180184
build-bootstrapper `
@@ -184,6 +188,7 @@ Add-CoderSignature $msiOutputPath
184188
--output-path $outputPath `
185189
--icon-file "App\coder.ico" `
186190
--msi-path $msiOutputPath `
191+
--windows-app-sdk-path $windowsAppSdkPath `
187192
--logo-png "scripts\files\logo.png"
188193
if ($LASTEXITCODE -ne 0) { throw "Failed to build bootstrapper" }
189194

scripts/files/.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
mutagen-*.tar.gz
22
mutagen-*.exe
33
*.etag
4+
windows-app-sdk-*.exe

0 commit comments

Comments
 (0)