Files
CydandClaude Fable 5 91640dcbf2 XP11: whole suite on net40 — Console + vPOD run on XP SP3 through Win11
The Launcher's XP11 port (8730b9b) now extends to everything: one net40
flavor across Console, vPOD, Contract, and SecureConfig (Newtonsoft.Json
everywhere; the net48/System.Text.Json legs and their #if splits are gone
since nothing consumed them).

Console (net40, single TFM like the Launcher):
- The ~31 BinaryFormatter bitmap blobs in the .resx files became raw
  embedded files under assets/icons/ (extracted byte-faithfully via a
  serialization surrogate — the animated square_throbber.gif survives),
  loaded by Properties.Resources.EmbeddedBitmap/EmbeddedIcon. Reason:
  System.Resources.Extensions' DeserializingResourceReader is net461+
  and cannot load on net40. Strings stay in the .resx.
- IReadOnlyList -> IList in AppRegistry (net45+ interface).

vPOD (net40, single TFM):
- Zip extraction now shares the Launcher's MiniZip.cs (linked source), so
  the diff-test install round-trip exercises it against ZipArchive zips.
- RPC args as JTokens; LaunchApps.json persistence via Newtonsoft;
  Thread.VolatileRead instead of Volatile.Read.

Contract/SecureConfig: net40-only; Client/** (PodManagerConnection) now
ships in the one build. The Launcher package gains
TeslaSecureConfiguration.dll as a dependency of the client half.

Tests: the net48 xunit host loads the net40 assemblies (both CLR4), so
the suite exercises exactly what ships — 106/106 green. Also verified
live: net40 console provisioned, managed, and ran a full RP mission
against net40 vPOD (beacon/passphrase/RSA, 53290 RPC, egg load,
Run/Stop Mission).

Version: 4.11.4.3 across Launcher, Console, and vPOD (vPOD joins the
suite version line; was 1.0.0). Ship the dotNetFx40 redistributable in
Launcher/assets for XP-era pods.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-11 21:01:34 -05:00

60 lines
2.4 KiB
C#

using System;
using System.IO;
namespace TeslaConsole.DiffTests
{
/// <summary>
/// Locates the two assemblies under comparison:
/// * Original - original/TeslaConsole.exe (the lost-source reference baseline)
/// * Recovered - bin/Release/net40/TeslaConsole.exe (freshly built reconstruction;
/// net40 since XP11 — loads fine in this net48 test host, both are CLR4)
/// </summary>
public static class AssemblyPaths
{
public static string RepoRoot { get; } = FindRepoRoot();
public static string OriginalExe { get; } =
Path.Combine(RepoRoot, "original", "TeslaConsole.exe");
// The reconstruction's build output. Release is what README documents; fall
// back to Debug so the suite still runs from either configuration.
public static string RecoveredExe { get; } = FindRecoveredExe();
// The product catalog copied next to the recovered exe.
public static string RecoveredCatalog { get; } =
Path.Combine(Path.GetDirectoryName(RecoveredExe), "RedPlanet", "Apps.xml");
private static string FindRepoRoot()
{
var dir = new DirectoryInfo(AppDomain.CurrentDomain.BaseDirectory);
while (dir != null)
{
if (File.Exists(Path.Combine(dir.FullName, "TeslaConsole.csproj")))
return dir.FullName;
dir = dir.Parent;
}
throw new InvalidOperationException(
"Could not locate repo root (TeslaConsole.csproj) above " +
AppDomain.CurrentDomain.BaseDirectory);
}
private static string FindRecoveredExe()
{
string release = Path.Combine(RepoRoot, "bin", "Release", "net40", "TeslaConsole.exe");
string debug = Path.Combine(RepoRoot, "bin", "Debug", "net40", "TeslaConsole.exe");
// Test whichever build is freshest, so a stale config never silently wins.
string best = null;
DateTime bestTime = DateTime.MinValue;
foreach (var candidate in new[] { release, debug })
{
if (!File.Exists(candidate)) continue;
var t = File.GetLastWriteTimeUtc(candidate);
if (t >= bestTime) { bestTime = t; best = candidate; }
}
// Fall back to the Release path; callers assert existence with a clear message.
return best ?? release;
}
}
}