using System; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Text; using System.Windows.Forms; namespace MrTrust { internal static class MrTrustLauncher { private const string PayloadResourcePrefix = "MrTrust.Payload."; private static readonly PayloadFile[] PayloadFiles = { new PayloadFile("MrTrust.ps1", "MrTrust.ps1"), new PayloadFile("scripts.Build-MrTrustExe.ps1", Path.Combine("scripts", "Build-MrTrustExe.ps1")), new PayloadFile("scripts.Install-MrTrust.ps1", Path.Combine("scripts", "Install-MrTrust.ps1")), new PayloadFile("scripts.New-MrTrustCertificate.ps1", Path.Combine("scripts", "New-MrTrustCertificate.ps1")), new PayloadFile("scripts.New-MrTrustIcon.ps1", Path.Combine("scripts", "New-MrTrustIcon.ps1")), new PayloadFile("scripts.New-MrTrustRelease.ps1", Path.Combine("scripts", "New-MrTrustRelease.ps1")), new PayloadFile("scripts.Sign-MrTrustProject.ps1", Path.Combine("scripts", "Sign-MrTrustProject.ps1")), new PayloadFile("scripts.Sign-MrTrustProjectLinux.sh", Path.Combine("scripts", "Sign-MrTrustProjectLinux.sh")), new PayloadFile("scripts.Start-MrTrustGui.ps1", Path.Combine("scripts", "Start-MrTrustGui.ps1")), new PayloadFile("scripts.Uninstall-MrTrust.ps1", Path.Combine("scripts", "Uninstall-MrTrust.ps1")), new PayloadFile("assets.MrTrust.ico", Path.Combine("assets", "MrTrust.ico")), new PayloadFile("assets.certificates.MrSphay-LocalTrust-Root.cer", Path.Combine("assets", "certificates", "MrSphay-LocalTrust-Root.cer")), new PayloadFile("assets.certificates.MrSphay-CodeSigning.cer", Path.Combine("assets", "certificates", "MrSphay-CodeSigning.cer")), new PayloadFile("assets.certificates.thumbprints.txt", Path.Combine("assets", "certificates", "thumbprints.txt")) }; [STAThread] private static int Main(string[] args) { string baseDirectory = string.Empty; try { baseDirectory = ExtractPayload(); string scriptPath = Path.Combine(baseDirectory, "MrTrust.ps1"); string commandArguments = BuildCommandArguments(args); ProcessStartInfo startInfo = new ProcessStartInfo { FileName = "powershell.exe", Arguments = "-NoProfile -ExecutionPolicy Bypass -File " + QuoteArgument(scriptPath) + " " + commandArguments, UseShellExecute = false, CreateNoWindow = true, WorkingDirectory = baseDirectory }; using (Process process = Process.Start(startInfo)) { if (process == null) { throw new InvalidOperationException("PowerShell could not be started."); } process.WaitForExit(); return process.ExitCode; } } catch (Exception ex) { MessageBox.Show( ex.Message, "MrTrust", MessageBoxButtons.OK, MessageBoxIcon.Error); return 1; } finally { TryDeleteDirectory(baseDirectory); } } private static string ExtractPayload() { Assembly assembly = Assembly.GetExecutingAssembly(); string versionKey = GetPayloadVersionKey(assembly); string targetDirectory = Path.Combine( Path.GetTempPath(), "MrTrust", "standalone", versionKey, Guid.NewGuid().ToString("N")); foreach (PayloadFile payloadFile in PayloadFiles) { string targetPath = Path.Combine(targetDirectory, payloadFile.RelativePath); string targetParent = Path.GetDirectoryName(targetPath); if (!string.IsNullOrEmpty(targetParent)) { Directory.CreateDirectory(targetParent); } using (Stream stream = assembly.GetManifestResourceStream(PayloadResourcePrefix + payloadFile.ResourceName)) { if (stream == null) { throw new FileNotFoundException("Embedded MrTrust payload file was not found.", payloadFile.RelativePath); } using (FileStream file = File.Create(targetPath)) { stream.CopyTo(file); } } } return targetDirectory; } private static void TryDeleteDirectory(string directory) { if (string.IsNullOrEmpty(directory) || !Directory.Exists(directory)) { return; } try { Directory.Delete(directory, true); } catch { // Best-effort cleanup only. A locked icon or antivirus scan should not mask the command result. } } private static string GetPayloadVersionKey(Assembly assembly) { string location = Application.ExecutablePath; if (File.Exists(location)) { FileInfo fileInfo = new FileInfo(location); return fileInfo.Length.ToString("x") + "-" + fileInfo.LastWriteTimeUtc.Ticks.ToString("x"); } return assembly.GetName().Version.ToString(); } private static string BuildCommandArguments(string[] args) { string[] effectiveArgs = args.Length == 0 ? new[] { "gui" } : args; return string.Join(" ", effectiveArgs.Select(QuoteArgument).ToArray()); } private static string QuoteArgument(string value) { if (string.IsNullOrEmpty(value)) { return "\"\""; } if (value.IndexOfAny(new[] { ' ', '\t', '\n', '\r', '"' }) < 0) { return value; } StringBuilder builder = new StringBuilder(); builder.Append('"'); foreach (char character in value) { if (character == '"') { builder.Append('\\'); } builder.Append(character); } builder.Append('"'); return builder.ToString(); } private sealed class PayloadFile { public PayloadFile(string resourceName, string relativePath) { ResourceName = resourceName; RelativePath = relativePath; } public string ResourceName { get; private set; } public string RelativePath { get; private set; } } } }