Improved Updates

This commit is contained in:
CreepyCrafter24 2019-11-11 14:41:11 +01:00
parent ec18671b4f
commit 128434f1f7
5 changed files with 139 additions and 47 deletions

View File

@ -3,7 +3,6 @@ More apps: Laptop Sim (when done)
Split up main File (MainForm.cs) to (more or less) independent modules
Allow Repos to contain "Links" to seperate Repos/App files (Repo with only one app & without a repo tag)
Automatically push Meta.xml changes after building
Allow Zips for updates
Allow 3rd party update source in main.xml
Show number of available updates
NOTE: All command prompts will be removed soon (tm) Update your scripts to reflect this change (there may be some things provided for dialogs)

View File

@ -46,6 +46,7 @@
this.controls_reload = new System.Windows.Forms.Button();
this.toolTip = new System.Windows.Forms.ToolTip(this.components);
this.searchPackageDialog = new System.Windows.Forms.OpenFileDialog();
this.controls_local = new System.Windows.Forms.Button();
this.infoPanel.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.splitContainer)).BeginInit();
this.splitContainer.Panel1.SuspendLayout();
@ -169,6 +170,7 @@
this.optionsPanel.Controls.Add(this.searchBox);
this.optionsPanel.Controls.Add(this.controls_settings);
this.optionsPanel.Controls.Add(this.controls_reload);
this.optionsPanel.Controls.Add(this.controls_local);
this.optionsPanel.Dock = System.Windows.Forms.DockStyle.Top;
this.optionsPanel.Location = new System.Drawing.Point(0, 0);
this.optionsPanel.Name = "optionsPanel";
@ -204,7 +206,7 @@
| System.Windows.Forms.AnchorStyles.Right)));
this.searchBox.Location = new System.Drawing.Point(3, 33);
this.searchBox.Name = "searchBox";
this.searchBox.Size = new System.Drawing.Size(262, 20);
this.searchBox.Size = new System.Drawing.Size(233, 20);
this.searchBox.TabIndex = 2;
this.searchBox.TextChanged += new System.EventHandler(this.updateSidebarV);
//
@ -239,6 +241,17 @@
//
this.searchPackageDialog.Filter = "Packages (*.zip)|*.zip";
//
// controls_local
//
this.controls_local.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.controls_local.Location = new System.Drawing.Point(242, 31);
this.controls_local.Name = "controls_local";
this.controls_local.Size = new System.Drawing.Size(23, 23);
this.controls_local.TabIndex = 6;
this.controls_local.Text = "⇓";
this.controls_local.UseVisualStyleBackColor = true;
this.controls_local.Click += new System.EventHandler(this.controls_local_Click);
//
// MainForm
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
@ -281,6 +294,7 @@
private System.Windows.Forms.Button action_run;
private System.Windows.Forms.Button controls_upload;
private System.Windows.Forms.OpenFileDialog searchPackageDialog;
private System.Windows.Forms.Button controls_local;
}
}

View File

@ -14,6 +14,7 @@ using Microsoft.VisualBasic;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.Threading;
using System.Runtime.InteropServices;
namespace UpTool2
{
@ -162,6 +163,9 @@ namespace UpTool2
toolTip.SetToolTip(controls_settings, "Settings");
toolTip.SetToolTip(controls_reload, "Refresh repositories");
toolTip.SetToolTip(controls_upload, "Install package from disk");
toolTip.SetToolTip(controls_local, "Install UpTool2 locally");
controls_local.Visible = Application.ExecutablePath != dir + @"\UpTool2.exe";
searchBox.Size = (Application.ExecutablePath != dir + @"\UpTool2.exe") ? new Size(233, 20) : new Size(262, 20);
toolTip.SetToolTip(filterBox, "Filter");
toolTip.SetToolTip(action_install, "Install");
toolTip.SetToolTip(action_remove, "Remove");
@ -283,10 +287,8 @@ namespace UpTool2
tmp_apps_list.Last().Add(new XElement("MainFile", app.Element("MainFile").Value));
if (app.Element("Icon") != null)
{
#if !DEBUG
try
{
#endif
//Scale Image and save as Base64
Image src = Image.FromStream(client.OpenRead(app.Element("Icon").Value));
Bitmap dest = new Bitmap(70, 70);
@ -309,10 +311,8 @@ namespace UpTool2
dest.Save(ms, ImageFormat.Png);
tmp_apps_list.Last().Add(new XElement("Icon", Convert.ToBase64String(ms.ToArray())));
}
#if !DEBUG
}
catch { }
#endif
}
if (tmp_apps_list.Where(a => a.Element("ID").Value == app.Element("ID").Value).Count() > 1)
tmp_apps_list.Where(a => a.Element("ID").Value == app.Element("ID").Value).Reverse().Skip(1).ToList().ForEach(a => tmp_apps_list.Remove(a));
@ -335,8 +335,8 @@ namespace UpTool2
tmp_apps_list.ForEach(app => repos.Add(app));
meta.Save(xml);
}
#endregion
#region Run/Update/Reload/Settings (Small links to other stuff)
#endregion
#region Run/Update/Reload/Settings (Small links to other stuff)
private void Action_run_Click(object sender, EventArgs e)
{
Console.WriteLine(new string('-', 10));
@ -345,7 +345,8 @@ namespace UpTool2
Console.WriteLine(((App)action_run.Tag).mainFile);
Console.WriteLine(getDataPath((App)action_run.Tag));
_ = Process.Start(
new ProcessStartInfo {
new ProcessStartInfo
{
FileName = getDataPath((App)action_run.Tag) + "\\" +
((App)action_run.Tag).mainFile,
WorkingDirectory = getDataPath((App)action_run.Tag)
@ -374,8 +375,8 @@ namespace UpTool2
}
private void Controls_settings_Click(object sender, EventArgs e) => new SettingsForms().ShowDialog();
#endregion
#region GUI (stuff only present for GUI)
#endregion
#region GUI (stuff only present for GUI)
void clearSelection()
{
action_install.Enabled = false;
@ -401,14 +402,14 @@ namespace UpTool2
else
{
#endif
Enum.TryParse(filterBox.SelectedValue.ToString(), out Status status);
for (int i = 0; i < sidebarPanel.Controls.Count; i++)
{
Panel sidebarIcon = (Panel)sidebarPanel.Controls[i];
App app = (App)sidebarIcon.Tag;
sidebarIcon.Visible = app.name.Contains(searchBox.Text) && ((int)app.status & (int)(Program.online ? status : Status.Installed)) != 0;
}
clearSelection();
Enum.TryParse(filterBox.SelectedValue.ToString(), out Status status);
for (int i = 0; i < sidebarPanel.Controls.Count; i++)
{
Panel sidebarIcon = (Panel)sidebarPanel.Controls[i];
App app = (App)sidebarIcon.Tag;
sidebarIcon.Visible = app.name.Contains(searchBox.Text) && ((int)app.status & (int)(Program.online ? status : Status.Installed)) != 0;
}
clearSelection();
#if DEBUG
}
#endif
@ -435,8 +436,64 @@ namespace UpTool2
Program.splash.Hide();
BringToFront();
}
#endregion
#region Definitions
private void controls_local_Click(object sender, EventArgs e)
{
File.Copy(dir + @"\update.exe", dir + @"\UpTool2.exe", true);
Shortcut.Create(Path.GetDirectoryName(Application.ExecutablePath) + "\\UpTool2.lnk", dir + @"\UpTool2.exe", null, null, null, null, null);
Shortcut.Create(Environment.GetFolderPath(Environment.SpecialFolder.Programs) + "\\UpTool2.lnk", dir + @"\UpTool2.exe", null, null, null, null, null);
Close();
}
public class Shortcut
{
private static Type m_type = Type.GetTypeFromProgID("WScript.Shell");
private static object m_shell = Activator.CreateInstance(m_type);
[ComImport, TypeLibType((short)0x1040), Guid("F935DC23-1CF0-11D0-ADB9-00C04FD58A0B")]
private interface IWshShortcut
{
[DispId(0)]
string FullName { [return: MarshalAs(UnmanagedType.BStr)] [DispId(0)] get; }
[DispId(0x3e8)]
string Arguments { [return: MarshalAs(UnmanagedType.BStr)] [DispId(0x3e8)] get; [param: In, MarshalAs(UnmanagedType.BStr)] [DispId(0x3e8)] set; }
[DispId(0x3e9)]
string Description { [return: MarshalAs(UnmanagedType.BStr)] [DispId(0x3e9)] get; [param: In, MarshalAs(UnmanagedType.BStr)] [DispId(0x3e9)] set; }
[DispId(0x3ea)]
string Hotkey { [return: MarshalAs(UnmanagedType.BStr)] [DispId(0x3ea)] get; [param: In, MarshalAs(UnmanagedType.BStr)] [DispId(0x3ea)] set; }
[DispId(0x3eb)]
string IconLocation { [return: MarshalAs(UnmanagedType.BStr)] [DispId(0x3eb)] get; [param: In, MarshalAs(UnmanagedType.BStr)] [DispId(0x3eb)] set; }
[DispId(0x3ec)]
string RelativePath { [param: In, MarshalAs(UnmanagedType.BStr)] [DispId(0x3ec)] set; }
[DispId(0x3ed)]
string TargetPath { [return: MarshalAs(UnmanagedType.BStr)] [DispId(0x3ed)] get; [param: In, MarshalAs(UnmanagedType.BStr)] [DispId(0x3ed)] set; }
[DispId(0x3ee)]
int WindowStyle { [DispId(0x3ee)] get; [param: In] [DispId(0x3ee)] set; }
[DispId(0x3ef)]
string WorkingDirectory { [return: MarshalAs(UnmanagedType.BStr)] [DispId(0x3ef)] get; [param: In, MarshalAs(UnmanagedType.BStr)] [DispId(0x3ef)] set; }
[TypeLibFunc((short)0x40), DispId(0x7d0)]
void Load([In, MarshalAs(UnmanagedType.BStr)] string PathLink);
[DispId(0x7d1)]
void Save();
}
public static void Create(string fileName, string targetPath, string arguments, string workingDirectory, string description, string hotkey, string iconPath)
{
IWshShortcut shortcut = (IWshShortcut)m_type.InvokeMember("CreateShortcut", System.Reflection.BindingFlags.InvokeMethod, null, m_shell, new object[] { fileName });
shortcut.Description = description;
shortcut.TargetPath = targetPath;
shortcut.WorkingDirectory = workingDirectory;
shortcut.Arguments = arguments;
if (!string.IsNullOrEmpty(hotkey))
shortcut.Hotkey = hotkey;
if (!string.IsNullOrEmpty(iconPath))
shortcut.IconLocation = iconPath;
shortcut.Save();
}
}
#endregion
#region Definitions
private struct App : IEquatable<App>
{
public string name;
@ -504,6 +561,6 @@ namespace UpTool2
string getAppPath(Guid app) => appsPath + @"\" + app.ToString();
string getDataPath(Guid app) => getAppPath(app) + @"\app";
bool relE = true;
#endregion
#endregion
}
}

View File

@ -14,6 +14,7 @@ using System.Drawing;
using System.Linq;
using System.Collections.Generic;
using System.Xml;
using System.IO.Compression;
namespace UpTool2
{
@ -26,14 +27,13 @@ namespace UpTool2
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
showSplash();
ShowSplash();
string appGuid = ((GuidAttribute)Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(GuidAttribute), false).GetValue(0)).Value.ToString();
string mutexId = string.Format("Global\\{{{0}}}", appGuid);
bool createdNew;
var allowEveryoneRule = new MutexAccessRule(new SecurityIdentifier(WellKnownSidType.WorldSid, null), MutexRights.FullControl, AccessControlType.Allow);
var securitySettings = new MutexSecurity();
securitySettings.AddAccessRule(allowEveryoneRule);
using (var mutex = new Mutex(false, mutexId, out createdNew, securitySettings))
using (var mutex = new Mutex(false, mutexId, out bool createdNew, securitySettings))
{
var hasHandle = false;
#if !DEBUG
@ -57,10 +57,10 @@ namespace UpTool2
if (!Directory.Exists(dir + @"\Apps"))
Directory.CreateDirectory(dir + @"\Apps");
string xml = dir + @"\info.xml";
fixXML(xml);
string metaXml = "https://raw.githubusercontent.com/CreepyCrafter24/UpTool2/master/Meta.xml";
online = Ping(metaXml);
if (!online || updateCheck(dir, xml, metaXml))
FixXML(xml);
string metaXML = XDocument.Load(xml).Element("meta").Element("UpdateSource").Value;
online = Ping(metaXML);
if (!online || UpdateCheck(dir, xml, metaXML))
Application.Run(new MainForm());
#if !DEBUG
}
@ -77,7 +77,7 @@ namespace UpTool2
}
}
static void showSplash()
static void ShowSplash()
{
splash = new Form
{
@ -107,27 +107,30 @@ namespace UpTool2
splash.BringToFront();
}
static void fixXML(string xml)
static void FixXML(string xml)
{
try
{
if ((!File.Exists(xml)) || XDocument.Load(xml).Element("meta") == null)
new XElement("meta", new XElement("Version", 0), new XElement("Repos", new XElement("Repo", new XElement("Name", "UpTool2 official Repo"), new XElement("Link", "https://raw.githubusercontent.com/CreepyCrafter24/UpTool2/master/Repo.xml"))), new XElement("LocalRepo")).Save(xml);
new XElement("meta", new XElement("Version", 0), new XElement("UpdateSource", "https://raw.githubusercontent.com/CreepyCrafter24/UpTool2/master/Meta.xml"), new XElement("Repos", new XElement("Repo", new XElement("Name", "UpTool2 official Repo"), new XElement("Link", "https://raw.githubusercontent.com/CreepyCrafter24/UpTool2/master/Repo.xml"))), new XElement("LocalRepo")).Save(xml);
else
{
XDocument x = XDocument.Load(xml);
XElement meta = x.Element("meta");
if (XDocument.Load(xml).Element("meta").Element("Repos") == null || XDocument.Load(xml).Element("meta").Element("Repos").Elements("Repo").Count() == 0)
{
if (XDocument.Load(xml).Element("meta").Element("Version") == null)
meta.Add(new XElement("Version", 0));
if (XDocument.Load(xml).Element("meta").Element("UpdateSource") == null)
meta.Add(new XElement("UpdateSource", "https://raw.githubusercontent.com/CreepyCrafter24/UpTool2/master/Meta.xml"));
if (XDocument.Load(xml).Element("meta").Element("Repos") == null)
meta.Add(new XElement("Repos", new XElement("Repo", new XElement("Name", "UpTool2 official Repo"), new XElement("Link", "https://raw.githubusercontent.com/CreepyCrafter24/UpTool2/master/Repo.xml"))));
meta.Add(new XElement("LocalRepo"));
}
else if (XDocument.Load(xml).Element("meta").Element("Repos").Elements("Repo").Count() == 0)
meta.Element("Repos").Add(new XElement("Repo", new XElement("Name", "UpTool2 official Repo"), new XElement("Link", "https://raw.githubusercontent.com/CreepyCrafter24/UpTool2/master/Repo.xml")));
else
{
XElement repos = meta.Element("Repos");
IEnumerable<XElement> reposa = repos.Elements("Repo");
reposa.Select(s => s.Element("Link")).Where(s => s.Value == "https://github.com/CreepyCrafter24/UpTool2/releases/download/Repo/Repo.xml").ToList().ForEach(s => s.Value = "https://raw.githubusercontent.com/CreepyCrafter24/UpTool2/master/Repo.xml");
}
meta.Element("Repos").Elements("Repo").Select(s => s.Element("Link"))
.Where(s => s.Value == "https://github.com/CreepyCrafter24/UpTool2/releases/download/Repo/Repo.xml")
.ToList().ForEach(s => s.Value = "https://raw.githubusercontent.com/CreepyCrafter24/UpTool2/master/Repo.xml");
if (XDocument.Load(xml).Element("meta").Element("LocalRepo") == null)
meta.Add(new XElement("LocalRepo"));
x.Save(xml);
}
}
@ -137,20 +140,38 @@ namespace UpTool2
}
}
static bool updateCheck(string dir, string xml, string metaXml)
static bool UpdateCheck(string dir, string xml, string metaXML)
{
XElement meta = XDocument.Load(metaXml).Element("meta");
XElement meta = XDocument.Load(metaXML).Element("meta");
int version = int.Parse(meta.Element("Version").Value);
if (int.Parse(XDocument.Load(xml).Element("meta").Element("Version").Value) < version)
{
if (new DownloadDialog(meta.Element("File").Value, dir + @"\update.exe").ShowDialog() != DialogResult.OK)
throw new Exception("Failed to update");
using (DownloadDialog dlg = new DownloadDialog(meta.Element("File").Value, dir + @"\update.tmp"))
{
if (dlg.ShowDialog() != DialogResult.OK)
throw new Exception("Failed to update");
}
using (SHA256CryptoServiceProvider sha256 = new SHA256CryptoServiceProvider())
{
string pkghash = BitConverter.ToString(sha256.ComputeHash(File.ReadAllBytes(dir + @"\update.exe"))).Replace("-", string.Empty).ToUpper();
string pkghash = BitConverter.ToString(sha256.ComputeHash(File.ReadAllBytes(dir + @"\update.tmp"))).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());
}
try
{
//Try extracting. This is done to support automatically built updates
if (Directory.Exists(dir + @"\update"))
Directory.Delete(dir + @"\update", true);
ZipFile.ExtractToDirectory(dir + @"\update.tmp", dir + @"\update");
File.Delete(dir + @"\update.tmp");
File.Copy(dir + @"\update", dir + @"\update.exe", true);
}
catch (InvalidDataException)
{
//If it can not be extracted as a .zip we try reading to see if it is a binary by trying to read it's name
AssemblyName.GetAssemblyName(dir + @"\update.tmp");
File.Move(dir + @"\update.tmp", dir + @"\update.exe");
}
new XElement("meta", new XElement("Version", version)).Save(xml);
splash.Hide();
Process.Start(new ProcessStartInfo { FileName = "cmd.exe", Arguments = "/C timeout /t 2 & copy /b/v/y \"" + dir + @"\update.exe" + "\" \"" + Application.ExecutablePath + "\" & \"" + Application.ExecutablePath + "\"", CreateNoWindow = true, WindowStyle = ProcessWindowStyle.Hidden });

View File

@ -40,6 +40,7 @@
<Reference Include="Microsoft.VisualBasic" />
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.IO.Compression" />
<Reference Include="System.IO.Compression.FileSystem" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />