mirror of
https://github.com/cyanfish/naps2.git
synced 2024-09-20 12:17:37 +03:00
Exe installer verification and better console output
This commit is contained in:
parent
4b6cfb6ffe
commit
a29e69505d
@ -13,6 +13,7 @@ OutputDir=../publish/{#AppVersion}
|
||||
OutputBaseFilename=naps2-{#AppVersion}-{#AppPlatform}
|
||||
Compression=lzma
|
||||
SolidCompression=yes
|
||||
; !arch
|
||||
|
||||
LicenseFile=..\..\LICENSE
|
||||
UninstallDisplayIcon={app}\scanner-app.ico
|
||||
@ -54,11 +55,11 @@ Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{
|
||||
; !files
|
||||
|
||||
; Delete files from old locations in case of upgrade
|
||||
; TODO: Delete from Program Files (x86)?
|
||||
[InstallDelete]
|
||||
Type: files; Name: "{app}\*.exe"
|
||||
Type: files; Name: "{app}\*.exe.config"
|
||||
Type: filesandordirs; Name: "{app}\lib"
|
||||
; !clean32
|
||||
|
||||
[Icons]
|
||||
Name: "{group}\NAPS2"; Filename: "{app}\NAPS2.exe"
|
||||
|
@ -2,7 +2,7 @@ namespace NAPS2.Tools;
|
||||
|
||||
public static class Cli
|
||||
{
|
||||
public static void Run(string command, string args, Dictionary<string, string>? env = null)
|
||||
public static void Run(string command, string args, bool verbose, Dictionary<string, string>? env = null)
|
||||
{
|
||||
var startInfo = new ProcessStartInfo
|
||||
{
|
||||
@ -29,23 +29,26 @@ public static class Cli
|
||||
// TODO: Maybe we forward Console.CancelKeyPress
|
||||
while (!proc.WaitForExit(100))
|
||||
{
|
||||
PrintAll(proc.StandardOutput);
|
||||
PrintAll(proc.StandardError);
|
||||
PrintAll(proc.StandardOutput, verbose);
|
||||
PrintAll(proc.StandardError, true);
|
||||
}
|
||||
PrintAll(proc.StandardOutput);
|
||||
PrintAll(proc.StandardError);
|
||||
PrintAll(proc.StandardOutput, verbose);
|
||||
PrintAll(proc.StandardError, true);
|
||||
if (proc.ExitCode != 0)
|
||||
{
|
||||
throw new Exception($"Command failed: {command} {args}");
|
||||
}
|
||||
}
|
||||
|
||||
private static void PrintAll(StreamReader stream)
|
||||
private static void PrintAll(StreamReader stream, bool forwardToStdout)
|
||||
{
|
||||
string? line;
|
||||
while ((line = stream.ReadLine()) != null)
|
||||
{
|
||||
Console.WriteLine(line);
|
||||
if (forwardToStdout)
|
||||
{
|
||||
Console.WriteLine(line);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -7,7 +7,7 @@ public static class BuildCommand
|
||||
foreach (var config in GetConfigs(opts.What))
|
||||
{
|
||||
Console.WriteLine($"---------- BUILDING CONFIGURATION: {config} ----------");
|
||||
Cli.Run("dotnet", $"build -c {config}");
|
||||
Cli.Run("dotnet", $"build -c {config}", opts.Verbose);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -7,4 +7,7 @@ public class BuildOptions
|
||||
{
|
||||
[Value(0, MetaName = "what", Required = true, HelpText = "all|debug|exe|msi|zip")]
|
||||
public string? What { get; set; }
|
||||
|
||||
[Option('v', "verbose", Required = false, HelpText = "Show full output")]
|
||||
public bool Verbose { get; set; }
|
||||
}
|
@ -4,13 +4,18 @@ namespace NAPS2.Tools.Project.Packaging;
|
||||
|
||||
public static class InnoSetupPackager
|
||||
{
|
||||
public static void PackageExe(PackageInfo packageInfo)
|
||||
public static void PackageExe(PackageInfo packageInfo, bool verbose)
|
||||
{
|
||||
var exePath = packageInfo.GetPath("exe");
|
||||
Console.WriteLine($"Packaging exe installer: {exePath}");
|
||||
|
||||
var innoDefPath = GenerateInnoDef(packageInfo);
|
||||
|
||||
// TODO: Use https://github.com/DomGries/InnoDependencyInstaller for .net dependency
|
||||
var iscc = Environment.ExpandEnvironmentVariables("%PROGRAMFILES(X86)%/Inno Setup 6/iscc.exe");
|
||||
Cli.Run(iscc, $"\"{innoDefPath}\"");
|
||||
Cli.Run(iscc, $"\"{innoDefPath}\"", verbose);
|
||||
|
||||
Console.WriteLine(verbose ? $"Packaged exe installer: {exePath}" : "Done.");
|
||||
}
|
||||
|
||||
private static string GenerateInnoDef(PackageInfo packageInfo)
|
||||
@ -22,6 +27,15 @@ public static class InnoSetupPackager
|
||||
defLines.AppendLine($"#define AppPlatform \"{packageInfo.Platform.PackageName()}\"");
|
||||
template = template.Replace("; !defs", defLines.ToString());
|
||||
|
||||
if (packageInfo.Platform == Platform.Win64)
|
||||
{
|
||||
var arch = new StringBuilder();
|
||||
arch.AppendLine("ArchitecturesInstallIn64BitMode=x64");
|
||||
arch.AppendLine("ArchitecturesAllowed=x64");
|
||||
template = template.Replace("; !arch", arch.ToString());
|
||||
template = template.Replace("; !clean32", @"Type: filesandordirs; Name: ""{commonpf32}\NAPS2""");
|
||||
}
|
||||
|
||||
var fileLines = new StringBuilder();
|
||||
foreach (var pkgFile in packageInfo.Files)
|
||||
{
|
||||
|
@ -13,24 +13,24 @@ public static class PackageCommand
|
||||
// TODO: Allow customizing net version, platform, etc
|
||||
// TODO: The fact that we only have one project config for the app but multiple for the SDK is problematic; things will overwrite each other unless we either pull them explicitly from the right project or have a separate config or normalize things somehow to avoid needing multiple configs
|
||||
var pkgInfo = GetPackageInfo(platform, "InstallerEXE");
|
||||
InnoSetupPackager.PackageExe(pkgInfo);
|
||||
InnoSetupPackager.PackageExe(pkgInfo, opts.Verbose);
|
||||
}
|
||||
if (opts.What == "msi" || opts.What == "all")
|
||||
{
|
||||
var pkgInfo = GetPackageInfo(platform, "InstallerMSI");
|
||||
WixToolsetPackager.PackageMsi(pkgInfo);
|
||||
WixToolsetPackager.PackageMsi(pkgInfo, opts.Verbose);
|
||||
}
|
||||
if (opts.What == "zip" || opts.What == "all")
|
||||
{
|
||||
var pkgInfo = GetPackageInfo(platform, "Standalone");
|
||||
ZipArchivePackager.PackageZip(pkgInfo);
|
||||
ZipArchivePackager.PackageZip(pkgInfo, opts.Verbose);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
private static PackageInfo GetPackageInfo(Platform platform, string preferredConfig)
|
||||
{
|
||||
var pkgInfo = new PackageInfo(platform, VersionHelper.GetProjectVersion("NAPS2.App.WinForms"));
|
||||
var pkgInfo = new PackageInfo(platform, ProjectHelper.GetProjectVersion("NAPS2.App.WinForms"));
|
||||
foreach (var project in new[]
|
||||
{ "NAPS2.Sdk", "NAPS2.Lib.Common", "NAPS2.App.Worker", "NAPS2.App.Console", "NAPS2.App.WinForms" })
|
||||
{
|
||||
|
@ -15,7 +15,10 @@ public class PackageInfo
|
||||
|
||||
public string Version { get; }
|
||||
|
||||
public string FileName => $"naps2-{Version}-{Platform.PackageName()}";
|
||||
public string GetPath(string ext)
|
||||
{
|
||||
return ProjectHelper.GetPackagePath(ext, Platform, Version);
|
||||
}
|
||||
|
||||
public IEnumerable<PackageFile> Files => _files;
|
||||
|
||||
|
@ -11,6 +11,9 @@ public class PackageOptions
|
||||
// TODO: Allow platform combos (e.g. win32+win64)
|
||||
[Option('p', "platform", Required = false, HelpText = "win32|win64|mac|macarm|linux")]
|
||||
public string? Platform { get; set; }
|
||||
|
||||
[Option('v', "verbose", Required = false, HelpText = "Show full output")]
|
||||
public bool Verbose { get; set; }
|
||||
|
||||
// TODO: Add net target (net462/net5/net5-windows etc.)
|
||||
}
|
@ -5,18 +5,20 @@ namespace NAPS2.Tools.Project.Packaging;
|
||||
|
||||
public static class WixToolsetPackager
|
||||
{
|
||||
public static void PackageMsi(PackageInfo pkgInfo)
|
||||
public static void PackageMsi(PackageInfo pkgInfo, bool verbose)
|
||||
{
|
||||
var msiPath = pkgInfo.GetPath("msi");
|
||||
Console.WriteLine($"Packaging msi installer: {msiPath}");
|
||||
var wxsPath = GenerateWxs(pkgInfo);
|
||||
|
||||
var candle = Environment.ExpandEnvironmentVariables("%PROGRAMFILES(X86)%/WiX Toolset v3.11/bin/candle.exe");
|
||||
Cli.Run(candle, $"\"{wxsPath}\" -o \"{Paths.SetupObj}/\"");
|
||||
Cli.Run(candle, $"\"{wxsPath}\" -o \"{Paths.SetupObj}/\"", verbose);
|
||||
|
||||
var wixobjPath = wxsPath.Replace(".wxs", ".wixobj");
|
||||
|
||||
var light = Environment.ExpandEnvironmentVariables("%PROGRAMFILES(X86)%/WiX Toolset v3.11/bin/light.exe");
|
||||
var publishFile = Path.Combine(Paths.Publish, pkgInfo.Version, $"{pkgInfo.FileName}.msi");
|
||||
Cli.Run(light, $"\"{wixobjPath}\" -spdb -ext WixUIExtension -o \"{publishFile}\"");
|
||||
Cli.Run(light, $"\"{wixobjPath}\" -spdb -ext WixUIExtension -o \"{msiPath}\"", verbose);
|
||||
Console.WriteLine(verbose ? $"Packaged msi installer: {msiPath}" : "Done.");
|
||||
}
|
||||
|
||||
private static string GenerateWxs(PackageInfo packageInfo)
|
||||
|
@ -4,9 +4,10 @@ namespace NAPS2.Tools.Project.Packaging;
|
||||
|
||||
public static class ZipArchivePackager
|
||||
{
|
||||
public static void PackageZip(PackageInfo pkgInfo)
|
||||
public static void PackageZip(PackageInfo pkgInfo, bool verbose)
|
||||
{
|
||||
var zipPath = Path.Combine(Paths.Publish, pkgInfo.Version, $"{pkgInfo.FileName}.zip");
|
||||
var zipPath = pkgInfo.GetPath("zip");
|
||||
Console.WriteLine($"Packaging zip archive: {zipPath}");
|
||||
if (File.Exists(zipPath))
|
||||
{
|
||||
File.Delete(zipPath);
|
||||
@ -22,9 +23,24 @@ public static class ZipArchivePackager
|
||||
using var archive = ZipFile.Open(zipPath, ZipArchiveMode.Create);
|
||||
foreach (var file in pkgInfo.Files)
|
||||
{
|
||||
archive.CreateEntryFromFile(file.SourcePath, Path.Combine("App", file.DestPath));
|
||||
var destPath = Path.Combine("App", file.DestPath);
|
||||
if (verbose)
|
||||
{
|
||||
Console.WriteLine($"Compressing {destPath}");
|
||||
}
|
||||
archive.CreateEntryFromFile(file.SourcePath, destPath);
|
||||
}
|
||||
if (verbose)
|
||||
{
|
||||
Console.WriteLine($"Creating Data/");
|
||||
}
|
||||
archive.CreateEntry("Data/");
|
||||
if (verbose)
|
||||
{
|
||||
Console.WriteLine($"Compressing NAPS2.Portable.exe");
|
||||
}
|
||||
archive.CreateEntryFromFile(portableExe, "NAPS2.Portable.exe");
|
||||
|
||||
Console.WriteLine(verbose ? $"Packaged zip archive: {zipPath}" : "Done.");
|
||||
}
|
||||
}
|
@ -2,7 +2,7 @@ using System.Text.RegularExpressions;
|
||||
|
||||
namespace NAPS2.Tools.Project;
|
||||
|
||||
public static class VersionHelper
|
||||
public static class ProjectHelper
|
||||
{
|
||||
public static string GetProjectVersion(string projectName)
|
||||
{
|
||||
@ -19,4 +19,15 @@ public static class VersionHelper
|
||||
}
|
||||
return version;
|
||||
}
|
||||
|
||||
public static string GetDefaultProjectVersion()
|
||||
{
|
||||
return GetProjectVersion("NAPS2.App.WinForms");
|
||||
}
|
||||
|
||||
public static string GetPackagePath(string ext, Platform platform, string? version = null)
|
||||
{
|
||||
version ??= GetProjectVersion("NAPS2.App.WinForms");
|
||||
return Path.Combine(Paths.Publish, version, $"naps2-{version}-{platform.PackageName()}.{ext}");
|
||||
}
|
||||
}
|
@ -5,7 +5,7 @@ public static class TestCommand
|
||||
public static int Run(TestOptions opts)
|
||||
{
|
||||
// TODO: Do we want to test on .net core too?
|
||||
Cli.Run("dotnet", "test -f net462", new()
|
||||
Cli.Run("dotnet", "test -f net462", opts.Verbose, new()
|
||||
{
|
||||
{"NAPS2_TEST_ROOT", Path.Combine(Paths.SolutionRoot, "NAPS2.App.Tests", "bin", "Debug", "net462")}
|
||||
});
|
||||
|
@ -5,4 +5,6 @@ namespace NAPS2.Tools.Project;
|
||||
[Verb("test", HelpText = "Runs the project tests")]
|
||||
public class TestOptions
|
||||
{
|
||||
[Option('v', "verbose", Required = false, HelpText = "Show full output")]
|
||||
public bool Verbose { get; set; }
|
||||
}
|
@ -4,19 +4,21 @@ public class AppDriverRunner : IDisposable
|
||||
{
|
||||
private readonly Process _process;
|
||||
|
||||
public static AppDriverRunner Start()
|
||||
public static AppDriverRunner Start(bool verbose)
|
||||
{
|
||||
return new AppDriverRunner();
|
||||
return new AppDriverRunner(verbose);
|
||||
}
|
||||
|
||||
private AppDriverRunner()
|
||||
private AppDriverRunner(bool verbose)
|
||||
{
|
||||
var path = @"C:\Program Files (x86)\Windows Application Driver\WinAppDriver.exe";
|
||||
// TODO: Wait for successful starting and handle errors (e.g. if the dev doesn't have developer mode on)
|
||||
_process = Process.Start(new ProcessStartInfo
|
||||
{
|
||||
FileName = path,
|
||||
UseShellExecute = false
|
||||
UseShellExecute = false,
|
||||
// TODO: Fix (use Cli.Run from a thread? Or similar)
|
||||
// RedirectStandardOutput = !verbose
|
||||
}) ?? throw new Exception($"Could not start WinAppDriver: {path}");
|
||||
}
|
||||
|
||||
|
25
NAPS2.Tools/Project/Verification/ExeSetupVerifier.cs
Normal file
25
NAPS2.Tools/Project/Verification/ExeSetupVerifier.cs
Normal file
@ -0,0 +1,25 @@
|
||||
namespace NAPS2.Tools.Project.Verification;
|
||||
|
||||
public static class ExeSetupVerifier
|
||||
{
|
||||
public static void Verify(Platform platform, string version, bool verbose)
|
||||
{
|
||||
var exePath = ProjectHelper.GetPackagePath("exe", platform, version);
|
||||
Console.WriteLine($"Starting exe installer: {exePath}");
|
||||
var process = Process.Start(new ProcessStartInfo
|
||||
{
|
||||
FileName = exePath,
|
||||
Arguments = "/SILENT /CLOSEAPPLICATIONS"
|
||||
});
|
||||
if (process == null)
|
||||
{
|
||||
throw new Exception($"Could not start installer: {exePath}");
|
||||
}
|
||||
process.WaitForExit();
|
||||
|
||||
var pfVar = platform == Platform.Win64 ? "%PROGRAMFILES%" : "%PROGRAMFILES(X86)%";
|
||||
var pfPath = Environment.ExpandEnvironmentVariables(pfVar);
|
||||
Verifier.RunVerificationTests(Path.Combine(pfPath, "NAPS2"), verbose);
|
||||
Console.WriteLine(verbose ? $"Verified exe installer: {exePath}" : "Done.");
|
||||
}
|
||||
}
|
17
NAPS2.Tools/Project/Verification/Verifier.cs
Normal file
17
NAPS2.Tools/Project/Verification/Verifier.cs
Normal file
@ -0,0 +1,17 @@
|
||||
namespace NAPS2.Tools.Project.Verification;
|
||||
|
||||
public static class Verifier
|
||||
{
|
||||
public static void RunVerificationTests(string testRoot, bool verbose)
|
||||
{
|
||||
Console.WriteLine($"Running verification tests in: {testRoot}");
|
||||
Cli.Run("dotnet", "test NAPS2.App.Tests -f net462", verbose, new()
|
||||
{
|
||||
{ "NAPS2_TEST_ROOT", testRoot }
|
||||
});
|
||||
if (verbose)
|
||||
{
|
||||
Console.WriteLine($"Ran verification tests in: {testRoot}");
|
||||
}
|
||||
}
|
||||
}
|
@ -5,14 +5,12 @@ public class VerifyCommand
|
||||
public static int Run(VerifyOptions opts)
|
||||
{
|
||||
var platform = PlatformHelper.FromOption(opts.Platform, Platform.Win64);
|
||||
var version = ProjectHelper.GetDefaultProjectVersion();
|
||||
|
||||
var version = VersionHelper.GetProjectVersion("NAPS2.App.WinForms");
|
||||
var basePath = Path.Combine(Paths.Publish, version, $"naps2-{version}-{platform.PackageName()}");
|
||||
|
||||
using var appDriverRunner = AppDriverRunner.Start();
|
||||
using var appDriverRunner = AppDriverRunner.Start(opts.Verbose);
|
||||
if (opts.What == "exe" || opts.What == "all")
|
||||
{
|
||||
// ExeSetupVerifier.Verify()
|
||||
ExeSetupVerifier.Verify(platform, version, opts.Verbose);
|
||||
}
|
||||
if (opts.What == "msi" || opts.What == "all")
|
||||
{
|
||||
@ -20,7 +18,7 @@ public class VerifyCommand
|
||||
}
|
||||
if (opts.What == "zip" || opts.What == "all")
|
||||
{
|
||||
ZipArchiveVerifier.Verify(basePath + ".zip", opts.NoCleanup);
|
||||
ZipArchiveVerifier.Verify(platform, version, opts.NoCleanup, opts.Verbose);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -13,4 +13,7 @@ public class VerifyOptions
|
||||
|
||||
[Option("nocleanup", Required = false, HelpText = "Skip cleaning up temp files")]
|
||||
public bool NoCleanup { get; set; }
|
||||
|
||||
[Option('v', "verbose", Required = false, HelpText = "Show full output")]
|
||||
public bool Verbose { get; set; }
|
||||
}
|
@ -4,17 +4,17 @@ namespace NAPS2.Tools.Project.Verification;
|
||||
|
||||
public class ZipArchiveVerifier
|
||||
{
|
||||
public static void Verify(string zipPath, bool noCleanup)
|
||||
public static void Verify(Platform platform, string version, bool verbose, bool noCleanup)
|
||||
{
|
||||
var zipPath = ProjectHelper.GetPackagePath("zip", platform, version);
|
||||
Console.WriteLine($"Extracting zip archive: {zipPath}");
|
||||
// TODO: We probably want other commands to use unique paths too
|
||||
var extractPath = Path.Combine(Paths.SetupObj, Path.GetRandomFileName());
|
||||
try
|
||||
{
|
||||
ZipFile.ExtractToDirectory(zipPath, extractPath);
|
||||
Cli.Run("dotnet", "test NAPS2.App.Tests -f net462", new()
|
||||
{
|
||||
{ "NAPS2_TEST_ROOT", Path.Combine(extractPath, "App") }
|
||||
});
|
||||
Verifier.RunVerificationTests(Path.Combine(extractPath, "App"), verbose);
|
||||
Console.WriteLine(verbose ? $"Verified zip archive: {zipPath}" : "Done.");
|
||||
}
|
||||
finally
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user