Example #1
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="Archive"></param>
        /// <param name="OutputFolder"></param>
        /// <returns></returns>
        public static bool UnpackArchive(string ArchivePath, string OutputFolder, ScriptBuildProgressDelegate ProgressCallback = null)
        {
            string installLocation = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location);
            string sevenZipPath    = Path.Combine(Path.Combine(Path.Combine(installLocation, "Libraries"), "7zip"), "7za.exe");

            ProgressParser Parser = new ProgressParser();

            Parser.ParsePartialLines = false;
            Parser.LineSeperator     = "\r";
            Parser.AddPattern(@"^\s+(\d+)\% \- (.+)$",
                              new ProgressMatch(ProgressMatchType.Progress, ProgressMatchFormat.Float, 100),
                              new ProgressMatch(ProgressMatchType.CurrentFileName, ProgressMatchFormat.String));

            ScriptBuildOutputCallbackDelegate OutputCallback = (string Line) =>
            {
                Parser.Parse(Line);
                ProgressCallback?.Invoke("Decompressing " + Parser.CurrentFileName + "...", Parser.Progress);
            };

            int exitCode = RunAndWait(sevenZipPath, installLocation, "x \"" + ArchivePath + "\" -o\"" + OutputFolder + "\" -r -y -bsp1", OutputCallback);

            return(exitCode == 0);

            /*
             *
             * // SharpCompress is waaaaaaaaaaaaaaaaaaaaaaaaaaaaaay to slow :|
             * try
             * {
             *  using (IArchive Archive = ArchiveFactory.Open(ArchivePath))
             *  {
             *      int BufferLength = 1 * 1024 * 1024;
             *      byte[] Buffer = new byte[BufferLength];
             *
             *      long TotalUncompressed = Archive.TotalUncompressSize;
             *      long Uncompressed = 0;
             *
             *      foreach (IArchiveEntry Entry in Archive.Entries.Where(entry => !entry.IsDirectory))
             *      {
             *          using (Stream ArchiveStream = Entry.OpenEntryStream())
             *          {
             *              using (FileStream FileStream = new FileStream(OutputFolder + @"\" + Entry.Key, FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite))
             *              {
             *                  int BytesRead = 0;
             *                  while ((BytesRead = ArchiveStream.Read(Buffer, 0, Buffer.Length)) > 0)
             *                  {
             *                      FileStream.Write(Buffer, 0, BytesRead);
             *                      Uncompressed += BytesRead;
             *
             *                      float Progress = (float)Uncompressed / (float)TotalUncompressed;
             *                      ProgressCallback?.Invoke("Unpacking " + Entry.Key + "...", Progress);
             *                  }
             *              }
             *          }
             *      }
             *  }
             * }
             * catch (Exception Ex) // Should be more specific, but sharpcompress has so little documentation and looking through the code there are so many potential exceptions...
             * {
             *  Logger.Log(LogLevel.Error, LogCategory.Script, "Failed to extract archive with error: {0}", Ex.Message.ToString());
             *  return false;
             * }
             *
             * return true;
             */
        }
Example #2
0
        /// <summary>
        ///     Runs a process (executed via shell) with the given arguments and waits for it to finish.
        /// </summary>
        /// <param name="ExePath">Path to exe or command to run</param>
        /// <param name="WorkingDirectory">Directory to execute command within.</param>
        /// <param name="Arguments">Arguments to pass to command.</param>
        /// <returns>Exit code returned by the process. If process fails to start -1 is returned.</returns>
        public static int RunAndWait(string ExePath, string WorkingDirectory, string Arguments, ScriptBuildOutputCallbackDelegate OutputCallback = null)
        {
            Logger.Log(LogLevel.Info, LogCategory.Script, "Running (and waiting for result) '{0}' in '{1}' with arguments '{2}'.", ExePath, WorkingDirectory, Arguments);

            try
            {
                ProcessStartInfo StartInfo = new ProcessStartInfo();
                StartInfo.FileName               = ExePath;
                StartInfo.WorkingDirectory       = WorkingDirectory;
                StartInfo.Arguments              = Arguments;
                StartInfo.RedirectStandardOutput = true;
                StartInfo.RedirectStandardError  = true;
                StartInfo.UseShellExecute        = false;
                StartInfo.CreateNoWindow         = true;

                Process process = Process.Start(StartInfo);
                ChildProcessTracker.AddProcess(process);

                /*process.OutputDataReceived += delegate (object sender, DataReceivedEventArgs e)
                 * {
                 *  OutputLineBuilder.Add(e.Data);
                 *  while (true)
                 *  {
                 *      string Line = OutputLineBuilder.Read();
                 *      if (Line == null)
                 *      {
                 *          break;
                 *      }
                 *      Logger.Log(LogLevel.Info, LogCategory.Main, "{0}", Line);
                 *  }
                 *
                 *  OutputCallback?.Invoke(e.Data);
                 * };
                 * process.ErrorDataReceived += delegate (object sender, DataReceivedEventArgs e)
                 * {
                 *  while (true)
                 *  {
                 *      string Line = ErrorLineBuilder.Read();
                 *      if (Line == null)
                 *      {
                 *          break;
                 *      }
                 *      Logger.Log(LogLevel.Info, LogCategory.Main, "{0}", Line);
                 *  }
                 *
                 *  OutputCallback?.Invoke(e.Data);
                 * };
                 *
                 * //process.BeginErrorReadLine();
                 * //process.BeginOutputReadLine();
                 */

                Func <StreamReader, ConcurrentQueue <string>, bool> QueueBuilder = (StreamReader Reader, ConcurrentQueue <string> Queue) =>
                {
                    int Char = Reader.Read();
                    if (Char < 0)
                    {
                        return(true);
                    }

                    string Value = new string((char)Char, 1);
                    Queue.Enqueue(Value);

                    return(false);
                };

                Func <ConcurrentQueue <string>, LineBuilder, bool> Parser = (ConcurrentQueue <string> Queue, LineBuilder Builder) =>
                {
                    while (Queue.Count > 0)
                    {
                        string Value = "";
                        if (Queue.TryDequeue(out Value))
                        {
                            Builder.Add(Value);
                            while (true)
                            {
                                string Line = Builder.Read();
                                if (Line == null)
                                {
                                    break;
                                }
                                Logger.Log(LogLevel.Info, LogCategory.Main, "{0}", Line);
                            }

                            OutputCallback?.Invoke(Value);
                        }
                    }

                    return(true);
                };

                Func <LineBuilder, bool> DrainBuilder = (LineBuilder Builder) =>
                {
                    Builder.End();
                    while (true)
                    {
                        string Line = Builder.Read();
                        if (Line == null)
                        {
                            break;
                        }
                        Logger.Log(LogLevel.Info, LogCategory.Main, "{0}", Line);
                    }

                    return(true);
                };

                LineBuilder OutputLineBuilder = new LineBuilder();
                LineBuilder ErrorLineBuilder  = new LineBuilder();

                // This is retarded, the blocking api for all of this in C# is s***e.
                ConcurrentQueue <string> OutputData = new ConcurrentQueue <string>();
                ConcurrentQueue <string> ErrorData  = new ConcurrentQueue <string>();

                Task OutputTask = Task.Run(() => { while (!QueueBuilder(process.StandardOutput, OutputData))
                                                   {
                                                       ;
                                                   }
                                           });
                Task ErrorTask = Task.Run(() => { while (!QueueBuilder(process.StandardError, ErrorData))
                                                  {
                                                      ;
                                                  }
                                          });

                // Wait for process to exit.
                while (!OutputTask.IsCompleted || !ErrorTask.IsCompleted || OutputData.Count > 0 || ErrorData.Count > 0)
                {
                    Parser(OutputData, OutputLineBuilder);
                    Parser(ErrorData, ErrorLineBuilder);
                    Thread.Sleep(1);
                }

                process.WaitForExit();

                // Drain any output.
                DrainBuilder(OutputLineBuilder);
                DrainBuilder(ErrorLineBuilder);

                Logger.Log(LogLevel.Info, LogCategory.Script, "Finished running with exit code {0}.", process.ExitCode);
                return(process.ExitCode);
            }
            catch (Exception Ex)
            {
                Logger.Log(LogLevel.Error, LogCategory.Script, "Failed to run program with error: {0}", Ex.Message.ToString());
                return(-1);
            }
        }