Skip to content

Commit

Permalink
🔀 Merge branch 'develop' into master
Browse files Browse the repository at this point in the history
  • Loading branch information
oliverbooth committed Jun 28, 2019
2 parents 94357ec + bbcc7b4 commit 3339356
Show file tree
Hide file tree
Showing 13 changed files with 573 additions and 79 deletions.
18 changes: 13 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,25 @@ This tool is directly inspired by [VPUpdater](https://github.com/Evonex/VPUpdate
I've rewritten the tool from the ground up to correct all of these issues.

## How to use
1. Download the [latest release](https://github.com/oliverbooth/VPUpdater/releases/latest) and extract the files to your Virtual Paradise directory
2. Create a shortcut to VPUpdater.exe
3. Rename the shortcut to something meaningful (you know... like `Virtual Paradise`)
4. Place that shortcut on your desktop / taskbar / useful location.
1. Ensure you have the [.NET Framework 4.8 Runtime](https://dotnet.microsoft.com/download/dotnet-framework/net48)
2. Download the [latest release](https://github.com/oliverbooth/VPUpdater/releases/latest) and extract the files to your Virtual Paradise directory
3. Create a shortcut to VPUpdater.exe
4. Rename the shortcut to something meaningful (you know... like `Virtual Paradise`)
5. Place that shortcut on your desktop / taskbar / useful location.

Now when you launch "Virtual Paradise", it will launch the updater first. If there are no updates, the tool with simply launch Virtual Paradise. If there is an update, it will download the latest setup and you can go from there.

## How to enable pre-release builds
Edit (or create) file `VPUpdater.cfg` in the Virtual Paradise directory with the line:
```properties
stable_only=0
```
The next time the updater runs, it will check for pre-release builds.

## Building prerequisites
|Prerequisite|Version|
|- |- |
|.NET|4.6|
|[.NET Framework Developer Pack](https://dotnet.microsoft.com/download/dotnet-framework/net48)|4.8|

## Nuget package dependencies
|Dependency|Version|
Expand Down
6 changes: 3 additions & 3 deletions VPUpdater/App.config
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8" ?>
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6" />
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.8"/>
</startup>
</configuration>
</configuration>
41 changes: 41 additions & 0 deletions VPUpdater/ControlExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
#region Copyright

// -----------------------------------------------------------------------
// <copyright file="ControlExtensions.cs" company="VPUpdater">
// (C) 2019 Oliver Booth. All rights reserved.
// </copyright>
// -----------------------------------------------------------------------

#endregion

namespace VPUpdater
{
#region Using Directives

using System.Windows.Forms;

#endregion

/// <summary>
/// Extension methods for <see cref="Control"/>.
/// </summary>
public static class ControlExtensions
{
/// <summary>
/// Thread-safe method invocation. Calls <see cref="Control.Invoke"/> if <see cref="Control.InvokeRequired"/> returns <see langword="true"/>.
/// </summary>
/// <param name="control">The control from which to invoke.</param>
/// <param name="action">The action to invoke.</param>
public static void InvokeIfRequired(this Control control, MethodInvoker action)
{
if (control?.InvokeRequired ?? false)
{
control.Invoke(action);
}
else
{
action();
}
}
}
}
131 changes: 106 additions & 25 deletions VPUpdater/DownloadForm.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ namespace VPUpdater

using System;
using System.Net;
using System.Threading.Tasks;
using System.Windows.Forms;
using Properties;
using Version = SemVer.Version;
Expand All @@ -30,6 +31,7 @@ public partial class DownloadForm : Form
private readonly string[] commandLineArgs;
private readonly Updater updater;
private readonly VirtualParadise virtualParadise;
private readonly UpdateChannel updateChannel;

#endregion

Expand All @@ -38,20 +40,65 @@ public partial class DownloadForm : Form
/// <summary>
/// Initializes a new instance of the <see cref="DownloadForm"/> class.
/// </summary>
public DownloadForm(string[] args)
/// <param name="args">Command-line arguments to pass to Virtual Paradise.</param>
/// <param name="virtualParadise">The instance of <see cref="VirtualParadise"/> to use.</param>
/// <param name="channel">The update channel to use.</param>
private DownloadForm(string[] args, VirtualParadise virtualParadise, UpdateChannel channel)
{
this.InitializeComponent();

// Store CLI args as DI to pass to VP
this.commandLineArgs = args;
this.virtualParadise = VirtualParadise.GetCurrent();
this.updater = new Updater();
this.virtualParadise = virtualParadise;
this.updateChannel = channel;
this.updater = new Updater(virtualParadise);
}

#endregion

#region Methods

/// <summary>
/// Builds a <see cref="DownloadForm"/>.
/// </summary>
/// <param name="args">Command-line arguments to pass to Virtual Paradise.</param>
/// <returns>Returns a new instance of <see cref="DownloadForm"/>.</returns>
public static async Task<DownloadForm> Build(string[] args)
{
UpdaterConfig config = await UpdaterConfig.Load();

await config.LoadDefaults();

UpdateChannel channel = (int)config["stable_only", 1] == 1
? UpdateChannel.Stable
: UpdateChannel.PreRelease;

try
{
VirtualParadise virtualParadise = VirtualParadise.GetCurrent();
if (channel == UpdateChannel.PreRelease)
{
VirtualParadise preVirtualParadise = VirtualParadise.GetPreRelease();
if (!(preVirtualParadise is null))
{
virtualParadise = preVirtualParadise;
}
}

return new DownloadForm(args, virtualParadise, channel);
}
catch (Exception ex)
{
MessageBox.Show(String.Format(Resources.VpObjectBuildError, ex.Message),
Resources.Error,
MessageBoxButtons.OK,
MessageBoxIcon.Error);

// There's nothing we can do from here
Environment.Exit(0);
return null;
}
}

/// <summary>
/// Called when <see cref="buttonCancel"/> is clicked.
/// </summary>
Expand Down Expand Up @@ -90,29 +137,49 @@ private void ButtonCancel_Click(object sender, EventArgs e)
Environment.Exit(0);
}

/// <summary>
/// Checks for a Virtual Paradise update.
/// </summary>
/// <param name="channel">The update channel to use.</param>
/// <returns>Returns <see langword="true"/> if the there is an updated and the user accepted, <see langword="false"/> otherwise.</returns>
private async Task<Version> CheckForUpdates(UpdateChannel channel)
{
return await this.updater.FetchLatest(channel);
}

/// <summary>
/// Called when the form first loads.
/// </summary>
/// <param name="sender">The event sender.</param>
/// <param name="e">The event data.</param>
private void DownloadForm_Load(object sender, EventArgs e)
private async void DownloadForm_Load(object sender, EventArgs e)
{
this.Show();
this.Run();
this.InvokeIfRequired(async () => await this.Run());
}

/// <summary>
/// Performs the update routine.
/// </summary>
private async void Run()
private async Task Run()
{
this.labelDownloading.Text = String.Format(Resources.VpExeCheck, VirtualParadise.ExeFilename);
this.progressBar.Style = ProgressBarStyle.Marquee;
this.InvokeIfRequired(
() =>
{
this.labelDownloading.Text =
String.Format(Resources.VpExeCheck, VirtualParadise.ExeFilename);

this.progressBar.Style = ProgressBarStyle.Marquee;
});

if (this.virtualParadise == null)
{
this.progressBar.Style = ProgressBarStyle.Continuous;
this.progressBar.Value = 0;
this.InvokeIfRequired(
() =>
{
this.progressBar.Style = ProgressBarStyle.Continuous;
this.progressBar.Value = 0;
});

MessageBox.Show(String.Format(Resources.VpExeNotFound, VirtualParadise.ExeFilename),
Resources.Error,
Expand All @@ -123,10 +190,10 @@ private async void Run()
return;
}

this.labelDownloading.Text = Resources.UpdateCheck;

this.InvokeIfRequired(() => { this.labelDownloading.Text = Resources.UpdateCheck; });
Version currentVersion = this.virtualParadise.Version;
Version latestVersion = await this.updater.FetchLatest();
Version latestVersion = await this.CheckForUpdates(this.updateChannel);

if (currentVersion < latestVersion)
{
DialogResult result = MessageBox.Show(
Expand All @@ -146,22 +213,27 @@ private async void Run()
else
{
// Everything is up to date!
this.labelDownloading.Text = Resources.UpToDate;
this.progressBar.Style = ProgressBarStyle.Continuous;
this.progressBar.Value = this.progressBar.Maximum;
this.buttonCancel.Text = Resources.Close;
this.InvokeIfRequired(
() =>
{
this.labelDownloading.Text = Resources.UpToDate;
this.progressBar.Style = ProgressBarStyle.Continuous;
this.progressBar.Value = this.progressBar.Maximum;
this.buttonCancel.Text = Resources.Close;
});

this.virtualParadise.Launch(this.commandLineArgs);

Environment.Exit(0);
return;
}

this.labelDownloading.Text = Resources.DownloadLinkFetch;
this.InvokeIfRequired(() => { this.labelDownloading.Text = Resources.DownloadLinkFetch; });
Uri downloadUri;

try
{
downloadUri = await this.updater.FetchDownloadLink();
downloadUri = await this.updater.FetchDownloadLink(this.updateChannel);
}
catch (Exception ex)
{
Expand Down Expand Up @@ -214,8 +286,12 @@ private async void Run()
return;
}

this.progressBar.Style = ProgressBarStyle.Marquee;
this.labelDownloading.Text = Resources.WaitingForSetup;
this.InvokeIfRequired(
() =>
{
this.progressBar.Style = ProgressBarStyle.Marquee;
this.labelDownloading.Text = Resources.WaitingForSetup;
});

try
{
Expand Down Expand Up @@ -255,9 +331,14 @@ private async void Run()
private void WebClientProgressChanged(object sender, DownloadProgressChangedEventArgs e)
{
// Update progress for user
this.progressBar.Style = ProgressBarStyle.Continuous;
this.progressBar.Value = e.ProgressPercentage;
this.labelDownloading.Text = String.Format(Resources.DownloadingUpdate, e.ProgressPercentage);
this.InvokeIfRequired(
() =>
{
this.progressBar.Style = ProgressBarStyle.Continuous;
this.progressBar.Value = e.ProgressPercentage;
this.labelDownloading.Text =
String.Format(Resources.DownloadingUpdate, e.ProgressPercentage);
});
}

#endregion
Expand Down
9 changes: 7 additions & 2 deletions VPUpdater/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ namespace VPUpdater

using System;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;

#endregion
Expand All @@ -27,13 +28,17 @@ internal static class Program
/// Application entry point.
/// </summary>
[STAThread]
private static void Main(string[] args)
private static async Task Main(string[] args)
{
args = args.Skip(1).ToArray();

Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new DownloadForm(args));

using (DownloadForm form = await DownloadForm.Build(args))
{
Application.Run(form);
}
}
}
}
11 changes: 11 additions & 0 deletions VPUpdater/Properties/Resources.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions VPUpdater/Properties/Resources.resx
Original file line number Diff line number Diff line change
Expand Up @@ -199,4 +199,9 @@ Current version: {0}</value>
<data name="UriNotFromVp" xml:space="preserve">
<value>The provided download URI is not from {0}.</value>
</data>
<data name="VpObjectBuildError" xml:space="preserve">
<value>Could not create VirtualParadise object:

{0}</value>
</data>
</root>
22 changes: 9 additions & 13 deletions VPUpdater/Properties/Settings.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 3339356

Please sign in to comment.