New installer

This commit is contained in:
Jiiks 2018-01-10 17:17:15 +02:00
parent 55a6fb8697
commit 4114a6ee26
111 changed files with 3577 additions and 0 deletions

View File

@ -0,0 +1,22 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.26430.16
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BetterDiscordWI", "BetterDiscordWI\BetterDiscordWI.csproj", "{390615F1-CE33-4173-9E8C-4E4F3EB1758D}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{390615F1-CE33-4173-9E8C-4E4F3EB1758D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{390615F1-CE33-4173-9E8C-4E4F3EB1758D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{390615F1-CE33-4173-9E8C-4E4F3EB1758D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{390615F1-CE33-4173-9E8C-4E4F3EB1758D}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.2"/>
</startup>
</configuration>

View File

@ -0,0 +1,162 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{390615F1-CE33-4173-9E8C-4E4F3EB1758D}</ProjectGuid>
<OutputType>WinExe</OutputType>
<RootNamespace>BetterDiscordWI</RootNamespace>
<AssemblyName>BetterDiscordWI</AssemblyName>
<TargetFrameworkVersion>v4.6.2</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<TargetFrameworkProfile />
<NuGetPackageImportStamp>
</NuGetPackageImportStamp>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup>
<ApplicationIcon>betterdiscord_small_white_blue_icO_icon.ico</ApplicationIcon>
</PropertyGroup>
<PropertyGroup>
<ApplicationManifest>app.manifest</ApplicationManifest>
</PropertyGroup>
<ItemGroup>
<Reference Include="asardotnetasync">
<HintPath>..\..\..\..\..\..\Projects\C#\asardotnetasync\asardotnetasync\bin\Release\asardotnetasync.dll</HintPath>
</Reference>
<Reference Include="Costura, Version=1.6.2.0, Culture=neutral, PublicKeyToken=9919ef960d84173d, processorArchitecture=MSIL">
<HintPath>..\packages\Costura.Fody.1.6.2\lib\dotnet\Costura.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="Newtonsoft.Json">
<HintPath>..\..\..\..\..\..\libs\Newtonsoft.Json.dll</HintPath>
</Reference>
<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" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Deployment" />
<Reference Include="System.Drawing" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="controls\Button.cs">
<SubType>Component</SubType>
</Compile>
<Compile Include="controls\Button.Designer.cs">
<DependentUpon>Button.cs</DependentUpon>
</Compile>
<Compile Include="FormMain.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="FormMain.Designer.cs">
<DependentUpon>FormMain.cs</DependentUpon>
</Compile>
<Compile Include="panels\ConfigPanel.cs">
<SubType>UserControl</SubType>
</Compile>
<Compile Include="panels\ConfigPanel.Designer.cs">
<DependentUpon>ConfigPanel.cs</DependentUpon>
</Compile>
<Compile Include="panels\InstallPanel.cs">
<SubType>UserControl</SubType>
</Compile>
<Compile Include="panels\InstallPanel.Designer.cs">
<DependentUpon>InstallPanel.cs</DependentUpon>
</Compile>
<Compile Include="panels\IPanel.cs" />
<Compile Include="panels\LicensePanel.cs">
<SubType>UserControl</SubType>
</Compile>
<Compile Include="panels\LicensePanel.Designer.cs">
<DependentUpon>LicensePanel.cs</DependentUpon>
</Compile>
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Utils.cs" />
<EmbeddedResource Include="FormMain.resx">
<DependentUpon>FormMain.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="panels\ConfigPanel.resx">
<DependentUpon>ConfigPanel.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="panels\InstallPanel.resx">
<DependentUpon>InstallPanel.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="panels\LicensePanel.resx">
<DependentUpon>LicensePanel.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Properties\Resources.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
<SubType>Designer</SubType>
</EmbeddedResource>
<Compile Include="Properties\Resources.Designer.cs">
<AutoGen>True</AutoGen>
<DependentUpon>Resources.resx</DependentUpon>
<DesignTime>True</DesignTime>
</Compile>
<None Include="app.manifest" />
<None Include="packages.config" />
<None Include="Properties\Settings.settings">
<Generator>SettingsSingleFileGenerator</Generator>
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
</None>
<Compile Include="Properties\Settings.Designer.cs">
<AutoGen>True</AutoGen>
<DependentUpon>Settings.settings</DependentUpon>
<DesignTimeSharedInput>True</DesignTimeSharedInput>
</Compile>
</ItemGroup>
<ItemGroup>
<None Include="App.config" />
</ItemGroup>
<ItemGroup>
<None Include="Resources\Betterdiscord small black+blue.png" />
</ItemGroup>
<ItemGroup>
<None Include="Resources\Betterdiscord small white+blue.png" />
</ItemGroup>
<ItemGroup>
<None Include="FodyWeavers.xml" />
</ItemGroup>
<ItemGroup>
<Content Include="betterdiscord_small_white_blue_icO_icon.ico" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Import Project="..\packages\Fody.2.0.0\build\netstandard1.4\Fody.targets" Condition="Exists('..\packages\Fody.2.0.0\build\netstandard1.4\Fody.targets')" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('..\packages\Fody.2.0.0\build\netstandard1.4\Fody.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Fody.2.0.0\build\netstandard1.4\Fody.targets'))" />
<Error Condition="!Exists('..\packages\Costura.Fody.1.6.2\build\dotnet\Costura.Fody.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Costura.Fody.1.6.2\build\dotnet\Costura.Fody.targets'))" />
</Target>
<Import Project="..\packages\Costura.Fody.1.6.2\build\dotnet\Costura.Fody.targets" Condition="Exists('..\packages\Costura.Fody.1.6.2\build\dotnet\Costura.Fody.targets')" />
</Project>

View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<Weavers>
<Costura />
</Weavers>

View File

@ -0,0 +1,128 @@
namespace BetterDiscordWI {
partial class FormMain {
/// <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(FormMain));
this.panelDock = new System.Windows.Forms.Panel();
this.lblTitle = new System.Windows.Forms.Label();
this.panel2 = new System.Windows.Forms.Panel();
this.btnBack = new BetterDiscordWI.controls.Button();
this.btnNext = new BetterDiscordWI.controls.Button();
this.btnCancel = new BetterDiscordWI.controls.Button();
this.SuspendLayout();
//
// panelDock
//
this.panelDock.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.panelDock.Location = new System.Drawing.Point(12, 96);
this.panelDock.Name = "panelDock";
this.panelDock.Size = new System.Drawing.Size(752, 339);
this.panelDock.TabIndex = 0;
//
// lblTitle
//
this.lblTitle.AutoSize = true;
this.lblTitle.BackColor = System.Drawing.SystemColors.Window;
this.lblTitle.Font = new System.Drawing.Font("Microsoft Sans Serif", 9.75F, System.Drawing.FontStyle.Bold);
this.lblTitle.ForeColor = System.Drawing.Color.Black;
this.lblTitle.Location = new System.Drawing.Point(82, 37);
this.lblTitle.Name = "lblTitle";
this.lblTitle.Size = new System.Drawing.Size(147, 16);
this.lblTitle.TabIndex = 5;
this.lblTitle.Text = "BetterDiscord Setup";
//
// panel2
//
this.panel2.BackColor = System.Drawing.SystemColors.Window;
this.panel2.BackgroundImage = global::BetterDiscordWI.Properties.Resources.Betterdiscord_small_black_blue;
this.panel2.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Stretch;
this.panel2.Location = new System.Drawing.Point(12, 12);
this.panel2.Name = "panel2";
this.panel2.Size = new System.Drawing.Size(64, 64);
this.panel2.TabIndex = 4;
//
// btnBack
//
this.btnBack.Location = new System.Drawing.Point(527, 466);
this.btnBack.Name = "btnBack";
this.btnBack.Size = new System.Drawing.Size(75, 23);
this.btnBack.TabIndex = 6;
this.btnBack.Text = "< Back";
this.btnBack.UseVisualStyleBackColor = true;
this.btnBack.Click += new System.EventHandler(this.btnBack_Click);
//
// btnNext
//
this.btnNext.Location = new System.Drawing.Point(608, 466);
this.btnNext.Name = "btnNext";
this.btnNext.Size = new System.Drawing.Size(75, 23);
this.btnNext.TabIndex = 7;
this.btnNext.Text = "Next >";
this.btnNext.UseVisualStyleBackColor = true;
this.btnNext.Click += new System.EventHandler(this.btnNext_Click);
//
// btnCancel
//
this.btnCancel.Location = new System.Drawing.Point(689, 466);
this.btnCancel.Name = "btnCancel";
this.btnCancel.Size = new System.Drawing.Size(75, 23);
this.btnCancel.TabIndex = 8;
this.btnCancel.Text = "Cancel";
this.btnCancel.UseVisualStyleBackColor = true;
this.btnCancel.Click += new System.EventHandler(this.btnCancel_Click);
//
// FormMain
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.BackColor = System.Drawing.SystemColors.Control;
this.ClientSize = new System.Drawing.Size(776, 501);
this.Controls.Add(this.btnCancel);
this.Controls.Add(this.btnNext);
this.Controls.Add(this.btnBack);
this.Controls.Add(this.lblTitle);
this.Controls.Add(this.panel2);
this.Controls.Add(this.panelDock);
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.Fixed3D;
this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
this.MaximizeBox = false;
this.Name = "FormMain";
this.Text = "Setup - BetterDiscord";
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.Panel panelDock;
private System.Windows.Forms.Panel panel2;
private System.Windows.Forms.Label lblTitle;
public controls.Button btnNext;
public controls.Button btnCancel;
public controls.Button btnBack;
}
}

View File

@ -0,0 +1,71 @@
using System;
using System.Drawing;
using System.Windows.Forms;
using BetterDiscordWI.panels;
namespace BetterDiscordWI {
public partial class FormMain : Form {
private readonly IPanel[] _panels = { new LicensePanel(), new ConfigPanel(), new InstallPanel() };
private int _currentPanel;
public string DiscordPath = null;
public bool RestartDiscord = true;
public bool Stable = true, Canary, Ptb;
public FormMain() {
InitializeComponent();
foreach (var panel in _panels) {
panel.SetForm(this);
panel.Control.Dock = DockStyle.Fill;
panelDock.Controls.Add(panel.Control);
}
SwitchPanel(0);
}
public void SetTitle(string title) => lblTitle.Text = title;
public void SwitchPanel(int index) {
_currentPanel = index;
foreach (var panel in _panels) { panel.HidePanel(); }
SetTitle($"BetterDiscord {_panels[index].Title}");
_panels[index].ShowPanel();
}
private readonly Pen _borderPen = new Pen(Color.FromArgb(160, 160, 160));
protected override void OnPaint(PaintEventArgs e) {
base.OnPaint(e);
var g = e.Graphics;
g.FillRectangle(SystemBrushes.Window, new Rectangle(0, 0, Width, 85));
g.DrawLine(_borderPen, 0, 85, Width, 85);
g.DrawLine(SystemPens.Window, 0, 86, Width, 86);
g.DrawLine(_borderPen, 0, 445, Width, 445);
g.DrawLine(SystemPens.Window, 0, 446, Width, 446);
}
private void btnNext_Click(object sender, EventArgs e) {
_currentPanel++;
SwitchPanel(_currentPanel);
}
private void btnCancel_Click(object sender, EventArgs e) {
Application.Exit();
}
private void btnBack_Click(object sender, EventArgs e) {
_currentPanel--;
SwitchPanel(_currentPanel);
}
public void Fail() {
btnCancel.ShowEnable();
btnNext.ShowDisable();
btnBack.ShowEnable();
}
}
}

View File

@ -0,0 +1,541 @@
<?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>
<assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
<data name="$this.Icon" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
AAABAAUAEBAAAAEAIABoBAAAVgAAABgYAAABACAAiAkAAL4EAAAgIAAAAQAgAKgQAABGDgAAMDAAAAEA
IACoJQAA7h4AAAAAAAABACAA4BwAAJZEAAAoAAAAEAAAACAAAAABACAAAAAAAAAEAAATCwAAEwsAAAAA
AAAAAAAA5YI+geWCPoHlgj6B5YI+geWCPoHlgj6B5YI+fOWCPmHlgDsv99jDE////2D///9r////OP//
/wr///8A////AOWCPv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj765YI+5eWDQJj32sZi////2///
/+3///+p////MP///wDlgj7/5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7/5H85pvzy
6nX////7/////////9H///8z5YI+meWCPprlgj6a5YI+muWCPprlgj6Z5YI+rOWCPu3lgj7/5YI+/+WB
PPPtqXtl////2v//////////////qwAAAAAAAAAAAAAAAAAAAADlgj4A5YI+AOWCPgLlgj5y5YI+/uWC
Pv/lgj3/6I5Ref///8D//////////////+4AAAAA5YI+AOWCPgDlgj4J5YI+AuWCPgDlgj4A5YI+X+WC
Pv3lgj7/5YI+/+eMTXT///+7///////////////+5YI+AOWCPgDlgj4t5YI+feWCPj3lgj5u5YI+geWC
Ptvlgj7/5YI+/+WCPvTokVVN////u////////////////+WCPgDlgj425YI+0OWCPrzlgj5/5YI+/+WC
Pv/lgj7/5YI+/+WCPv/lgj218LaOFv///77////////////////lgj5O5YI+1+WCPv/lgj675YI+f+WC
Pv/lgj7/5YI+/+WCPv/lgj7/5YI9tvC1jhb///++////////////////5YI+7OWCPv/lgj7/5YI+veWC
Pjvlgj5s5YI+gOWCPtvlgj7/5YI+/+WCPvTokVVN////u////////////////+WCPv/lgj7/5YI+/+WC
Pr/lgj4J5YI+AOWCPgDlgj5f5YI+/eWCPv/lgj7/54xNdf///7v///////////////7lgj7/5YI+/+WC
Pv/lgj6/5YI+CeWCPgDlgj4C5YI+c+WCPv7lgj7/5YI9/+iOUXn////A///////////////r5YI+/+WC
Pv/lgj7/5YI+5uWCPp7lgj6a5YI+reWCPu3lgj7/5YI+/+WBPPPtqntl////2///////////////puWC
Pv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPv/kfzml/PLrdf////v/////////zv//
/y7lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7/5YI++uWCPuTlhECX+NvHYv///9v////s////pv//
/y3///8A5YI+gOWCPoDlgj6A5YI+gOWCPoDlgj6A5YI+e+WCPmDlgDou+NvHFP///2H///9q////N///
/wn///8A////AAADAAAAAQAAAAAAAAAAAAD8AAAA5gAAAMAAAACAAAAAAAAAAAAAAAAGAAAABAAAAAAA
AAAAAAAAAAEAAAADAAAoAAAAGAAAADAAAAABACAAAAAAAAAJAAATCwAAEwsAAAAAAAAAAAAA5YI+P+WC
Pj/lgj4/5YI+P+WCPj/lgj4/5YI+P+WCPj/lgj4/5YI+PeWCPjDlgj4Z5YI+Bfrm2AD///8S////PP//
/zb///8f////CP///wD///8AAAAAAAAAAAAAAAAA5YI+8OWCPvDlgj7w5YI+8OWCPvDlgj7w5YI+8OWC
PvDlgj7w5YI+7+WCPuflgj7T5YI+p+WBPFnxupQe////dP///+D////b////tP///23///8e////AP//
/wAAAAAA5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WC
PvrlgT235ohIMv///3P////4//////////3////T////Vv///wP///8A5YI+/+WCPv/lgj7/5YI+/+WC
Pv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7/5YE9yOqcZyv///+n////////
////////////7////2D///8A5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WC
Pv/lgj7/5YI+/+WCPv/lgj7/5YI+/+R/OYf///5H////9P///////////////////97///805YI+buWC
Pm/lgj5v5YI+b+WCPm/lgj5v5YI+b+WCPm/lgj5u5YI+euWCPrzlgj775YI+/+WCPv/lgj7/5YI+/+WB
PdLyv50t////0v////////////////////////+ZAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AADlgj4A5YI+AOWCPhLlgj6u5YI+/+WCPv/lgj7/5YI+/+WCPu3okFQ3////s///////////////////
///////dAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA5YI+AOWCPgDlgj5m5YI+/+WC
Pv/lgj7/5YI+/+WCPvPmiEc9////qP/////////////////////////5AAAAAAAAAAAAAAAA5YI+AOWC
PgHlgj4N5YI+AeWCPgAAAAAA5YI+AOWCPgLlgj6P5YI+/+WCPv/lgj7/5YI+/+WCPuvmiUkw////qP//
////////////////////////AAAAAAAAAADlgj4A5YI+AOWCPkTlgj5/5YI+EOWCPjHlgj4z5YI+POWC
PoPlgj7v5YI+/+WCPv/lgj7/5YI+/+WCPtDokVQX////qf//////////////////////////AAAAAOWC
PgDlgj4B5YI+TuWCPuPlgj6p5YI+POWCPuXlgj7w5YI+9OWCPv7lgj7/5YI+/+WCPv/lgj7/5YI+/+WC
Pov//f0D////q///////////////////////////5YI+AOWCPgPlgj5f5YI+6OWCPv/lgj6n5YI+P+WC
PvTlgj7/5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7/5YI+2eWBPSf///8B////q///////////////////
////////5YI+B+WCPm/lgj7w5YI+/+WCPv/lgj6n5YI+P+WCPvTlgj7/5YI+/+WCPv/lgj7/5YI+/+WC
Pv/lgj7/5YI+2eWBPSf///8B////q///////////////////////////5YI+keWCPvTlgj7/5YI+/+WC
Pv/lgj6n5YI+O+WCPuTlgj7v5YI+8+WCPv7lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPoz++vcD////q///
////////////////////////5YI+/OWCPv/lgj7/5YI+/+WCPv/lgj6q5YI+DuWCPi/lgj4x5YI+OuWC
PoHlgj7v5YI+/+WCPv/lgj7/5YI+/+WCPtDokFQY////qf//////////////////////////5YI+/+WC
Pv/lgj7/5YI+/+WCPv/lgj6r5YI+A+WCPgAAAAAA5YI+AOWCPgLlgj6O5YI+/+WCPv/lgj7/5YI+/+WC
PuvmiUkx////qP//////////////////////////5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj6r5YI+A+WC
PgAAAAAA5YI+AOWCPgDlgj5n5YI+/+WCPv/lgj7/5YI+/+WCPvPmiEc9////qP//////////////////
///////45YI+/+WCPv/lgj7/5YI+/+WCPv/lgj6q5YI+A+WCPgDlgj4A5YI+AOWCPhLlgj6v5YI+/+WC
Pv/lgj7/5YI+/+WCPu3okFQ3////s//////////////////////////Y5YI+/+WCPv/lgj7/5YI+/+WC
Pv/lgj7Q5YI+cuWCPnDlgj5w5YI+fOWCPr3lgj775YI+/+WCPv/lgj7/5YI+/+WBPdHywJ4t////0v//
//////////////////////+R5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WC
Pv/lgj7/5YI+/+WCPv/lgj7/5YI+/+R/OYb///9I////9P///////////////////9n///8u5YI+/+WC
Pv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7/5YE9x+ud
aCv///+o////////////////////7P///1j///8A5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WC
Pv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPvrlgTy15olJMf///3T////5//////////3////P////UP//
/wL///8A5YI+7+WCPvDlgj7w5YI+8OWCPvDlgj7w5YI+8OWCPvDlgj7w5YI+7uWCPublgj7S5YI+peWB
PFfxvZof////d////+H////b////sv///2r///8b////AP///wAAAAAA5YI+PuWCPj7lgj4+5YI+PuWC
Pj7lgj4+5YI+PuWCPj7lgj4+5YI+O+WCPi7lgj4Y5YI+BPrn2gD///8T////Pf///zf///8f////CP//
/wD///8AAAAAAAAAAAAAAAAAAAQfAAAABwAAAAEAAAABAAAAAAAAAAAA/8AAAP/gAADxwAAA8AAAAMAA
AACAAAAAAAAAAAAAAAAAAAAAAcAAAAHgAAABwAAAAAAAAAAAAAAAAAEAAAABAAAABwAABB8AKAAAACAA
AABAAAAAAQAgAAAAAAAAEAAAEwsAABMLAAAAAAAAAAAAAOWCPhLlgj4S5YI+EuWCPhLlgj4S5YI+EuWC
PhLlgj4S5YI+EuWCPhLlgj4S5YI+EuWCPhHlgj4N5YI+BOWCPgDlgj4A////AP///wD///8L////FP//
/w////8H////Af///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA5YI+y+WCPszlgj7M5YI+zOWC
Pszlgj7M5YI+zOWCPszlgj7M5YI+zOWCPszlgj7M5YI+yuWCPsHlgj6r5YI+h+WCPlTlgj4ewgAAAf//
/yT///+V////x////7X///+V////Zf///y3///8G////AP///wAAAAAAAAAAAAAAAADlgj7/5YI+/+WC
Pv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7/5YI++uWC
Ptrlgj6I5H02If///x7///+p/////v/////////+////6P///6f///9A////BP///wAAAAAAAAAAAOWC
Pv7lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WC
Pv/lgj7/5YI+/+WCPv/lgj7R5H44RP///xT///+u/////////////////////////+3///+C////D///
/wAAAAAA5YI+/uWCPv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WC
Pv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7g5H02O////yr////d////////////////////////
//z///+W////DP///wDlgj7/5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WC
Pv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj685HszEf///3//////////////
//////////////////r///9y////AOWCPvflgj745YI++OWCPvjlgj745YI++OWCPvjlgj745YI++OWC
Pvjlgj745YI++OWCPvrlgj7/5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPvnkfjdS////L///
/+v//////////////////////////////9z///8t5YI+RuWCPkblgj5G5YI+RuWCPkblgj5G5YI+RuWC
Pkblgj5G5YI+RuWCPkblgj5G5YI+TeWCPn7lgj7b5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WB
PZj//fwP////x////////////////////////////////v///4MAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADlgj4A5YI+AOWCPjnlgj7e5YI+/+WCPv/lgj7/5YI+/+WC
Pv/lgj7/5YI+wOqaYw3///+n////////////////////////////////////yQAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADlgj4A5YI+AOWCPpDlgj7/5YI+/+WC
Pv/lgj7/5YI+/+WCPv/lgj7Q5Hs0Ef///5b////////////////////////////////////vAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOWCPgDlgj4A5YI+gOWC
Pv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPs3jdy4P////lP//////////////////////////////////
//0AAAAAAAAAAAAAAAAAAAAAAAAAAOWCPgDlgj4D5YI+EeWCPgHlgj4AAAAAAAAAAAAAAAAA5YI+AOWC
PhPlgj6+5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7/5YI+uuBrGwf///+U////////////////////////
/////////////wAAAAAAAAAAAAAAAAAAAADlgj4A5YI+AuWCPl3lgj575YI+AeWCPgvlgj4N5YI+DeWC
PhDlgj4w5YI+n+WCPvzlgj7/5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj6T9dG4AP///5X/////////////
///////////////////////+AAAAAAAAAAAAAAAA5YI+AOWCPgXlgj5q5YI+8eWCPpXlgj4O5YI+pOWC
Psnlgj7G5YI+zeWCPunlgj7+5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7/5YI++eWCPlLsom8A////lf//
//////////////////////////////////4AAAAAAAAAAOWCPgDlgj4J5YI+e+WCPvPlgj7/5YI+lOWC
PhPlgj7T5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7B5YI+E/LC
oQD///+V/////////////////////////////////////gAAAADlgj4A5YI+D+WCPo3lgj745YI+/+WC
Pv/lgj6U5YI+E+WCPtPlgj7/5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7/5YI+7+WC
PknlhEEA//79AP///5X////////////////////////////////////+5YI+AOWCPhblgj6e5YI+/OWC
Pv/lgj7/5YI+/+WCPpTlgj4T5YI+0+WCPv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WC
Pv/lgj7v5YI+S+WEQQD//f0A////lf////////////////////////////////////7lgj4k5YI+reWC
Pv7lgj7/5YI+/+WCPv/lgj7/5YI+lOWCPhPlgj7T5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WC
Pv/lgj7/5YI+/+WCPv/lgj7C5YI+E/LBoAD///+V/////////////////////////////////////uWC
Pszlgj7+5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj6U5YI+DuWCPqLlgj7G5YI+xOWCPsvlgj7o5YI+/uWC
Pv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPvnlgj5T7KJvAP///5X/////////////////////////////
///////+5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPpXlgj4A5YI+CuWCPgzlgj4M5YI+D+WC
Pi7lgj6e5YI+++WCPv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPpP21LwA////lf//////////////////
//////////////////7lgj7+5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7/5YI+leWCPgDlgj4AAAAAAAAA
AAAAAAAA5YI+AOWCPhLlgj695YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7/5YI+u+BrGwf///+U////////
/////////////////////////////+WCPv7lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj6V5YI+AOWC
PgAAAAAAAAAAAAAAAADlgj4A5YI+AOWCPoDlgj7/5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7N43cuEP//
/5T////////////////////////////////////85YI+/uWCPv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WC
PpXlgj4A5YI+AAAAAAAAAAAAAAAAAOWCPgDlgj4A5YI+keWCPv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WC
PtDkfDQR////lv///////////////////////////////////+vlgj7+5YI+/+WCPv/lgj7/5YI+/+WC
Pv/lgj7/5YI+lOWCPgDlgj4AAAAAAAAAAADlgj4A5YI+AOWCPjrlgj7f5YI+/+WCPv/lgj7/5YI+/+WC
Pv/lgj7/5YI+wOqaZA3///+n////////////////////////////////////wuWCPv7lgj7/5YI+/+WC
Pv/lgj7/5YI+/+WCPv/lgj6z5YI+R+WCPkjlgj5I5YI+SOWCPk/lgj6A5YI+3OWCPv/lgj7/5YI+/+WC
Pv/lgj7/5YI+/+WCPv/lgT2X//79D////8j///////////////////////////////z///955YI+/uWC
Pv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPvzlgj745YI++OWCPvjlgj745YI+++WCPv/lgj7/5YI+/+WC
Pv/lgj7/5YI+/+WCPv/lgj7/5YI++OR9N1H///8w////7P//////////////////////////////1f//
/yblgj7+5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WC
Pv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj675Hw0EP///4D/////////////////////////////
//j///9n////AOWCPv7lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WC
Pv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7/5YI+3+R9Njr///8r////3f//////////////////
///////6////i////wn///8A5YI+/uWCPv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WC
Pv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPtDkfjhC////Ff///7D/////////////
////////////6f///3j///8L////AAAAAADlgj7/5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WC
Pv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7/5YI++uWCPtnlgj6G5H02IP///x////+r/////v//
///////9////5v///6H///86////A////wAAAAAAAAAAAOWCPsrlgj7K5YI+yuWCPsrlgj7K5YI+yuWC
Psrlgj7K5YI+yuWCPsrlgj7K5YI+yuWCPsjlgj6/5YI+qeWCPoXlgj5S5YI+HbwAAAH///8n////mP//
/8j///+1////lP///2P///8q////Bf///wD///8AAAAAAAAAAAAAAAAA5YI+EeWCPhHlgj4R5YI+EeWC
PhHlgj4R5YI+EeWCPhHlgj4R5YI+EeWCPhHlgj4R5YI+EOWCPgzlgj4E5YI+AOWCPgD///8A////AP//
/wz///8V////EP///wj///8B////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAeD/AAAAHwAA
AAcAAAADAAAAAQAAAAEAAAAAAAAAAP/8AAD//gAA//4AAPx8AAD4AAEA8AABAOAAAQDAAAMAgAADAAAA
AQAAAAEAAIABAAD8AAAA/gAAAP4AAAD8AAAAAAAAAAAAAAAAAAEAAAABAAAAAwAAAAcAAAAfAAHg/ygA
AAAwAAAAYAAAAAEAIAAAAAAAACQAABMLAAATCwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADlgj5V5YI+VeWC
PlXlgj5V5YI+VeWCPlXlgj5V5YI+VeWCPlXlgj5V5YI+VeWCPlXlgj5V5YI+VeWCPlXlgj5V5YI+VeWC
PlXlgj5U5YI+TuWCPkHlgj4t5YI+GeWCPgjlgj4A5YI+AAAAAAD///8A////BP///zX///9V////Uv//
/0r///85////JP///xD///8C////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AADlgj785YI+/eWCPv3lgj795YI+/eWCPv3lgj795YI+/eWCPv3lgj795YI+/eWCPv3lgj795YI+/eWC
Pv3lgj795YI+/eWCPv3lgj795YI+++WCPvXlgj7q5YI+1+WCPrflgj6F5YI+R+WCPhPSJwAA////Af//
/yz///+h////9v////v////y////4////8n///+e////Y////yf///8F////AAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAADlgj7+5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WC
Pv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7/5YI+9uWC
Psrlgj5z5YI+HPjgywD///8L////cf///+3//////////////////////////f///+P///+e////QP//
/wb///8AAAAAAAAAAAAAAAAAAAAAAAAAAADlgj7+5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WC
Pv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WC
Pv/lgj7/5YI+/+WCPv/lgj795YI+zeWCPlXkezMF////Av///1/////t////////////////////////
////////////7v///5j///8l////AP///wAAAAAAAAAAAAAAAADlgj7+5YI+/+WCPv/lgj7/5YI+/+WC
Pv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WC
Pv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPvHlgj595H44Cf///wH///9y////+P//
///////////////////////////////////////R////Rv///wH///8AAAAAAAAAAADlgj7+5YI+/+WC
Pv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WC
Pv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj745YI+fd9n
FAT///8L////p///////////////////////////////////////////////5P///1D///8A////AAAA
AADlgj7+5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WC
Pv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WC
Pv/lgj7/5YI+8OWCPlPzx6gA////Nv///+f/////////////////////////////////////////////
/9////87////AP///wDlgj7+5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WC
Pv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WC
Pv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPsflgDsX////Av///5v/////////////////////////////
//////////////////////+9////Ff///wDlgj7/5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WC
Pv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WC
Pv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPvvlgj5h88SjAP///0v////2////////
///////////////////////////////////////8////bf///wDlgj7H5YI+yOWCPsjlgj7I5YI+yOWC
Psjlgj7I5YI+yOWCPsjlgj7I5YI+yOWCPsjlgj7I5YI+yOWCPsjlgj7I5YI+yOWCPsjlgj7M5YI+4OWC
Pvnlgj7/5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj6u3FUABf//
/xr////W////////////////////////////////////////////////////yf///xnlgj4O5YI+DuWC
Pg7lgj4O5YI+DuWCPg7lgj4O5YI+DuWCPg7lgj4O5YI+DuWCPg7lgj4O5YI+DuWCPg7lgj4O5YI+DuWC
Pg7lgj4R5YI+IeWCPlnlgj7D5YI+/uWCPv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WC
Pv/lgj7d5YE8H////wP///+u////////////////////////////////////////////////////9f//
/1cAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAA5YI+AOWCPgDlgj4c5YI+s+WCPv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WC
Pv/lgj7/5YI+/+WCPv/lgj7z5YI+Pe6vhAD///+L////////////////////////////////////////
/////////////////5wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOWCPgDlgj4A5YI+N+WCPunlgj7/5YI+/+WC
Pv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj775YI+VPG9mQD///90////////////////////////
/////////////////////////////////84AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADlgj4A5YI+CuWC
Prvlgj7/5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7+5YI+X/LAngD///9p////////
/////////////////////////////////////////////////+0AAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AADlgj4A5YI+BOWCPq3lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj795YI+W/LA
ngD///9o//////////////////////////////////////////////////////////sAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAADlgj4A5YI+FOWCPs3lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WC
Pv/lgj755YI+TPLCoAD///9o////////////////////////////////////////////////////////
//4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADlgj4A5YI+DeWCPhflgj4A5YI+AAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAOWCPgDlgj4A5YI+YuWCPvjlgj7/5YI+/+WCPv/lgj7/5YI+/+WC
Pv/lgj7/5YI+/+WCPv/lgj7v5YI+NfTJrAD///9o////////////////////////////////////////
//////////////////4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA5YI+AOWCPgDlgj4R5YI+keWC
PmHlgj4A5YI+AAAAAAAAAAAAAAAAAAAAAADlgj4A5YI+AOWCPgjlgj5W5YI+4eWCPv/lgj7/5YI+/+WC
Pv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7X5YI+GvjcyQD///9o////////////////////////
//////////////////////////////////4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADlgj4A5YI+AOWC
Phjlgj6i5YI+/OWCPmjlgj4A5YI+HeWCPkzlgj5M5YI+TOWCPkzlgj5Q5YI+beWCPq/lgj7x5YI+/+WC
Pv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj6n5YI+BP328AD///9o////////
//////////////////////////////////////////////////4AAAAAAAAAAAAAAAAAAAAAAAAAAOWC
PgDlgj4A5YI+IuWCPrLlgj7+5YI+/+WCPmjlgj4A5YI+YOWCPvnlgj755YI++eWCPvnlgj775YI+/uWC
Pv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPvvlgj5e5YI+AP//
/wD///9o//////////////////////////////////////////////////////////4AAAAAAAAAAAAA
AAAAAAAA5YI+AOWCPgDlgj4t5YI+weWCPv/lgj7/5YI+/+WCPmjlgj4A5YI+YuWCPv/lgj7/5YI+/+WC
Pv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WC
Pszlgj4Z5YI+AP///wD///9o////////////////////////////////////////////////////////
//4AAAAAAAAAAAAAAADlgj4A5YI+AOWCPjvlgj7P5YI+/+WCPv/lgj7/5YI+/+WCPmjlgj4A5YI+YuWC
Pv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WC
Pv/lgj7/5YI+9uWCPl/lgj4A5YNAAP///wD///9o////////////////////////////////////////
//////////////////4AAAAAAAAAAOWCPgDlgj4B5YI+SeWCPtrlgj7/5YI+/+WCPv/lgj7/5YI+/+WC
Pmjlgj4A5YI+YuWCPv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WC
Pv/lgj7/5YI+/+WCPv/lgj7/5YI+meWCPgjlgj4A////AP///wD///9o////////////////////////
//////////////////////////////////4AAAAA5YI+AOWCPgLlgj5Z5YI+5OWCPv/lgj7/5YI+/+WC
Pv/lgj7/5YI+/+WCPmjlgj4A5YI+YuWCPv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WC
Pv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7/5YI+m+WCPgnlgj4A////AP///wD///9o////////
//////////////////////////////////////////////////7lgj4A5YI+BeWCPmrlgj7t5YI+/+WC
Pv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPmjlgj4A5YI+YuWCPv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WC
Pv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7/5YI+9+WCPmHlgj4A5YNAAP//
/wD///9o//////////////////////////////////////////////////////////7lgj4L5YI+e+WC
PvPlgj7/5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPmjlgj4A5YI+YuWCPv/lgj7/5YI+/+WC
Pv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WC
Ps3lgj4a5YI+AP///wD///9o////////////////////////////////////////////////////////
//7lgj6c5YI+9uWCPv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPmjlgj4A5YI+X+WC
Pvjlgj745YI++OWCPvjlgj765YI+/uWCPv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WC
Pv/lgj7/5YI+/+WCPvvlgj5g5YI+AP///wD///9o////////////////////////////////////////
//////////////////7lgj795YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WC
Pmjlgj4A5YI+HOWCPkjlgj5I5YI+SOWCPkjlgj5N5YI+auWCPqzlgj7w5YI+/+WCPv/lgj7/5YI+/+WC
Pv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj6o5YI+Bf318AD///9o////////////////////////
//////////////////////////////////7lgj7+5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WC
Pv/lgj7/5YI+/+WCPmjlgj4A5YI+AAAAAAAAAAAAAAAAAAAAAADlgj4A5YI+AOWCPgflgj5U5YI+4OWC
Pv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7X5YI+GvjbyAD///9o////////
//////////////////////////////////////////////////7lgj7+5YI+/+WCPv/lgj7/5YI+/+WC
Pv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPmjlgj4A5YI+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOWC
PgDlgj4A5YI+YOWCPvjlgj7/5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7v5YI+NfTJ
rAD///9o//////////////////////////////////////////////////////////7lgj7+5YI+/+WC
Pv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPmjlgj4A5YI+AAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAADlgj4A5YI+FOWCPszlgj7/5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WC
Pv/lgj755YI+TPLCoAD///9o////////////////////////////////////////////////////////
//7lgj7+5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPmjlgj4A5YI+AAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADlgj4A5YI+BOWCPq3lgj7/5YI+/+WCPv/lgj7/5YI+/+WC
Pv/lgj7/5YI+/+WCPv/lgj795YI+W/LAngD///9o////////////////////////////////////////
//////////////////nlgj7+5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WC
Pmjlgj4A5YI+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADlgj4A5YI+CuWCPrzlgj7/5YI+/+WC
Pv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7+5YI+X/LAngD///9p////////////////////////
/////////////////////////////////+jlgj7+5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WC
Pv/lgj7/5YI+/+WCPmjlgj4A5YI+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOWCPgDlgj4A5YI+OOWC
Purlgj7/5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj775YI+VPG9mQD///90////////
/////////////////////////////////////////////////8blgj7+5YI+/+WCPv/lgj7/5YI+/+WC
Pv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPmflgj4A5YI+AAAAAAAAAAAAAAAAAAAAAAAAAAAA5YI+AOWC
PgDlgj4d5YI+teWCPv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7z5YI+Pe6v
gwD///+L/////////////////////////////////////////////////////////5Dlgj7+5YI+/+WC
Pv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPnHlgj4M5YI+EOWCPhDlgj4Q5YI+EOWC
PhDlgj4S5YI+I+WCPlzlgj7F5YI+/uWCPv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WC
Pv/lgj7c5YE8Hv///wP///+v////////////////////////////////////////////////////8f//
/0vlgj7+5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPuDlgj7K5YI+yuWC
Psrlgj7K5YI+yuWCPsrlgj7P5YI+4uWCPvrlgj7/5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WC
Pv/lgj7/5YI+/+WCPv/lgj6t21EABP///xr////X////////////////////////////////////////
////////////vv///xLlgj7+5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WC
Pv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WC
Pv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPvvlgj5f88OjAP///0z////3////////////////////////
///////////////////////5////X////wDlgj7+5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WC
Pv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WC
Pv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPsblgDsW////Av///53/////////////
//////////////////////////////////////+v////Dv///wDlgj7+5YI+/+WCPv/lgj7/5YI+/+WC
Pv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WC
Pv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7/5YI+7+WCPlHzxqgA////N///
/+j//////////////////////////////////////////////9X///8v////AP///wDlgj7+5YI+/+WC
Pv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WC
Pv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj735YI+et5h
CwP///8M////qf//////////////////////////////////////////////2////0L///8A////AAAA
AADlgj7+5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WC
Pv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WC
PvDlgj565H43CP///wL///90////+f////////////////////////////////////7////G////Ov//
/wD///8AAAAAAAAAAADlgj7+5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WC
Pv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WC
Pv/lgj785YI+y+WCPlLjeTAE////Av///2L////u////////////////////////////////////6v//
/43///8d////AP///wAAAAAAAAAAAAAAAADlgj7+5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WC
Pv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WCPv/lgj7/5YI+/+WC
Pv/lgj7/5YI+9OWCPsflgj5w5YI+GvbVvgD///8M////dP///+7//////////////////////////P//
/9////+X////OP///wT///8AAAAAAAAAAAAAAAAAAAAAAAAAAADlgj775YI+/OWCPvzlgj785YI+/OWC
Pvzlgj785YI+/OWCPvzlgj785YI+/OWCPvzlgj785YI+/OWCPvzlgj785YI+/OWCPvzlgj785YI++uWC
PvTlgj7p5YI+1eWCPrTlgj6B5YI+ROWCPhL///8A////Af///zD///+l////9/////v////y////4///
/8j///+b////X////yT///8D////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADlgj5S5YI+U+WC
PlPlgj5T5YI+U+WCPlPlgj5T5YI+U+WCPlPlgj5T5YI+U+WCPlPlgj5T5YI+U+WCPlPlgj5T5YI+U+WC
PlPlgj5S5YI+TOWCPj7lgj4r5YI+F+WCPgflgj4A5YI+AAAAAAD///8A////Bf///zn///9Y////VP//
/0v///86////JP///w////8C////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
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
</value>
</data>
</root>

View File

@ -0,0 +1,19 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace BetterDiscordWI {
static class Program {
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main() {
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new FormMain());
}
}
}

View File

@ -0,0 +1,36 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("BetterDiscordWI")]
[assembly: AssemblyDescription("BetterDiscord Windows Installer")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("CSharpForLife")]
[assembly: AssemblyProduct("BetterDiscordWI")]
[assembly: AssemblyCopyright("Copyright © 2018")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("390615f1-ce33-4173-9e8c-4e4f3eb1758d")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("0.3.0.0")]
[assembly: AssemblyFileVersion("0.3.0.0")]

View File

@ -0,0 +1,83 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace BetterDiscordWI.Properties {
using System;
/// <summary>
/// A strongly-typed resource class, for looking up localized strings, etc.
/// </summary>
// This class was auto-generated by the StronglyTypedResourceBuilder
// class via a tool like ResGen or Visual Studio.
// To add or remove a member, edit your .ResX file then rerun ResGen
// with the /str option, or rebuild your VS project.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class Resources {
private static global::System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture;
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal Resources() {
}
/// <summary>
/// Returns the cached ResourceManager instance used by this class.
/// </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("BetterDiscordWI.Properties.Resources", typeof(Resources).Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
/// <summary>
/// Overrides the current thread's CurrentUICulture property for all
/// resource lookups using this strongly typed resource class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture {
get {
return resourceCulture;
}
set {
resourceCulture = value;
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap Betterdiscord_small_black_blue {
get {
object obj = ResourceManager.GetObject("Betterdiscord_small_black_blue", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap Betterdiscord_small_white_blue {
get {
object obj = ResourceManager.GetObject("Betterdiscord_small_white_blue", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
}
}

View File

@ -0,0 +1,127 @@
<?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>
<assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<data name="Betterdiscord_small_black_blue" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\Betterdiscord small black+blue.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="Betterdiscord_small_white_blue" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\Betterdiscord small white+blue.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
</root>

View File

@ -0,0 +1,26 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace BetterDiscordWI.Properties {
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "15.1.0.0")]
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
public static Settings Default {
get {
return defaultInstance;
}
}
}
}

View File

@ -0,0 +1,7 @@
<?xml version='1.0' encoding='utf-8'?>
<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)">
<Profiles>
<Profile Name="(Default)" />
</Profiles>
<Settings />
</SettingsFile>

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

View File

@ -0,0 +1,22 @@
using System;
using System.Net;
using System.Threading.Tasks;
namespace BetterDiscordWI {
public static class Utils {
public static WebHeaderCollection Headers = new WebHeaderCollection { ["User-Agent"] = "Mozilla/5.0" };
public static async Task<string> GetHash() {
using (var wc = new WebClient { Headers = Headers }) {
var result = await wc.DownloadStringTaskAsync(@"https://api.github.com/repos/Jiiks/BetterDiscordApp/commits/master");
var start = result.IndexOf("{\"sha\":") + 8;
var end = result.IndexOf("\",\"") - 8;
return result.Substring(start, end);
}
}
}
}

View File

@ -0,0 +1,76 @@
<?xml version="1.0" encoding="utf-8"?>
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
<assemblyIdentity version="1.0.0.0" name="MyApplication.app"/>
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
<security>
<requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">
<!-- UAC Manifest Options
If you want to change the Windows User Account Control level replace the
requestedExecutionLevel node with one of the following.
<requestedExecutionLevel level="asInvoker" uiAccess="false" />
<requestedExecutionLevel level="requireAdministrator" uiAccess="false" />
<requestedExecutionLevel level="highestAvailable" uiAccess="false" />
Specifying requestedExecutionLevel element will disable file and registry virtualization.
Remove this element if your application requires this virtualization for backwards
compatibility.
-->
<requestedExecutionLevel level="requireAdministrator" uiAccess="false" />
</requestedPrivileges>
</security>
</trustInfo>
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
<application>
<!-- A list of the Windows versions that this application has been tested on and is
is designed to work with. Uncomment the appropriate elements and Windows will
automatically selected the most compatible environment. -->
<!-- Windows Vista -->
<!--<supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}" />-->
<!-- Windows 7 -->
<!--<supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}" />-->
<!-- Windows 8 -->
<!--<supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}" />-->
<!-- Windows 8.1 -->
<!--<supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}" />-->
<!-- Windows 10 -->
<!--<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" />-->
</application>
</compatibility>
<!-- Indicates that the application is DPI-aware and will not be automatically scaled by Windows at higher
DPIs. Windows Presentation Foundation (WPF) applications are automatically DPI-aware and do not need
to opt in. Windows Forms applications targeting .NET Framework 4.6 that opt into this setting, should
also set the 'EnableWindowsFormsHighDpiAutoResizing' setting to 'true' in their app.config. -->
<!--
<application xmlns="urn:schemas-microsoft-com:asm.v3">
<windowsSettings>
<dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true</dpiAware>
</windowsSettings>
</application>
-->
<!-- Enable themes for Windows common controls and dialogs (Windows XP and later) -->
<!--
<dependency>
<dependentAssembly>
<assemblyIdentity
type="win32"
name="Microsoft.Windows.Common-Controls"
version="6.0.0.0"
processorArchitecture="*"
publicKeyToken="6595b64144ccf1df"
language="*"
/>
</dependentAssembly>
</dependency>
-->
</assembly>

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.2"/>
</startup>
</configuration>

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.2"/>
</startup>
</configuration>

View File

@ -0,0 +1,31 @@
namespace BetterDiscordWI.controls {
partial class Button {
/// <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 Component 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() {
components = new System.ComponentModel.Container();
}
#endregion
}
}

View File

@ -0,0 +1,36 @@
namespace BetterDiscordWI.controls {
public partial class Button : System.Windows.Forms.Button {
public Button() {
InitializeComponent();
}
public Button HideDisable(string newText = null) {
if (newText != null) Text = newText;
Hide();
Enabled = false;
return this;
}
public Button HideEnable(string newText = null) {
if (newText != null) Text = newText;
Hide();
Enabled = true;
return this;
}
public Button ShowDisable(string newText = null) {
if (newText != null) Text = newText;
Show();
Enabled = false;
return this;
}
public Button ShowEnable(string newText = null) {
if (newText != null) Text = newText;
Show();
Enabled = true;
return this;
}
}
}

View File

@ -0,0 +1,15 @@
G:\Github\BetterDiscordApp\Installers\dotNet2\BetterDiscordWI\BetterDiscordWI\bin\Debug\BetterDiscordWI.exe.config
G:\Github\BetterDiscordApp\Installers\dotNet2\BetterDiscordWI\BetterDiscordWI\bin\Debug\BetterDiscordWI.exe
G:\Github\BetterDiscordApp\Installers\dotNet2\BetterDiscordWI\BetterDiscordWI\bin\Debug\BetterDiscordWI.pdb
G:\Github\BetterDiscordApp\Installers\dotNet2\BetterDiscordWI\BetterDiscordWI\obj\Debug\BetterDiscordWI.csprojResolveAssemblyReference.cache
G:\Github\BetterDiscordApp\Installers\dotNet2\BetterDiscordWI\BetterDiscordWI\obj\Debug\BetterDiscordWI.FormMain.resources
G:\Github\BetterDiscordApp\Installers\dotNet2\BetterDiscordWI\BetterDiscordWI\obj\Debug\BetterDiscordWI.Properties.Resources.resources
G:\Github\BetterDiscordApp\Installers\dotNet2\BetterDiscordWI\BetterDiscordWI\obj\Debug\BetterDiscordWI.csproj.GenerateResource.Cache
G:\Github\BetterDiscordApp\Installers\dotNet2\BetterDiscordWI\BetterDiscordWI\obj\Debug\BetterDiscordWI.exe
G:\Github\BetterDiscordApp\Installers\dotNet2\BetterDiscordWI\BetterDiscordWI\obj\Debug\BetterDiscordWI.pdb
G:\Github\BetterDiscordApp\Installers\dotNet2\BetterDiscordWI\BetterDiscordWI\obj\Debug\BetterDiscordWI.panels.LicensePanel.resources
G:\Github\BetterDiscordApp\Installers\dotNet2\BetterDiscordWI\BetterDiscordWI\obj\Debug\BetterDiscordWI.panels.ConfigPanel.resources
G:\Github\BetterDiscordApp\Installers\dotNet2\BetterDiscordWI\BetterDiscordWI\obj\Debug\BetterDiscordWI.panels.InstallPanel.resources
G:\Github\BetterDiscordApp\Installers\dotNet2\BetterDiscordWI\BetterDiscordWI\bin\Debug\Newtonsoft.Json.dll
G:\Github\BetterDiscordApp\Installers\dotNet2\BetterDiscordWI\BetterDiscordWI\bin\Debug\asardotnetasync.dll
G:\Github\BetterDiscordApp\Installers\dotNet2\BetterDiscordWI\BetterDiscordWI\bin\Debug\asardotnetasync.pdb

View File

@ -0,0 +1 @@
9ed8cc2d0146708e9135d42f9b545d4d9dc45abd

View File

@ -0,0 +1,12 @@
G:\Github\BetterDiscordApp\Installers\dotNet2\BetterDiscordWI\BetterDiscordWI\bin\Release\BetterDiscordWI.exe.config
G:\Github\BetterDiscordApp\Installers\dotNet2\BetterDiscordWI\BetterDiscordWI\bin\Release\BetterDiscordWI.exe
G:\Github\BetterDiscordApp\Installers\dotNet2\BetterDiscordWI\BetterDiscordWI\bin\Release\BetterDiscordWI.pdb
G:\Github\BetterDiscordApp\Installers\dotNet2\BetterDiscordWI\BetterDiscordWI\obj\Release\BetterDiscordWI.FormMain.resources
G:\Github\BetterDiscordApp\Installers\dotNet2\BetterDiscordWI\BetterDiscordWI\obj\Release\BetterDiscordWI.panels.ConfigPanel.resources
G:\Github\BetterDiscordApp\Installers\dotNet2\BetterDiscordWI\BetterDiscordWI\obj\Release\BetterDiscordWI.panels.InstallPanel.resources
G:\Github\BetterDiscordApp\Installers\dotNet2\BetterDiscordWI\BetterDiscordWI\obj\Release\BetterDiscordWI.panels.LicensePanel.resources
G:\Github\BetterDiscordApp\Installers\dotNet2\BetterDiscordWI\BetterDiscordWI\obj\Release\BetterDiscordWI.Properties.Resources.resources
G:\Github\BetterDiscordApp\Installers\dotNet2\BetterDiscordWI\BetterDiscordWI\obj\Release\BetterDiscordWI.csproj.GenerateResource.Cache
G:\Github\BetterDiscordApp\Installers\dotNet2\BetterDiscordWI\BetterDiscordWI\obj\Release\BetterDiscordWI.exe
G:\Github\BetterDiscordApp\Installers\dotNet2\BetterDiscordWI\BetterDiscordWI\obj\Release\BetterDiscordWI.pdb
G:\Github\BetterDiscordApp\Installers\dotNet2\BetterDiscordWI\BetterDiscordWI\obj\Release\BetterDiscordWI.csprojResolveAssemblyReference.cache

View File

@ -0,0 +1,297 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.IO.Compression;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Security.AccessControl;
using System.Security.Cryptography;
using System.Security.Principal;
using System.Text;
using System.Threading;
static class Common
{
private const int DelayUntilReboot = 4;
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
static extern bool MoveFileEx(string lpExistingFileName, string lpNewFileName, int dwFlags);
[DllImport("kernel32", SetLastError = true, CharSet = CharSet.Unicode)]
static extern IntPtr LoadLibrary(string dllToLoad);
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool SetDllDirectory(string lpPathName);
[Conditional("DEBUG")]
public static void Log(string format, params object[] args)
{
// Should this be trace?
Debug.WriteLine("=== COSTURA === " + string.Format(format, args));
}
static void CopyTo(Stream source, Stream destination)
{
var array = new byte[81920];
int count;
while ((count = source.Read(array, 0, array.Length)) != 0)
{
destination.Write(array, 0, count);
}
}
static void CreateDirectory(string tempBasePath)
{
if (!Directory.Exists(tempBasePath))
{
Directory.CreateDirectory(tempBasePath);
}
}
static byte[] ReadStream(Stream stream)
{
var data = new Byte[stream.Length];
stream.Read(data, 0, data.Length);
return data;
}
public static string CalculateChecksum(string filename)
{
using (var fs = new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.ReadWrite | FileShare.Delete))
using (var bs = new BufferedStream(fs))
using (var sha1 = new SHA1CryptoServiceProvider())
{
var hash = sha1.ComputeHash(bs);
var formatted = new StringBuilder(2 * hash.Length);
foreach (var b in hash)
{
formatted.AppendFormat("{0:X2}", b);
}
return formatted.ToString();
}
}
public static Assembly ReadExistingAssembly(AssemblyName name)
{
var currentDomain = AppDomain.CurrentDomain;
var assemblies = currentDomain.GetAssemblies();
foreach (var assembly in assemblies)
{
var currentName = assembly.GetName();
if (string.Equals(currentName.Name, name.Name, StringComparison.InvariantCultureIgnoreCase) &&
string.Equals(CultureToString(currentName.CultureInfo), CultureToString(name.CultureInfo), StringComparison.InvariantCultureIgnoreCase))
{
Log("Assembly '{0}' already loaded, returning existing assembly", assembly.FullName);
return assembly;
}
}
return null;
}
static string CultureToString(CultureInfo culture)
{
if (culture == null)
return "";
return culture.Name;
}
public static Assembly ReadFromDiskCache(string tempBasePath, AssemblyName requestedAssemblyName)
{
var name = requestedAssemblyName.Name.ToLowerInvariant();
if (requestedAssemblyName.CultureInfo != null && !String.IsNullOrEmpty(requestedAssemblyName.CultureInfo.Name))
name = $"{requestedAssemblyName.CultureInfo.Name}.{name}";
var bittyness = IntPtr.Size == 8 ? "64" : "32";
var assemblyTempFilePath = Path.Combine(tempBasePath, String.Concat(name, ".dll"));
if (File.Exists(assemblyTempFilePath))
{
return Assembly.LoadFile(assemblyTempFilePath);
}
assemblyTempFilePath = Path.ChangeExtension(assemblyTempFilePath, "exe");
if (File.Exists(assemblyTempFilePath))
{
return Assembly.LoadFile(assemblyTempFilePath);
}
assemblyTempFilePath = Path.Combine(Path.Combine(tempBasePath, bittyness), String.Concat(name, ".dll"));
if (File.Exists(assemblyTempFilePath))
{
return Assembly.LoadFile(assemblyTempFilePath);
}
assemblyTempFilePath = Path.ChangeExtension(assemblyTempFilePath, "exe");
if (File.Exists(assemblyTempFilePath))
{
return Assembly.LoadFile(assemblyTempFilePath);
}
return null;
}
public static Assembly ReadFromEmbeddedResources(Dictionary<string, string> assemblyNames, Dictionary<string, string> symbolNames, AssemblyName requestedAssemblyName)
{
var name = requestedAssemblyName.Name.ToLowerInvariant();
if (requestedAssemblyName.CultureInfo != null && !String.IsNullOrEmpty(requestedAssemblyName.CultureInfo.Name))
name = $"{requestedAssemblyName.CultureInfo.Name}.{name}";
byte[] assemblyData;
using (var assemblyStream = LoadStream(assemblyNames, name))
{
if (assemblyStream == null)
{
return null;
}
assemblyData = ReadStream(assemblyStream);
}
using (var pdbStream = LoadStream(symbolNames, name))
{
if (pdbStream != null)
{
var pdbData = ReadStream(pdbStream);
return Assembly.Load(assemblyData, pdbData);
}
}
return Assembly.Load(assemblyData);
}
static Stream LoadStream(Dictionary<string, string> resourceNames, string name)
{
string value;
if (resourceNames.TryGetValue(name, out value))
return LoadStream(value);
return null;
}
static Stream LoadStream(string fullname)
{
var executingAssembly = Assembly.GetExecutingAssembly();
if (fullname.EndsWith(".compressed"))
{
using (var stream = executingAssembly.GetManifestResourceStream(fullname))
using (var compressStream = new DeflateStream(stream, CompressionMode.Decompress))
{
var memStream = new MemoryStream();
CopyTo(compressStream, memStream);
memStream.Position = 0;
return memStream;
}
}
return executingAssembly.GetManifestResourceStream(fullname);
}
// Mutex code from http://stackoverflow.com/questions/229565/what-is-a-good-pattern-for-using-a-global-mutex-in-c
public static void PreloadUnmanagedLibraries(string hash, string tempBasePath, IEnumerable<string> libs, Dictionary<string, string> checksums)
{
var mutexId = $"Global\\Costura{hash}";
using (var mutex = new Mutex(false, mutexId))
{
var allowEveryoneRule = new MutexAccessRule(new SecurityIdentifier(WellKnownSidType.WorldSid, null), MutexRights.FullControl, AccessControlType.Allow);
var securitySettings = new MutexSecurity();
securitySettings.AddAccessRule(allowEveryoneRule);
mutex.SetAccessControl(securitySettings);
var hasHandle = false;
try
{
try
{
hasHandle = mutex.WaitOne(60000, false);
if (hasHandle == false)
throw new TimeoutException("Timeout waiting for exclusive access");
}
catch (AbandonedMutexException)
{
hasHandle = true;
}
var bittyness = IntPtr.Size == 8 ? "64" : "32";
CreateDirectory(Path.Combine(tempBasePath, bittyness));
InternalPreloadUnmanagedLibraries(tempBasePath, libs, checksums);
}
finally
{
if (hasHandle)
mutex.ReleaseMutex();
}
}
}
static void InternalPreloadUnmanagedLibraries(string tempBasePath, IEnumerable<string> libs, Dictionary<string, string> checksums)
{
string name;
foreach (var lib in libs)
{
name = ResourceNameToPath(lib);
var assemblyTempFilePath = Path.Combine(tempBasePath, name);
if (File.Exists(assemblyTempFilePath))
{
var checksum = CalculateChecksum(assemblyTempFilePath);
if (checksum != checksums[lib])
File.Delete(assemblyTempFilePath);
}
if (!File.Exists(assemblyTempFilePath))
{
using (var copyStream = LoadStream(lib))
using (var assemblyTempFile = File.OpenWrite(assemblyTempFilePath))
{
CopyTo(copyStream, assemblyTempFile);
}
if (!MoveFileEx(assemblyTempFilePath, null, DelayUntilReboot))
{
//TODO: for now we ignore the return value.
}
}
}
SetDllDirectory(tempBasePath);
foreach (var lib in libs)
{
name = ResourceNameToPath(lib);
if (name.EndsWith(".dll"))
{
var assemblyTempFilePath = Path.Combine(tempBasePath, name);
LoadLibrary(assemblyTempFilePath);
}
}
}
static string ResourceNameToPath(string lib)
{
var bittyness = IntPtr.Size == 8 ? "64" : "32";
var name = lib;
if (lib.StartsWith(String.Concat("costura", bittyness, ".")))
{
name = Path.Combine(bittyness, lib.Substring(10));
}
else if (lib.StartsWith("costura."))
{
name = lib.Substring(8);
}
if (name.EndsWith(".compressed"))
{
name = name.Substring(0, name.Length - 11);
}
return name;
}
}

View File

@ -0,0 +1 @@
003befe214f35e255c343afecd5f5dea062bb193

View File

@ -0,0 +1,63 @@
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Threading;
static class ILTemplate
{
static readonly object nullCacheLock = new object();
static readonly Dictionary<string, bool> nullCache = new Dictionary<string, bool>();
static readonly Dictionary<string, string> assemblyNames = new Dictionary<string, string>();
static readonly Dictionary<string, string> symbolNames = new Dictionary<string, string>();
static int isAttached = 0;
public static void Attach()
{
if (Interlocked.Exchange(ref isAttached, 1) == 1)
{
return;
}
var currentDomain = AppDomain.CurrentDomain;
currentDomain.AssemblyResolve += ResolveAssembly;
}
public static Assembly ResolveAssembly(object sender, ResolveEventArgs e)
{
lock (nullCacheLock)
{
if (nullCache.ContainsKey(e.Name))
{
return null;
}
}
var requestedAssemblyName = new AssemblyName(e.Name);
var assembly = Common.ReadExistingAssembly(requestedAssemblyName);
if (assembly != null)
{
return assembly;
}
Common.Log("Loading assembly '{0}' into the AppDomain", requestedAssemblyName);
assembly = Common.ReadFromEmbeddedResources(assemblyNames, symbolNames, requestedAssemblyName);
if (assembly == null)
{
lock (nullCacheLock)
{
nullCache[e.Name] = true;
}
// Handles retargeted assemblies like PCL
if (requestedAssemblyName.Flags == AssemblyNameFlags.Retargetable)
{
assembly = Assembly.Load(requestedAssemblyName);
}
}
return assembly;
}
}

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Costura.Fody" version="1.6.2" targetFramework="net462" developmentDependency="true" />
<package id="Fody" version="2.0.0" targetFramework="net462" developmentDependency="true" />
</packages>

View File

@ -0,0 +1,205 @@
namespace BetterDiscordWI.panels {
partial class ConfigPanel {
/// <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 Component 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() {
this.label1 = new System.Windows.Forms.Label();
this.tbPath = new System.Windows.Forms.TextBox();
this.btnBrowse = new BetterDiscordWI.controls.Button();
this.label2 = new System.Windows.Forms.Label();
this.label3 = new System.Windows.Forms.Label();
this.cbRestart = new System.Windows.Forms.CheckBox();
this.cbCanary = new System.Windows.Forms.CheckBox();
this.cbPtb = new System.Windows.Forms.CheckBox();
this.lblCanarywarning = new System.Windows.Forms.Label();
this.lblPtbwarning = new System.Windows.Forms.Label();
this.cbStable = new System.Windows.Forms.CheckBox();
this.lblStablewarning = new System.Windows.Forms.Label();
this.SuspendLayout();
//
// label1
//
this.label1.AutoSize = true;
this.label1.Location = new System.Drawing.Point(3, 3);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(380, 13);
this.label1.TabIndex = 0;
this.label1.Text = "Setup will install BetterDiscord to the following location. Click Install to cont" +
"inue.";
//
// tbPath
//
this.tbPath.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.tbPath.Location = new System.Drawing.Point(6, 31);
this.tbPath.Name = "tbPath";
this.tbPath.ReadOnly = true;
this.tbPath.Size = new System.Drawing.Size(377, 20);
this.tbPath.TabIndex = 1;
//
// btnBrowse
//
this.btnBrowse.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.btnBrowse.Location = new System.Drawing.Point(389, 31);
this.btnBrowse.Name = "btnBrowse";
this.btnBrowse.Size = new System.Drawing.Size(75, 23);
this.btnBrowse.TabIndex = 2;
this.btnBrowse.Text = "Browse";
this.btnBrowse.UseVisualStyleBackColor = true;
this.btnBrowse.Click += new System.EventHandler(this.btnBrowse_Click);
//
// label2
//
this.label2.AutoSize = true;
this.label2.Location = new System.Drawing.Point(3, 66);
this.label2.Name = "label2";
this.label2.Size = new System.Drawing.Size(422, 13);
this.label2.TabIndex = 3;
this.label2.Text = "*If the path is not pointing to the latest version of Discord then click browse a" +
"nd select it.";
//
// label3
//
this.label3.AutoSize = true;
this.label3.Location = new System.Drawing.Point(3, 79);
this.label3.Name = "label3";
this.label3.Size = new System.Drawing.Size(161, 13);
this.label3.TabIndex = 4;
this.label3.Text = "*Installer will kill Discord process.";
//
// cbRestart
//
this.cbRestart.AutoSize = true;
this.cbRestart.Location = new System.Drawing.Point(6, 106);
this.cbRestart.Name = "cbRestart";
this.cbRestart.Size = new System.Drawing.Size(175, 17);
this.cbRestart.TabIndex = 5;
this.cbRestart.Text = "Restart Discord after installation";
this.cbRestart.UseVisualStyleBackColor = true;
this.cbRestart.CheckedChanged += new System.EventHandler(this.cbRestart_CheckedChanged);
//
// cbCanary
//
this.cbCanary.AutoSize = true;
this.cbCanary.Location = new System.Drawing.Point(6, 150);
this.cbCanary.Name = "cbCanary";
this.cbCanary.Size = new System.Drawing.Size(137, 17);
this.cbCanary.TabIndex = 6;
this.cbCanary.Text = "Install to DiscordCanary";
this.cbCanary.UseVisualStyleBackColor = true;
this.cbCanary.CheckedChanged += new System.EventHandler(this.cbCanary_CheckedChanged);
//
// cbPtb
//
this.cbPtb.AutoSize = true;
this.cbPtb.Location = new System.Drawing.Point(6, 173);
this.cbPtb.Name = "cbPtb";
this.cbPtb.Size = new System.Drawing.Size(125, 17);
this.cbPtb.TabIndex = 7;
this.cbPtb.Text = "Install to DiscordPTB";
this.cbPtb.UseVisualStyleBackColor = true;
this.cbPtb.CheckedChanged += new System.EventHandler(this.cbPtb_CheckedChanged);
//
// lblCanarywarning
//
this.lblCanarywarning.AutoSize = true;
this.lblCanarywarning.ForeColor = System.Drawing.Color.Red;
this.lblCanarywarning.Location = new System.Drawing.Point(149, 151);
this.lblCanarywarning.Name = "lblCanarywarning";
this.lblCanarywarning.Size = new System.Drawing.Size(97, 13);
this.lblCanarywarning.TabIndex = 8;
this.lblCanarywarning.Text = "(Canary not found!)";
this.lblCanarywarning.Visible = false;
//
// lblPtbwarning
//
this.lblPtbwarning.AutoSize = true;
this.lblPtbwarning.ForeColor = System.Drawing.Color.Red;
this.lblPtbwarning.Location = new System.Drawing.Point(149, 173);
this.lblPtbwarning.Name = "lblPtbwarning";
this.lblPtbwarning.Size = new System.Drawing.Size(85, 13);
this.lblPtbwarning.TabIndex = 9;
this.lblPtbwarning.Text = "(PTB not found!)";
this.lblPtbwarning.Visible = false;
//
// cbStable
//
this.cbStable.AutoSize = true;
this.cbStable.Location = new System.Drawing.Point(6, 127);
this.cbStable.Name = "cbStable";
this.cbStable.Size = new System.Drawing.Size(98, 17);
this.cbStable.TabIndex = 10;
this.cbStable.Text = "Install to Stable";
this.cbStable.UseVisualStyleBackColor = true;
this.cbStable.CheckedChanged += new System.EventHandler(this.cbStable_CheckedChanged);
//
// lblStablewarning
//
this.lblStablewarning.AutoSize = true;
this.lblStablewarning.ForeColor = System.Drawing.Color.Red;
this.lblStablewarning.Location = new System.Drawing.Point(149, 128);
this.lblStablewarning.Name = "lblStablewarning";
this.lblStablewarning.Size = new System.Drawing.Size(97, 13);
this.lblStablewarning.TabIndex = 11;
this.lblStablewarning.Text = "(Canary not found!)";
this.lblStablewarning.Visible = false;
//
// ConfigPanel
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.Controls.Add(this.lblStablewarning);
this.Controls.Add(this.cbStable);
this.Controls.Add(this.lblPtbwarning);
this.Controls.Add(this.lblCanarywarning);
this.Controls.Add(this.cbPtb);
this.Controls.Add(this.cbCanary);
this.Controls.Add(this.cbRestart);
this.Controls.Add(this.label3);
this.Controls.Add(this.label2);
this.Controls.Add(this.btnBrowse);
this.Controls.Add(this.tbPath);
this.Controls.Add(this.label1);
this.Name = "ConfigPanel";
this.Size = new System.Drawing.Size(538, 284);
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.Label label1;
private System.Windows.Forms.TextBox tbPath;
private controls.Button btnBrowse;
private System.Windows.Forms.Label label2;
private System.Windows.Forms.Label label3;
private System.Windows.Forms.CheckBox cbRestart;
private System.Windows.Forms.CheckBox cbCanary;
private System.Windows.Forms.CheckBox cbPtb;
private System.Windows.Forms.Label lblCanarywarning;
private System.Windows.Forms.Label lblPtbwarning;
private System.Windows.Forms.CheckBox cbStable;
private System.Windows.Forms.Label lblStablewarning;
}
}

View File

@ -0,0 +1,126 @@
using System;
using System.IO;
using System.Text.RegularExpressions;
using System.Windows.Forms;
namespace BetterDiscordWI.panels {
public partial class ConfigPanel : UserControl, IPanel {
private FormMain _formMain;
private readonly Regex _matcher = new Regex(@"[0-9]+\.[0-9]+\.[0-9]+");
private static string StablePath => $"{Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData)}\\Discord";
private static bool StableExists() => Directory.Exists(StablePath);
private static string CanaryPath => $"{Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData)}\\DiscordCanary";
private static bool CanaryExists() => Directory.Exists(CanaryPath);
private static string PtbPath => $"{Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData)}\\DiscordPTB";
private static bool PtbExists() => Directory.Exists(PtbPath);
public ConfigPanel() {
InitializeComponent();
}
public void ShowPanel() {
_formMain.btnBack.ShowEnable();
_formMain.btnCancel.ShowEnable();
_formMain.btnNext.ShowEnable("Install");
if (!CanaryExists()) {
lblCanarywarning.Show();
cbCanary.Enabled = false;
}
if (!PtbExists()) {
lblPtbwarning.Show();
cbPtb.Enabled = false;
}
if (!StableExists()) {
lblStablewarning.Show();
cbStable.Enabled = false;
}
if (!StableExists() && !CanaryExists() && PtbExists()) {
_formMain.btnNext.ShowDisable();
}
cbRestart.Checked = _formMain.RestartDiscord;
cbCanary.Checked = _formMain.Canary;
cbPtb.Checked = _formMain.Ptb;
cbStable.Checked = _formMain.Stable;
LocateDiscord();
Show();
}
public void HidePanel() {
Hide();
}
public void SetForm(FormMain formMain) => _formMain = formMain;
public string Title => "Installation";
public UserControl Control => this;
private void btnBrowse_Click(object sender, System.EventArgs e) {
var fbd = new FolderBrowserDialog {SelectedPath = tbPath.Text};
fbd.ShowDialog();
tbPath.Text = fbd.SelectedPath;
_formMain.DiscordPath = fbd.SelectedPath;
}
private void LocateDiscord() {
var finalPath = GetLatestVersion(cbPtb.Checked ? PtbPath : cbCanary.Checked ? CanaryPath : StablePath);
tbPath.Text = finalPath;
_formMain.DiscordPath = finalPath;
_formMain.Stable = cbStable.Checked;
_formMain.Canary = cbCanary.Checked;
_formMain.Ptb = cbPtb.Checked;
}
private string GetLatestVersion(string path) {
var dirs = Directory.GetDirectories(path);
var latest = dirs[0];
foreach (var dir in dirs) {
if (!_matcher.IsMatch(dir)) continue;
if (string.CompareOrdinal(dir, latest) > 0) latest = dir;
}
return latest;
}
private void cbCanary_CheckedChanged(object sender, EventArgs e) {
if (cbCanary.Checked) {
cbPtb.Checked = false;
cbStable.Checked = false;
}
LocateDiscord();
}
private void cbPtb_CheckedChanged(object sender, EventArgs e) {
if (cbPtb.Checked) {
cbCanary.Checked = false;
cbStable.Checked = false;
}
LocateDiscord();
}
private void cbRestart_CheckedChanged(object sender, EventArgs e) {
_formMain.RestartDiscord = cbRestart.Checked;
}
private void cbStable_CheckedChanged(object sender, EventArgs e) {
if (cbStable.Checked) {
cbCanary.Checked = false;
cbPtb.Checked = false;
}
LocateDiscord();
}
}
}

View File

@ -0,0 +1,120 @@
<?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>
</root>

View File

@ -0,0 +1,11 @@
using System.Windows.Forms;
namespace BetterDiscordWI.panels {
internal interface IPanel {
void ShowPanel();
void HidePanel();
void SetForm(FormMain formMain);
string Title { get; }
UserControl Control { get; }
}
}

View File

@ -0,0 +1,98 @@
namespace BetterDiscordWI.panels {
partial class InstallPanel {
/// <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 Component 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() {
this.rtbStatus = new System.Windows.Forms.RichTextBox();
this.pbStatus = new System.Windows.Forms.ProgressBar();
this.cbDetailed = new System.Windows.Forms.CheckBox();
this.rtbDetailed = new System.Windows.Forms.RichTextBox();
this.SuspendLayout();
//
// rtbStatus
//
this.rtbStatus.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.rtbStatus.Location = new System.Drawing.Point(3, 3);
this.rtbStatus.Name = "rtbStatus";
this.rtbStatus.Size = new System.Drawing.Size(492, 126);
this.rtbStatus.TabIndex = 0;
this.rtbStatus.Text = "";
//
// pbStatus
//
this.pbStatus.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.pbStatus.Location = new System.Drawing.Point(67, 135);
this.pbStatus.Name = "pbStatus";
this.pbStatus.Size = new System.Drawing.Size(428, 23);
this.pbStatus.TabIndex = 1;
//
// cbDetailed
//
this.cbDetailed.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.cbDetailed.AutoSize = true;
this.cbDetailed.Location = new System.Drawing.Point(4, 138);
this.cbDetailed.Name = "cbDetailed";
this.cbDetailed.Size = new System.Drawing.Size(58, 17);
this.cbDetailed.TabIndex = 2;
this.cbDetailed.Text = "Details";
this.cbDetailed.UseVisualStyleBackColor = true;
this.cbDetailed.CheckedChanged += new System.EventHandler(this.cbDetailed_CheckedChanged);
//
// rtbDetailed
//
this.rtbDetailed.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.rtbDetailed.Location = new System.Drawing.Point(3, 3);
this.rtbDetailed.Name = "rtbDetailed";
this.rtbDetailed.Size = new System.Drawing.Size(492, 126);
this.rtbDetailed.TabIndex = 3;
this.rtbDetailed.Text = "";
this.rtbDetailed.Visible = false;
//
// InstallPanel
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.Controls.Add(this.rtbDetailed);
this.Controls.Add(this.cbDetailed);
this.Controls.Add(this.pbStatus);
this.Controls.Add(this.rtbStatus);
this.Name = "InstallPanel";
this.Size = new System.Drawing.Size(501, 166);
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.RichTextBox rtbStatus;
private System.Windows.Forms.ProgressBar pbStatus;
private System.Windows.Forms.CheckBox cbDetailed;
private System.Windows.Forms.RichTextBox rtbDetailed;
}
}

View File

@ -0,0 +1,315 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.IO.Compression;
using System.Net;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using asardotnetasync;
namespace BetterDiscordWI.panels {
public partial class InstallPanel : UserControl, IPanel {
private FormMain _formMain;
private readonly SynchronizationContext _synchronizationContext;
private string _asarPath => $"{_formMain.DiscordPath}\\modules\\discord_desktop_core";
public InstallPanel() {
InitializeComponent();
_synchronizationContext = SynchronizationContext.Current;
}
private async Task<int> InstallTask() {
var asarExists = LocateAsar();
if (!asarExists) return 0;
Append("Killing Discord Processes");
var discordPname = _formMain.Canary ? "DiscordCanary" : _formMain.Ptb ? "DiscordPTB" : "Discord";
string discordExePath = null;
foreach (var process in Process.GetProcessesByName(discordPname)) {
Append($"Killing Discord process {process.Id}", true);
discordExePath = process.MainModule.FileName;
process.Kill();
}
if (await AsarExtract() != 1) return 0;
if (await InjectBd() != 1) return 0;
if (await DownloadBd() != 1) return 0;
if (await Verify() != 1) return 0;
if (_formMain.RestartDiscord && discordExePath != null) {
Append("Restarting Discord");
Process.Start(discordExePath);
}
Append("Finished installing BetterDiscord!");
return 1;
}
private async Task<int> AsarExtract() {
Append("Extracting core.asar");
var asarArchive = new AsarArchive($"{_asarPath}\\core.asar");
var asarExtractor = new AsarExtractor();
asarExtractor.FileExtracted += (s, e) => {
_synchronizationContext.Post(o => {
pbStatus.Value = (int)((AsarExtractEvent)o).Progress;
}, e);
Append(e.File.Path, true);
};
asarExtractor.Finished += (s, e) => {
Append($"Finished extracting core.asar");
};
try {
if (!Directory.Exists($"{_asarPath}\\app")) Directory.CreateDirectory($"{_asarPath}\\core");
await asarExtractor.ExtractAll(asarArchive, $"{_asarPath}\\core\\");
}
catch (Exception e) {
Debug.Print(e.Message);
}
return 1;
}
private async Task<int> InjectBd() {
var mainScreenPath = $"{_asarPath}\\core\\app\\mainScreen.js";
var indexPath = $"{_asarPath}\\index.js";
Append($"Injecting BetterDiscord to {_asarPath}\\core");
if (!File.Exists(mainScreenPath)) {
Append($"{mainScreenPath} does not exist! Cannot continue.");
_formMain.Fail();
return 0;
}
Append("Rewriting index.js");
File.WriteAllText(indexPath, "module.exports = require('./core');");
var lines = new List<string>();
foreach (var line in File.ReadAllLines(mainScreenPath)) {
lines.Add(line);
if (line.Contains("mainWindow = new")) {
lines.Add(" _betterDiscord2 = new _betterDiscord.BetterDiscord(mainWindow);");
}
}
lines.Insert(1, "var _betterDiscord = require('BetterDiscord');");
lines.Insert(2, "var _betterDiscord2;");
File.WriteAllLines(mainScreenPath, lines.ToArray());
Append("Finished injecting BetterDiscord");
return 1;
}
private async Task<int> DownloadBd() {
Append("Fetching latest hash");
// var hash = await Utils.GetHash();
// Append($"Latest hash: {hash}");
var repo = "Jiiks";
var branch = "stable16";
var channel = $"https://github.com/{repo}/BetterDiscordApp/archive/{branch}.zip";
var dest = $"{_formMain.DiscordPath}\\modules\\discord_desktop_core\\BetterDiscord.zip";
Append("Downloading BetterDiscord package");
using (var wc = new WebClient {Headers = Utils.Headers}) {
wc.DownloadProgressChanged += (sender, args) => {
_synchronizationContext.Post(e => {
var state = (DownloadProgressChangedEventArgs) e;
pbStatus.Value = state.ProgressPercentage;
}, args);
};
Append($"Using channel: {channel}", true);
Append($"Downloading to: {dest}", true);
await wc.DownloadFileTaskAsync(channel, dest);
}
Append("Finished downloading BetterDiscord package");
await ExtractBd(dest, $"{_formMain.DiscordPath}\\modules\\discord_desktop_core\\node_modules");
return 1;
}
private async Task<int> ExtractBd(string path, string dest) {
if (Directory.Exists($"{dest}\\BetterDiscord")) {
Append("Deleting old BetterDiscord");
Directory.Delete($"{dest}\\BetterDiscord", true);
}
if (Directory.Exists($"{dest}\\BetterDiscordApp-stable16")) {
Append("Deleting old BetterDiscordApp-stable16");
Directory.Delete($"{dest}\\BetterDiscordApp-stable16", true);
}
Append("Extracting BetterDiscord package");
if (!File.Exists(path)) {
Append($"BetterDiscord package does not exist in: {path}. Cannot continue.");
_formMain.Fail();
return 0;
}
var zar = ZipFile.OpenRead(path);
if (!Directory.Exists(dest)) {
Directory.CreateDirectory(dest);
}
zar.ExtractToDirectory(dest);
zar.Dispose();
if (!Directory.Exists($"{dest}\\BetterDiscordApp-stable16")) {
Append($"BetterDiscord package does not exist in: {dest}\\BetterDiscordApp-stable16. Cannot continue.");
_formMain.Fail();
return 0;
}
Append("Renaming package dir", true);
Directory.Move($"{dest}\\BetterDiscordApp-stable16", $"{dest}\\BetterDiscord");
if (File.Exists(path)) {
Append($"Deleting temp file {path}");
File.Delete(path);
}
return 1;
}
private async Task<int> Verify() {
Append("Verifying installation");
var mainScreenPath = $"{_asarPath}\\core\\app\\mainScreen.js";
var indexPath = $"{_asarPath}\\index.js";
Append("Verifying: Discord files");
if (!File.ReadAllText(indexPath).Contains("module.exports = require('./core');")) {
Append($"{indexPath} NOT OK! Verification failed!");
_formMain.Fail();
return 0;
}
var mainScreen = File.ReadAllText(mainScreenPath);
if (!mainScreen.Contains("var _betterDiscord = require('BetterDiscord');") && mainScreen.Contains("var _betterDiscord2;") && mainScreen.Contains("_betterDiscord2 = new _betterDiscord.BetterDiscord(mainWindow);")) {
Append($"{mainScreenPath} NOT OK! Verification failed!");
_formMain.Fail();
return 0;
}
Append($"Verifying BetterDiscord package");
var modulePath = $"{_formMain.DiscordPath}\\modules\\discord_desktop_core\\node_modules";
if (!Directory.Exists(modulePath)) {
Append($"{modulePath} does not exist! Verification failed!");
_formMain.Fail();
return 0;
}
var bdPath = $"{modulePath}\\BetterDiscord";
if (!Directory.Exists(modulePath)) {
Append($"{modulePath} does not exist! Verification failed!");
_formMain.Fail();
return 0;
}
var currentPath = $"{bdPath}\\lib";
if (!Directory.Exists(currentPath)) {
Append($"{currentPath} does not exist! Verification failed!");
_formMain.Fail();
return 0;
}
var bdFiles = new[]{"betterdiscord.js", "package.json", "lib\\BetterDiscord.js", "lib\\config.json", "lib\\Utils.js"};
foreach (var bdFile in bdFiles) {
if (File.Exists($"{bdPath}\\{bdFile}")) continue;
Append($"{bdPath}\\{bdFile} does not exist! Verification failed!");
_formMain.Fail();
return 0;
}
Append("Verification successful");
return 1;
}
public void ShowPanel() {
_formMain.btnBack.HideDisable();
_formMain.btnNext.HideDisable();
_formMain.btnCancel.ShowDisable("Exit");
rtbStatus.Text = "";
Task.Run(InstallTask).ContinueWith(result => {
Debug.WriteLine($"Install task finished with code: {result.Result}");
if (result.Result == 0) _formMain.Fail();
_synchronizationContext.Post(o => {
_formMain.btnCancel.ShowEnable("Exit");
}, result);
});
}
private bool LocateAsar() {
Append($"Searching for Discord core in: {_asarPath}");
if (!File.Exists($"{_asarPath}\\core.asar")) {
Append($"core.asar does not exist in: {_asarPath}!");
Append("Unable to continue installation.");
return false;
}
Append($"Located core.asar in: {_asarPath}");
return true;
}
public void HidePanel() {
}
public void SetForm(FormMain formMain) => _formMain = formMain;
public string Title => "Installing";
public UserControl Control => this;
private void Append(string text, bool detailed = false) {
_synchronizationContext.Post(o => {
if (!detailed) {
rtbStatus.AppendText((string) o);
rtbStatus.AppendText(Environment.NewLine);
}
rtbDetailed.AppendText((string)o);
rtbDetailed.AppendText(Environment.NewLine);
rtbStatus.ScrollToCaret();
rtbDetailed.ScrollToCaret();
}, text);
}
private void cbDetailed_CheckedChanged(object sender, EventArgs e) {
rtbDetailed.Visible = cbDetailed.Checked;
rtbStatus.Visible = !cbDetailed.Checked;
}
}
}

View File

@ -0,0 +1,120 @@
<?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>
</root>

View File

@ -0,0 +1,101 @@
namespace BetterDiscordWI.panels {
partial class LicensePanel {
/// <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 Component 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(LicensePanel));
this.radioAccept = new System.Windows.Forms.RadioButton();
this.radioDecline = new System.Windows.Forms.RadioButton();
this.label1 = new System.Windows.Forms.Label();
this.richTextBox1 = new System.Windows.Forms.RichTextBox();
this.SuspendLayout();
//
// radioAccept
//
this.radioAccept.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.radioAccept.AutoSize = true;
this.radioAccept.Location = new System.Drawing.Point(413, 286);
this.radioAccept.Name = "radioAccept";
this.radioAccept.Size = new System.Drawing.Size(59, 17);
this.radioAccept.TabIndex = 0;
this.radioAccept.Text = "Accept";
this.radioAccept.UseVisualStyleBackColor = true;
//
// radioDecline
//
this.radioDecline.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.radioDecline.AutoSize = true;
this.radioDecline.Checked = true;
this.radioDecline.Location = new System.Drawing.Point(478, 286);
this.radioDecline.Name = "radioDecline";
this.radioDecline.Size = new System.Drawing.Size(61, 17);
this.radioDecline.TabIndex = 1;
this.radioDecline.TabStop = true;
this.radioDecline.Text = "Decline";
this.radioDecline.UseVisualStyleBackColor = true;
//
// label1
//
this.label1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.label1.Location = new System.Drawing.Point(3, 5);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(480, 13);
this.label1.TabIndex = 2;
this.label1.Text = "Please read the following License Agreement and accept the terms before continuin" +
"g the installation.";
//
// richTextBox1
//
this.richTextBox1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.richTextBox1.Location = new System.Drawing.Point(3, 21);
this.richTextBox1.Name = "richTextBox1";
this.richTextBox1.Size = new System.Drawing.Size(533, 259);
this.richTextBox1.TabIndex = 3;
this.richTextBox1.Text = resources.GetString("richTextBox1.Text");
//
// LicensePanel
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.Controls.Add(this.richTextBox1);
this.Controls.Add(this.label1);
this.Controls.Add(this.radioDecline);
this.Controls.Add(this.radioAccept);
this.Name = "LicensePanel";
this.Size = new System.Drawing.Size(542, 306);
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.RadioButton radioAccept;
private System.Windows.Forms.RadioButton radioDecline;
private System.Windows.Forms.Label label1;
private System.Windows.Forms.RichTextBox richTextBox1;
}
}

View File

@ -0,0 +1,40 @@
using System.Windows.Forms;
namespace BetterDiscordWI.panels {
public partial class LicensePanel : UserControl, IPanel {
private FormMain _formMain;
public string Title => "License Agreement";
public UserControl Control => this;
public LicensePanel() {
InitializeComponent();
radioAccept.CheckedChanged += (sender, args) => {
if (radioAccept.Checked) {
_formMain.btnBack.HideDisable();
_formMain.btnNext.ShowEnable();
_formMain.btnCancel.ShowEnable();
return;
}
_formMain.btnBack.HideDisable();
_formMain.btnNext.ShowDisable();
_formMain.btnCancel.ShowEnable();
};
}
public void SetForm(FormMain formMain) => _formMain = formMain;
public void ShowPanel() {
radioAccept.Checked = false;
radioDecline.Checked = true;
_formMain.btnBack.HideDisable();
_formMain.btnNext.ShowDisable();
_formMain.btnCancel.ShowEnable();
Show();
}
public void HidePanel() => Hide();
}
}

View File

@ -0,0 +1,132 @@
<?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="richTextBox1.Text" xml:space="preserve">
<value>Copyright (c) 2015-Present Jiiks
https://jiiks.net
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
</value>
</data>
</root>

View File

@ -0,0 +1,29 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<CosturaPath Condition="$(CosturaPath) == '' Or $(CosturaPath) == '*Undefined*'">$(MSBuildThisFileDirectory)..\..\</CosturaPath>
</PropertyGroup>
<UsingTask
TaskName="Costura.Tasks.FilterReferenceCopyLocalPaths"
AssemblyFile="$(CosturaPath)\Costura.Tasks.dll" />
<Target Name="CosturaFilterReferenceCopyLocalPaths" BeforeTargets="_CopyFilesMarkedCopyLocal" DependsOnTargets="FodyTarget">
<Costura.Tasks.FilterReferenceCopyLocalPaths
ProjectDirectory="$(ProjectDir)"
SolutionDir="$(FodySolutionDir)"
References="@(ReferencePath)"
ReferenceCopyLocalPaths="@(ReferenceCopyLocalPaths)"
>
<Output TaskParameter="FilteredReferenceCopyLocalPaths" ItemName="FilteredReferenceCopyLocalPaths" />
</Costura.Tasks.FilterReferenceCopyLocalPaths>
<ItemGroup>
<ReferenceCopyLocalPaths Remove="@(ReferenceCopyLocalPaths)" />
<ReferenceCopyLocalPaths Include="@(FilteredReferenceCopyLocalPaths)" />
</ItemGroup>
</Target>
</Project>

View File

@ -0,0 +1,29 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<CosturaPath Condition="$(CosturaPath) == '' Or $(CosturaPath) == '*Undefined*'">$(MSBuildThisFileDirectory)..\..\</CosturaPath>
</PropertyGroup>
<UsingTask
TaskName="Costura.Tasks.FilterReferenceCopyLocalPaths"
AssemblyFile="$(CosturaPath)\Costura.Tasks.dll" />
<Target Name="CosturaFilterReferenceCopyLocalPaths" BeforeTargets="_CopyFilesMarkedCopyLocal" DependsOnTargets="FodyTarget">
<Costura.Tasks.FilterReferenceCopyLocalPaths
ProjectDirectory="$(ProjectDir)"
SolutionDir="$(FodySolutionDir)"
References="@(ReferencePath)"
ReferenceCopyLocalPaths="@(ReferenceCopyLocalPaths)"
>
<Output TaskParameter="FilteredReferenceCopyLocalPaths" ItemName="FilteredReferenceCopyLocalPaths" />
</Costura.Tasks.FilterReferenceCopyLocalPaths>
<ItemGroup>
<ReferenceCopyLocalPaths Remove="@(ReferenceCopyLocalPaths)" />
<ReferenceCopyLocalPaths Include="@(FilteredReferenceCopyLocalPaths)" />
</ItemGroup>
</Target>
</Project>

View File

@ -0,0 +1,94 @@
param($installPath, $toolsPath, $package, $project)
function RemoveForceProjectLevelHack($project)
{
Write-Host "RemoveForceProjectLevelHack"
Foreach ($item in $project.ProjectItems)
{
if ($item.Name -eq "Fody_ToBeDeleted.txt")
{
$item.Delete()
}
}
}
function FlushVariables()
{
Write-Host "Flushing environment variables"
$env:FodyLastProjectPath = ""
$env:FodyLastWeaverName = ""
$env:FodyLastXmlContents = ""
}
function Update-FodyConfig($addinName, $project)
{
Write-Host "Update-FodyConfig"
$fodyWeaversPath = [System.IO.Path]::Combine([System.IO.Path]::GetDirectoryName($project.FullName), "FodyWeavers.xml")
$FodyLastProjectPath = $env:FodyLastProjectPath
$FodyLastWeaverName = $env:FodyLastWeaverName
$FodyLastXmlContents = $env:FodyLastXmlContents
if (
($FodyLastProjectPath -eq $project.FullName) -and
($FodyLastWeaverName -eq $addinName))
{
Write-Host "Upgrade detected. Restoring content for $addinName"
[System.IO.File]::WriteAllText($fodyWeaversPath, $FodyLastXmlContents)
FlushVariables
return
}
FlushVariables
$xml = [xml](get-content $fodyWeaversPath)
$weavers = $xml["Weavers"]
$node = $weavers.SelectSingleNode($addinName)
if (-not $node)
{
Write-Host "Appending node"
$newNode = $xml.CreateElement($addinName)
$weavers.AppendChild($newNode)
}
$xml.Save($fodyWeaversPath)
}
function Fix-ReferencesCopyLocal($package, $project)
{
Write-Host "Fix-ReferencesCopyLocal $($package.Id)"
$asms = $package.AssemblyReferences | %{$_.Name}
foreach ($reference in $project.Object.References)
{
if ($asms -contains $reference.Name + ".dll")
{
if($reference.CopyLocal -eq $true)
{
$reference.CopyLocal = $false;
}
}
}
}
function UnlockWeaversXml($project)
{
$fodyWeaversProjectItem = $project.ProjectItems.Item("FodyWeavers.xml");
if ($fodyWeaversProjectItem)
{
$fodyWeaversProjectItem.Open("{7651A701-06E5-11D1-8EBD-00A0C90F26EA}")
$fodyWeaversProjectItem.Save()
$fodyWeaversProjectItem.Document.Close()
}
}
UnlockWeaversXml($project)
RemoveForceProjectLevelHack $project
Update-FodyConfig $package.Id.Replace(".Fody", "") $project
Fix-ReferencesCopyLocal $package $project

View File

@ -0,0 +1,47 @@
param($installPath, $toolsPath, $package, $project)
function Update-FodyConfig($addinName, $project)
{
$fodyWeaversPath = [System.IO.Path]::Combine([System.IO.Path]::GetDirectoryName($project.FullName), "FodyWeavers.xml")
if (!(Test-Path ($fodyWeaversPath)))
{
return
}
Write-Host "Caching variables for possible update"
$env:FodyLastProjectPath = $project.FullName
$env:FodyLastWeaverName = $addinName
$env:FodyLastXmlContents = [IO.File]::ReadAllText($fodyWeaversPath)
$xml = [xml](get-content $fodyWeaversPath)
$weavers = $xml["Weavers"]
$node = $weavers.SelectSingleNode($addinName)
if ($node)
{
Write-Host "Removing node from FodyWeavers.xml"
$weavers.RemoveChild($node)
}
$xml.Save($fodyWeaversPath)
}
function UnlockWeaversXml($project)
{
$fodyWeaversProjectItem = $project.ProjectItems.Item("FodyWeavers.xml");
if ($fodyWeaversProjectItem)
{
$fodyWeaversProjectItem.Open("{7651A701-06E5-11D1-8EBD-00A0C90F26EA}")
$fodyWeaversProjectItem.Save()
$fodyWeaversProjectItem.Document.Close()
}
}
UnlockWeaversXml($project)
Update-FodyConfig $package.Id.Replace(".Fody", "") $project

View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8" ?>
<Weavers>
</Weavers>

Binary file not shown.

Binary file not shown.

Some files were not shown because too many files have changed in this diff Show More