WIP 3 - Updater works as expected!

- New updater program icon
- Safer code
- Optimized code (not really)
- Version shown properly in the about window
This commit is contained in:
MelonSpeedruns 2020-02-02 14:41:52 -05:00 committed by Ash
parent 73bba287c2
commit 859b10d65b
10 changed files with 199 additions and 218 deletions

View file

@ -6,10 +6,10 @@ using System.Net;
namespace Ryujinx.Updater
{
public class Program
class Program
{
public static string RyuDir = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "Ryujinx");
public static string launchDir = Environment.CurrentDirectory;
public static string localAppPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "Ryujinx");
public static string ryuDir = Environment.CurrentDirectory;
public static string updateSaveLocation;
@ -47,28 +47,37 @@ namespace Ryujinx.Updater
}
}
[STAThread]
public static void Main(string[] args)
static void Main(string[] args)
{
if (args.Length < 2)
{
return;
}
File.WriteAllText(Path.Combine(launchDir, "Version.json"), args[1]);
if (!File.Exists(Path.Combine(localAppPath, "Version.json")))
{
File.Create(Path.Combine(localAppPath, "Version.json")).Close();
File.WriteAllText(Path.Combine(localAppPath, "Version.json"), "Unknown Version");
}
Console.WriteLine($"Updating Ryujinx... | {File.ReadAllText(Path.Combine(localAppPath, "Version.json"))} -> {args[1]}");
File.WriteAllText(Path.Combine(localAppPath, "Version.json"), args[1]);
// Create temp directory
if (!Directory.Exists(Path.Combine(RyuDir, "Temp")))
if (!Directory.Exists(Path.Combine(localAppPath, "Temp")))
{
Directory.CreateDirectory(Path.Combine(RyuDir, "Temp"));
Directory.CreateDirectory(Path.Combine(localAppPath, "Temp"));
}
// Download latest update
string downloadUrl = args[0];
updateSaveLocation = Path.Combine(RyuDir, "Temp", "RyujinxPackage.zip");
updateSaveLocation = Path.Combine(localAppPath, "Temp", "RyujinxPackage.zip");
Console.WriteLine($"Downloading latest Ryujinx package...");
using (WebClient client = new WebClient())
{
@ -77,20 +86,26 @@ namespace Ryujinx.Updater
// Extract Update .zip
ZipFile.ExtractToDirectory(updateSaveLocation, RyuDir, true);
Console.WriteLine($"Extracting Ryujinx...");
ZipFile.ExtractToDirectory(updateSaveLocation, localAppPath, true);
// Copy new files over to Ryujinx folder
MoveAllFilesOver(Path.Combine(RyuDir, "publish"), launchDir);
Console.WriteLine($"Replacing old version...");
MoveAllFilesOver(Path.Combine(localAppPath, "publish"), ryuDir);
// Remove temp folders
Directory.Delete(Path.Combine(RyuDir, "publish"), true);
Directory.Delete(Path.Combine(RyuDir, "Temp"), true);
Directory.Delete(Path.Combine(localAppPath, "publish"), true);
Directory.Delete(Path.Combine(localAppPath, "Temp"), true);
// Start new Ryujinx version and close Updater
Process.Start(Path.Combine(launchDir, "Ryujinx.exe"));
ProcessStartInfo startInfo = new ProcessStartInfo(Path.Combine(ryuDir, "Ryujinx.exe"));
startInfo.UseShellExecute = true;
Process.Start(startInfo);
}
}

View file

@ -4,13 +4,20 @@
<TargetFramework>netcoreapp3.0</TargetFramework>
<RuntimeIdentifiers>win-x64;osx-x64;linux-x64;</RuntimeIdentifiers>
<Configurations>Debug;Release;Profile Debug;Profile Release</Configurations>
<ApplicationIcon>Ryujinx.ico</ApplicationIcon>
<ApplicationIcon>Updater.ico</ApplicationIcon>
<OutputType>Exe</OutputType>
<AssemblyName>Updater</AssemblyName>
</PropertyGroup>
<Target Name="AddRuntimeDependenciesToContent" Condition=" '$(TargetFrameworkIdentifier)' == '.NETCoreApp'" BeforeTargets="GetCopyToOutputDirectoryItems" DependsOnTargets="GenerateBuildDependencyFile;GenerateBuildRuntimeConfigurationFiles">
<ItemGroup>
<ProjectReference Include="..\ARMeilleure\ARMeilleure.csproj" />
<ContentWithTargetPath Include="$(ProjectDepsFilePath)" CopyToOutputDirectory="PreserveNewest" TargetPath="$(ProjectDepsFileName)" />
<ContentWithTargetPath Include="$(ProjectRuntimeConfigFilePath)" CopyToOutputDirectory="PreserveNewest" TargetPath="$(ProjectRuntimeConfigFileName)" />
</ItemGroup>
</Target>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
</Project>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 106 KiB

BIN
Ryujinx.Updater/Updater.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 103 KiB

View file

@ -16,30 +16,45 @@ namespace Ryujinx.Ui
#pragma warning disable CS0649
#pragma warning disable IDE0044
[GUI] Window _aboutWin;
[GUI] Label _versionText;
[GUI] Image _ryujinxLogo;
[GUI] Image _patreonLogo;
[GUI] Image _gitHubLogo;
[GUI] Image _discordLogo;
[GUI] Image _twitterLogo;
[GUI] Label _versionText;
[GUI] Image _ryujinxLogo;
[GUI] Image _patreonLogo;
[GUI] Image _gitHubLogo;
[GUI] Image _discordLogo;
[GUI] Image _twitterLogo;
#pragma warning restore CS0649
#pragma warning restore IDE0044
public string localAppPath = System.IO.Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "Ryujinx");
public AboutWindow() : this(new Builder("Ryujinx.Ui.AboutWindow.glade")) { }
private AboutWindow(Builder builder) : base(builder.GetObject("_aboutWin").Handle)
{
builder.Autoconnect(this);
_aboutWin.Icon = new Gdk.Pixbuf(Assembly.GetExecutingAssembly(), "Ryujinx.Ui.assets.Icon.png");
_ryujinxLogo.Pixbuf = new Gdk.Pixbuf(Assembly.GetExecutingAssembly(), "Ryujinx.Ui.assets.Icon.png" , 100, 100);
_patreonLogo.Pixbuf = new Gdk.Pixbuf(Assembly.GetExecutingAssembly(), "Ryujinx.Ui.assets.PatreonLogo.png", 30 , 30 );
_gitHubLogo.Pixbuf = new Gdk.Pixbuf(Assembly.GetExecutingAssembly(), "Ryujinx.Ui.assets.GitHubLogo.png" , 30 , 30 );
_discordLogo.Pixbuf = new Gdk.Pixbuf(Assembly.GetExecutingAssembly(), "Ryujinx.Ui.assets.DiscordLogo.png", 30 , 30 );
_twitterLogo.Pixbuf = new Gdk.Pixbuf(Assembly.GetExecutingAssembly(), "Ryujinx.Ui.assets.TwitterLogo.png", 30 , 30 );
_aboutWin.Icon = new Gdk.Pixbuf(Assembly.GetExecutingAssembly(), "Ryujinx.Ui.assets.Icon.png");
_ryujinxLogo.Pixbuf = new Gdk.Pixbuf(Assembly.GetExecutingAssembly(), "Ryujinx.Ui.assets.Icon.png", 100, 100);
_patreonLogo.Pixbuf = new Gdk.Pixbuf(Assembly.GetExecutingAssembly(), "Ryujinx.Ui.assets.PatreonLogo.png", 30, 30);
_gitHubLogo.Pixbuf = new Gdk.Pixbuf(Assembly.GetExecutingAssembly(), "Ryujinx.Ui.assets.GitHubLogo.png", 30, 30);
_discordLogo.Pixbuf = new Gdk.Pixbuf(Assembly.GetExecutingAssembly(), "Ryujinx.Ui.assets.DiscordLogo.png", 30, 30);
_twitterLogo.Pixbuf = new Gdk.Pixbuf(Assembly.GetExecutingAssembly(), "Ryujinx.Ui.assets.TwitterLogo.png", 30, 30);
// todo: Get version string
_versionText.Text = "Unknown Version";
if (!Directory.Exists(localAppPath))
{
Directory.CreateDirectory(localAppPath);
}
string versionJsonFile = System.IO.Path.Combine(localAppPath, "Version.json");
try
{
_versionText.Text = "Version " + File.ReadAllText(versionJsonFile);
}
catch
{
_versionText.Text = "Unknown Version";
}
}
private static void OpenUrl(string url)
@ -94,4 +109,4 @@ namespace Ryujinx.Ui
Dispose();
}
}
}
}

View file

@ -1,5 +1,4 @@
using Gtk;
using Ryujinx.Updater.Parser;
using System;
using System.IO;
using System.Reflection;

View file

@ -1,7 +1,5 @@
using Gtk;
using JsonPrettyPrinterPlus;
using Ryujinx.Audio;
using Ryujinx.Updater.Parser;
using Ryujinx.Common.Logging;
using Ryujinx.Configuration;
using Ryujinx.Debugger.Profiler;
@ -13,7 +11,6 @@ using System;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

Binary file not shown.

Before

Width:  |  Height:  |  Size: 60 KiB

After

Width:  |  Height:  |  Size: 10 KiB

View file

@ -1,182 +0,0 @@
using Gtk;
using Newtonsoft.Json.Linq;
using Ryujinx.Common.Logging;
using Ryujinx.Ui;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.IO.Compression;
using System.Net;
using System.Runtime.InteropServices;
using System.Threading.Tasks;
namespace Ryujinx.Updater.Parser
{
public class UpdateParser
{
private static string _jobId;
private static string _buildVer;
private static string _buildUrl = "https://ci.appveyor.com/api/projects/gdkchan/ryujinx/branch/master";
private static string _buildCommit;
private static string _branch;
private static string _platformExt;
public static string _buildArt;
public static string RyuDir = Environment.CurrentDirectory;
public static WebClient Package = new WebClient();
public static int PackageProgress;
public static double Percentage;
public static void BeginParse()
{
try
{
// Detect current platform
if (RuntimeInformation.ProcessArchitecture == Architecture.X64)
{
if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
{
_platformExt = "osx_x64.zip";
}
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
_platformExt = "win_x64.zip";
}
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
{
_platformExt = "linux_x64.tar.gz";
}
}
// Begin the Appveyor parsing
WebClient jsonClient = new WebClient();
string fetchedJSON = jsonClient.DownloadString(_buildUrl);
JObject jsonRoot = JObject.Parse(fetchedJSON);
var __Build = jsonRoot["build"];
string __Version = (string)__Build["version"];
string __JobsId = (string)__Build["jobs"][0]["jobId"];
string __branch = (string)__Build["branch"];
string __buildCommit = (string)__Build["commitId"];
_jobId = __JobsId;
_buildVer = __Version;
_buildArt = "https://ci.appveyor.com/api/buildjobs/" + _jobId + "/artifacts/ryujinx-" + _buildVer + "-" + _platformExt;
_buildCommit = __buildCommit.Substring(0, 7);
_branch = __branch;
Logger.PrintInfo(LogClass.Application, "Fetched JSON and Parsed:" + Environment.NewLine + "MetaData: JobID(" + __JobsId + ") BuildVer(" + __Version + ")" + Environment.NewLine + "BuildURL(" + _buildArt + ")");
Logger.PrintInfo(LogClass.Application, "Commit-id: (" + _buildCommit + ")" + " Branch: (" + _branch + ")");
using (MessageDialog dialog = GtkDialog.CreateAcceptDialog("Update", "Ryujinx - Update", "Would you like to update?", "Version " + _buildVer + " is available."))
{
if (dialog.Run() == (int)ResponseType.Yes)
{
try
{
// Start Updater.exe
string updaterPath = Path.Combine(RyuDir, "Updater.exe");
Process.Start(updaterPath, _buildArt + " " + _buildVer);
}
catch (Exception ex)
{
GtkDialog.CreateErrorDialog(ex.Message);
}
}
}
}
catch (Exception ex)
{
Logger.PrintError(LogClass.Application, ex.Message);
GtkDialog.CreateErrorDialog("Update canceled by user or failed to grab or parse the information.\nPlease try at a later time, or report the error to our GitHub.");
}
}
private static async void GrabPackage()
{
// Check if paths exist
if (!Directory.Exists(Path.Combine(RyuDir, "Data", "Update")) || !Directory.Exists(Path.Combine(RyuDir, "Data")) || !Directory.Exists(Path.Combine(Environment.CurrentDirectory, "temp")))
{
Directory.CreateDirectory(Path.Combine(RyuDir, "Data", "Update"));
Directory.CreateDirectory(Path.Combine(RyuDir, "Data"));
Directory.CreateDirectory(Path.Combine(Environment.CurrentDirectory, "temp"));
}
try
{
// Attempt to grab the latest package
Package.DownloadProgressChanged += new DownloadProgressChangedEventHandler(PackageDownloadProgress);
Package.DownloadFileCompleted += new AsyncCompletedEventHandler(PackageDownloadedAsync);
using (MessageDialog dialog = GtkDialog.CreateProgressDialog("Update", "Ryujinx - Update", "Downloading update " + _buildVer, "Please wait while we download the latest package and extract it."))
{
dialog.Run();
}
}
catch (Exception ex)
{
Logger.PrintError(LogClass.Application, ex.InnerException.ToString());
GtkDialog.CreateErrorDialog(ex.Message);
}
}
private static async void PackageDownloadedAsync(object sender, AsyncCompletedEventArgs e)
{
if (e.Cancelled == true)
{
Logger.PrintError(LogClass.Application, "Package download failed or cancelled");
}
else
{
Logger.PrintWarning(LogClass.Application, "Package is now installing");
await ExtractPackageAsync();
}
}
private static void PackageDownloadProgress(object sender, DownloadProgressChangedEventArgs e)
{
Percentage = e.ProgressPercentage;
PackageProgress = e.ProgressPercentage;
}
public static async Task ExtractPackageAsync()
{
try
{
// Begin the extaction process
await Task.Run(() => ZipFile.ExtractToDirectory(Path.Combine(RyuDir, "Data", "Update", "RyujinxPackage.zip"), Path.Combine(Environment.CurrentDirectory, "temp")));
try
{
Process.Start(new ProcessStartInfo(Path.Combine(Environment.CurrentDirectory, "temp", "publish", "Ryujinx.exe"), "/U") { UseShellExecute = true });
Application.Quit();
}
catch (Exception ex)
{
GtkDialog.CreateErrorDialog("Package installation has failed\nCheck the log for more information.");
Logger.PrintError(LogClass.Application, "Package installation has failed\n" + ex.InnerException.ToString());
return;
}
}
catch (Exception ex)
{
Logger.PrintError(LogClass.Application, "Package installation has failed\n" + ex.InnerException.ToString());
GtkDialog.CreateErrorDialog("Package installation has failed\nCheck the log for more information.");
}
}
}
}

View file

@ -0,0 +1,130 @@
using Gtk;
using Newtonsoft.Json.Linq;
using Ryujinx.Common.Logging;
using Ryujinx.Ui;
using System;
using System.Diagnostics;
using System.IO;
using System.Net;
using System.Runtime.InteropServices;
namespace Ryujinx
{
public class UpdateParser
{
private static string _jobId;
private static string _buildVer;
private static string _buildUrl = "https://ci.appveyor.com/api/projects/gdkchan/ryujinx/branch/master";
private static string _buildCommit;
private static string _branch;
private static string _platformExt;
public static string _buildArt;
public static string RyuDir = Environment.CurrentDirectory;
public static string localAppPath = System.IO.Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "Ryujinx");
public static WebClient Package = new WebClient();
public static int PackageProgress;
public static double Percentage;
public static void BeginParse()
{
try
{
// Detect current platform
if (RuntimeInformation.ProcessArchitecture == Architecture.X64)
{
if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
{
_platformExt = "osx_x64.zip";
}
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
_platformExt = "win_x64.zip";
}
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
{
_platformExt = "linux_x64.tar.gz";
}
}
// Begin the Appveyor parsing
WebClient jsonClient = new WebClient();
string fetchedJSON = jsonClient.DownloadString(_buildUrl);
JObject jsonRoot = JObject.Parse(fetchedJSON);
var __Build = jsonRoot["build"];
string __Version = (string)__Build["version"];
string __JobsId = (string)__Build["jobs"][0]["jobId"];
string __branch = (string)__Build["branch"];
string __buildCommit = (string)__Build["commitId"];
_jobId = __JobsId;
_buildVer = __Version;
_buildArt = "https://ci.appveyor.com/api/buildjobs/" + _jobId + "/artifacts/ryujinx-" + _buildVer + "-" + _platformExt;
_buildCommit = __buildCommit.Substring(0, 7);
_branch = __branch;
if (!Directory.Exists(localAppPath))
{
Directory.CreateDirectory(localAppPath);
}
if (File.Exists(Path.Combine(localAppPath, "Version.json")))
{
try
{
Version newVersion = Version.Parse(_buildVer);
string currentVersionJson = File.ReadAllLines(Path.Combine(localAppPath, "Version.json"))[0];
Version currentVersion = Version.Parse(currentVersionJson);
if (newVersion.CompareTo(currentVersion) == 0)
{
GtkDialog.CreateErrorDialog("You are already using the most updated version!");
return;
}
}
catch
{
}
}
using (MessageDialog dialog = GtkDialog.CreateAcceptDialog("Update", "Ryujinx - Update", "Would you like to update?", "Version " + _buildVer + " is available."))
{
if (dialog.Run() == (int)ResponseType.Yes)
{
try
{
// Start Updater.exe
string updaterPath = Path.Combine(RyuDir, "Updater.exe");
ProcessStartInfo startInfo = new ProcessStartInfo(updaterPath);
startInfo.Arguments = _buildArt + " " + _buildVer;
startInfo.UseShellExecute = true;
Process.Start(startInfo);
Application.Quit();
}
catch (Exception ex)
{
GtkDialog.CreateErrorDialog(ex.Message);
}
}
}
}
catch (Exception ex)
{
Logger.PrintError(LogClass.Application, ex.Message);
GtkDialog.CreateErrorDialog("Update canceled by user or failed to grab or parse the information.\nPlease try at a later time, or report the error to our GitHub.");
}
}
}
}