Port to .NET 5

This commit is contained in:
Dankrushen
2021-01-26 02:37:16 -05:00
parent 0a236361e0
commit 72dcf90b68
95 changed files with 24769 additions and 1 deletions

347
Code5/OS/AiProcess.cs Normal file
View File

@@ -0,0 +1,347 @@
using Flowframes.IO;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using Flowframes.OS;
using Flowframes.UI;
using Flowframes.Main;
using Flowframes.Data;
using Flowframes.MiscUtils;
namespace Flowframes
{
class AiProcess
{
public static bool hasShownError;
public static Process currentAiProcess;
public static Stopwatch processTime = new Stopwatch();
public static Stopwatch processTimeMulti = new Stopwatch();
public static int lastStartupTimeMs = 1000;
static string lastInPath;
public static Dictionary<string, string> filenameMap = new Dictionary<string, string>(); // TODO: Store on disk instead for crashes?
static void AiStarted (Process proc, int startupTimeMs, string inPath = "")
{
lastStartupTimeMs = startupTimeMs;
processTime.Restart();
currentAiProcess = proc;
lastInPath = string.IsNullOrWhiteSpace(inPath) ? Interpolate.current.framesFolder : inPath;
hasShownError = false;
}
static void SetProgressCheck(string interpPath, int factor)
{
int frames = IOUtils.GetAmountOfFiles(lastInPath, false, "*.png");
int target = (frames * factor) - (factor - 1);
InterpolateUtils.progressPaused = false;
InterpolateUtils.currentFactor = factor;
if (InterpolateUtils.progCheckRunning)
InterpolateUtils.targetFrames = target;
else
InterpolateUtils.GetProgressByFrameAmount(interpPath, target);
}
static async Task AiFinished (string aiName)
{
Program.mainForm.SetProgress(100);
InterpolateUtils.UpdateInterpProgress(IOUtils.GetAmountOfFiles(Interpolate.current.interpFolder, false, "*.png"), InterpolateUtils.targetFrames);
string logStr = $"Done running {aiName} - Interpolation took {FormatUtils.Time(processTime.Elapsed)}";
if (Interpolate.currentlyUsingAutoEnc && AutoEncode.HasWorkToDo())
logStr += " - Waiting for encoding to finish...";
Logger.Log(logStr);
processTime.Stop();
Stopwatch timeSinceFfmpegRan = new Stopwatch();
timeSinceFfmpegRan.Restart();
while (Interpolate.currentlyUsingAutoEnc && Program.busy)
{
if (AvProcess.lastProcess != null && !AvProcess.lastProcess.HasExited && AvProcess.lastTask == AvProcess.TaskType.Encode)
{
timeSinceFfmpegRan.Restart();
string lastLine = AvProcess.lastOutputFfmpeg.SplitIntoLines().Last();
Logger.Log(lastLine.Trim().TrimWhitespaces(), false, Logger.GetLastLine().Contains("frame"));
}
if (timeSinceFfmpegRan.ElapsedMilliseconds > 3000)
break;
// Logger.Log($"AiProcess loop - Program.busy = {Program.busy}");
await Task.Delay(500);
}
}
public static async Task RunRifeCuda(string framesPath, int interpFactor, string mdl)
{
string rifeDir = Path.Combine(Paths.GetPkgPath(), Path.GetFileNameWithoutExtension(Packages.rifeCuda.fileName));
string script = "inference_video.py";
if (!File.Exists(Path.Combine(rifeDir, script)))
{
Interpolate.Cancel("RIFE script not found! Make sure you didn't modify any files.");
return;
}
await RunRifeCudaProcess(framesPath, Paths.interpDir, script, interpFactor, mdl);
if (!Interpolate.canceled && Interpolate.current.alpha)
{
InterpolateUtils.progressPaused = true;
Logger.Log("Interpolating alpha channel...");
await RunRifeCudaProcess(framesPath + "-a", Paths.interpDir + "-a", script, interpFactor, mdl);
}
await AiFinished("RIFE");
if (!Interpolate.canceled && Interpolate.current.alpha)
{
Logger.Log("Processing alpha...");
string rgbInterpDir = Path.Combine(Interpolate.current.tempFolder, Paths.interpDir);
await FFmpegCommands.MergeAlphaIntoRgb(rgbInterpDir, Padding.interpFrames, rgbInterpDir + "-a", Padding.interpFrames);
}
}
public static async Task RunRifeCudaProcess (string inPath, string outDir, string script, int interpFactor, string mdl)
{
string uhdStr = await InterpolateUtils.UseUHD() ? "--UHD" : "";
string args = $" --input {inPath.Wrap()} --model {mdl} --exp {(int)Math.Log(interpFactor, 2)} {uhdStr} --imgformat {InterpolateUtils.GetOutExt()} --output {outDir}";
Process rifePy = OSUtils.NewProcess(!OSUtils.ShowHiddenCmd());
AiStarted(rifePy, 3500);
SetProgressCheck(Path.Combine(Interpolate.current.tempFolder, outDir), interpFactor);
rifePy.StartInfo.Arguments = $"{OSUtils.GetCmdArg()} cd /D {PkgUtils.GetPkgFolder(Packages.rifeCuda).Wrap()} & " +
$"set CUDA_VISIBLE_DEVICES={Config.Get("torchGpus")} & {Python.GetPyCmd()} {script} {args}";
Logger.Log($"Running RIFE {(await InterpolateUtils.UseUHD() ? "(UHD Mode)" : "")} ({script})...".TrimWhitespaces(), false);
Logger.Log("cmd.exe " + rifePy.StartInfo.Arguments, true);
if (!OSUtils.ShowHiddenCmd())
{
rifePy.OutputDataReceived += (sender, outLine) => { LogOutput("[O] " + outLine.Data, "rife-cuda-log"); };
rifePy.ErrorDataReceived += (sender, outLine) => { LogOutput("[E] " + outLine.Data, "rife-cuda-log", true); };
}
rifePy.Start();
if (!OSUtils.ShowHiddenCmd())
{
rifePy.BeginOutputReadLine();
rifePy.BeginErrorReadLine();
}
while (!rifePy.HasExited) await Task.Delay(1);
}
public static async Task RunRifeNcnn (string framesPath, string outPath, int factor, string mdl)
{
processTimeMulti.Restart();
Logger.Log($"Running RIFE{(await InterpolateUtils.UseUHD() ? " (UHD Mode)" : "")}...", false);
bool useAutoEnc = Interpolate.currentlyUsingAutoEnc;
if(factor > 2)
AutoEncode.paused = true; // Disable autoenc until the last iteration
await RunRifeNcnnProcess(framesPath, outPath, mdl);
if (factor == 4 || factor == 8) // #2
{
if (Interpolate.canceled) return;
Logger.Log("Re-Running RIFE for 4x interpolation...", false);
string run1ResultsPath = outPath + "-run1";
IOUtils.TryDeleteIfExists(run1ResultsPath);
Directory.Move(outPath, run1ResultsPath);
Directory.CreateDirectory(outPath);
if (useAutoEnc && factor == 4)
AutoEncode.paused = false;
await RunRifeNcnnProcess(run1ResultsPath, outPath, mdl);
IOUtils.TryDeleteIfExists(run1ResultsPath);
}
if (factor == 8) // #3
{
if (Interpolate.canceled) return;
Logger.Log("Re-Running RIFE for 8x interpolation...", false);
string run2ResultsPath = outPath + "-run2";
IOUtils.TryDeleteIfExists(run2ResultsPath);
Directory.Move(outPath, run2ResultsPath);
Directory.CreateDirectory(outPath);
if (useAutoEnc && factor == 8)
AutoEncode.paused = false;
await RunRifeNcnnProcess(run2ResultsPath, outPath, mdl);
IOUtils.TryDeleteIfExists(run2ResultsPath);
}
if (Interpolate.canceled) return;
if (!Interpolate.currentlyUsingAutoEnc)
IOUtils.ZeroPadDir(outPath, InterpolateUtils.GetOutExt(), Padding.interpFrames);
AiFinished("RIFE");
}
static async Task RunRifeNcnnProcess(string inPath, string outPath, string mdl)
{
Process rifeNcnn = OSUtils.NewProcess(!OSUtils.ShowHiddenCmd());
AiStarted(rifeNcnn, 1500, inPath);
SetProgressCheck(outPath, 2);
string uhdStr = await InterpolateUtils.UseUHD() ? "-u" : "";
string ttaStr = Config.GetBool("rifeNcnnUseTta", false) ? "-x" : "";
rifeNcnn.StartInfo.Arguments = $"{OSUtils.GetCmdArg()} cd /D {PkgUtils.GetPkgFolder(Packages.rifeNcnn).Wrap()} & rife-ncnn-vulkan.exe " +
$" -v -i {inPath.Wrap()} -o {outPath.Wrap()} -m {mdl.ToLower()} {ttaStr} {uhdStr} -g {Config.Get("ncnnGpus")} -f {GetNcnnPattern()} -j {GetNcnnThreads()}";
Logger.Log("cmd.exe " + rifeNcnn.StartInfo.Arguments, true);
if (!OSUtils.ShowHiddenCmd())
{
rifeNcnn.OutputDataReceived += (sender, outLine) => { LogOutput("[O] " + outLine.Data, "rife-ncnn-log"); };
rifeNcnn.ErrorDataReceived += (sender, outLine) => { LogOutput("[E] " + outLine.Data, "rife-ncnn-log", true); };
}
rifeNcnn.Start();
if (!OSUtils.ShowHiddenCmd())
{
rifeNcnn.BeginOutputReadLine();
rifeNcnn.BeginErrorReadLine();
}
while (!rifeNcnn.HasExited) await Task.Delay(1);
}
public static async Task RunDainNcnn(string framesPath, string outPath, int factor, string mdl, int tilesize)
{
string dainDir = Path.Combine(Paths.GetPkgPath(), Path.GetFileNameWithoutExtension(Packages.dainNcnn.fileName));
Process dain = OSUtils.NewProcess(!OSUtils.ShowHiddenCmd());
AiStarted(dain, 1500);
SetProgressCheck(outPath, factor);
int targetFrames = (IOUtils.GetAmountOfFiles(lastInPath, false, "*.png") * factor) - (factor - 1);
string args = $" -v -i {framesPath.Wrap()} -o {outPath.Wrap()} -n {targetFrames} -m {mdl.ToLower()}" +
$" -t {GetNcnnTilesize(tilesize)} -g {Config.Get("ncnnGpus")} -f {GetNcnnPattern()} -j 2:1:2";
dain.StartInfo.Arguments = $"{OSUtils.GetCmdArg()} cd /D {dainDir.Wrap()} & dain-ncnn-vulkan.exe {args}";
Logger.Log("Running DAIN...", false);
Logger.Log("cmd.exe " + dain.StartInfo.Arguments, true);
if (!OSUtils.ShowHiddenCmd())
{
dain.OutputDataReceived += (sender, outLine) => { LogOutput("[O] " + outLine.Data, "dain-ncnn-log"); };
dain.ErrorDataReceived += (sender, outLine) => { LogOutput("[E] " + outLine.Data, "dain-ncnn-log", true); };
}
dain.Start();
if (!OSUtils.ShowHiddenCmd())
{
dain.BeginOutputReadLine();
dain.BeginErrorReadLine();
}
while (!dain.HasExited)
await Task.Delay(1);
if (Interpolate.canceled) return;
//if (!Interpolate.currentlyUsingAutoEnc)
// IOUtils.ZeroPadDir(outPath, InterpolateUtils.GetOutExt(), Padding.interpFrames);
AiFinished("DAIN");
}
static void LogOutput (string line, string logFilename, bool err = false)
{
if (string.IsNullOrWhiteSpace(line) || line.Length < 6)
return;
Logger.LogToFile(line, false, logFilename);
if (line.Contains("ff:nocuda-cpu"))
Logger.Log("WARNING: CUDA-capable GPU device is not available, running on CPU instead!");
if (!hasShownError && err && line.ToLower().Contains("out of memory"))
{
hasShownError = true;
InterpolateUtils.ShowMessage($"Your GPU ran out of VRAM! Please try a video with a lower resolution or use the Max Video Size option in the settings.\n\n{line}", "Error");
}
if (!hasShownError && err && line.ToLower().Contains("modulenotfounderror"))
{
hasShownError = true;
InterpolateUtils.ShowMessage($"A python module is missing.\nCheck {logFilename} for details.\n\n{line}", "Error");
if(!Python.HasEmbeddedPyFolder())
Process.Start("https://github.com/n00mkrad/flowframes/blob/main/PythonDependencies.md");
}
if (!hasShownError && line.ToLower().Contains("no longer supports this gpu"))
{
hasShownError = true;
InterpolateUtils.ShowMessage($"Your GPU seems to be outdated and is not supported!\n\n{line}", "Error");
}
if (!hasShownError && err && (line.Contains("RuntimeError") || line.Contains("ImportError") || line.Contains("OSError")))
{
hasShownError = true;
InterpolateUtils.ShowMessage($"A python error occured during interpolation!\nCheck {logFilename} for details.\n\n{line}", "Error");
}
if (!hasShownError && err && line.Contains("vk") && line.Contains(" failed"))
{
hasShownError = true;
string dain = (Interpolate.current.ai.aiName == Networks.dainNcnn.aiName) ? "\n\nTry reducing the tile size in the AI settings." : "";
InterpolateUtils.ShowMessage($"A Vulkan error occured during interpolation!\n\n{line}{dain}", "Error");
}
if (!hasShownError && err && line.Contains("vkAllocateMemory failed"))
{
hasShownError = true;
bool usingDain = (Interpolate.current.ai.aiName == Networks.dainNcnn.aiName);
string msg = usingDain ? "\n\nTry reducing the tile size in the AI settings." : "Try a lower resolution (Settings -> Max Video Size).";
InterpolateUtils.ShowMessage($"Vulkan ran out of memory!\n\n{line}{msg}", "Error");
}
if (!hasShownError && err && line.Contains("invalid gpu device"))
{
hasShownError = true;
InterpolateUtils.ShowMessage($"A Vulkan error occured during interpolation!\n\n{line}\n\nAre your GPU IDs set correctly?", "Error");
}
if (hasShownError)
Interpolate.Cancel();
}
static string GetNcnnPattern ()
{
return $"%0{Padding.interpFrames}d.{InterpolateUtils.GetOutExt()}";
}
static string GetNcnnTilesize(int tilesize)
{
int gpusAmount = Config.Get("ncnnGpus").Split(',').Length;
string tilesizeStr = $"{tilesize}";
for (int i = 1; i < gpusAmount; i++)
tilesizeStr += $",{tilesize}";
return tilesizeStr;
}
static string GetNcnnThreads ()
{
int gpusAmount = Config.Get("ncnnGpus").Split(',').Length;
int procThreads = Config.GetInt("ncnnThreads");
string progThreadsStr = $"{procThreads}";
for (int i = 1; i < gpusAmount; i++)
progThreadsStr += $",{procThreads}";
return $"4:{progThreadsStr}:4"; ;
}
}
}

76
Code5/OS/NvApi.cs Normal file
View File

@@ -0,0 +1,76 @@
using NvAPIWrapper;
using NvAPIWrapper.GPU;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Flowframes.OS
{
class NvApi
{
static PhysicalGPU gpu;
public static async void Init()
{
try
{
NVIDIA.Initialize();
PhysicalGPU[] gpus = PhysicalGPU.GetPhysicalGPUs();
if (gpus.Length == 0)
return;
gpu = gpus[0];
Logger.Log($"Initialized NvApi. GPU: {gpu.FullName}");
}
catch (Exception e)
{
Logger.Log($"Failed to initialize NvApi: {e.Message}\nIgnore this if you don't have an Nvidia GPU.");
}
}
public static float GetVramGb ()
{
try
{
return (gpu.MemoryInformation.AvailableDedicatedVideoMemoryInkB / 1000f / 1024f);
}
catch (Exception e)
{
return 0f;
}
}
public static float GetFreeVramGb()
{
try
{
return (gpu.MemoryInformation.CurrentAvailableDedicatedVideoMemoryInkB / 1000f / 1024f);
}
catch (Exception e)
{
return 0f;
}
}
public static string GetGpuName()
{
try
{
NVIDIA.Initialize();
PhysicalGPU[] gpus = PhysicalGPU.GetPhysicalGPUs();
if (gpus.Length == 0)
return "";
return gpus[0].FullName;
}
catch
{
return "";
}
}
}
}

139
Code5/OS/OSUtils.cs Normal file
View File

@@ -0,0 +1,139 @@
using System.Collections.Generic;
using System.Text;
using System.Security.Principal;
using System;
using System.Diagnostics;
using System.Management;
using Flowframes.IO;
using DiskDetector;
using DiskDetector.Models;
using Microsoft.VisualBasic.Devices;
namespace Flowframes.OS
{
class OSUtils
{
public static bool IsUserAdministrator()
{
//bool value to hold our return value
bool isAdmin;
WindowsIdentity user = null;
try
{
//get the currently logged in user
user = WindowsIdentity.GetCurrent();
WindowsPrincipal principal = new WindowsPrincipal(user);
isAdmin = principal.IsInRole(WindowsBuiltInRole.Administrator);
}
catch (UnauthorizedAccessException ex)
{
isAdmin = false;
}
catch (Exception ex)
{
isAdmin = false;
}
finally
{
if (user != null)
user.Dispose();
}
return isAdmin;
}
public static Process SetStartInfo(Process proc, bool hidden, string filename = "cmd.exe")
{
proc.StartInfo.UseShellExecute = !hidden;
proc.StartInfo.RedirectStandardOutput = hidden;
proc.StartInfo.RedirectStandardError = hidden;
proc.StartInfo.CreateNoWindow = hidden;
proc.StartInfo.FileName = filename;
return proc;
}
public static Process NewProcess(bool hidden, string filename = "cmd.exe")
{
Process proc = new Process();
return SetStartInfo(proc, hidden, filename);
}
public static void KillProcessTree(int pid)
{
ManagementObjectSearcher processSearcher = new ManagementObjectSearcher
("Select * From Win32_Process Where ParentProcessID=" + pid);
ManagementObjectCollection processCollection = processSearcher.Get();
try
{
Process proc = Process.GetProcessById(pid);
if (!proc.HasExited) proc.Kill();
}
catch (ArgumentException)
{
// Process already exited.
}
if (processCollection != null)
{
foreach (ManagementObject mo in processCollection)
{
KillProcessTree(Convert.ToInt32(mo["ProcessID"])); //kill child processes(also kills childrens of childrens etc.)
}
}
}
public static string GetCmdArg()
{
bool stayOpen = Config.GetInt("cmdDebugMode") == 2;
if (stayOpen)
return "/K";
else
return "/C";
}
public static bool ShowHiddenCmd()
{
return Config.GetInt("cmdDebugMode") > 0;
}
public static bool DriveIsSSD(string path)
{
try
{
var detectedDrives = Detector.DetectFixedDrives(QueryType.SeekPenalty);
if (detectedDrives.Count != 0)
{
char pathDriveLetter = (path[0].ToString().ToUpper())[0];
foreach (var detectedDrive in detectedDrives)
{
if (detectedDrive.DriveLetter == pathDriveLetter && detectedDrive.HardwareType.ToString().ToLower().Trim() == "ssd")
return true;
}
}
}
catch (Exception e)
{
Logger.Log("Failed to detect drive type: " + e.Message);
return true; // Default to SSD on fail
}
return false;
}
public static bool HasNonAsciiChars(string str)
{
return (Encoding.UTF8.GetByteCount(str) != str.Length);
}
public static int GetFreeRamMb ()
{
try
{
return (int)(new ComputerInfo().AvailablePhysicalMemory / 1048576);
}
catch
{
return 1000;
}
}
}
}

182
Code5/OS/Python.cs Normal file
View File

@@ -0,0 +1,182 @@
using Flowframes.IO;
using Flowframes.MiscUtils;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Flowframes.OS
{
class Python
{
static bool hasCheckedSysPy = false;
static bool sysPyInstalled = false;
public static string compactOutput;
public static async Task CheckCompression ()
{
if(HasEmbeddedPyFolder() && (Config.Get("compressedPyVersion") != Updater.GetInstalledVer().ToString()))
{
Program.mainForm.SetWorking(true, false);
Stopwatch sw = new Stopwatch();
sw.Restart();
try
{
bool shownPatienceMsg = false;
Logger.Log("Compressing python runtime. This only needs to be done once.");
compactOutput = "";
Process compact = OSUtils.NewProcess(true);
compact.StartInfo.Arguments = $"/C compact /C /S:{GetPyFolder().Wrap()} /EXE:LZX";
compact.OutputDataReceived += new DataReceivedEventHandler(CompactOutputHandler);
compact.ErrorDataReceived += new DataReceivedEventHandler(CompactOutputHandler);
compact.Start();
compact.BeginOutputReadLine();
compact.BeginErrorReadLine();
while (!compact.HasExited)
{
await Task.Delay(500);
if(sw.ElapsedMilliseconds > 10000)
{
Logger.Log($"This can take up to a few minutes... (Elapsed: {FormatUtils.Time(sw.Elapsed)})", false, shownPatienceMsg);
shownPatienceMsg = true;
await Task.Delay(500);
}
}
Config.Set("compressedPyVersion", Updater.GetInstalledVer().ToString());
Logger.Log("Done compressing python runtime.");
Logger.WriteToFile(compactOutput, true, "compact");
}
catch { }
Program.mainForm.SetWorking(false);
}
}
static void CompactOutputHandler (object sendingProcess, DataReceivedEventArgs outLine)
{
if (outLine == null || outLine.Data == null)
return;
string line = outLine.Data;
compactOutput = compactOutput + line + "\n";
}
public static string GetPyCmd ()
{
if (HasEmbeddedPyFolder())
{
Logger.Log("Using embedded Python runtime.");
return Path.Combine(GetPyFolder(), "python.exe").Wrap();
}
else
{
if (IsSysPyInstalled())
{
return "python";
}
else
{
MessageBox.Show("System python installation not found!\nPlease install Python or download the package from the package installer.");
Interpolate.Cancel("Neither the Flowframes Python Runtime nor System Python installation could be found!");
}
}
return "";
}
public static bool HasEmbeddedPyFolder ()
{
return (Directory.Exists(GetPyFolder()) && IOUtils.GetDirSize(GetPyFolder(), false) > 1024 * 1024 * 5);
}
public static string GetPyFolder ()
{
if (Directory.Exists(Path.Combine(Paths.GetPkgPath(), "py-amp")))
return Path.Combine(Paths.GetPkgPath(), "py-amp");
if (Directory.Exists(Path.Combine(Paths.GetPkgPath(), "py-tu")))
return Path.Combine(Paths.GetPkgPath(), "py-tu");
return "";
}
public static bool IsPytorchReady ()
{
string torchVer = GetPytorchVer();
if (!string.IsNullOrWhiteSpace(torchVer) && torchVer.Length <= 35)
return true;
else
return false;
}
static string GetPytorchVer()
{
try
{
Process py = OSUtils.NewProcess(true);
py.StartInfo.Arguments = "\"/C\" " + GetPyCmd() + " -c \"import torch; print(torch.__version__)\"";
Logger.Log("[DepCheck] CMD: " + py.StartInfo.Arguments);
py.Start();
py.WaitForExit();
string output = py.StandardOutput.ReadToEnd();
string err = py.StandardError.ReadToEnd();
if (!string.IsNullOrWhiteSpace(err)) output += "\n" + err;
Logger.Log("[DepCheck] Pytorch Check Output: " + output.Trim());
return output;
}
catch
{
return "";
}
}
public static bool IsSysPyInstalled ()
{
if (hasCheckedSysPy)
return sysPyInstalled;
bool isInstalled = false;
Logger.Log("Checking if system Python is available...", true);
string sysPyVer = GetSysPyVersion();
if (!string.IsNullOrWhiteSpace(sysPyVer) && !sysPyVer.ToLower().Contains("not found") && sysPyVer.Length <= 35)
{
isInstalled = true;
Logger.Log("Using Python installation: " + sysPyVer, true);
}
hasCheckedSysPy = true;
sysPyInstalled = isInstalled;
return sysPyInstalled;
}
static string GetSysPyVersion()
{
string pythonOut = GetSysPythonOutput();
Logger.Log("[DepCheck] System Python Check Output: " + pythonOut.Trim(), true);
try
{
string ver = pythonOut.Split('(')[0].Trim();
Logger.Log("[DepCheck] Sys Python Ver: " + ver, true);
return ver;
}
catch
{
return "";
}
}
static string GetSysPythonOutput()
{
Process py = OSUtils.NewProcess(true);
py.StartInfo.Arguments = "/C python -V";
Logger.Log("[DepCheck] CMD: " + py.StartInfo.Arguments, true);
py.Start();
py.WaitForExit();
string output = py.StandardOutput.ReadToEnd();
string err = py.StandardError.ReadToEnd();
return output + "\n" + err;
}
}
}

149
Code5/OS/Updater.cs Normal file
View File

@@ -0,0 +1,149 @@
using Flowframes.Data;
using Flowframes.Forms;
using Flowframes.IO;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Flowframes.OS
{
class Updater
{
public static string latestVerUrl = "https://dl.nmkd.de/flowframes/exe/ver.ini";
public static SemVer GetInstalledVer()
{
try
{
string verStr = IOUtils.ReadLines(Paths.GetVerPath())[0];
return new SemVer(verStr);
}
catch (Exception e)
{
Logger.Log("Error getting installed version: " + e.Message);
return new SemVer(0, 0, 0);
}
}
public static bool IsVersionNewer (SemVer currentVer, SemVer newVer)
{
if (newVer.major > currentVer.major)
{
return true;
}
else
{
if(newVer.minor > currentVer.minor)
{
return true;
}
else
{
if (newVer.patch > currentVer.patch)
{
return true;
}
else
{
return false;
}
}
}
}
public static bool VersionMatches (SemVer v1, SemVer v2)
{
return v1.major == v2.major && v1.minor == v2.minor && v1.patch == v2.patch;
}
public static SemVer GetLatestVer (bool patreon)
{
var client = new WebClient();
int line = patreon ? 0 : 2;
return new SemVer(client.DownloadString(latestVerUrl).SplitIntoLines()[line]);
}
public static string GetLatestVerLink(bool patreon)
{
int line = patreon ? 1 : 3;
var client = new WebClient();
try
{
return client.DownloadString(latestVerUrl).SplitIntoLines()[line].Trim();
}
catch
{
Logger.Log("Failed to get latest version link from ver.ini!", true);
return "";
}
}
public static async Task UpdateTo (int version, UpdaterForm form = null)
{
Logger.Log("Updating to " + version, true);
string savePath = Path.Combine(IOUtils.GetExeDir(), $"FlowframesV{version}");
try
{
var client = new WebClient();
client.DownloadProgressChanged += async (sender, args) =>
{
if (form != null && (args.ProgressPercentage % 5 == 0))
{
Logger.Log("Downloading update... " + args.ProgressPercentage, true);
form.SetProgLabel(args.ProgressPercentage, $"Downloading latest version... {args.ProgressPercentage}%");
await Task.Delay(20);
}
};
client.DownloadFileCompleted += (sender, args) =>
{
form.SetProgLabel(100f, $"Downloading latest version... 100%");
};
await client.DownloadFileTaskAsync(new Uri($"https://dl.nmkd.de/flowframes/exe/{version}/Flowframes.exe"), savePath);
}
catch (Exception e)
{
MessageBox.Show("Error: Failed to download update.\n\n" + e.Message, "Error");
Logger.Log("Updater Error during download: " + e.Message, true);
return;
}
try
{
Logger.Log("Installing v" + version, true);
string runningExePath = IOUtils.GetExe();
string oldExePath = runningExePath + ".old";
IOUtils.TryDeleteIfExists(oldExePath);
File.Move(runningExePath, oldExePath);
File.Move(savePath, runningExePath);
}
catch (Exception e)
{
MessageBox.Show("Error: Failed to install update.\n\n" + e.Message, "Error");
Logger.Log("Updater Error during install: " + e.Message, true);
return;
}
form.SetProgLabel(101f, $"Update downloaded.");
await Task.Delay(20);
MessageBox.Show("Update was installed!\nFlowframes will now close. Restart it to use the new version.", "Message");
Application.Exit();
}
public static async Task AsyncUpdateCheck ()
{
SemVer installed = GetInstalledVer();
SemVer latestPat = GetLatestVer(true);
SemVer latestFree = GetLatestVer(false);
Logger.Log($"You are running Flowframes {installed}. The latest Patreon version is {latestPat}, the latest free version is {latestFree}.");
// if (IsVersionNewer(installed, latest))
// Logger.Log($"An update for Flowframes ({latest}) is available! Download it from the Updater.");
// else
// Logger.Log($"Flowframes is up to date ({installed}).");
}
}
}