/// <summary> /// Creates the loader that will be needed for loading the application /// </summary> /// <param name="tmpFolder">Where the temp folder is</param> /// <param name="path">The relative path to the application</param> /// <param name="iconLocation">Where the icon is for this application</param> /// <param name="outputFile">Where to put the loader</param> /// <param name="applicationName">The application name</param> /// <returns>If the loader was created</returns> public static LoadCreateStatus CreateLoader(TemporaryFolder tmpFolder, string path, string?iconLocation, string outputFile, string applicationName) { if (OSHelper.ActiveOS != OSPlatform.Windows) { Logger.Warning("Not running on Windows, can't create loader from source"); return(LoadCreateStatus.UnableToCreate); } //TODO: Get based on OS //Get stream of template (contained in zip) var zipStream = LoaderCreator.Assembly.GetManifestResourceStream("TinyUpdate.Binary.LoaderTemplate.Windows.source.zip"); if (zipStream == null) { Logger.Error("Wasn't able to get zip stream, can't create loader"); return(LoadCreateStatus.Failed); } //Extract zip using var templateFolder = tmpFolder.CreateTemporaryFolder(Path.Combine(applicationName, "Loader Template")); var templateZip = new ZipArchive(zipStream, ZipArchiveMode.Read); templateZip.ExtractToDirectory(templateFolder.Location); templateZip.Dispose(); //Drop icon into folder if it exists if (!string.IsNullOrWhiteSpace(iconLocation)) { File.Copy(iconLocation, Path.Combine(templateFolder.Location, "app.ico")); File.WriteAllText(Path.Combine(templateFolder.Location, "app.rc"), "IDI_ICON1 ICON DISCARDABLE \"app.ico\""); } //Change main.cpp var mainFileLocation = Path.Combine(templateFolder.Location, "main.cpp"); var mainFile = File.ReadAllLines(mainFileLocation); var changedContent = false; for (int i = 0; i < mainFile.Length; i++) { if (mainFile[i].Contains("{APPLICATIONLOCATION}")) { mainFile[i] = mainFile[i].Replace("{APPLICATIONLOCATION}", path); changedContent = true; break; } } if (!changedContent) { Logger.Error("Didn't find APPLICATIONLOCATION in main.cpp, can't create loader"); return(LoadCreateStatus.Failed); } File.WriteAllLines(mainFileLocation, mainFile); //Build var toolsFile = GetVsTools(); var cmakeLocation = GetCmake(); if (string.IsNullOrWhiteSpace(toolsFile)) { Logger.Warning("Unable to find VS Tools. Can't create loader"); return(LoadCreateStatus.Failed); } toolsFile += @"\VC\Auxiliary\Build\vcvars64.bat"; if (!File.Exists(toolsFile)) { Logger.Error("Can't see vcvars64.bat file. Do you have the C++ Toolset installed?"); return(LoadCreateStatus.Failed); } if (string.IsNullOrWhiteSpace(cmakeLocation)) { Logger.Warning("Unable to find cmake. Can't create loader"); return(LoadCreateStatus.Failed); } using var buildFolder = templateFolder.CreateTemporaryFolder("cmake-build"); //TODO: Make this OS dependent using var cacheBat = templateFolder.CreateTemporaryFile("processCache.bat"); File.WriteAllLines(cacheBat.Location, new [] { $"@call \"{toolsFile}\"", $"\"{cmakeLocation}\" -DCMAKE_BUILD_TYPE=Release -G \"CodeBlocks - NMake Makefiles\" -S \"{templateFolder}\" -B \"{buildFolder}\"", $"\"{cmakeLocation}\" --build \"{buildFolder}\" --target all" }); var buildProcess = new Process { StartInfo = new ProcessStartInfo("cmd.exe") { Arguments = $"/c \"{cacheBat}\"", UseShellExecute = false, RedirectStandardOutput = true, RedirectStandardError = true } }; //Setup grabbing output for us if needed using var buildLog = templateFolder.CreateTemporaryFile(DateTime.Now.ToFileName() + ".log"); var buildLogStream = buildLog.GetTextStream(); buildProcess.OutputDataReceived += (sender, args) => buildLogStream.WriteLineAsync(args.Data); buildProcess.ErrorDataReceived += (sender, args) => buildLogStream.WriteLineAsync(args.Data); //Build buildProcess.Start(); buildProcess.BeginOutputReadLine(); buildProcess.BeginErrorReadLine(); //Wait buildProcess.WaitForExit(); buildLog.Dispose(); if (buildProcess.ExitCode != 0) { Logger.Error("Failed to create loader"); Logger.Error(File.ReadAllText(buildLog.Location)); return(LoadCreateStatus.Failed); } File.Move(Path.Combine(buildFolder.Location, "ApplicationLoader.exe"), outputFile); return(LoadCreateStatus.Successful); }