| File: src\Shared\WindowsTrayPayload.cs | Web Access |
| Project: src\src\Aspire.Cli\Aspire.Cli.csproj (aspire) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System.Reflection.PortableExecutable; namespace Aspire.Shared; /// <summary> /// Validates the Windows tray payload before packaging and before launching it. /// </summary> internal static class WindowsTrayPayload { internal const string ExecutableName = "aspire-tray.exe"; internal const string IconName = "Aspire.ico"; internal const string ExecutablePath = "tray/aspire-tray.exe"; internal static void Validate(string directory, string rid) { var machine = rid switch { "win-x64" => Machine.Amd64, "win-arm64" => Machine.Arm64, _ => throw new InvalidDataException($"Unsupported Windows tray RID: {rid}.") }; foreach (var name in new[] { ExecutableName, IconName }) { var path = Path.Combine(directory, name); if (!File.Exists(path) || new FileInfo(path).Length == 0) { throw new InvalidDataException($"Required Windows tray payload is missing or empty: {path}."); } } // Read the PE/COFF machine and optional header, not the directory name: a // stale or overridden publish directory can contain another architecture. // https://learn.microsoft.com/windows/win32/debug/pe-format using var stream = File.OpenRead(Path.Combine(directory, ExecutableName)); using var reader = new PEReader(stream); var headers = reader.PEHeaders; if (headers.CoffHeader.Machine != machine || headers.PEHeader?.Magic != PEMagic.PE32Plus || headers.PEHeader.Subsystem != Subsystem.WindowsGui || headers.CorHeader is not null || (headers.CoffHeader.Characteristics & Characteristics.Dll) != 0) { throw new InvalidDataException($"Windows tray payload must be a native WinExe for {rid}."); } } }