|
@@ -0,0 +1,509 @@
|
|
|
+using System;
|
|
|
+using System.Diagnostics;
|
|
|
+using System.IO.Compression;
|
|
|
+
|
|
|
+namespace FisTools
|
|
|
+{
|
|
|
+ public class FFmpegException : Exception
|
|
|
+ {
|
|
|
+ public FFmpegException(int exitCode, Exception innerException = null)
|
|
|
+ : base($"Exit Code: {exitCode}.\nSee FFmpeg Log for more info.", innerException) { }
|
|
|
+ }
|
|
|
+
|
|
|
+ public class FFmpegService
|
|
|
+ {
|
|
|
+ private string _ffmpegPath = "ffmpeg";
|
|
|
+ public void SetFFmpegPath(string ffmpegPath)
|
|
|
+ {
|
|
|
+ _ffmpegPath = ffmpegPath;
|
|
|
+ }
|
|
|
+
|
|
|
+ public void StartFFmpeg(out Process process, string arguments)
|
|
|
+ {
|
|
|
+ process = new Process
|
|
|
+ {
|
|
|
+ StartInfo =
|
|
|
+ {
|
|
|
+ FileName = _ffmpegPath,
|
|
|
+ Arguments = arguments,
|
|
|
+ UseShellExecute = false,
|
|
|
+ Verb = "runas",
|
|
|
+ CreateNoWindow = true,
|
|
|
+ RedirectStandardError = true,
|
|
|
+ RedirectStandardInput = true
|
|
|
+ },
|
|
|
+ EnableRaisingEvents = true
|
|
|
+ };
|
|
|
+ process.Start();
|
|
|
+ process.BeginErrorReadLine();
|
|
|
+ }
|
|
|
+ public void ForceCloseFFmpegIfStillAlive()
|
|
|
+ {
|
|
|
+ var fmpegProcess = Process.GetProcessesByName("ffmpeg");
|
|
|
+ foreach (var f in fmpegProcess)
|
|
|
+ {
|
|
|
+ f.Kill();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public class LoaderCenter
|
|
|
+ {
|
|
|
+ private string _processName=string.Empty;
|
|
|
+ public void StartProcessWithFileName(string filePath, string arguments,string processName)
|
|
|
+ {
|
|
|
+ _processName = processName;
|
|
|
+ var process = new Process
|
|
|
+ {
|
|
|
+ StartInfo =
|
|
|
+ {
|
|
|
+ FileName = filePath,
|
|
|
+ Arguments = arguments,
|
|
|
+ UseShellExecute = false,
|
|
|
+ Verb = "runas",
|
|
|
+ CreateNoWindow = true,
|
|
|
+ RedirectStandardError = true,
|
|
|
+ RedirectStandardInput = true
|
|
|
+ },
|
|
|
+ };
|
|
|
+ process.Start();
|
|
|
+ }
|
|
|
+
|
|
|
+ public void StartProcessWithWorkingDirectory(string filePath,string workingDirectory)
|
|
|
+ {
|
|
|
+ var process = new Process
|
|
|
+ {
|
|
|
+ StartInfo =
|
|
|
+ {
|
|
|
+ FileName = filePath,
|
|
|
+ WorkingDirectory = workingDirectory,
|
|
|
+ UseShellExecute = false,
|
|
|
+ CreateNoWindow = true,
|
|
|
+ RedirectStandardOutput = true,
|
|
|
+ Verb = "runas",
|
|
|
+ },
|
|
|
+ };
|
|
|
+ process.Start();
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 校验APP是否已存在,已存在则直接唤起
|
|
|
+ /// </summary>
|
|
|
+ /// <returns></returns>
|
|
|
+ public bool CheckAppIsInvalid(Action<string> logger)
|
|
|
+ {
|
|
|
+ var id = Process.GetCurrentProcess().Id;
|
|
|
+ Process[] processesByNames = Process.GetProcessesByName("fis");
|
|
|
+ bool appInvalid=false;
|
|
|
+ foreach (var pn in processesByNames)
|
|
|
+ {
|
|
|
+ //如果存在同名但不同id的进程
|
|
|
+ if (pn.Id != id)
|
|
|
+ {
|
|
|
+ logger.Invoke("Got another fis process");
|
|
|
+ var threads = pn.Threads;
|
|
|
+ foreach (ProcessThread t in threads)
|
|
|
+ {
|
|
|
+ logger.Invoke("Exist process status is:");
|
|
|
+ logger.Invoke(t.ThreadState.ToString());
|
|
|
+ var appHangup = t.ThreadState == System.Diagnostics.ThreadState.Unknown
|
|
|
+ || t.ThreadState == System.Diagnostics.ThreadState.Terminated
|
|
|
+ || t.ThreadState == System.Diagnostics.ThreadState.Wait;
|
|
|
+
|
|
|
+ if (appHangup)
|
|
|
+ {
|
|
|
+ logger.Invoke("Kill the existing hang up process");
|
|
|
+ //如果存在挂起线程,则杀死
|
|
|
+ KillProcessWithGivenName("fis", false);
|
|
|
+ }
|
|
|
+ if (t.ThreadState == System.Diagnostics.ThreadState.Running)
|
|
|
+ {
|
|
|
+ appInvalid = true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return appInvalid;
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 打开守护进程
|
|
|
+ /// </summary>
|
|
|
+ public void OpenFlyinsonoDaemon()
|
|
|
+ {
|
|
|
+ var process = Process.GetProcessesByName("FlyinsonoDaemon.exe").FirstOrDefault();
|
|
|
+ if (process == null)
|
|
|
+ {
|
|
|
+ var flyinsonoDaemonPath = "C:\\vinno\\daemon\\FlyinsonoDaemon.exe";
|
|
|
+ ToolManager.Instance.LoaderCenter.StartProcessDirectly(flyinsonoDaemonPath);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ public void StartProcessDirectly(string filePath)
|
|
|
+ {
|
|
|
+ var process = new Process
|
|
|
+ {
|
|
|
+ StartInfo =
|
|
|
+ {
|
|
|
+ FileName = filePath,
|
|
|
+ UseShellExecute = false,
|
|
|
+ Verb = "runas",
|
|
|
+ CreateNoWindow = true,
|
|
|
+ RedirectStandardError = true,
|
|
|
+ },
|
|
|
+ EnableRaisingEvents = true
|
|
|
+ };
|
|
|
+ process.Start();
|
|
|
+ }
|
|
|
+
|
|
|
+ public void StartProcessWithUI(string filePath)
|
|
|
+ {
|
|
|
+ var process = new Process
|
|
|
+ {
|
|
|
+ StartInfo =
|
|
|
+ {
|
|
|
+ FileName = filePath,
|
|
|
+ },
|
|
|
+
|
|
|
+ };
|
|
|
+ process.Start();
|
|
|
+ }
|
|
|
+ public void ForceCloseIfStillAlive()
|
|
|
+ {
|
|
|
+ if (!string.IsNullOrEmpty(_processName))
|
|
|
+ {
|
|
|
+ var fmpegProcess = Process.GetProcessesByName(_processName);
|
|
|
+ foreach (var f in fmpegProcess)
|
|
|
+ {
|
|
|
+ f.Kill();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ public void KillProcessWithGivenName(string processName,bool killSelf=true)
|
|
|
+ {
|
|
|
+ var processes = Process.GetProcessesByName(processName);
|
|
|
+ foreach (Process process in processes)
|
|
|
+ {
|
|
|
+ if (process.ProcessName == processName)
|
|
|
+ {
|
|
|
+ if (killSelf)
|
|
|
+ {
|
|
|
+ process.Kill();
|
|
|
+ process.WaitForExit();
|
|
|
+ }
|
|
|
+ else if(process.Id != Process.GetCurrentProcess().Id)
|
|
|
+ {
|
|
|
+ process.Kill();
|
|
|
+ process.WaitForExit();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+// public class AutoStartHelper
|
|
|
+// {
|
|
|
+// /// <summary>
|
|
|
+// /// App开机自启动 Reg key
|
|
|
+// /// </summary>
|
|
|
+// private const string AppAutoStartRegistryKey = "FisAutoStart";
|
|
|
+
|
|
|
+// /// <summary>
|
|
|
+// /// 当前用户注册表开启启动路径
|
|
|
+// /// </summary>
|
|
|
+// private const string RegPath = @"Software\Microsoft\Windows\CurrentVersion\Run";
|
|
|
+// /// <summary>
|
|
|
+// /// 设置APP开机自启动
|
|
|
+// /// </summary>
|
|
|
+// /// <returns></returns>
|
|
|
+// public bool SetAppAutoStart()
|
|
|
+// {
|
|
|
+// ///默认选择Release下的loader.exe
|
|
|
+// var path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "loader.exe");
|
|
|
+//#if DEBUG
|
|
|
+// ///Debug模式下启动fis.exe
|
|
|
+// path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "fis.exe");
|
|
|
+//#endif
|
|
|
+// return SetAutoStartByPath(path, AppAutoStartRegistryKey);
|
|
|
+// }
|
|
|
+
|
|
|
+// /// <summary>
|
|
|
+// /// 取消APP开机自启动
|
|
|
+// /// </summary>
|
|
|
+// /// <returns></returns>
|
|
|
+// public bool AbortAppAutoStart()
|
|
|
+// {
|
|
|
+// return AbortAutoByRegKey(AppAutoStartRegistryKey);
|
|
|
+// }
|
|
|
+
|
|
|
+// /// <summary>
|
|
|
+// /// 根据指定的key取消开机自启动
|
|
|
+// /// </summary>
|
|
|
+// /// <param name="regkey"></param>
|
|
|
+// /// <returns></returns>
|
|
|
+// public bool AbortAutoByRegKey(string regkey)
|
|
|
+// {
|
|
|
+// try
|
|
|
+// {
|
|
|
+// var currentUserRegKey = Registry.CurrentUser;
|
|
|
+// var startUpKey = currentUserRegKey.CreateSubKey(RegPath);
|
|
|
+// startUpKey.DeleteValue(regkey, false);
|
|
|
+// startUpKey.Close();
|
|
|
+// currentUserRegKey.Close();
|
|
|
+// return true;
|
|
|
+
|
|
|
+// }
|
|
|
+// catch (Exception ex)
|
|
|
+// {
|
|
|
+// return false;
|
|
|
+// }
|
|
|
+// }
|
|
|
+// /// <summary>
|
|
|
+// /// 根据给定开机自启动文件路径和注册表的key设置开启自启动
|
|
|
+// /// </summary>
|
|
|
+// /// <param name="regkey"></param>
|
|
|
+// /// <returns></returns>
|
|
|
+// public bool SetAutoStartByPath(string path, string regKey)
|
|
|
+// {
|
|
|
+// try
|
|
|
+// {
|
|
|
+// var currentUserKey = Registry.CurrentUser;
|
|
|
+// var startUpKey = currentUserKey.CreateSubKey(RegPath);
|
|
|
+// startUpKey.SetValue(regKey, path);
|
|
|
+// startUpKey.Close();
|
|
|
+// currentUserKey.Close();
|
|
|
+// return true;
|
|
|
+
|
|
|
+// }
|
|
|
+// catch (Exception)
|
|
|
+// {
|
|
|
+// return false;
|
|
|
+// }
|
|
|
+// }
|
|
|
+
|
|
|
+// }
|
|
|
+
|
|
|
+ public class UpgradeCenter
|
|
|
+ {
|
|
|
+ private int _totalEntrysCount;
|
|
|
+ private int _finishedCount;
|
|
|
+ private const int ExpirationCount = 90;
|
|
|
+ private Action<double>? _onProgressChanged;
|
|
|
+
|
|
|
+ public void ExecutePartUpgrade(Action<string> logger)
|
|
|
+ {
|
|
|
+ logger.Invoke($"Part upgrade");
|
|
|
+ ToolManager.Instance.LoaderCenter.KillProcessWithGivenName("fis");
|
|
|
+ var currentDir = AppDomain.CurrentDomain.BaseDirectory;
|
|
|
+ var fisDir = Directory.GetParent(currentDir)!.Parent!.FullName;
|
|
|
+ logger($"Fis dir is {fisDir}");
|
|
|
+ var webZipPath = Path.Combine(fisDir, "App", "flyinsono");
|
|
|
+ var updateCacheDir = Path.Combine(fisDir, "UpgradCache");
|
|
|
+ var filesToCopy = Directory.GetFiles(updateCacheDir);
|
|
|
+ foreach (var file in filesToCopy)
|
|
|
+ {
|
|
|
+ var ext = Path.GetExtension(file);
|
|
|
+ if (ext != ".zip")
|
|
|
+ {
|
|
|
+ logger($"Skipped none zip file for part upgrade");
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ var fileName = Path.GetFileName(file);
|
|
|
+ var fileDest = Path.Combine(webZipPath, fileName);
|
|
|
+ File.Copy(file, fileDest, true);
|
|
|
+ File.Delete(file);
|
|
|
+ }
|
|
|
+ var fisFileName = Path.Combine(fisDir, "fis.exe");
|
|
|
+ ToolManager.Instance.LoaderCenter.StartProcessDirectly(fisFileName);
|
|
|
+ }
|
|
|
+
|
|
|
+ public void ExecuteFullUpgrade(Action<string> logger,Action<double>? onProgressChanged = null)
|
|
|
+ {
|
|
|
+ logger.Invoke($"Full upgrade");
|
|
|
+ _onProgressChanged=onProgressChanged;
|
|
|
+ ToolManager.Instance.LoaderCenter.KillProcessWithGivenName("fis");
|
|
|
+ var currentDir = AppDomain.CurrentDomain.BaseDirectory;
|
|
|
+
|
|
|
+
|
|
|
+ var fisDir = Directory.GetParent(currentDir)!.Parent!.FullName;
|
|
|
+ logger($"Fis dir is {fisDir}");
|
|
|
+ var filesToCopy = Directory.GetFiles(currentDir);
|
|
|
+
|
|
|
+ foreach (var file in filesToCopy)
|
|
|
+ {
|
|
|
+ var ext = Path.GetExtension(file);
|
|
|
+ logger($"File name {file}");
|
|
|
+ if (ext != ".zip")
|
|
|
+ {
|
|
|
+ logger($"None zip file skipped {file}");
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ var fileName = Path.GetFileName(file);
|
|
|
+ if (!fileName.Contains("fis_package"))
|
|
|
+ {
|
|
|
+ logger($"Zip file skipped {file}");
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ logger($"Do extract {file} begin");
|
|
|
+ var fileNameWithoutExt = Path.GetFileNameWithoutExtension(file);
|
|
|
+ var filePathToSkip = $"{fileNameWithoutExt}/";
|
|
|
+ logger("Begin to extract");
|
|
|
+ Task.Run(() =>
|
|
|
+ {
|
|
|
+ var waitCount = 0;
|
|
|
+ while (true)
|
|
|
+ {
|
|
|
+ waitCount++;
|
|
|
+ Thread.Sleep(1000);
|
|
|
+ if (waitCount == ExpirationCount)
|
|
|
+ {
|
|
|
+ _onProgressChanged?.Invoke(2.0);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ var progress = Math.Round((double)_finishedCount / (double)_totalEntrysCount, 2);
|
|
|
+ _onProgressChanged?.Invoke(progress);
|
|
|
+ if (progress == 1)
|
|
|
+ {
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ });
|
|
|
+ using (ZipArchive archive = ZipFile.OpenRead(file))
|
|
|
+ {
|
|
|
+ try
|
|
|
+ {
|
|
|
+ var entrys = archive.Entries;
|
|
|
+ _totalEntrysCount = entrys.Count;
|
|
|
+ var fileDirs = entrys.Where(c => c.Name == "");
|
|
|
+ var filesEntries = entrys.Where(c => c.Name != "");
|
|
|
+ foreach (var dir in fileDirs)
|
|
|
+ {
|
|
|
+ _finishedCount++;
|
|
|
+ var entrySubPath = dir.FullName.Replace(filePathToSkip, "");
|
|
|
+ if (string.IsNullOrEmpty(entrySubPath))
|
|
|
+ {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ string entryPath = Path.Combine(fisDir, entrySubPath);
|
|
|
+ if (!Directory.Exists(entryPath))
|
|
|
+ {
|
|
|
+ Directory.CreateDirectory(entryPath);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ foreach (ZipArchiveEntry fileEntry in filesEntries)
|
|
|
+ {
|
|
|
+ var entrySubPath = fileEntry.FullName.Replace(filePathToSkip, "");
|
|
|
+ string entryPath = Path.Combine(fisDir, entrySubPath);
|
|
|
+ if (fileEntry.Name.Contains("libHarfBuzzSharp") || fileEntry.Name.Contains("libSkiaSharp"))
|
|
|
+ {
|
|
|
+ _finishedCount++;
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ try
|
|
|
+ {
|
|
|
+ fileEntry.ExtractToFile(entryPath, true);
|
|
|
+ }
|
|
|
+ catch (Exception ex)
|
|
|
+ {
|
|
|
+ logger($"Extract single file error {ex}");
|
|
|
+ }
|
|
|
+ logger($"{fileEntry.FullName} extract success.");
|
|
|
+ _finishedCount++;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ catch (Exception ex)
|
|
|
+ {
|
|
|
+ logger($"Extract error {ex}");
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ logger("End to extract");
|
|
|
+
|
|
|
+ logger($"Do extract {file} end");
|
|
|
+ logger($"Do delete {file} begin");
|
|
|
+ File.Delete(file);
|
|
|
+ logger($"Do delete {file} end");
|
|
|
+ }
|
|
|
+ logger($"Do restart begin");
|
|
|
+ var fisFileName = Path.Combine(fisDir, "fis.exe");
|
|
|
+ if (_onProgressChanged == null)
|
|
|
+ {
|
|
|
+ ToolManager.Instance.LoaderCenter.StartProcessDirectly(fisFileName);
|
|
|
+ }
|
|
|
+ logger($"Do restart end");
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ public class ToolManager
|
|
|
+ {
|
|
|
+ private ToolManager()
|
|
|
+ {
|
|
|
+ }
|
|
|
+ private FFmpegService _ffmpegService;
|
|
|
+ private LoaderCenter _loaderCenter;
|
|
|
+ //private AutoStartHelper _autoStartHelper;
|
|
|
+ private UpgradeCenter _upgradeCenter;
|
|
|
+ static private ToolManager _instance;
|
|
|
+ public static ToolManager Instance
|
|
|
+ {
|
|
|
+ get{
|
|
|
+ if (_instance == null)
|
|
|
+ {
|
|
|
+ _instance = new ToolManager();
|
|
|
+ }
|
|
|
+ return _instance;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ public LoaderCenter LoaderCenter
|
|
|
+ {
|
|
|
+ get {
|
|
|
+ if (_loaderCenter == null)
|
|
|
+ {
|
|
|
+ _loaderCenter = new LoaderCenter();
|
|
|
+ }
|
|
|
+ return _loaderCenter;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public FFmpegService FFmpegService
|
|
|
+ {
|
|
|
+ get
|
|
|
+ {
|
|
|
+ if (_ffmpegService == null)
|
|
|
+ {
|
|
|
+ _ffmpegService = new FFmpegService();
|
|
|
+ }
|
|
|
+ return _ffmpegService;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ public UpgradeCenter UpgradeCenter
|
|
|
+ {
|
|
|
+ get
|
|
|
+ {
|
|
|
+ if (_upgradeCenter == null)
|
|
|
+ {
|
|
|
+ _upgradeCenter = new UpgradeCenter();
|
|
|
+ }
|
|
|
+ return _upgradeCenter;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ //public AutoStartHelper AutoStartHelper
|
|
|
+ //{
|
|
|
+ // get {
|
|
|
+ // if (_autoStartHelper == null)
|
|
|
+ // {
|
|
|
+ // _autoStartHelper = new AutoStartHelper();
|
|
|
+ // }
|
|
|
+ // return _autoStartHelper;
|
|
|
+ // }
|
|
|
+ //}
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+}
|