Added One Click Install handlers.

Made exceptions more verbose.
This commit is contained in:
Assistant 2019-05-07 12:56:54 -04:00
parent dd28764494
commit c367dd2e92
6 changed files with 229 additions and 48 deletions

View file

@ -63,7 +63,17 @@ namespace ModAssistant
break;
case "--register":
OneClickInstaller.Register();
if (!String.IsNullOrEmpty(Args[1]))
OneClickInstaller.Register(Args[1], true);
else
Utils.SendNotify("Invalid argument! '--register' requires an option.");
break;
case "--unregister":
if (!String.IsNullOrEmpty(Args[1]))
OneClickInstaller.Unregister(Args[1], true);
else
Utils.SendNotify("Invalid argument! '--unregister' requires an option.");
break;
default:
@ -75,13 +85,9 @@ namespace ModAssistant
private void Application_DispatcherUnhandledException(object sender, System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e)
{
MessageBox.Show("An unhandled exception just occurred: " + e.Exception.Message, "Exception", MessageBoxButton.OK, MessageBoxImage.Warning);
MessageBox.Show("An unhandled exception just occurred: " + e.Exception, "Exception", MessageBoxButton.OK, MessageBoxImage.Warning);
e.Handled = true;
}
public void RegisterOneClickInstalls ()
{
Application.Current.Shutdown();
}
}
}

View file

@ -8,20 +8,24 @@ using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Security.Principal;
using Microsoft.Win32;
using System.IO.Compression;
namespace ModAssistant
{
class OneClickInstaller
{
private const string ModelSaberURLPrefix = "https://modelsaber.com/files/";
private const string BeatSaverURLPrefix = "https://beatsaver.com/download/";
private static string BeatSaberPath = App.BeatSaberInstallDirectory;
private const string CustomAvatarsFolder = "CustomAvatars";
private const string CustomSabersFolder = "CustomSabers";
private const string CustomPlatformsFolder = "CustomPlatforms";
private const string CustomSongsFolder = "CustomSongs";
private static readonly string[] Protocols = new[] { "modelsaber" };
private static bool IsElevated => new WindowsPrincipal(WindowsIdentity.GetCurrent()).IsInRole(WindowsBuiltInRole.Administrator);
private static readonly string[] Protocols = new[] { "modelsaber", "beatsaver", "modsaber" };
public static void InstallAsset(string link)
{
@ -33,6 +37,69 @@ namespace ModAssistant
case "modelsaber":
ModelSaber(uri);
break;
case "beatsaver":
BeatSaver(uri);
break;
case "modsaber":
ModSaber(uri);
break;
}
}
private static void BeatSaver(Uri uri)
{
string ID = uri.Segments.Last<string>();
DownloadAsset(BeatSaverURLPrefix + ID, CustomSongsFolder);
File.Move(Path.Combine(BeatSaberPath, CustomSongsFolder, ID), Path.Combine(BeatSaberPath, CustomSongsFolder, ID + ".zip"));
string directory = Path.Combine(BeatSaberPath, CustomSongsFolder, ID);
using (FileStream stream = new FileStream(directory + ".zip", FileMode.Open))
{
using (ZipArchive archive = new ZipArchive(stream))
{
foreach (ZipArchiveEntry file in archive.Entries)
{
string fileDirectory = Path.GetDirectoryName(Path.Combine(directory, file.FullName));
if (!Directory.Exists(fileDirectory))
Directory.CreateDirectory(fileDirectory);
if (!String.IsNullOrEmpty(file.Name))
file.ExtractToFile(Path.Combine(directory, file.FullName), true);
}
}
}
File.Delete(Path.Combine(BeatSaberPath, CustomSongsFolder, ID + ".zip"));
}
private static void ModSaber(Uri uri)
{
switch (uri.Host)
{
case "song":
string ID = uri.Segments.Last<string>();
DownloadAsset(BeatSaverURLPrefix + ID, CustomSongsFolder);
File.Move(Path.Combine(BeatSaberPath, CustomSongsFolder, ID), Path.Combine(BeatSaberPath, CustomSongsFolder, ID + ".zip"));
string directory = Path.Combine(BeatSaberPath, CustomSongsFolder, ID);
using (FileStream stream = new FileStream(directory + ".zip", FileMode.Open))
{
using (ZipArchive archive = new ZipArchive(stream))
{
foreach (ZipArchiveEntry file in archive.Entries)
{
string fileDirectory = Path.GetDirectoryName(Path.Combine(directory, file.FullName));
if (!Directory.Exists(fileDirectory))
Directory.CreateDirectory(fileDirectory);
if (!String.IsNullOrEmpty(file.Name))
file.ExtractToFile(Path.Combine(directory, file.FullName), true);
}
}
}
File.Delete(Path.Combine(BeatSaberPath, CustomSongsFolder, ID + ".zip"));
break;
}
}
@ -54,7 +121,6 @@ namespace ModAssistant
private static void DownloadAsset(string link, string folder)
{
string BeatSaberPath = App.BeatSaberInstallDirectory;
if (string.IsNullOrEmpty(BeatSaberPath))
{
Utils.SendNotify("Beat Saber installation path not found.");
@ -72,17 +138,88 @@ namespace ModAssistant
}
}
public static void Register()
public static void Register(string Protocol, bool Background = false)
{
foreach (string protocol in Protocols)
if (IsRegistered(Protocol) == true)
return;
try
{
if (Utils.IsAdmin)
{
RegistryKey ProtocolKey = Registry.ClassesRoot.OpenSubKey(Protocol, true);
if (ProtocolKey == null)
ProtocolKey = Registry.ClassesRoot.CreateSubKey(Protocol, true);
RegistryKey CommandKey = ProtocolKey.CreateSubKey(@"shell\open\command", true);
if (CommandKey == null)
CommandKey = Registry.ClassesRoot.CreateSubKey(@"shell\open\command", true);
if (ProtocolKey.GetValue("OneClick-Provider", "").ToString() != "ModAssistant")
{
ProtocolKey.SetValue("URL Protocol", "", RegistryValueKind.String);
ProtocolKey.SetValue("OneClick-Provider", "ModAssistant", RegistryValueKind.String);
CommandKey.SetValue("", $"\"{Utils.ExePath}\" \"--install\" \"%1\"");
}
Utils.SendNotify($"{Protocol} One Click Install handlers registered!");
}
else
{
Utils.StartAsAdmin($"\"--register\" \"{Protocol}\"");
}
} catch (Exception e)
{
MessageBox.Show(e.ToString());
}
if (Background)
Application.Current.Shutdown();
else
Pages.Options.Instance.UpdateHandlerStatus();
}
public static bool IsRegistered()
public static void Unregister(string Protocol, bool Background = false)
{
return false;
if (IsRegistered(Protocol) == false)
return;
try
{
if (Utils.IsAdmin)
{
using (RegistryKey ProtocolKey = Registry.ClassesRoot.OpenSubKey(Protocol, true))
{
if (ProtocolKey != null
&& ProtocolKey.GetValue("OneClick-Provider", "").ToString() == "ModAssistant")
{
Registry.ClassesRoot.DeleteSubKeyTree(Protocol);
}
}
Utils.SendNotify($"{Protocol} One Click Install handlers unregistered!");
}
else
{
Utils.StartAsAdmin($"\"--unregister\" \"{Protocol}\"");
}
}
catch (Exception e)
{
MessageBox.Show(e.ToString());
}
if (Background)
Application.Current.Shutdown();
else
Pages.Options.Instance.UpdateHandlerStatus();
}
public static bool IsRegistered(string Protocol)
{
RegistryKey ProtocolKey = Registry.ClassesRoot.OpenSubKey(Protocol);
if (ProtocolKey != null
&& ProtocolKey.GetValue("OneClick-Provider", "").ToString() == "ModAssistant")
return true;
else
return false;
}
}
}

View file

@ -16,7 +16,6 @@ namespace ModAssistant
{
private static string APILatestURL = "https://api.github.com/repos/Assistant/ModAssistant/releases/latest";
private static string ExePath = System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName;
private static Update LatestUpdate;
private static Version CurrentVersion;
private static Version LatestVersion;
@ -60,7 +59,7 @@ namespace ModAssistant
public static void StartUpdate()
{
string Directory = Path.GetDirectoryName(ExePath);
string Directory = Path.GetDirectoryName(Utils.ExePath);
string OldExe = Path.Combine(Directory, "ModAssistant.old.exe");
string DownloadLink = null;
@ -82,10 +81,10 @@ namespace ModAssistant
if (File.Exists(OldExe))
File.Delete(OldExe);
File.Move(ExePath, OldExe);
File.Move(Utils.ExePath, OldExe);
Utils.Download(DownloadLink, ExePath);
Process.Start(ExePath);
Utils.Download(DownloadLink, Utils.ExePath);
Process.Start(Utils.ExePath);
App.Current.Shutdown();
}

View file

@ -18,6 +18,9 @@ namespace ModAssistant
{
public class Utils
{
public static bool IsAdmin = new WindowsPrincipal(WindowsIdentity.GetCurrent()).IsInRole(WindowsBuiltInRole.Administrator);
public static string ExePath = Process.GetCurrentProcess().MainModule.FileName;
public class Constants
{
public const string BeatSaberAPPID = "620980";
@ -25,7 +28,6 @@ namespace ModAssistant
public const string BeatModsURL = "https://beatmods.com";
public const string BeatModsModsOptions = "mod?status=approved";
public const string MD5Spacer = " ";
public static bool IsAdmin = new WindowsPrincipal(WindowsIdentity.GetCurrent()).IsInRole(WindowsBuiltInRole.Administrator);
}
public static void SendNotify(string message, string title = "Mod Assistant")
@ -43,22 +45,26 @@ namespace ModAssistant
notification.Dispose();
}
private static void RestartAsAdmin(string Arguments)
public static void StartAsAdmin(string Arguments, bool Close = false)
{
Process process = new Process();
process.StartInfo.FileName = Process.GetCurrentProcess().MainModule.FileName;
process.StartInfo.Arguments = Arguments;
process.StartInfo.UseShellExecute = true;
process.StartInfo.Verb = "runas";
try
{
process.Start();
if (!Close)
process.WaitForExit();
}
catch
{
MessageBox.Show("Mod Assistant Updater needs to run as Admin. Please try again.");
MessageBox.Show("Mod Assistant needs to run this task as Admin. Please try again.");
}
App.Current.Shutdown();
if (Close)
App.Current.Shutdown();
}
public static string CalculateMD5(string filename)

View file

@ -40,30 +40,41 @@
<Border Grid.ColumnSpan="2" Grid.Row="2" Margin="5" Background="LightGray" Height="30" MinWidth="450" >
<TextBlock Margin="5" Text="{Binding InstallDirectory}" HorizontalAlignment="Left" VerticalAlignment="Center" FontSize="16"/>
</Border>
<Button Grid.Row="2" Grid.Column="2" Margin="3" Height="30" Width="80" Content="Select Folder" Click="Button_Click"/>
<Button Grid.Row="2" Grid.Column="2" Margin="3" Height="30" Width="80" Content="Select Folder" Click="SelectDirButton_Click"/>
<TextBlock Grid.Row="3" Margin="5" Text="Save Selected Mods" FontWeight="Bold" HorizontalAlignment="Left" FontSize="16" />
<CheckBox Grid.Row="3" Grid.Column="1" Name="SaveSelected" VerticalAlignment="Center" HorizontalAlignment="Left" IsChecked="{Binding SaveSelection, Mode=TwoWay}" Checked="SaveSelected_Checked" Unchecked="SaveSelected_Unchecked"/>
<TextBlock Grid.Row="4" Margin="5" Text="Check Installed Mods" FontWeight="Bold" HorizontalAlignment="Left" FontSize="16" />
<CheckBox Grid.Row="4" Grid.Column="1" Name="CheckInstalled" VerticalAlignment="Center" HorizontalAlignment="Left" IsChecked="{Binding CheckInstalledMods, Mode=TwoWay}" Checked="CheckInstalled_Checked" Unchecked="CheckInstalled_Unchecked"/>
<StackPanel Grid.Row="5" Margin="20,0,0,0" Background="LightYellow" HorizontalAlignment="Left">
<StackPanel Grid.Row="4" Grid.Column="1" Margin="20,0,0,0" Background="LightYellow" HorizontalAlignment="Left">
<TextBlock Margin="5,5,5,0" Text="Will slow down mod list loading" HorizontalAlignment="Left" />
<TextBlock Margin="5,0,5,5" Text="Requires application restart" HorizontalAlignment="Left" />
</StackPanel>
<TextBlock Grid.Row="6" Margin="20,5,5,5" Text="Select Installed Mods" FontWeight="Bold" HorizontalAlignment="Left" FontSize="16" />
<CheckBox Grid.Row="6" Grid.Column="1" Name="SelectInstalled" VerticalAlignment="Center" HorizontalAlignment="Left" IsChecked="{Binding SelectInstalledMods, Mode=TwoWay}" Checked="SelectInstalled_Checked" Unchecked="SelectInstalled_Unchecked"/>
<TextBlock Grid.Row="5" Margin="20,5,5,5" Text="Select Installed Mods" FontWeight="Bold" HorizontalAlignment="Left" FontSize="16" />
<CheckBox Grid.Row="5" Grid.Column="1" Name="SelectInstalled" VerticalAlignment="Center" HorizontalAlignment="Left" IsChecked="{Binding SelectInstalledMods, Mode=TwoWay}" Checked="SelectInstalled_Checked" Unchecked="SelectInstalled_Unchecked"/>
<TextBlock Grid.Row="7" Margin="5" Text="Enable OneClick Installs" FontWeight="Bold" HorizontalAlignment="Left" FontSize="16" />
<CheckBox Grid.Row="7" Grid.Column="1" Name="ProtocolHandler" VerticalAlignment="Center" HorizontalAlignment="Left" IsChecked="{Binding ProtocolHandlerEnabled, Mode=TwoWay}" Checked="ProtocolHandler_Checked" Unchecked="ProtocolHandler_Unchecked"/>
<StackPanel Grid.Row="8" Margin="20,0,0,0" Background="LightYellow" HorizontalAlignment="Left">
<TextBlock Grid.Row="6" Margin="5" Text="Enable OneClick Installs" FontWeight="Bold" HorizontalAlignment="Left" FontSize="16" />
<StackPanel Grid.Row="6" Grid.Column="1" Margin="20,0,0,0" Background="LightYellow" HorizontalAlignment="Left">
<TextBlock Margin="5,5,5,0" Text="Allows use of OneClick Install links" HorizontalAlignment="Left" />
<TextBlock Margin="5,0,5,5" Text="Coming soon!" HorizontalAlignment="Left" />
<!-- <TextBlock Margin="5,0,5,5" Text="Requires Admin" HorizontalAlignment="Left" /> -->
<TextBlock Margin="5,0,5,5" Text="Requires Admin" HorizontalAlignment="Left" />
</StackPanel>
<TextBlock Grid.Row="7" Margin="20,5,5,5" Text="ModelSaber" FontWeight="Bold" HorizontalAlignment="Left" FontSize="16" />
<CheckBox Grid.Row="7" Grid.Column="1" Name="ModelSaberProtocolHandler" VerticalAlignment="Center" HorizontalAlignment="Left" IsChecked="{Binding ModelSaberProtocolHandlerEnabled}" Checked="ModelSaberProtocolHandler_Checked" Unchecked="ModelSaberProtocolHandler_Unchecked"/>
<TextBlock Grid.Row="8" Margin="20,5,5,5" Text="BeatSaver" FontWeight="Bold" HorizontalAlignment="Left" FontSize="16" />
<CheckBox Grid.Row="8" Grid.Column="1" Name="BeatSaverProtocolHandler" VerticalAlignment="Center" HorizontalAlignment="Left" IsChecked="{Binding BeatSaberProtocolHandlerEnabled}" Checked="BeatSaverProtocolHandler_Checked" Unchecked="BeatSaverProtocolHandler_Unchecked"/>
<TextBlock Grid.Row="9" Margin="20,5,5,5" Text="ModSaber" FontWeight="Bold" HorizontalAlignment="Left" FontSize="16" />
<CheckBox Grid.Row="9" Grid.Column="1" Name="ModSaberProtocolHandler" VerticalAlignment="Center" HorizontalAlignment="Left" IsChecked="{Binding ModSaberProtocolHandlerEnabled}" Checked="ModSaberProtocolHandler_Checked" Unchecked="ModSaberProtocolHandler_Unchecked"/>
<StackPanel Grid.Row="9" Margin="5" Orientation="Horizontal" HorizontalAlignment="Left">
<StackPanel Grid.Row="12" Margin="5" Orientation="Horizontal" HorizontalAlignment="Left">
<TextBlock Text="Game Type: " FontWeight="Bold" FontSize="16" />
<TextBlock Text="{Binding InstallType}" FontSize="16"/>
</StackPanel>

View file

@ -29,6 +29,10 @@ namespace ModAssistant.Pages
public bool SaveSelection { get; set; }
public bool CheckInstalledMods { get; set; }
public bool SelectInstalledMods { get; set; }
public bool ModelSaberProtocolHandlerEnabled { get; set; }
public bool BeatSaverProtocolHandlerEnabled { get; set; }
public bool ModSaberProtocolHandlerEnabled { get; set; }
public Options()
@ -42,21 +46,19 @@ namespace ModAssistant.Pages
if (!CheckInstalledMods)
SelectInstalled.IsEnabled = false;
if (OneClickInstaller.IsRegistered())
{
ProtocolHandler.IsChecked = true;
}
else
{
ProtocolHandler.IsChecked = false;
}
ProtocolHandler.IsEnabled = false;
UpdateHandlerStatus();
this.DataContext = this;
}
private void Button_Click(object sender, RoutedEventArgs e)
public void UpdateHandlerStatus()
{
ModelSaberProtocolHandlerEnabled = OneClickInstaller.IsRegistered("modelsaber");
BeatSaverProtocolHandlerEnabled = OneClickInstaller.IsRegistered("beatsaver");
ModSaberProtocolHandlerEnabled = OneClickInstaller.IsRegistered("modsaber");
}
private void SelectDirButton_Click(object sender, RoutedEventArgs e)
{
Utils.GetManualDir();
}
@ -98,14 +100,34 @@ namespace ModAssistant.Pages
SelectInstalled.IsEnabled = false;
}
private void ProtocolHandler_Checked(object sender, RoutedEventArgs e)
public void ModelSaberProtocolHandler_Checked(object sender, RoutedEventArgs e)
{
OneClickInstaller.Register("modelsaber");
}
private void ProtocolHandler_Unchecked(object sender, RoutedEventArgs e)
public void ModelSaberProtocolHandler_Unchecked(object sender, RoutedEventArgs e)
{
OneClickInstaller.Unregister("modelsaber");
}
public void BeatSaverProtocolHandler_Checked(object sender, RoutedEventArgs e)
{
OneClickInstaller.Register("beatsaver");
}
public void BeatSaverProtocolHandler_Unchecked(object sender, RoutedEventArgs e)
{
OneClickInstaller.Unregister("beatsaver");
}
public void ModSaberProtocolHandler_Checked(object sender, RoutedEventArgs e)
{
OneClickInstaller.Register("modsaber");
}
public void ModSaberProtocolHandler_Unchecked(object sender, RoutedEventArgs e)
{
OneClickInstaller.Unregister("modsaber");
}
private void SelectInstalled_Checked(object sender, RoutedEventArgs e)