seperated cli & some work for options

This commit is contained in:
2025-08-20 08:17:33 +02:00
parent b434ddf480
commit 582752c987
26 changed files with 254 additions and 166 deletions

View File

@@ -1,6 +0,0 @@
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<appSettings>
<add key="TelerikWinFormsThemeName" value="Windows11CompactDark" />
</appSettings>
</configuration>

View File

@@ -1,26 +0,0 @@
using Newtonsoft.Json;
using Pilz.Configuration;
namespace ModpackUpdater.Apps.Client;
public class AppConfig : IChildSettings, ISettingsIdentifier
{
public static string Identifier => "pilz.appconfig";
public string LastMinecraftProfilePath { get; set; }
[JsonIgnore, Obsolete]
public string ConfigFilePath { get; private set; }
[JsonProperty("ConfigFilePath"), Obsolete]
private string ConfigFilePathLegacy
{
set => ConfigFilePath = value;
}
public void Reset()
{
LastMinecraftProfilePath = null;
}
public static AppConfig Instance => Program.Settings.Get<AppConfig>();
}

View File

@@ -1,81 +0,0 @@
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using Pilz.Extensions;
using System.Reflection;
using System.Runtime.InteropServices;
namespace ModpackUpdater.Apps.Client;
public class AppUpdater
{
private class UpdateInfo
{
[JsonConverter(typeof(VersionConverter))]
public Version Version { get; set; }
public string DownloadUrl { get; set; }
}
private const string UPDATE_URL = "https://git.pilzinsel64.de/litw-refined/minecraft-modpack-updater/-/snippets/3/raw/main/updates.json";
private readonly HttpClient httpClient = new();
private UpdateInfo info;
public async Task<bool> Check()
{
var hasUpdate = false;
try
{
var appVersion = Assembly.GetExecutingAssembly().GetAppVersion().Version;
var result = await httpClient.GetStringAsync(UPDATE_URL);
info = JsonConvert.DeserializeObject<UpdateInfo>(result);
if (info is not null && info.Version > appVersion)
hasUpdate = true;
}
catch
{
}
return hasUpdate;
}
public async Task Install()
{
var client = new HttpClient();
var tempFileName = Path.GetTempFileName();
var appFileName = Environment.ProcessPath;
var oldFileName = appFileName + ".old";
// Delete old file
try
{
File.Delete(oldFileName);
}
catch
{
}
// Download the new file
using (var tempFileStream = new FileStream(tempFileName, FileMode.Create, FileAccess.ReadWrite))
{
Stream downloadStream = null;
try
{
var url = info.DownloadUrl;
downloadStream = await client.GetStreamAsync(url);
await downloadStream.CopyToAsync(tempFileStream);
}
catch
{
}
finally
{
downloadStream?.Dispose();
}
}
// Replace current application file with new file
File.Move(appFileName, oldFileName, true);
File.Move(tempFileName, appFileName);
}
}

View File

@@ -1,81 +0,0 @@
//------------------------------------------------------------------------------
// <auto-generated>
// Dieser Code wurde von einem Tool generiert.
// Laufzeitversion:4.0.30319.42000
//
// Änderungen an dieser Datei können falsches Verhalten verursachen und gehen verloren, wenn
// der Code erneut generiert wird.
// </auto-generated>
//------------------------------------------------------------------------------
namespace ModpackUpdater.My.Resources {
using System;
/// <summary>
/// Eine stark typisierte Ressourcenklasse zum Suchen von lokalisierten Zeichenfolgen usw.
/// </summary>
// Diese Klasse wurde von der StronglyTypedResourceBuilder automatisch generiert
// -Klasse über ein Tool wie ResGen oder Visual Studio automatisch generiert.
// Um einen Member hinzuzufügen oder zu entfernen, bearbeiten Sie die .ResX-Datei und führen dann ResGen
// mit der /str-Option erneut aus, oder Sie erstellen Ihr VS-Projekt neu.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class FiledialogFilters {
private static global::System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture;
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal FiledialogFilters() {
}
/// <summary>
/// Gibt die zwischengespeicherte ResourceManager-Instanz zurück, die von dieser Klasse verwendet wird.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Resources.ResourceManager ResourceManager {
get {
if (object.ReferenceEquals(resourceMan, null)) {
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("ModpackUpdater.Apps.Client.FiledialogFilters", typeof(FiledialogFilters).Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
/// <summary>
/// Überschreibt die CurrentUICulture-Eigenschaft des aktuellen Threads für alle
/// Ressourcenzuordnungen, die diese stark typisierte Ressourcenklasse verwenden.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture {
get {
return resourceCulture;
}
set {
resourceCulture = value;
}
}
/// <summary>
/// Sucht eine lokalisierte Zeichenfolge, die Json files (*.json) ähnelt.
/// </summary>
internal static string JSON_Display {
get {
return ResourceManager.GetString("JSON_Display", resourceCulture);
}
}
/// <summary>
/// Sucht eine lokalisierte Zeichenfolge, die *.json ähnelt.
/// </summary>
internal static string JSON_Filter {
get {
return ResourceManager.GetString("JSON_Filter", resourceCulture);
}
}
}
}

View File

@@ -1,126 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="JSON_Display" xml:space="preserve">
<value>Json files (*.json)</value>
</data>
<data name="JSON_Filter" xml:space="preserve">
<value>*.json</value>
</data>
</root>

View File

@@ -1,162 +0,0 @@
//------------------------------------------------------------------------------
// <auto-generated>
// Dieser Code wurde von einem Tool generiert.
// Laufzeitversion:4.0.30319.42000
//
// Änderungen an dieser Datei können falsches Verhalten verursachen und gehen verloren, wenn
// der Code erneut generiert wird.
// </auto-generated>
//------------------------------------------------------------------------------
namespace ModpackUpdater.My.Resources {
using System;
/// <summary>
/// Eine stark typisierte Ressourcenklasse zum Suchen von lokalisierten Zeichenfolgen usw.
/// </summary>
// Diese Klasse wurde von der StronglyTypedResourceBuilder automatisch generiert
// -Klasse über ein Tool wie ResGen oder Visual Studio automatisch generiert.
// Um einen Member hinzuzufügen oder zu entfernen, bearbeiten Sie die .ResX-Datei und führen dann ResGen
// mit der /str-Option erneut aus, oder Sie erstellen Ihr VS-Projekt neu.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class LangRes {
private static global::System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture;
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal LangRes() {
}
/// <summary>
/// Gibt die zwischengespeicherte ResourceManager-Instanz zurück, die von dieser Klasse verwendet wird.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Resources.ResourceManager ResourceManager {
get {
if (object.ReferenceEquals(resourceMan, null)) {
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("ModpackUpdater.Apps.Client.LangRes", typeof(LangRes).Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
/// <summary>
/// Überschreibt die CurrentUICulture-Eigenschaft des aktuellen Threads für alle
/// Ressourcenzuordnungen, die diese stark typisierte Ressourcenklasse verwenden.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture {
get {
return resourceCulture;
}
set {
resourceCulture = value;
}
}
/// <summary>
/// Sucht eine lokalisierte Zeichenfolge, die A new version of this program is available. If you confirm, the update will be installed automatically. It takes just a few seconds. Continue? ähnelt.
/// </summary>
internal static string MsgBox_UpdateAvailable {
get {
return ResourceManager.GetString("MsgBox_UpdateAvailable", resourceCulture);
}
}
/// <summary>
/// Sucht eine lokalisierte Zeichenfolge, die New program version available ähnelt.
/// </summary>
internal static string MsgBox_UpdateAvailable_Title {
get {
return ResourceManager.GetString("MsgBox_UpdateAvailable_Title", resourceCulture);
}
}
/// <summary>
/// Sucht eine lokalisierte Zeichenfolge, die Everything is right and up-to-date. ähnelt.
/// </summary>
internal static string StatusTest_EverythingOk {
get {
return ResourceManager.GetString("StatusTest_EverythingOk", resourceCulture);
}
}
/// <summary>
/// Sucht eine lokalisierte Zeichenfolge, die Checking for Updates... ähnelt.
/// </summary>
internal static string StatusText_CheckingForUpdates {
get {
return ResourceManager.GetString("StatusText_CheckingForUpdates", resourceCulture);
}
}
/// <summary>
/// Sucht eine lokalisierte Zeichenfolge, die Config incomplete or not loaded! ähnelt.
/// </summary>
internal static string StatusText_ConfigIncompleteOrNotLoaded {
get {
return ResourceManager.GetString("StatusText_ConfigIncompleteOrNotLoaded", resourceCulture);
}
}
/// <summary>
/// Sucht eine lokalisierte Zeichenfolge, die Error on update check or while updating! ähnelt.
/// </summary>
internal static string StatusText_ErrorWhileUpdateCheckOrUpdate {
get {
return ResourceManager.GetString("StatusText_ErrorWhileUpdateCheckOrUpdate", resourceCulture);
}
}
/// <summary>
/// Sucht eine lokalisierte Zeichenfolge, die Installing... ähnelt.
/// </summary>
internal static string StatusText_Installing {
get {
return ResourceManager.GetString("StatusText_Installing", resourceCulture);
}
}
/// <summary>
/// Sucht eine lokalisierte Zeichenfolge, die Downloading program update... ähnelt.
/// </summary>
internal static string StatusText_InstallingAppUpdate {
get {
return ResourceManager.GetString("StatusText_InstallingAppUpdate", resourceCulture);
}
}
/// <summary>
/// Sucht eine lokalisierte Zeichenfolge, die The update servers are in maintenance. ähnelt.
/// </summary>
internal static string StatusText_Maintenance {
get {
return ResourceManager.GetString("StatusText_Maintenance", resourceCulture);
}
}
/// <summary>
/// Sucht eine lokalisierte Zeichenfolge, die Minecraft profile folder seems to be not valid. ähnelt.
/// </summary>
internal static string StatusText_MinecraftProfileWarning {
get {
return ResourceManager.GetString("StatusText_MinecraftProfileWarning", resourceCulture);
}
}
/// <summary>
/// Sucht eine lokalisierte Zeichenfolge, die An update is available! ähnelt.
/// </summary>
internal static string StatusText_UpdateAvailable {
get {
return ResourceManager.GetString("StatusText_UpdateAvailable", resourceCulture);
}
}
}
}

View File

@@ -1,153 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="MsgBox_UpdateAvailable" xml:space="preserve">
<value>A new version of this program is available. If you confirm, the update will be installed automatically. It takes just a few seconds. Continue?</value>
</data>
<data name="MsgBox_UpdateAvailable_Title" xml:space="preserve">
<value>New program version available</value>
</data>
<data name="StatusTest_EverythingOk" xml:space="preserve">
<value>Everything is right and up-to-date.</value>
</data>
<data name="StatusText_CheckingForUpdates" xml:space="preserve">
<value>Checking for Updates...</value>
</data>
<data name="StatusText_ConfigIncompleteOrNotLoaded" xml:space="preserve">
<value>Config incomplete or not loaded!</value>
</data>
<data name="StatusText_ErrorWhileUpdateCheckOrUpdate" xml:space="preserve">
<value>Error on update check or while updating!</value>
</data>
<data name="StatusText_Installing" xml:space="preserve">
<value>Installing...</value>
</data>
<data name="StatusText_InstallingAppUpdate" xml:space="preserve">
<value>Downloading program update...</value>
</data>
<data name="StatusText_Maintenance" xml:space="preserve">
<value>The update servers are in maintenance.</value>
</data>
<data name="StatusText_MinecraftProfileWarning" xml:space="preserve">
<value>Minecraft profile folder seems to be not valid.</value>
</data>
<data name="StatusText_UpdateAvailable" xml:space="preserve">
<value>An update is available!</value>
</data>
</root>

View File

@@ -1,288 +0,0 @@
using System;
using System.Diagnostics;
using System.Drawing;
using System.Windows.Forms;
namespace ModpackUpdater.Apps.Client
{
[Microsoft.VisualBasic.CompilerServices.DesignerGenerated()]
public partial class MainForm : Telerik.WinControls.UI.RadForm
{
// Das Formular überschreibt den Löschvorgang, um die Komponentenliste zu bereinigen.
[DebuggerNonUserCode()]
protected override void Dispose(bool disposing)
{
try
{
if (disposing && components is not null)
components.Dispose();
}
finally
{
base.Dispose(disposing);
}
}
// Wird vom Windows Form-Designer benötigt.
private System.ComponentModel.IContainer components = new System.ComponentModel.Container();
// Hinweis: Die folgende Prozedur ist für den Windows Form-Designer erforderlich.
// Das Bearbeiten ist mit dem Windows Form-Designer möglich.
// Das Bearbeiten mit dem Code-Editor ist nicht möglich.
[DebuggerStepThrough()]
private void InitializeComponent()
{
var resources = new System.ComponentModel.ComponentResourceManager(typeof(MainForm));
RadLabel_MinecraftProfile = new Telerik.WinControls.UI.RadLabel();
RadLabel_ModpackUrl = new Telerik.WinControls.UI.RadLabel();
RadTextBox_MinecraftProfileFolder = new Telerik.WinControls.UI.RadTextBoxControl();
RadTextBox_ModpackConfig = new Telerik.WinControls.UI.RadTextBoxControl();
RadButton_Install = new Telerik.WinControls.UI.RadSplitButton();
radMenuItem_Install = new Telerik.WinControls.UI.RadMenuItem();
radMenuItem_Repair = new Telerik.WinControls.UI.RadMenuItem();
RadButton_CheckForUpdates = new Telerik.WinControls.UI.RadButton();
RadButton_SearchMinecraftProfileFolder = new Telerik.WinControls.UI.RadButton();
tableLayoutPanel1 = new TableLayoutPanel();
RadLabel_Status = new Telerik.WinControls.UI.RadLabel();
RadLabel_StatusDesc = new Telerik.WinControls.UI.RadLabel();
radLabel_InstallationKey = new Telerik.WinControls.UI.RadLabel();
radTextBox_InstallKey = new Telerik.WinControls.UI.RadTextBoxControl();
((System.ComponentModel.ISupportInitialize)RadLabel_MinecraftProfile).BeginInit();
((System.ComponentModel.ISupportInitialize)RadLabel_ModpackUrl).BeginInit();
((System.ComponentModel.ISupportInitialize)RadTextBox_MinecraftProfileFolder).BeginInit();
((System.ComponentModel.ISupportInitialize)RadTextBox_ModpackConfig).BeginInit();
((System.ComponentModel.ISupportInitialize)RadButton_Install).BeginInit();
((System.ComponentModel.ISupportInitialize)RadButton_CheckForUpdates).BeginInit();
((System.ComponentModel.ISupportInitialize)RadButton_SearchMinecraftProfileFolder).BeginInit();
tableLayoutPanel1.SuspendLayout();
((System.ComponentModel.ISupportInitialize)RadLabel_Status).BeginInit();
((System.ComponentModel.ISupportInitialize)RadLabel_StatusDesc).BeginInit();
((System.ComponentModel.ISupportInitialize)radLabel_InstallationKey).BeginInit();
((System.ComponentModel.ISupportInitialize)radTextBox_InstallKey).BeginInit();
((System.ComponentModel.ISupportInitialize)this).BeginInit();
SuspendLayout();
//
// RadLabel_MinecraftProfile
//
RadLabel_MinecraftProfile.Anchor = AnchorStyles.Left;
RadLabel_MinecraftProfile.Location = new Point(3, 6);
RadLabel_MinecraftProfile.Name = "RadLabel_MinecraftProfile";
RadLabel_MinecraftProfile.Size = new Size(89, 18);
RadLabel_MinecraftProfile.TabIndex = 0;
RadLabel_MinecraftProfile.Text = "Minecraft profile";
//
// RadLabel_ModpackUrl
//
RadLabel_ModpackUrl.Anchor = AnchorStyles.Left;
RadLabel_ModpackUrl.Location = new Point(3, 36);
RadLabel_ModpackUrl.Name = "RadLabel_ModpackUrl";
RadLabel_ModpackUrl.Size = new Size(76, 18);
RadLabel_ModpackUrl.TabIndex = 1;
RadLabel_ModpackUrl.Text = "Modpack URL";
//
// RadTextBox_MinecraftProfileFolder
//
RadTextBox_MinecraftProfileFolder.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right;
tableLayoutPanel1.SetColumnSpan(RadTextBox_MinecraftProfileFolder, 3);
RadTextBox_MinecraftProfileFolder.Location = new Point(98, 3);
RadTextBox_MinecraftProfileFolder.Name = "RadTextBox_MinecraftProfileFolder";
RadTextBox_MinecraftProfileFolder.NullText = "C:\\Users\\...\\AppData\\...";
RadTextBox_MinecraftProfileFolder.Size = new Size(221, 24);
RadTextBox_MinecraftProfileFolder.TabIndex = 1;
RadTextBox_MinecraftProfileFolder.TextChanged += RadTextBox_MinecraftFolder_TextInserted;
//
// RadTextBox_ModpackConfig
//
RadTextBox_ModpackConfig.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right;
tableLayoutPanel1.SetColumnSpan(RadTextBox_ModpackConfig, 5);
RadTextBox_ModpackConfig.Location = new Point(98, 33);
RadTextBox_ModpackConfig.Name = "RadTextBox_ModpackConfig";
RadTextBox_ModpackConfig.NullText = "https://...";
RadTextBox_ModpackConfig.Size = new Size(321, 24);
RadTextBox_ModpackConfig.TabIndex = 3;
RadTextBox_ModpackConfig.TextChanged += RadTextBox_ModpackUrl_TextInserted;
//
// RadButton_Install
//
RadButton_Install.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right;
tableLayoutPanel1.SetColumnSpan(RadButton_Install, 2);
RadButton_Install.ImageAlignment = ContentAlignment.MiddleRight;
RadButton_Install.Items.AddRange(new Telerik.WinControls.RadItem[] { radMenuItem_Install, radMenuItem_Repair });
RadButton_Install.Location = new Point(325, 121);
RadButton_Install.Name = "RadButton_Install";
RadButton_Install.Size = new Size(94, 24);
RadButton_Install.TabIndex = 0;
RadButton_Install.Text = "Install";
RadButton_Install.TextAlignment = ContentAlignment.MiddleLeft;
RadButton_Install.TextImageRelation = TextImageRelation.ImageBeforeText;
//
// radMenuItem_Install
//
radMenuItem_Install.Name = "radMenuItem_Install";
radMenuItem_Install.Text = "Install";
radMenuItem_Install.Click += RadMenuItem_Install_Click;
//
// radMenuItem_Repair
//
radMenuItem_Repair.Name = "radMenuItem_Repair";
radMenuItem_Repair.Text = "Repair";
radMenuItem_Repair.Click += RadMenuItem_Repair_Click;
//
// RadButton_CheckForUpdates
//
RadButton_CheckForUpdates.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right;
tableLayoutPanel1.SetColumnSpan(RadButton_CheckForUpdates, 3);
RadButton_CheckForUpdates.ImageAlignment = ContentAlignment.MiddleRight;
RadButton_CheckForUpdates.Location = new Point(98, 121);
RadButton_CheckForUpdates.Name = "RadButton_CheckForUpdates";
RadButton_CheckForUpdates.Size = new Size(221, 24);
RadButton_CheckForUpdates.TabIndex = 100;
RadButton_CheckForUpdates.Text = "Check for Updates";
RadButton_CheckForUpdates.TextAlignment = ContentAlignment.MiddleLeft;
RadButton_CheckForUpdates.TextImageRelation = TextImageRelation.ImageBeforeText;
RadButton_CheckForUpdates.Click += ButtonX_CheckForUpdates_Click;
//
// RadButton_SearchMinecraftProfileFolder
//
RadButton_SearchMinecraftProfileFolder.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right;
tableLayoutPanel1.SetColumnSpan(RadButton_SearchMinecraftProfileFolder, 2);
RadButton_SearchMinecraftProfileFolder.ImageAlignment = ContentAlignment.MiddleRight;
RadButton_SearchMinecraftProfileFolder.Location = new Point(325, 3);
RadButton_SearchMinecraftProfileFolder.Name = "RadButton_SearchMinecraftProfileFolder";
RadButton_SearchMinecraftProfileFolder.Size = new Size(94, 24);
RadButton_SearchMinecraftProfileFolder.TabIndex = 2;
RadButton_SearchMinecraftProfileFolder.Text = "Search";
RadButton_SearchMinecraftProfileFolder.TextAlignment = ContentAlignment.MiddleLeft;
RadButton_SearchMinecraftProfileFolder.TextImageRelation = TextImageRelation.ImageBeforeText;
RadButton_SearchMinecraftProfileFolder.Click += ButtonX_SearchMinecraftProfile_Click;
//
// tableLayoutPanel1
//
tableLayoutPanel1.AutoSize = true;
tableLayoutPanel1.AutoSizeMode = AutoSizeMode.GrowAndShrink;
tableLayoutPanel1.ColumnCount = 6;
tableLayoutPanel1.ColumnStyles.Add(new ColumnStyle());
tableLayoutPanel1.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100F));
tableLayoutPanel1.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 50F));
tableLayoutPanel1.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 50F));
tableLayoutPanel1.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 50F));
tableLayoutPanel1.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 50F));
tableLayoutPanel1.Controls.Add(RadLabel_MinecraftProfile, 0, 0);
tableLayoutPanel1.Controls.Add(RadLabel_ModpackUrl, 0, 1);
tableLayoutPanel1.Controls.Add(RadTextBox_MinecraftProfileFolder, 1, 0);
tableLayoutPanel1.Controls.Add(RadTextBox_ModpackConfig, 1, 1);
tableLayoutPanel1.Controls.Add(RadLabel_Status, 1, 3);
tableLayoutPanel1.Controls.Add(RadLabel_StatusDesc, 0, 3);
tableLayoutPanel1.Controls.Add(RadButton_Install, 4, 4);
tableLayoutPanel1.Controls.Add(radLabel_InstallationKey, 0, 2);
tableLayoutPanel1.Controls.Add(radTextBox_InstallKey, 1, 2);
tableLayoutPanel1.Controls.Add(RadButton_CheckForUpdates, 1, 4);
tableLayoutPanel1.Controls.Add(RadButton_SearchMinecraftProfileFolder, 4, 0);
tableLayoutPanel1.Dock = DockStyle.Fill;
tableLayoutPanel1.Location = new Point(0, 0);
tableLayoutPanel1.Name = "tableLayoutPanel1";
tableLayoutPanel1.RowCount = 5;
tableLayoutPanel1.RowStyles.Add(new RowStyle());
tableLayoutPanel1.RowStyles.Add(new RowStyle());
tableLayoutPanel1.RowStyles.Add(new RowStyle());
tableLayoutPanel1.RowStyles.Add(new RowStyle());
tableLayoutPanel1.RowStyles.Add(new RowStyle());
tableLayoutPanel1.Size = new Size(422, 151);
tableLayoutPanel1.TabIndex = 7;
//
// RadLabel_Status
//
RadLabel_Status.Anchor = AnchorStyles.Left;
tableLayoutPanel1.SetColumnSpan(RadLabel_Status, 5);
RadLabel_Status.Location = new Point(98, 95);
RadLabel_Status.Name = "RadLabel_Status";
RadLabel_Status.Size = new Size(11, 18);
RadLabel_Status.TabIndex = 3;
RadLabel_Status.Text = "-";
RadLabel_Status.TextImageRelation = TextImageRelation.ImageBeforeText;
//
// RadLabel_StatusDesc
//
RadLabel_StatusDesc.Anchor = AnchorStyles.Left;
RadLabel_StatusDesc.Location = new Point(3, 93);
RadLabel_StatusDesc.Name = "RadLabel_StatusDesc";
RadLabel_StatusDesc.Size = new Size(46, 22);
RadLabel_StatusDesc.TabIndex = 2;
RadLabel_StatusDesc.Text = "Status";
//
// radLabel_InstallationKey
//
radLabel_InstallationKey.Anchor = AnchorStyles.Left;
radLabel_InstallationKey.Location = new Point(3, 66);
radLabel_InstallationKey.Name = "radLabel_InstallationKey";
radLabel_InstallationKey.Size = new Size(81, 18);
radLabel_InstallationKey.TabIndex = 12;
radLabel_InstallationKey.Text = "Installation key";
radLabel_InstallationKey.Visible = false;
//
// radTextBox_InstallKey
//
radTextBox_InstallKey.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right;
tableLayoutPanel1.SetColumnSpan(radTextBox_InstallKey, 5);
radTextBox_InstallKey.Location = new Point(98, 63);
radTextBox_InstallKey.Name = "radTextBox_InstallKey";
radTextBox_InstallKey.NullText = "AAAAA-BBBBB-CCCCC-DDDDD-EEEEE";
radTextBox_InstallKey.Size = new Size(321, 24);
radTextBox_InstallKey.TabIndex = 4;
radTextBox_InstallKey.Visible = false;
radTextBox_InstallKey.TextChanged += RadTextBox_InstallationKey_TextInserted;
//
// MainForm
//
AutoScaleBaseSize = new Size(7, 15);
AutoScaleDimensions = new SizeF(7F, 15F);
AutoScaleMode = AutoScaleMode.Font;
AutoSize = true;
AutoSizeMode = AutoSizeMode.GrowAndShrink;
ClientSize = new Size(422, 151);
Controls.Add(tableLayoutPanel1);
Icon = (Icon)resources.GetObject("$this.Icon");
MaximizeBox = false;
MinimumSize = new Size(430, 0);
Name = "MainForm";
StartPosition = FormStartPosition.CenterScreen;
Text = "Minecraft Modpack Updater";
FormClosing += Form1_FormClosing;
Load += Form1_Load;
Shown += Form1_Shown;
((System.ComponentModel.ISupportInitialize)RadLabel_MinecraftProfile).EndInit();
((System.ComponentModel.ISupportInitialize)RadLabel_ModpackUrl).EndInit();
((System.ComponentModel.ISupportInitialize)RadTextBox_MinecraftProfileFolder).EndInit();
((System.ComponentModel.ISupportInitialize)RadTextBox_ModpackConfig).EndInit();
((System.ComponentModel.ISupportInitialize)RadButton_Install).EndInit();
((System.ComponentModel.ISupportInitialize)RadButton_CheckForUpdates).EndInit();
((System.ComponentModel.ISupportInitialize)RadButton_SearchMinecraftProfileFolder).EndInit();
tableLayoutPanel1.ResumeLayout(false);
tableLayoutPanel1.PerformLayout();
((System.ComponentModel.ISupportInitialize)RadLabel_Status).EndInit();
((System.ComponentModel.ISupportInitialize)RadLabel_StatusDesc).EndInit();
((System.ComponentModel.ISupportInitialize)radLabel_InstallationKey).EndInit();
((System.ComponentModel.ISupportInitialize)radTextBox_InstallKey).EndInit();
((System.ComponentModel.ISupportInitialize)this).EndInit();
ResumeLayout(false);
PerformLayout();
}
internal Telerik.WinControls.UI.RadLabel RadLabel_MinecraftProfile;
internal Telerik.WinControls.UI.RadLabel RadLabel_ModpackUrl;
internal Telerik.WinControls.UI.RadTextBoxControl RadTextBox_MinecraftProfileFolder;
internal Telerik.WinControls.UI.RadTextBoxControl RadTextBox_ModpackConfig;
internal Telerik.WinControls.UI.RadSplitButton RadButton_Install;
internal Telerik.WinControls.UI.RadButton RadButton_CheckForUpdates;
internal Telerik.WinControls.UI.RadButton RadButton_SearchMinecraftProfileFolder;
private TableLayoutPanel tableLayoutPanel1;
internal Telerik.WinControls.UI.RadLabel radLabel_InstallationKey;
internal Telerik.WinControls.UI.RadTextBoxControl radTextBox_InstallKey;
private Telerik.WinControls.UI.RadMenuItem radMenuItem_Repair;
private Telerik.WinControls.UI.RadMenuItem radMenuItem_Install;
internal Telerik.WinControls.UI.RadLabel RadLabel_Status;
internal Telerik.WinControls.UI.RadLabel RadLabel_StatusDesc;
}
}

View File

@@ -1,323 +0,0 @@
using ModpackUpdater.Manager;
using ModpackUpdater.My.Resources;
using Pilz.Extensions;
using Pilz.UI.Symbols;
using Pilz.UI.WinForms.Extensions;
using System.Diagnostics;
using System.Reflection;
using Telerik.WinControls;
using Telerik.WinControls.UI;
namespace ModpackUpdater.Apps.Client;
public partial class MainForm
{
private readonly UpdateCheckOptionsAdv updateOptions;
private ModpackInfo modpackInfo = new();
private ModpackConfig updateConfig = new();
private ModpackFeatures features;
private UpdateCheckResult lastUpdateCheckResult;
private bool currentUpdating;
private bool loadingData;
private int curOptionsRow = 3;
public MainForm() : this(new())
{
}
public MainForm(UpdateCheckOptionsAdv updateOptions)
{
this.updateOptions = updateOptions;
InitializeComponent();
Text = $"{Text} (v{Assembly.GetExecutingAssembly().GetAppVersion()})";
RadButton_Install.DefaultItem = radMenuItem_Install;
RadButton_CheckForUpdates.SvgImage = AppGlobals.Symbols.GetSvgImage(AppSymbols.update_done, SymbolSize.Small);
RadButton_SearchMinecraftProfileFolder.SvgImage = AppGlobals.Symbols.GetSvgImage(AppSymbols.opened_folder, SymbolSize.Small);
RadButton_Install.SvgImage = AppGlobals.Symbols.GetSvgImage(AppSymbols.software_installer, SymbolSize.Small);
radMenuItem_Install.SvgImage = AppGlobals.Symbols.GetSvgImage(AppSymbols.software_installer, SymbolSize.Small);
radMenuItem_Repair.SvgImage = AppGlobals.Symbols.GetSvgImage(AppSymbols.wrench, SymbolSize.Small);
LoadProfileToUi();
}
#region Features
private void SetStatus(string statusText, RadSvgImage image)
{
RadLabel_Status.Text = statusText;
RadLabel_Status.SvgImage = image;
}
private void ClearStatus()
{
RadLabel_Status.Text = "-";
RadLabel_Status.SvgImage = null;
}
private void LoadProfileToUi()
{
loadingData = true;
RadTextBox_MinecraftProfileFolder.Text = modpackInfo?.LocaLPath ?? updateOptions.ProfileFolder ?? AppConfig.Instance.LastMinecraftProfilePath ?? RadTextBox_MinecraftProfileFolder.Text;
RadTextBox_ModpackConfig.Text = modpackInfo?.ConfigUrl ?? updateOptions.ModpackConfig ?? RadTextBox_ModpackConfig.Text;
radTextBox_InstallKey.Text = modpackInfo?.ExtrasKey ?? updateOptions.ExtrasKey ?? radTextBox_InstallKey.Text;
loadingData = false;
}
private async void CheckStatusAndUpdate(bool loadProfileToUi)
{
if (CheckStatus(loadProfileToUi))
await ExecuteUpdate(false, false);
}
private bool CheckStatus(bool loadProfileToUi)
{
try
{
modpackInfo = ModpackInfo.TryLoad(RadTextBox_MinecraftProfileFolder.Text.Trim());
}
catch
{
}
if (loadProfileToUi)
LoadProfileToUi();
try
{
updateConfig = ModpackConfig.LoadFromUrl(RadTextBox_ModpackConfig.Text);
}
catch (Exception)
{
}
if (modpackInfo != null)
features = new(updateConfig);
radTextBox_InstallKey.Visible = radLabel_InstallationKey.Visible = !string.IsNullOrWhiteSpace(updateConfig.UnleashApiUrl);
if (modpackInfo == null || string.IsNullOrWhiteSpace(RadTextBox_MinecraftProfileFolder.Text) /*|| modpackInfo.Valid*/)
{
SetStatus(LangRes.StatusText_MinecraftProfileWarning, AppGlobals.Symbols.GetSvgImage(AppSymbols.general_warning_sign, SymbolSize.Small));
RadButton_CheckForUpdates.Enabled = false;
RadButton_Install.Enabled = false;
return false;
}
else if (updateConfig == null || string.IsNullOrWhiteSpace(RadTextBox_ModpackConfig.Text))
{
SetStatus(LangRes.StatusText_ConfigIncompleteOrNotLoaded, AppGlobals.Symbols.GetSvgImage(AppSymbols.general_warning_sign, SymbolSize.Small));
RadButton_CheckForUpdates.Enabled = false;
RadButton_Install.Enabled = false;
return false;
}
else if (updateConfig.Maintenance && !updateOptions.IgnoreMaintenance)
{
SetStatus(LangRes.StatusText_Maintenance, AppGlobals.Symbols.GetSvgImage(AppSymbols.services, SymbolSize.Small));
RadButton_CheckForUpdates.Enabled = false;
RadButton_Install.Enabled = false;
return false;
}
RadButton_CheckForUpdates.Enabled = true;
RadButton_Install.Enabled = true;
return true;
}
private async Task ExecuteUpdate(bool doInstall, bool repair)
{
// Ensure set extras key
modpackInfo.ExtrasKey = radTextBox_InstallKey.Text.Trim();
var updater = new ModpackInstaller(updateConfig, modpackInfo)
{
OverwriteRefTag = Program.Options.RefTag,
OverwriteVersion = Program.Options.Version,
};
updater.InstallProgessUpdated += Update_InstallProgessUpdated;
updater.CheckingProgressUpdated += Updated_CheckingProgresssUpdated;
void error()
{
SetStatus(LangRes.StatusText_ErrorWhileUpdateCheckOrUpdate, AppGlobals.Symbols.GetSvgImage(AppSymbols.close, SymbolSize.Small));
currentUpdating = false;
}
void installing()
{
SetStatus(LangRes.StatusText_Installing, AppGlobals.Symbols.GetSvgImage(AppSymbols.software_installer, SymbolSize.Small));
currentUpdating = true;
}
void updatesAvailable()
{
SetStatus(LangRes.StatusText_UpdateAvailable, AppGlobals.Symbols.GetSvgImage(AppSymbols.software_installer, SymbolSize.Small));
}
void everythingOk()
{
SetStatus(LangRes.StatusTest_EverythingOk, AppGlobals.Symbols.GetSvgImage(AppSymbols.done, SymbolSize.Small));
currentUpdating = false;
}
// Check only if not pressed "install", not really needed otherwise.
if (lastUpdateCheckResult is null || !doInstall || repair)
{
SetStatus(LangRes.StatusText_CheckingForUpdates, AppGlobals.Symbols.GetSvgImage(AppSymbols.update_done, SymbolSize.Small));
// Check for extras once again
updateOptions.IncludeExtras = features.IsEnabled(ModpackFeatures.FeatureAllowExtas, new AllowExtrasFeatureContext(modpackInfo));
// Force re-install on repair
updateOptions.IgnoreInstalledVersion = repair;
try
{
lastUpdateCheckResult = await updater.Check(updateOptions);
}
catch (Exception)
{
error();
if (Debugger.IsAttached)
throw;
}
finally
{
}
}
// Error while update check
if (lastUpdateCheckResult is null || lastUpdateCheckResult.HasError)
{
error();
return;
}
// No updates available
if (!lastUpdateCheckResult.HasUpdates)
{
everythingOk();
return;
}
// Updates available (but don't install)
if (!doInstall)
{
updatesAvailable();
return;
}
// Install updates
installing();
currentUpdating = true;
try
{
// Install
if (await updater.Install(lastUpdateCheckResult) == false)
{
error();
return;
}
// Success
lastUpdateCheckResult = null; // Reset last update check, a new one would be needed now.
everythingOk();
}
catch (Exception)
{
// Error
error();
if (Debugger.IsAttached)
throw;
}
}
private void Updated_CheckingProgresssUpdated(int toCheck, int processed)
{
SetStatus(Math.Round(processed / (double)toCheck * 100d, 1) + "%", AppGlobals.Symbols.GetSvgImage(AppSymbols.update_done, SymbolSize.Small));
}
private void Update_InstallProgessUpdated(UpdateCheckResult result, int processedSyncs)
{
int actionCount = result.Actions.Count;
SetStatus(Math.Round(processedSyncs / (double)actionCount * 100d, 1) + "%", AppGlobals.Symbols.GetSvgImage(AppSymbols.software_installer, SymbolSize.Small));
}
#endregion
#region Gui
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
AppConfig.Instance.LastMinecraftProfilePath = RadTextBox_MinecraftProfileFolder.Text.Trim();
}
private void Form1_Load(object sender, EventArgs e)
{
}
private async void Form1_Shown(object sender, EventArgs e)
{
var updater = new AppUpdater();
if (!updateOptions.NoUpdate && await updater.Check() && RadMessageBox.Show(LangRes.MsgBox_UpdateAvailable, LangRes.MsgBox_UpdateAvailable_Title, MessageBoxButtons.YesNo, RadMessageIcon.Info).IsYes())
{
SetStatus(LangRes.StatusText_InstallingAppUpdate, AppGlobals.Symbols.GetSvgImage(AppSymbols.software_installer, SymbolSize.Small));
Enabled = false;
await updater.Install();
Application.Restart();
return;
}
CheckStatusAndUpdate(true);
}
private void RadTextBox_MinecraftFolder_TextInserted(object o, EventArgs args)
{
if (!loadingData)
CheckStatusAndUpdate(true);
}
private void RadTextBox_ModpackUrl_TextInserted(object o, EventArgs args)
{
if (!loadingData)
CheckStatusAndUpdate(false);
}
private void RadTextBox_InstallationKey_TextInserted(object o, EventArgs args)
{
if (!loadingData)
CheckStatusAndUpdate(false);
}
private void ButtonX_SearchMinecraftProfile_Click(object sender, EventArgs e)
{
var ofd = new RadOpenFolderDialog();
if (ofd.ShowDialog(this) == DialogResult.OK)
RadTextBox_MinecraftProfileFolder.Text = ofd.FileName;
}
private async void ButtonX_CheckForUpdates_Click(object sender, EventArgs e)
{
ClearStatus();
await ExecuteUpdate(false, false);
}
private async void RadMenuItem_Install_Click(object sender, EventArgs e)
{
if (!currentUpdating)
{
ClearStatus();
await ExecuteUpdate(true, false);
}
}
private async void RadMenuItem_Repair_Click(object sender, EventArgs e)
{
if (!currentUpdating)
{
ClearStatus();
await ExecuteUpdate(true, true);
}
}
#endregion
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,59 +1,27 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0-windows</TargetFramework>
<ApplicationIcon>minecraft modpack updater.ico</ApplicationIcon>
<AssemblyName>Minecraft Modpack Updater</AssemblyName>
<ImplicitUsings>true</ImplicitUsings>
<UseWindowsForms>true</UseWindowsForms>
<IncludeAllContentForSelfExtract>true</IncludeAllContentForSelfExtract>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<Compile Update="FiledialogFilters.Designer.cs">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
<DependentUpon>FiledialogFilters.resx</DependentUpon>
</Compile>
<Compile Update="LangRes.Designer.cs">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
<DependentUpon>LangRes.resx</DependentUpon>
</Compile>
<Compile Include="..\Version.cs" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Update="FiledialogFilters.resx">
<Generator>ResXFileCodeGenerator</Generator>
<CustomToolNamespace>ModpackUpdater.My.Resources</CustomToolNamespace>
<LastGenOutput>FiledialogFilters.Designer.cs</LastGenOutput>
</EmbeddedResource>
<EmbeddedResource Update="LangRes.resx">
<Generator>ResXFileCodeGenerator</Generator>
<CustomToolNamespace>ModpackUpdater.My.Resources</CustomToolNamespace>
<LastGenOutput>LangRes.Designer.cs</LastGenOutput>
</EmbeddedResource>
</ItemGroup>
<ItemGroup>
<PackageReference Include="Mono.Options" Version="6.12.0.148" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<PackageReference Include="Pilz.Configuration" Version="3.2.6" />
<PackageReference Include="Pilz.Cryptography" Version="2.1.2" />
<PackageReference Include="Pilz.IO" Version="2.1.0" />
<PackageReference Include="Pilz.UI" Version="3.0.0" />
<PackageReference Include="Pilz.UI.WinForms" Version="2.6.2" />
<PackageReference Include="Pilz.UI.WinForms.Telerik" Version="2.13.3" />
<PackageReference Include="Pilz.UI.WinForms.Telerik.Symbols" Version="1.2.1" />
<PackageReference Include="UI.for.WinForms.Common" Version="2025.2.612-preview" />
<PackageReference Include="UI.for.WinForms.Themes" Version="2025.2.612-preview" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\ModpackUpdater.Apps\ModpackUpdater.Apps.csproj" />
<ProjectReference Include="..\ModpackUpdater.Apps.AppUpdates\ModpackUpdater.Apps.AppUpdates.csproj" />
<ProjectReference Include="..\ModpackUpdater.Manager\ModpackUpdater.Manager.csproj" />
<ProjectReference Include="..\ModpackUpdater\ModpackUpdater.csproj" />
</ItemGroup>
</Project>
</Project>

View File

@@ -10,9 +10,8 @@ internal class Options
public IReadOnlyList<string> Additionals => additionals;
public bool Help { get; private set; }
public bool Silent { get; private set; }
public bool NoUi { get; private set; }
public string RefTag { get; private set; }
public string Version { get; private set; }
public string? RefTag { get; private set; }
public string? Version { get; private set; }
public UpdateCheckOptionsAdv UpdateOptions { get; } = new();
public Options(string[] args)
@@ -21,12 +20,10 @@ internal class Options
{
{ "silent", "Do not output anything.", s => Silent = true },
{ "h|help", "Writes the help text as output.", h => Help = true },
{ "n|noui", "Install without user interface.", n => NoUi = true },
{ "p|profile=", "Sets the minecraft profile folder.", p => UpdateOptions.ProfileFolder = p },
{ "c|config=", "Sets the modpack update info url.", c => UpdateOptions.ModpackConfig = c },
{ "s|side=", "Sets the installation side.\nDefault side is Client.\nAvailable: Client, Server", s => UpdateOptions.Side = Enum.Parse<Side>(s)},
{ "u|uai", "Disallow an update directly after install. This only has effect if there is no existing installation.", uai => UpdateOptions.AllowUpdaterAfterInstall = false},
{ "noupdate", "Skip the update check.", noupdate => UpdateOptions.NoUpdate = true},
{ "m|maintenance", "Ignores the maintenance mode.", m => UpdateOptions.IgnoreMaintenance = true},
{ "i|nonpublic", "Include non public (currently hidden) updates.", i => UpdateOptions.IncludeNonPublic = true},
{ "k|key=", "An key for retriving extra files on updates.", k => UpdateOptions.ExtrasKey = k},

View File

@@ -1,34 +1,14 @@
using Castle.Core.Logging;
using ModpackUpdater.Manager;
using Newtonsoft.Json;
using Pilz;
using Pilz.Configuration;
using System.Runtime.InteropServices;
[assembly: AssemblyAppVersion("1.9.2.0")]
namespace ModpackUpdater.Apps.Client;
public static class Program
{
private static readonly SettingsManager settingsManager;
private static readonly ILogger log = new ConsoleLogger();
public static ISettings Settings => settingsManager.Instance;
public static ILogger Log => log;
internal static Options Options { get; private set; }
[DllImport("kernel32.dll")]
static extern nint GetConsoleWindow();
[DllImport("user32.dll")]
static extern bool ShowWindow(nint hWnd, int nCmdShow);
static Program()
{
settingsManager = new(GetSettingsPath(2), true);
MigrateLegacySettings(GetSettingsPath(null));
}
internal static Options Options { get; private set; } = null!;
[STAThread]
internal static void Main(string[] args)
@@ -36,61 +16,14 @@ public static class Program
Options = new Options(args);
if (Options.Help)
Options.DrawHelp();
else if (Options.NoUi)
InstallWithoutGui(Options.UpdateOptions, Options.Silent);
else
{
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
ShowWindow(GetConsoleWindow(), 0);
RunApp(Options.UpdateOptions);
}
}
private static void RunApp(UpdateCheckOptionsAdv updateOptions)
{
ApplicationConfiguration.Initialize();
AppGlobals.Initialize();
Application.Run(new MainForm(updateOptions));
}
private static string GetSettingsPath(int? settingsVersion = 3)
{
const string AppDataDirectoryName = "MinecraftModpackUpdater";
var fileNamePostfix = settingsVersion == null ? string.Empty : $"V{settingsVersion}";
var SettingsFileName = $"Settings{fileNamePostfix}.json";
var settingsPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), AppDataDirectoryName);
Directory.CreateDirectory(settingsPath);
settingsPath = Path.Combine(settingsPath, SettingsFileName);
return settingsPath;
}
private static void MigrateLegacySettings(string settingsPath)
{
// Try load legacy config file
if (!File.Exists(settingsPath) || JsonConvert.DeserializeObject<AppConfig>(File.ReadAllText(settingsPath)) is not AppConfig legacyConfig)
return;
// Migrate
var newConfig = Settings.Get<AppConfig>();
newConfig.LastMinecraftProfilePath = legacyConfig.LastMinecraftProfilePath;
if (ModpackInfo.TryLoad(legacyConfig.LastMinecraftProfilePath) is ModpackInfo info)
#pragma warning disable CS0612 // Typ oder Element ist veraltet
info.ConfigUrl = legacyConfig.ConfigFilePath;
// Ensure save settings
settingsManager.Save();
// Delete legacy config file
File.Delete(settingsPath);
InstallWithoutGui(Options.UpdateOptions, Options.Silent);
}
private static void InstallWithoutGui(UpdateCheckOptionsAdv updateOptions, bool silent)
{
var info = ModpackInfo.TryLoad(updateOptions.ProfileFolder);
var config = ModpackConfig.LoadFromUrl(CheckModpackConfigUrl(updateOptions.ModpackConfig, info));
var config = ModpackConfig.LoadFromUrl(CheckModpackConfigUrl(updateOptions.ModpackConfig!, info));
var features = new ModpackFeatures(config);
// Check features
@@ -108,9 +41,6 @@ public static class Program
};
var result = installer.Check(updateOptions).Result;
if (!silent && !updateOptions.NoUpdate && new AppUpdater().Check().Result)
Log.Info("A new version is available!");
if (result.HasUpdates)
{
var success = installer.Install(result).Result;

View File

@@ -1,18 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
https://go.microsoft.com/fwlink/?LinkID=208121.
-->
<!-- https://go.microsoft.com/fwlink/?LinkID=208121. -->
<Project>
<PropertyGroup>
<Configuration>Release</Configuration>
<Platform>Any CPU</Platform>
<PublishDir>bin\publish\windows\</PublishDir>
<PublishDir>..\publish\cli\</PublishDir>
<PublishProtocol>FileSystem</PublishProtocol>
<_TargetId>Folder</_TargetId>
<TargetFramework>net8.0-windows</TargetFramework>
<TargetFramework>net8.0</TargetFramework>
<RuntimeIdentifier>win-x86</RuntimeIdentifier>
<SelfContained>false</SelfContained>
<SelfContained>true</SelfContained>
<PublishSingleFile>true</PublishSingleFile>
<PublishReadyToRun>false</PublishReadyToRun>
<PublishTrimmed>true</PublishTrimmed>
</PropertyGroup>
</Project>

View File

@@ -4,8 +4,7 @@ namespace ModpackUpdater.Apps.Client;
public class UpdateCheckOptionsAdv : UpdateCheckOptions
{
public string ProfileFolder { get; set; }
public string ModpackConfig { get; set; }
public bool NoUpdate { get; set; }
public string ExtrasKey { get; set; }
public string? ProfileFolder { get; set; }
public string? ModpackConfig { get; set; }
public string? ExtrasKey { get; set; }
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 108 KiB

View File

@@ -1,25 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<svg width="480" height="480" viewBox="0 0 480 480" fill="none" xmlns="http://www.w3.org/2000/svg">
<defs>
<clipPath id="clip_path_1">
<rect width="480" height="480" />
</clipPath>
</defs>
<g clip-path="url(#clip_path_1)">
<path d="M360 40L180 40L140 0C140 0 40 0 40 0C17.91 0 0 17.91 0 40C0 40 0 120 0 120L400 120C400 120 400 80 400 80C400 57.91 382.09 40 360 40C360 40 360 40 360 40Z" fill="#FFA000" transform="translate(20 100)" />
<g transform="translate(53 -7)">
<path d="M160.042 63.3334L0 7.91667L13.9167 213.75L160.042 300.833L278.333 205.833L292.25 0L160.042 63.3334Z" fill="#5D4037" fill-rule="evenodd" transform="translate(20.875 63.333)" />
<path d="M0 0L13.9167 205.834L160.042 292.917L160.042 55.4167L0 0Z" fill="#8D6E63" fill-rule="evenodd" transform="translate(20.875 71.25)" />
<path d="M13.9167 112.084L13.9167 79.1667L27.8333 72.2554L27.8333 95L41.75 87.0833L41.75 118.75L62.625 109.028L62.625 55.4167L76.5417 48.6954L76.5417 87.0833L90.4583 80.5679L90.4583 63.3333L104.375 55.4167L104.375 35.3637L118.292 28.6979L118.292 47.5L129.425 41.1667L132.208 0L0 63.3333L0 118.75L13.9167 112.084Z" fill="#43A047" fill-rule="evenodd" transform="translate(180.917 63.333)" />
<path d="M0 47.5L139.167 0L292.25 39.5833L160.042 102.917L0 47.5Z" fill="#B2FF59" fill-rule="evenodd" transform="translate(20.875 23.75)" />
<path d="M0 0L2.78333 40.6442L13.9167 44.3888L13.9167 34.9363L27.8333 39.5833L27.8333 65.0513L48.7083 72.2792L48.7083 34.6196L62.625 39.5833L62.625 77.1004L76.5417 81.9217L76.5417 58.9713L90.4583 63.7925L90.4583 86.743L104.375 91.5563L104.375 82.1671L118.292 87.0834L118.292 74.6067L132.208 79.1667L132.208 101.199L160.042 110.833L160.042 55.4167L0 0Z" fill="#66BB6A" fill-rule="evenodd" transform="translate(20.875 71.25)" />
</g>
<path d="M360 0C360 0 40 0 40 0C17.91 0 0 15.1595 0 33.8571C0 33.8571 0 203.143 0 203.143C0 221.84 17.91 237 40 237C40 237 360 237 360 237C382.09 237 400 221.84 400 203.143C400 203.143 400 33.8571 400 33.8571C400 15.1595 382.09 0 360 0C360 0 360 0 360 0Z" fill="#FFCA28" transform="translate(20 183)" />
<path d="M70 80L0 0L140 0L70 80Z" fill="#1565C0" transform="translate(150 380)" />
<path d="M0 0L60 0L60 111.25L0 111.25L0 0Z" fill="#1565C0" transform="translate(190 280)" />
<path d="M30 15C30 23.28 23.29 30 15 30C6.71002 30 0 23.28 0 15C0 6.72 6.71002 0 15 0C23.29 0 30 6.72 30 15C30 15 30 15 30 15Z" fill="#4A148C" transform="translate(430 60)" />
<path d="M125 100C72.62 100 30 57.38 30 5C30 5 30 0 30 0L0 0L0 10C0 10 0.25 10 0.25 10C2.84 74.93 55.08 127.16 120 129.75C120 129.75 120 130 120 130L130 130L130 100L125 100C125 100 125 100 125 100Z" fill="#9C27B0" transform="translate(330 60)" />
<path d="M75 50C50.19 50 30 29.81 30 5C30 5 30 0 30 0L0 0L0 10C0 10 0.25 10 0.25 10C2.73004 47.36 32.63 77.27 70 79.75C70 79.75 70 80 70 80L80 80L80 50L75 50C75 50 75 50 75 50Z" fill="#7B1FA2" transform="translate(380 60)" />
<path d="M175 150C95.05 150 30 84.95 30 5C30 5 30 0 30 0L0 0L0 10C0 10 0.25 10 0.25 10C2.88998 102.5 77.51 177.11 170 179.75C170 179.75 170 180 170 180L180 180L180 150L175 150C175 150 175 150 175 150Z" fill="#BA68C8" transform="translate(280 60)" />
</g>
</svg>

Before

Width:  |  Height:  |  Size: 3.2 KiB