public bool Run(string[] args, XtallStrategy strategy = null) { _args = args; _options = new Options(args); _strategy = strategy ?? new XtallStrategy(); try { _strategy.LogStatus("starting with command line: {0}", string.Join(" ", args)); if (_options.Keyed.Keys.Contains("uninstall:")) { Uninstall(_options.Keyed["uninstall:"]); return false; } if (_options.Loose.Count == 0) throw new ArgumentException("Site URL was not specified on the command line"); _strategy.InternalContext.Url = _options.Loose[0]; var @unsafe = true; // TODO get the strategy to handle this new Uri(_strategy.Context.Url).Scheme != "https"; // TODO: block unsafe unless environment is set up for it if (_options.Keyed.ContainsKey("debug:")) { _strategy.LogStatus("debug requested from the command line; no cache management will be used"); _strategy.InternalContext.Manifest = ManifestManager.Load(File.ReadAllText(_options.Keyed["debug:"])); _strategy.OnVerified(); _strategy.OnStatus("Debugging", 1.0); _strategy.OnSuccess(); } else { _strategy.OnStatus("Connecting and verifying", 0); if (!@unsafe) { _strategy.LogAction("setting the certificate validator"); ServicePointManager.CheckCertificateRevocationList = true; ServicePointManager.ServerCertificateValidationCallback = CheckServerCertificate; } else { _strategy.LogStatus("skipping server authentication checks"); } _strategy.LogAction("getting the manifest"); string manifestXml; using (var ms = new MemoryStream()) { _strategy.GetResource(_strategy.Context.Url + "/info", ms, t => t.StartsWith("text/xml")); ms.Seek(0, SeekOrigin.Begin); using (var sr = new StreamReader(ms)) manifestXml = sr.ReadToEnd(); } _strategy.LogAction("loading the manifest (first 100 characters are '{0}')", manifestXml.Substring(0, 100)); _strategy.InternalContext.Manifest = ManifestManager.Load(manifestXml); _strategy.LogAction("creating a code cache manager"); using (var cacheManager = new CodeCacheManager(_strategy)) { _strategy.LogAction("ensuring the boot package"); var candidate = Assembly.GetEntryAssembly().Location; var bootPath = cacheManager.EnsureBoot(candidate); if (bootPath == null) { _strategy.LogStatus("current process is the appropriate boot process"); _strategy.OnVerified(); _strategy.OnStatus("Loading", 0); UpdateInstall(cacheManager, candidate, _options.Keyed.Keys.Contains("install")); cacheManager.EnsureManifest(); _strategy.OnStatus("Loaded", 1.0); _strategy.OnSuccess(); } else { _strategy.LogStatus("current process is not executing the required image"); _strategy.LogAction("switching to image '{0}'", bootPath); _strategy.OnStatus("Transferring", 0); using (var p = Process.Start(bootPath, string.Join(" ", _args.Select(x => '"' + x + '"')))) { } _strategy.OnTransfer(); } } } } catch (Exception ex) { _strategy.OnFailure(ex); } return _strategy.WaitToProceed(); }
// USAGE: preparealloyassets -source: file_source_folder -boot: boot_file_path [-passenger: passenger_file_path] [-pfx: pfx_file_path] [-ignore: ignore_regex] [-gzip] [-icon: icon_file_path] [-product: name] [-menupath: path] output_folder static void Main(string[] args) { try { Log("Preparing manifest with args '{0}'", string.Join(" ", args)); var options = new Options(args); if (options.Loose.Count != 1) throw new ArgumentException("Must specify exactly one output folder."); var outputPath = options.Loose[0]; if (!options.Keyed.ContainsKey("source:")) throw new ArgumentException("Must specify the file source folder (-source: file_source_folder)."); if (!options.Keyed.ContainsKey("boot:")) throw new ArgumentException("Must specify the boot file (-boot: boot_file_path)."); var gzip = options.Keyed.ContainsKey("gzip"); // prepare manifest using the source folder var sourceFolder = options.Keyed["source:"]; Log("Preparing manifest using source folder '{0}'", sourceFolder); var prepared = ManifestManager.Prepare(sourceFolder, options.Keyed["boot:"], options.Keyed["product:"], options.Keyed["menupath:"], ignore: options.Keyed["ignore:"]); // write manifest output Directory.CreateDirectory(outputPath); var manifestPath = Path.Combine(outputPath, "manifest.xml"); Log("Writing output '{0}'", manifestPath); var writer = XmlWriter.Create(manifestPath); writer.WriteStartDocument(); ManifestManager.Write(writer, prepared); writer.WriteEndDocument(); writer.Close(); // move and prepare all files... var rawFolder = Path.Combine(outputPath, "raw"); CleanFolder("uncompressed", rawFolder); var gzipFolder = Path.Combine(outputPath, "gzip"); CleanFolder("gzip", gzipFolder); foreach (var file in prepared.Files) { var sourcePath = Path.Combine(sourceFolder, file.Filename); var rawPath = Path.Combine(rawFolder, file.Filename); var gzipPath = Path.Combine(gzipFolder, file.Filename + ".gzip"); using (var sourcefile = File.OpenRead(sourcePath)) { Log("Copying '{0}' to '{1}'", sourcePath, rawPath); Directory.CreateDirectory(Path.GetDirectoryName(rawPath)); using (var rawfile = File.Open(rawPath, FileMode.OpenOrCreate, FileAccess.Write, FileShare.None)) sourcefile.CopyTo(rawfile); sourcefile.Position = 0; if (gzip) { Log("GZipping '{0}' to '{1}'", sourcePath, gzipPath); Directory.CreateDirectory(Path.GetDirectoryName(gzipPath)); using (var gzipped = File.Open(gzipPath, FileMode.OpenOrCreate, FileAccess.Write, FileShare.None)) using (var compressor = new GZipStream(gzipped, CompressionMode.Compress, CompressionLevel.BestCompression)) sourcefile.CopyTo(compressor); } } } // prepare the shuttle using (var shuttleStream = Assembly.GetExecutingAssembly().GetManifestResourceStream("Xtall.XtallShuttle.exe")) { var setup = Path.Combine(outputPath, "setup.exe"); using (var setupStream = File.Create(setup)) { shuttleStream.CopyTo(setupStream); } string passengerFile; if (options.Keyed.ContainsKey("passenger:")) passengerFile = options.Keyed["passenger:"]; else passengerFile = options.Keyed["boot:"]; var passenger = File.ReadAllBytes(Path.Combine(sourceFolder, passengerFile)); var pin = GCHandle.Alloc(passenger, GCHandleType.Pinned); var handle = BeginUpdateResource(setup, false); // TODO test and feedback UpdateResource(handle, "EXE", "IDR_PASSENGER", 0, pin.AddrOfPinnedObject(), (uint) passenger.Length); EndUpdateResource(handle, false); using (var s = new FileStream(setup, FileMode.Append, FileAccess.Write)) using (var bw = new BinaryWriter(s)) { const int luggageSpace = 1024; bw.Write(new byte[luggageSpace]); bw.Write((int)0x42000042); // parameter space signature bw.Write((int) 0); bw.Write((int) luggageSpace + Marshal.SizeOf(luggageSpace)*3); } } } catch (Exception x) { Console.Error.WriteLine("error: {0}\r\n{1}", x.Message, x); Environment.ExitCode = 1; } }