Add simple installer
This commit is contained in:
parent
cd93b126e2
commit
ecc2512bba
13
Installer/Installer.csproj
Normal file
13
Installer/Installer.csproj
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
<Project Sdk="Microsoft.NET.Sdk.WindowsDesktop">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutputType>WinExe</OutputType>
|
||||||
|
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||||
|
<UseWindowsForms>true</UseWindowsForms>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Folder Include="Properties\" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
120
Installer/InstallerForm.Designer.cs
generated
Normal file
120
Installer/InstallerForm.Designer.cs
generated
Normal file
|
@ -0,0 +1,120 @@
|
||||||
|
namespace Installer
|
||||||
|
{
|
||||||
|
partial class InstallerForm
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Required designer variable.
|
||||||
|
/// </summary>
|
||||||
|
private System.ComponentModel.IContainer components = null;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Clean up any resources being used.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||||
|
protected override void Dispose(bool disposing)
|
||||||
|
{
|
||||||
|
if (disposing && (components != null))
|
||||||
|
{
|
||||||
|
components.Dispose();
|
||||||
|
}
|
||||||
|
base.Dispose(disposing);
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Windows Form Designer generated code
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Required method for Designer support - do not modify
|
||||||
|
/// the contents of this method with the code editor.
|
||||||
|
/// </summary>
|
||||||
|
private void InitializeComponent()
|
||||||
|
{
|
||||||
|
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(InstallerForm));
|
||||||
|
this.install = new System.Windows.Forms.Button();
|
||||||
|
this.installLabel = new System.Windows.Forms.Label();
|
||||||
|
this.progress = new System.Windows.Forms.ProgressBar();
|
||||||
|
this.processLabel = new System.Windows.Forms.Label();
|
||||||
|
this.log = new System.Windows.Forms.Button();
|
||||||
|
this.SuspendLayout();
|
||||||
|
//
|
||||||
|
// install
|
||||||
|
//
|
||||||
|
this.install.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)
|
||||||
|
| System.Windows.Forms.AnchorStyles.Right)));
|
||||||
|
this.install.Location = new System.Drawing.Point(12, 92);
|
||||||
|
this.install.Name = "install";
|
||||||
|
this.install.Size = new System.Drawing.Size(539, 27);
|
||||||
|
this.install.TabIndex = 0;
|
||||||
|
this.install.Text = "Install";
|
||||||
|
this.install.UseVisualStyleBackColor = true;
|
||||||
|
this.install.Click += new System.EventHandler(this.install_Click);
|
||||||
|
//
|
||||||
|
// installLabel
|
||||||
|
//
|
||||||
|
this.installLabel.AutoSize = true;
|
||||||
|
this.installLabel.Location = new System.Drawing.Point(12, 9);
|
||||||
|
this.installLabel.Name = "installLabel";
|
||||||
|
this.installLabel.Size = new System.Drawing.Size(550, 75);
|
||||||
|
this.installLabel.TabIndex = 1;
|
||||||
|
this.installLabel.Text = resources.GetString("installLabel.Text");
|
||||||
|
//
|
||||||
|
// progress
|
||||||
|
//
|
||||||
|
this.progress.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)
|
||||||
|
| System.Windows.Forms.AnchorStyles.Right)));
|
||||||
|
this.progress.Location = new System.Drawing.Point(12, 92);
|
||||||
|
this.progress.Maximum = 6;
|
||||||
|
this.progress.Name = "progress";
|
||||||
|
this.progress.Size = new System.Drawing.Size(539, 27);
|
||||||
|
this.progress.TabIndex = 2;
|
||||||
|
this.progress.Visible = false;
|
||||||
|
//
|
||||||
|
// processLabel
|
||||||
|
//
|
||||||
|
this.processLabel.ForeColor = System.Drawing.SystemColors.ControlText;
|
||||||
|
this.processLabel.Location = new System.Drawing.Point(422, 70);
|
||||||
|
this.processLabel.Name = "processLabel";
|
||||||
|
this.processLabel.Size = new System.Drawing.Size(129, 19);
|
||||||
|
this.processLabel.TabIndex = 3;
|
||||||
|
this.processLabel.TextAlign = System.Drawing.ContentAlignment.TopRight;
|
||||||
|
//
|
||||||
|
// log
|
||||||
|
//
|
||||||
|
this.log.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
|
||||||
|
this.log.Location = new System.Drawing.Point(524, 4);
|
||||||
|
this.log.Name = "log";
|
||||||
|
this.log.Size = new System.Drawing.Size(36, 23);
|
||||||
|
this.log.TabIndex = 4;
|
||||||
|
this.log.Text = "Log";
|
||||||
|
this.log.UseVisualStyleBackColor = true;
|
||||||
|
this.log.Visible = false;
|
||||||
|
this.log.Click += new System.EventHandler(this.log_Click);
|
||||||
|
//
|
||||||
|
// InstallerForm
|
||||||
|
//
|
||||||
|
this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F);
|
||||||
|
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||||
|
this.ClientSize = new System.Drawing.Size(563, 131);
|
||||||
|
this.Controls.Add(this.log);
|
||||||
|
this.Controls.Add(this.processLabel);
|
||||||
|
this.Controls.Add(this.progress);
|
||||||
|
this.Controls.Add(this.installLabel);
|
||||||
|
this.Controls.Add(this.install);
|
||||||
|
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
|
||||||
|
this.Name = "InstallerForm";
|
||||||
|
this.ShowIcon = false;
|
||||||
|
this.Text = "UpTool2 Installer";
|
||||||
|
this.ResumeLayout(false);
|
||||||
|
this.PerformLayout();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
private System.Windows.Forms.Button install;
|
||||||
|
private System.Windows.Forms.Label installLabel;
|
||||||
|
private System.Windows.Forms.ProgressBar progress;
|
||||||
|
private System.Windows.Forms.Label processLabel;
|
||||||
|
private System.Windows.Forms.Button log;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
89
Installer/InstallerForm.cs
Normal file
89
Installer/InstallerForm.cs
Normal file
|
@ -0,0 +1,89 @@
|
||||||
|
using System;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.Globalization;
|
||||||
|
using System.IO;
|
||||||
|
using System.IO.Compression;
|
||||||
|
using System.Net;
|
||||||
|
using System.Security.Cryptography;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
using System.Xml.Linq;
|
||||||
|
|
||||||
|
namespace Installer
|
||||||
|
{
|
||||||
|
public partial class InstallerForm : Form
|
||||||
|
{
|
||||||
|
private string Log = "";
|
||||||
|
|
||||||
|
public InstallerForm()
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
Step(0, "Initialized");
|
||||||
|
Log.TrimStart(Environment.NewLine.ToCharArray());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void install_Click(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
log.Visible = false;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
progress.Visible = true;
|
||||||
|
WebClient client = new WebClient();
|
||||||
|
Step(1, "Downloading metadata");
|
||||||
|
XElement meta = XDocument.Load("https://github.com/JFronny/UpTool2/releases/latest/download/meta.xml")
|
||||||
|
.Element("meta");
|
||||||
|
Step(2, "Downloading binary");
|
||||||
|
byte[] dl = client.DownloadData(meta.Element("File").Value);
|
||||||
|
Step(3, "Verifying integrity");
|
||||||
|
using (SHA256CryptoServiceProvider sha256 = new SHA256CryptoServiceProvider())
|
||||||
|
{
|
||||||
|
string pkgHash = BitConverter.ToString(sha256.ComputeHash(dl)).Replace("-", string.Empty).ToUpper();
|
||||||
|
if (pkgHash != meta.Element("Hash").Value.ToUpper())
|
||||||
|
throw new Exception(
|
||||||
|
$"The hash is not equal to the one stored in the repo:\r\nPackage: {pkgHash}\r\nOnline: {meta.Element("Hash").Value.ToUpper()}");
|
||||||
|
}
|
||||||
|
Step(4, "Extracting");
|
||||||
|
if (Directory.Exists(PathTool.GetRelative("Install")))
|
||||||
|
Directory.Delete(PathTool.GetRelative("Install"), true);
|
||||||
|
Directory.CreateDirectory(PathTool.GetRelative("Install"));
|
||||||
|
using (MemoryStream ms = new MemoryStream(dl))
|
||||||
|
{
|
||||||
|
using ZipArchive ar = new ZipArchive(ms);
|
||||||
|
ar.ExtractToDirectory(PathTool.GetRelative("Install"), true);
|
||||||
|
}
|
||||||
|
Step(5, "Creating shortcut");
|
||||||
|
Shortcut.Make(PathTool.GetRelative("Install", "UpTool2.exe"),
|
||||||
|
Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Programs), "UpTool2.lnk"));
|
||||||
|
Step(6, "Done!");
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Step(progress.Value, $"Failed!{Environment.NewLine}{ex}");
|
||||||
|
BackColor = Color.Red;
|
||||||
|
processLabel.Text = "Failed";
|
||||||
|
new Thread(() =>
|
||||||
|
{
|
||||||
|
Thread.Sleep(1000);
|
||||||
|
Invoke(new Action(() =>
|
||||||
|
{
|
||||||
|
BackColor = SystemColors.Control;
|
||||||
|
progress.Visible = false;
|
||||||
|
}));
|
||||||
|
}).Start();
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
log.Visible = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Step(int p, string text)
|
||||||
|
{
|
||||||
|
progress.Value = p;
|
||||||
|
processLabel.Text = text;
|
||||||
|
Log += $"{Environment.NewLine}[{DateTime.Now.ToString(CultureInfo.InvariantCulture).Split(' ')[1]}] {text}";
|
||||||
|
}
|
||||||
|
|
||||||
|
private void log_Click(object sender, EventArgs e) => new Thread(() => MessageBox.Show(Log)).Start();
|
||||||
|
}
|
||||||
|
}
|
68
Installer/InstallerForm.resx
Normal file
68
Installer/InstallerForm.resx
Normal file
|
@ -0,0 +1,68 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<root>
|
||||||
|
<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="installLabel.Text" xml:space="preserve">
|
||||||
|
<value>Thank you for downloading UpTool2.
|
||||||
|
To prevent inconsistent behavior you will need to install this before running.
|
||||||
|
Files will be placed in %appdata%\UpTool2 and %appdata%\Microsoft\Windows\Start Menu\Programs
|
||||||
|
|
||||||
|
Do you want to continue?</value>
|
||||||
|
</data>
|
||||||
|
</root>
|
19
Installer/PathTool.cs
Normal file
19
Installer/PathTool.cs
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace Installer
|
||||||
|
{
|
||||||
|
internal static class PathTool
|
||||||
|
{
|
||||||
|
public static string dir =>
|
||||||
|
Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "UpTool2");
|
||||||
|
|
||||||
|
public static string tempPath => GetRelative("tmp");
|
||||||
|
public static string appsPath => GetRelative("Apps");
|
||||||
|
public static string InfoXml => GetRelative("info.xml");
|
||||||
|
|
||||||
|
public static string GetRelative(params string[] segments) =>
|
||||||
|
Path.Combine(new[] {dir}.Concat(segments).ToArray());
|
||||||
|
}
|
||||||
|
}
|
20
Installer/Program.cs
Normal file
20
Installer/Program.cs
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
using System;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
|
||||||
|
namespace Installer
|
||||||
|
{
|
||||||
|
internal static class Program
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The main entry point for the application.
|
||||||
|
/// </summary>
|
||||||
|
[STAThread]
|
||||||
|
private static void Main()
|
||||||
|
{
|
||||||
|
Application.SetHighDpiMode(HighDpiMode.SystemAware);
|
||||||
|
Application.EnableVisualStyles();
|
||||||
|
Application.SetCompatibleTextRenderingDefault(false);
|
||||||
|
Application.Run(new InstallerForm());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,7 +2,7 @@
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
namespace UpTool2.Tool
|
namespace Installer
|
||||||
{
|
{
|
||||||
internal static class Shortcut
|
internal static class Shortcut
|
||||||
{
|
{
|
12
UpTool2.sln
12
UpTool2.sln
|
@ -3,16 +3,18 @@ Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
# Visual Studio Version 16
|
# Visual Studio Version 16
|
||||||
VisualStudioVersion = 16.0.29230.47
|
VisualStudioVersion = 16.0.29230.47
|
||||||
MinimumVisualStudioVersion = 10.0.40219.1
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UpTool2", "UpTool2\UpTool2.csproj", "{C0C1E002-9E13-4E8F-A035-DBDC5128E00E}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UpTool2", "UpTool2\UpTool2.csproj", "{C0C1E002-9E13-4E8F-A035-DBDC5128E00E}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{9841227C-3F1B-4C32-8123-3DB2CF4E15EE}"
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{9841227C-3F1B-4C32-8123-3DB2CF4E15EE}"
|
||||||
ProjectSection(SolutionItems) = preProject
|
ProjectSection(SolutionItems) = preProject
|
||||||
|
.gitignore = .gitignore
|
||||||
.github\workflows\main.yml = .github\workflows\main.yml
|
.github\workflows\main.yml = .github\workflows\main.yml
|
||||||
README.md = README.md
|
README.md = README.md
|
||||||
.gitignore = .gitignore
|
|
||||||
EndProjectSection
|
EndProjectSection
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UpTool build tool", "UpTool build tool\UpTool build tool.csproj", "{AAB8D6BA-3A43-4DC4-95EE-6757482B77FD}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UpTool build tool", "UpTool build tool\UpTool build tool.csproj", "{AAB8D6BA-3A43-4DC4-95EE-6757482B77FD}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Installer", "Installer\Installer.csproj", "{1D273392-3796-4BE9-A67F-BB402315D52D}"
|
||||||
EndProject
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
|
@ -28,6 +30,10 @@ Global
|
||||||
{AAB8D6BA-3A43-4DC4-95EE-6757482B77FD}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{AAB8D6BA-3A43-4DC4-95EE-6757482B77FD}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{AAB8D6BA-3A43-4DC4-95EE-6757482B77FD}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{AAB8D6BA-3A43-4DC4-95EE-6757482B77FD}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{AAB8D6BA-3A43-4DC4-95EE-6757482B77FD}.Release|Any CPU.Build.0 = Release|Any CPU
|
{AAB8D6BA-3A43-4DC4-95EE-6757482B77FD}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{1D273392-3796-4BE9-A67F-BB402315D52D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{1D273392-3796-4BE9-A67F-BB402315D52D}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{1D273392-3796-4BE9-A67F-BB402315D52D}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{1D273392-3796-4BE9-A67F-BB402315D52D}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
|
|
|
@ -9,6 +9,7 @@ using System.Windows.Forms;
|
||||||
using UpTool2.DataStructures;
|
using UpTool2.DataStructures;
|
||||||
using UpTool2.Properties;
|
using UpTool2.Properties;
|
||||||
using UpTool2.Tool;
|
using UpTool2.Tool;
|
||||||
|
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
@ -46,7 +47,7 @@ namespace UpTool2
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
#endif
|
#endif
|
||||||
AppInstall.Install((App) action_install.Tag);
|
AppInstall.Install((App) action_install.Tag);
|
||||||
#if !DEBUG
|
#if !DEBUG
|
||||||
}
|
}
|
||||||
catch (Exception e1)
|
catch (Exception e1)
|
||||||
|
@ -91,16 +92,15 @@ namespace UpTool2
|
||||||
#if !DEBUG
|
#if !DEBUG
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
if (searchPackageDialog.ShowDialog() != DialogResult.OK)
|
if (searchPackageDialog.ShowDialog() != DialogResult.OK)
|
||||||
return;
|
return;
|
||||||
Guid id = Guid.NewGuid();
|
Guid id = Guid.NewGuid();
|
||||||
while (GlobalVariables.Apps.ContainsKey(id) || Directory.Exists(PathTool.GetAppPath(id)))
|
while (GlobalVariables.Apps.ContainsKey(id) || Directory.Exists(PathTool.GetAppPath(id)))
|
||||||
id = Guid.NewGuid();
|
id = Guid.NewGuid();
|
||||||
App appI = new App(AppNameDialog.Show(), "Locally installed package, removal only",
|
App appI = new App(AppNameDialog.Show(), "Locally installed package, removal only",
|
||||||
GlobalVariables.minimumVer, "", true, "", id, Color.Red, Resources.C_64.ToBitmap(), false, "");
|
GlobalVariables.minimumVer, "", true, "", id, Color.Red, Resources.C_64.ToBitmap(), false, "");
|
||||||
AppInstall.InstallZip(searchPackageDialog.FileName, appI);
|
AppInstall.InstallZip(searchPackageDialog.FileName, appI);
|
||||||
#if !DEBUG
|
#if !DEBUG
|
||||||
}
|
}
|
||||||
catch (Exception e1)
|
catch (Exception e1)
|
||||||
|
@ -184,7 +184,7 @@ namespace UpTool2
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
+ $"{Environment.NewLine}File was: {path}"
|
+ $"{Environment.NewLine}File was: {path}"
|
||||||
#endif
|
#endif
|
||||||
+ "Failed to start!");
|
+ "Failed to start!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -242,15 +242,15 @@ namespace UpTool2
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
#endif
|
#endif
|
||||||
Enum.TryParse(filterBox.SelectedValue.ToString(), out Status status);
|
Enum.TryParse(filterBox.SelectedValue.ToString(), out Status status);
|
||||||
for (int i = 0; i < sidebarPanel.Controls.Count; i++)
|
for (int i = 0; i < sidebarPanel.Controls.Count; i++)
|
||||||
{
|
{
|
||||||
Panel sidebarIcon = (Panel) sidebarPanel.Controls[i];
|
Panel sidebarIcon = (Panel) sidebarPanel.Controls[i];
|
||||||
App app = (App) sidebarIcon.Tag;
|
App app = (App) sidebarIcon.Tag;
|
||||||
sidebarIcon.Visible = app.Name.Contains(searchBox.Text) &&
|
sidebarIcon.Visible = app.Name.Contains(searchBox.Text) &&
|
||||||
((int) app.status & (int) (Program.Online ? status : Status.Installed)) != 0;
|
((int) app.status & (int) (Program.Online ? status : Status.Installed)) != 0;
|
||||||
}
|
}
|
||||||
ClearSelection();
|
ClearSelection();
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -14,10 +14,6 @@ using System.Xml;
|
||||||
using System.Xml.Linq;
|
using System.Xml.Linq;
|
||||||
using UpTool2.Tool;
|
using UpTool2.Tool;
|
||||||
|
|
||||||
#if !DEBUG
|
|
||||||
using Shortcut = UpTool2.Tool.Shortcut;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace UpTool2
|
namespace UpTool2
|
||||||
{
|
{
|
||||||
internal static class Program
|
internal static class Program
|
||||||
|
@ -39,53 +35,33 @@ namespace UpTool2
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
#endif
|
#endif
|
||||||
try
|
try
|
||||||
{
|
|
||||||
hasHandle = mutex.WaitOne(5000, false);
|
|
||||||
if (hasHandle == false)
|
|
||||||
{
|
{
|
||||||
Console.WriteLine("Mutex property of other process, quitting");
|
hasHandle = mutex.WaitOne(5000, false);
|
||||||
Process[] processes = Process.GetProcessesByName("UpTool2");
|
if (hasHandle == false)
|
||||||
if (processes.Length > 0)
|
{
|
||||||
WindowHelper.BringProcessToFront(Process.GetProcessesByName("UpTool2")[0]);
|
Console.WriteLine("Mutex property of other process, quitting");
|
||||||
Environment.Exit(0);
|
Process[] processes = Process.GetProcessesByName("UpTool2");
|
||||||
|
if (processes.Length > 0)
|
||||||
|
WindowHelper.BringProcessToFront(Process.GetProcessesByName("UpTool2")[0]);
|
||||||
|
Environment.Exit(0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
catch (AbandonedMutexException)
|
||||||
catch (AbandonedMutexException)
|
{
|
||||||
{
|
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
Debug.WriteLine("Mutex abandoned");
|
Debug.WriteLine("Mutex abandoned");
|
||||||
#endif
|
#endif
|
||||||
hasHandle = true;
|
hasHandle = true;
|
||||||
}
|
|
||||||
if (!Directory.Exists(PathTool.dir))
|
|
||||||
Directory.CreateDirectory(PathTool.dir);
|
|
||||||
FixXml();
|
|
||||||
string metaXml = XDocument.Load(PathTool.InfoXml).Element("meta").Element("UpdateSource").Value;
|
|
||||||
Online = Ping(metaXml);
|
|
||||||
|
|
||||||
#if !DEBUG
|
|
||||||
if (Application.ExecutablePath != PathTool.GetRelative("Install", "UpTool2.dll"))
|
|
||||||
{
|
|
||||||
if (!Online)
|
|
||||||
throw new WebException("Could fetch Metadata (are you online?)");
|
|
||||||
if (MessageBox.Show(@"Thank you for downloading UpTool2.
|
|
||||||
To prevent inconsistent behavior you will need to install this before running.
|
|
||||||
Files will be placed in %appdata%\UpTool2 and %appdata%\Microsoft\Windows\Start Menu\Programs
|
|
||||||
Do you want to continue?", "UpTool2", MessageBoxButtons.YesNo) != DialogResult.Yes)
|
|
||||||
throw new Exception("Exiting...");
|
|
||||||
MessageBox.Show("Installing an Update. Please restart from your start menu!");
|
|
||||||
InstallUpdate(XDocument.Load(metaXml).Element("meta"));
|
|
||||||
Shortcut.Make(PathTool.GetRelative("Install", "UpTool2.exe"),
|
|
||||||
Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Programs), "UpTool2.lnk"));
|
|
||||||
mutex.ReleaseMutex();
|
|
||||||
Environment.Exit(0);
|
|
||||||
}
|
}
|
||||||
if (!File.Exists(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Programs),
|
if (!Directory.Exists(PathTool.dir))
|
||||||
"UpTool2.lnk")))
|
Directory.CreateDirectory(PathTool.dir);
|
||||||
Shortcut.Make(PathTool.GetRelative("Install", "UpTool2.exe"),
|
FixXml();
|
||||||
Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Programs), "UpTool2.lnk"));
|
string metaXml = XDocument.Load(PathTool.InfoXml).Element("meta").Element("UpdateSource").Value;
|
||||||
#endif
|
Online = Ping(metaXml);
|
||||||
|
if (Application.ExecutablePath != PathTool.GetRelative("Install", "UpTool2.dll"))
|
||||||
|
MessageBox.Show(
|
||||||
|
$"WARNING!{Environment.NewLine}Running from outside the install directory is not recommended!");
|
||||||
if (!Directory.Exists(PathTool.GetRelative("Apps")))
|
if (!Directory.Exists(PathTool.GetRelative("Apps")))
|
||||||
Directory.CreateDirectory(PathTool.GetRelative("Apps"));
|
Directory.CreateDirectory(PathTool.GetRelative("Apps"));
|
||||||
if (!Online || UpdateCheck(metaXml))
|
if (!Online || UpdateCheck(metaXml))
|
||||||
|
@ -187,12 +163,6 @@ Do you want to continue?", "UpTool2", MessageBoxButtons.YesNo) != DialogResult.Y
|
||||||
XElement meta = XDocument.Load(metaXml).Element("meta");
|
XElement meta = XDocument.Load(metaXml).Element("meta");
|
||||||
if (Assembly.GetExecutingAssembly().GetName().Version >= Version.Parse(meta.Element("Version").Value))
|
if (Assembly.GetExecutingAssembly().GetName().Version >= Version.Parse(meta.Element("Version").Value))
|
||||||
return true;
|
return true;
|
||||||
InstallUpdate(meta);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void InstallUpdate(XElement meta)
|
|
||||||
{
|
|
||||||
byte[] dl;
|
byte[] dl;
|
||||||
using (DownloadDialog dlg = new DownloadDialog(meta.Element("File").Value))
|
using (DownloadDialog dlg = new DownloadDialog(meta.Element("File").Value))
|
||||||
{
|
{
|
||||||
|
@ -207,24 +177,24 @@ Do you want to continue?", "UpTool2", MessageBoxButtons.YesNo) != DialogResult.Y
|
||||||
throw new Exception("The hash is not equal to the one stored in the repo:\r\nPackage: " + pkgHash +
|
throw new Exception("The hash is not equal to the one stored in the repo:\r\nPackage: " + pkgHash +
|
||||||
"\r\nOnline: " + meta.Element("Hash").Value.ToUpper());
|
"\r\nOnline: " + meta.Element("Hash").Value.ToUpper());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Directory.Exists(PathTool.GetRelative("Install", "tmp")))
|
if (Directory.Exists(PathTool.GetRelative("Install", "tmp")))
|
||||||
Directory.Delete(PathTool.GetRelative("Install", "tmp"), true);
|
Directory.Delete(PathTool.GetRelative("Install", "tmp"), true);
|
||||||
Directory.CreateDirectory(PathTool.GetRelative("Install", "tmp"));
|
Directory.CreateDirectory(PathTool.GetRelative("Install", "tmp"));
|
||||||
using (MemoryStream ms = new MemoryStream(dl))
|
using (MemoryStream ms = new MemoryStream(dl))
|
||||||
{
|
{
|
||||||
using ZipArchive ar = new ZipArchive(ms);
|
using ZipArchive ar = new ZipArchive(ms);
|
||||||
ar.Entries.Where(s => !string.IsNullOrEmpty(s.Name)).ToList().ForEach(s =>
|
ar.ExtractToDirectory(PathTool.GetRelative("Install", "tmp"), true);
|
||||||
{
|
|
||||||
s.ExtractToFile(PathTool.GetRelative("Install", "tmp", s.Name), true);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
Splash.Hide();
|
Splash.Hide();
|
||||||
Process.Start(new ProcessStartInfo
|
Process.Start(new ProcessStartInfo
|
||||||
{
|
{
|
||||||
FileName = "cmd.exe", Arguments = @"/C timeout /t 2 & xcopy /s /e /y tmp\* .", CreateNoWindow = true,
|
FileName = "cmd.exe",
|
||||||
WindowStyle = ProcessWindowStyle.Hidden, WorkingDirectory = PathTool.GetRelative("Install")
|
Arguments = @"/C timeout /t 2 & xcopy /s /e /y tmp\* .",
|
||||||
|
CreateNoWindow = true,
|
||||||
|
WindowStyle = ProcessWindowStyle.Hidden,
|
||||||
|
WorkingDirectory = PathTool.GetRelative("Install")
|
||||||
});
|
});
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static bool Ping(string url)
|
private static bool Ping(string url)
|
||||||
|
|
|
@ -19,28 +19,28 @@ namespace UpTool2.Tool
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
#endif
|
#endif
|
||||||
app = appI.appPath;
|
app = appI.appPath;
|
||||||
tmp = PathTool.tempPath;
|
tmp = PathTool.tempPath;
|
||||||
if (Directory.Exists(tmp))
|
if (Directory.Exists(tmp))
|
||||||
Directory.Delete(tmp, true);
|
Directory.Delete(tmp, true);
|
||||||
Directory.CreateDirectory(tmp);
|
Directory.CreateDirectory(tmp);
|
||||||
if (Directory.Exists(app))
|
if (Directory.Exists(app))
|
||||||
Directory.Delete(app, true);
|
Directory.Delete(app, true);
|
||||||
Directory.CreateDirectory(app);
|
Directory.CreateDirectory(app);
|
||||||
using DownloadDialog dlg = new DownloadDialog(appI.File);
|
using DownloadDialog dlg = new DownloadDialog(appI.File);
|
||||||
if (dlg.ShowDialog() != DialogResult.OK)
|
if (dlg.ShowDialog() != DialogResult.OK)
|
||||||
throw new Exception("Download failed");
|
throw new Exception("Download failed");
|
||||||
using (SHA256CryptoServiceProvider sha256 = new SHA256CryptoServiceProvider())
|
using (SHA256CryptoServiceProvider sha256 = new SHA256CryptoServiceProvider())
|
||||||
{
|
{
|
||||||
string pkgHash = BitConverter.ToString(sha256.ComputeHash(dlg.Result)).Replace("-", string.Empty)
|
string pkgHash = BitConverter.ToString(sha256.ComputeHash(dlg.Result)).Replace("-", string.Empty)
|
||||||
.ToUpper();
|
.ToUpper();
|
||||||
if (pkgHash != appI.Hash.ToUpper())
|
if (pkgHash != appI.Hash.ToUpper())
|
||||||
throw new Exception($@"The hash is not equal to the one stored in the repo:
|
throw new Exception($@"The hash is not equal to the one stored in the repo:
|
||||||
Package: {pkgHash}
|
Package: {pkgHash}
|
||||||
Online: {appI.Hash.ToUpper()}");
|
Online: {appI.Hash.ToUpper()}");
|
||||||
}
|
}
|
||||||
File.WriteAllBytes(Path.Combine(app, "package.zip"), dlg.Result);
|
File.WriteAllBytes(Path.Combine(app, "package.zip"), dlg.Result);
|
||||||
CompleteInstall(appI);
|
CompleteInstall(appI);
|
||||||
#if !DEBUG
|
#if !DEBUG
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
|
@ -52,8 +52,8 @@ Online: {appI.Hash.ToUpper()}");
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
#endif
|
#endif
|
||||||
if (tmp != "" && Directory.Exists(tmp))
|
if (tmp != "" && Directory.Exists(tmp))
|
||||||
Directory.Delete(tmp, true);
|
Directory.Delete(tmp, true);
|
||||||
#if !DEBUG
|
#if !DEBUG
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -97,8 +97,6 @@ Online: {appI.Hash.ToUpper()}");
|
||||||
string mainFile)
|
string mainFile)
|
||||||
{
|
{
|
||||||
#if !DEBUG
|
#if !DEBUG
|
||||||
try
|
|
||||||
{
|
|
||||||
#endif
|
#endif
|
||||||
string tmp = PathTool.tempPath;
|
string tmp = PathTool.tempPath;
|
||||||
ZipFile.ExtractToDirectory(Path.Combine(appPath, "package.zip"), tmp);
|
ZipFile.ExtractToDirectory(Path.Combine(appPath, "package.zip"), tmp);
|
||||||
|
@ -117,8 +115,6 @@ Online: {appI.Hash.ToUpper()}");
|
||||||
if (GlobalVariables.RelE)
|
if (GlobalVariables.RelE)
|
||||||
GlobalVariables.ReloadElements.Invoke();
|
GlobalVariables.ReloadElements.Invoke();
|
||||||
#if !DEBUG
|
#if !DEBUG
|
||||||
}
|
|
||||||
catch { throw; }
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,65 +32,68 @@ namespace UpTool2.Tool
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
#endif
|
#endif
|
||||||
XDocument repo = XDocument.Load(new Uri(repArr[i]).Unshorten().AbsoluteUri);
|
XDocument repo = XDocument.Load(new Uri(repArr[i]).Unshorten().AbsoluteUri);
|
||||||
repArr.AddRange(repo.Element("repo").Elements("repolink").Select(s => s.Value)
|
repArr.AddRange(repo.Element("repo").Elements("repolink").Select(s => s.Value)
|
||||||
.Where(s => !repArr.Contains(s)));
|
.Where(s => !repArr.Contains(s)));
|
||||||
XElement[] tmp_apparray = repo.Element("repo").Elements("app").Where(app =>
|
XElement[] tmp_apparray = repo.Element("repo").Elements("app").Where(app =>
|
||||||
!tmpAppsList.Any(a => a.Element("ID").Value == app.Element("ID").Value) ||
|
!tmpAppsList.Any(a => a.Element("ID").Value == app.Element("ID").Value) ||
|
||||||
!tmpAppsList
|
!tmpAppsList
|
||||||
.Where(a => a.Element("ID").Value == app.Element("ID").Value).Any(a =>
|
.Where(a => a.Element("ID").Value == app.Element("ID").Value).Any(a =>
|
||||||
GetVer(a.Element("Version")) >= app.Element("Version").GetVer())).ToArray()
|
GetVer(a.Element("Version")) >= app.Element("Version").GetVer())).ToArray()
|
||||||
.Concat(repo.Element("repo").Elements("applink")
|
.Concat(repo.Element("repo").Elements("applink")
|
||||||
.Select(s => XDocument.Load(new Uri(s.Value).Unshorten().AbsoluteUri).Element("app"))).ToArray();
|
.Select(s => XDocument.Load(new Uri(s.Value).Unshorten().AbsoluteUri).Element("app")))
|
||||||
for (int i1 = 0; i1 < tmp_apparray.Length; i1++)
|
.ToArray();
|
||||||
{
|
for (int i1 = 0; i1 < tmp_apparray.Length; i1++)
|
||||||
XElement app = tmp_apparray[i1];
|
{
|
||||||
//"Sanity check"
|
XElement app = tmp_apparray[i1];
|
||||||
Version.Parse(app.Element("Version").Value);
|
//"Sanity check"
|
||||||
Guid.Parse(app.Element("ID").Value);
|
Version.Parse(app.Element("Version").Value);
|
||||||
//Create XElement
|
Guid.Parse(app.Element("ID").Value);
|
||||||
tmpAppsList.Add(new XElement("App",
|
//Create XElement
|
||||||
new XElement("Name", app.Element("Name").Value),
|
tmpAppsList.Add(new XElement("App",
|
||||||
new XElement("Description", app.Element("Description").Value),
|
new XElement("Name", app.Element("Name").Value),
|
||||||
new XElement("Version", app.Element("Version").Value),
|
new XElement("Description", app.Element("Description").Value),
|
||||||
new XElement("ID", app.Element("ID").Value),
|
new XElement("Version", app.Element("Version").Value),
|
||||||
new XElement("File", app.Element("File").Value),
|
new XElement("ID", app.Element("ID").Value),
|
||||||
new XElement("Hash", app.Element("Hash").Value)
|
new XElement("File", app.Element("File").Value),
|
||||||
));
|
new XElement("Hash", app.Element("Hash").Value)
|
||||||
if (app.Element("MainFile") != null)
|
));
|
||||||
tmpAppsList.Last().Add(new XElement("MainFile", app.Element("MainFile").Value));
|
if (app.Element("MainFile") != null)
|
||||||
if (app.Element("Icon") != null)
|
tmpAppsList.Last().Add(new XElement("MainFile", app.Element("MainFile").Value));
|
||||||
try
|
if (app.Element("Icon") != null)
|
||||||
{
|
try
|
||||||
//Scale Image and save as Base64
|
{
|
||||||
Image src = Image.FromStream(client.OpenRead(new Uri(app.Element("Icon").Value).Unshorten()));
|
//Scale Image and save as Base64
|
||||||
Bitmap dest = new Bitmap(70, 70);
|
Image src = Image.FromStream(
|
||||||
dest.SetResolution(src.HorizontalResolution, src.VerticalResolution);
|
client.OpenRead(new Uri(app.Element("Icon").Value).Unshorten()));
|
||||||
using (Graphics g = Graphics.FromImage(dest))
|
Bitmap dest = new Bitmap(70, 70);
|
||||||
|
dest.SetResolution(src.HorizontalResolution, src.VerticalResolution);
|
||||||
|
using (Graphics g = Graphics.FromImage(dest))
|
||||||
|
{
|
||||||
|
g.CompositingMode = CompositingMode.SourceCopy;
|
||||||
|
g.CompositingQuality = CompositingQuality.HighQuality;
|
||||||
|
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
|
||||||
|
g.SmoothingMode = SmoothingMode.HighQuality;
|
||||||
|
g.PixelOffsetMode = PixelOffsetMode.HighQuality;
|
||||||
|
using ImageAttributes wrapMode = new ImageAttributes();
|
||||||
|
wrapMode.SetWrapMode(WrapMode.TileFlipXY);
|
||||||
|
g.DrawImage(src, new Rectangle(0, 0, 70, 70), 0, 0, src.Width, src.Height,
|
||||||
|
GraphicsUnit.Pixel, wrapMode);
|
||||||
|
}
|
||||||
|
using MemoryStream ms = new MemoryStream();
|
||||||
|
dest.Save(ms, ImageFormat.Png);
|
||||||
|
tmpAppsList.Last()
|
||||||
|
.Add(new XElement("Icon", Convert.ToBase64String(ms.ToArray())));
|
||||||
|
}
|
||||||
|
catch
|
||||||
{
|
{
|
||||||
g.CompositingMode = CompositingMode.SourceCopy;
|
|
||||||
g.CompositingQuality = CompositingQuality.HighQuality;
|
|
||||||
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
|
|
||||||
g.SmoothingMode = SmoothingMode.HighQuality;
|
|
||||||
g.PixelOffsetMode = PixelOffsetMode.HighQuality;
|
|
||||||
using ImageAttributes wrapMode = new ImageAttributes();
|
|
||||||
wrapMode.SetWrapMode(WrapMode.TileFlipXY);
|
|
||||||
g.DrawImage(src, new Rectangle(0, 0, 70, 70), 0, 0, src.Width, src.Height,
|
|
||||||
GraphicsUnit.Pixel, wrapMode);
|
|
||||||
}
|
}
|
||||||
using MemoryStream ms = new MemoryStream();
|
|
||||||
dest.Save(ms, ImageFormat.Png);
|
|
||||||
tmpAppsList.Last()
|
|
||||||
.Add(new XElement("Icon", Convert.ToBase64String(ms.ToArray())));
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tmpAppsList.Count(a => a.Element("ID").Value == app.Element("ID").Value) > 1)
|
if (tmpAppsList.Count(a => a.Element("ID").Value == app.Element("ID").Value) > 1)
|
||||||
tmpAppsList.Where(a => a.Element("ID").Value == app.Element("ID").Value).Reverse().Skip(1)
|
tmpAppsList.Where(a => a.Element("ID").Value == app.Element("ID").Value).Reverse()
|
||||||
.ToList().ForEach(a => tmpAppsList.Remove(a));
|
.Skip(1)
|
||||||
}
|
.ToList().ForEach(a => tmpAppsList.Remove(a));
|
||||||
|
}
|
||||||
#if !DEBUG
|
#if !DEBUG
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
|
|
Reference in New Issue
Block a user