Skip to content

Commit 2713aa9

Browse files
Added Installer
1 parent 203df13 commit 2713aa9

File tree

7 files changed

+399
-1
lines changed

7 files changed

+399
-1
lines changed

EZCode.sln

+6
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TestEnv", "TestEnv\TestEnv.
99
EndProject
1010
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ez", "ez\ez.csproj", "{A9062E15-5201-47CC-917D-C210E41A1AEC}"
1111
EndProject
12+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Installer", "Installer\Installer.csproj", "{5DB25D5B-AA77-4198-9BEE-17D8CF77DE23}"
13+
EndProject
1214
Global
1315
GlobalSection(SolutionConfigurationPlatforms) = preSolution
1416
Debug|Any CPU = Debug|Any CPU
@@ -27,6 +29,10 @@ Global
2729
{A9062E15-5201-47CC-917D-C210E41A1AEC}.Debug|Any CPU.Build.0 = Debug|Any CPU
2830
{A9062E15-5201-47CC-917D-C210E41A1AEC}.Release|Any CPU.ActiveCfg = Release|Any CPU
2931
{A9062E15-5201-47CC-917D-C210E41A1AEC}.Release|Any CPU.Build.0 = Release|Any CPU
32+
{5DB25D5B-AA77-4198-9BEE-17D8CF77DE23}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
33+
{5DB25D5B-AA77-4198-9BEE-17D8CF77DE23}.Debug|Any CPU.Build.0 = Debug|Any CPU
34+
{5DB25D5B-AA77-4198-9BEE-17D8CF77DE23}.Release|Any CPU.ActiveCfg = Release|Any CPU
35+
{5DB25D5B-AA77-4198-9BEE-17D8CF77DE23}.Release|Any CPU.Build.0 = Release|Any CPU
3036
EndGlobalSection
3137
GlobalSection(SolutionProperties) = preSolution
3238
HideSolutionNode = FALSE

EZCode/Package.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ public class Config
1616

1717
public static class Package
1818
{
19-
public static string PackagesDirectory = "D:\\EZCodeLanguage\\Packages\\";
19+
public static string PackagesDirectory = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86), "EZCodeLanguage", "Packages");
2020
public static void AddPackageToExecutionDirectory(PackageClass project, string executionDirectory)
2121
{
2222
string projectPath = GetPackageDirectory(project.Name);

Installer/Installer.csproj

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<OutputType>Exe</OutputType>
5+
<TargetFramework>net8.0</TargetFramework>
6+
<ImplicitUsings>enable</ImplicitUsings>
7+
<Nullable>enable</Nullable>
8+
<ApplicationManifest>app.manifest</ApplicationManifest>
9+
</PropertyGroup>
10+
11+
<ItemGroup>
12+
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
13+
</ItemGroup>
14+
15+
<ItemGroup>
16+
<ProjectReference Include="..\EZCode\EZCode.csproj" />
17+
</ItemGroup>
18+
19+
</Project>

Installer/Program.cs

+287
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,287 @@
1+
using EZCodeLanguage;
2+
using Microsoft.Win32;
3+
using System.IO.Compression;
4+
using System.Net;
5+
6+
class Program
7+
{
8+
private static readonly string owner = "EZCodeLanguage";
9+
private static readonly string repo = "EZCode";
10+
private static readonly string assetName = "EZCodeLanguage.zip";
11+
private static readonly string extractPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86), "EZCodeLanguage");
12+
private static readonly string directoryToAddToPath = extractPath + "\\";
13+
public class Option
14+
{
15+
public int Id { get; set; }
16+
17+
public string Name { get; set; }
18+
19+
public bool Checked { get; set; }
20+
21+
public Option(string name, int id, bool check)
22+
{
23+
Id = id;
24+
Name = name;
25+
Checked = check;
26+
}
27+
}
28+
29+
static async Task Main(string[] args)
30+
{
31+
try
32+
{
33+
List<Option> options = new List<Option>()
34+
{
35+
new Option($" - Install latest EZCode Version", 0, true),
36+
new Option(" - Uninstall EZCode", 1, false),
37+
};
38+
39+
int index = 0;
40+
41+
ConsoleKey key;
42+
43+
string txt1 = "EZCode Installer";
44+
string txt2 = "Use the arrow keys to select an option, press enter to submit.";
45+
46+
do
47+
{
48+
Console.ForegroundColor = ConsoleColor.Blue;
49+
Console.WriteLine(txt1);
50+
Console.ResetColor();
51+
Console.WriteLine(txt2);
52+
53+
for (int i = 0; i < options.Count; i++)
54+
{
55+
if (i == index)
56+
{
57+
Console.ForegroundColor = ConsoleColor.Cyan;
58+
}
59+
60+
Console.WriteLine($"{options[i].Name}");
61+
62+
Console.ResetColor();
63+
}
64+
65+
key = Console.ReadKey().Key;
66+
67+
switch (key)
68+
{
69+
case ConsoleKey.UpArrow:
70+
index = index == 0 ? options.Count - 1 : index - 1;
71+
for (int i = 0; i < options.Count; i++)
72+
{
73+
options[i].Checked = false;
74+
}
75+
options[index].Checked = true;
76+
break;
77+
case ConsoleKey.DownArrow:
78+
index = index == options.Count - 1 ? 0 : index + 1;
79+
for (int i = 0; i < options.Count; i++)
80+
{
81+
options[i].Checked = false;
82+
}
83+
options[index].Checked = true;
84+
break;
85+
case ConsoleKey.Enter:
86+
break;
87+
default:
88+
Console.ForegroundColor = ConsoleColor.DarkRed;
89+
Console.WriteLine(" is invalid input. Please use the arrow keys or enter.");
90+
Console.ResetColor();
91+
Console.ReadKey();
92+
break;
93+
}
94+
Console.Clear();
95+
96+
} while (key != ConsoleKey.Enter);
97+
98+
foreach (var option in options)
99+
{
100+
if (!option.Checked) continue;
101+
switch (option.Id)
102+
{
103+
case 0: // Install
104+
Console.WriteLine("Starting Installation");
105+
await Install();
106+
Console.WriteLine("Finished installation");
107+
break;
108+
case 1: // Uninstall
109+
Console.WriteLine("Starting Uninstall");
110+
Uninstall();
111+
Console.WriteLine("Finished Uninstalling");
112+
break;
113+
}
114+
}
115+
116+
Console.ForegroundColor = ConsoleColor.Yellow;
117+
Console.WriteLine();
118+
Console.WriteLine("Press any key to exit...");
119+
Console.ResetColor();
120+
Console.ReadKey();
121+
}
122+
catch (Exception ex)
123+
{
124+
Console.WriteLine($"Error: {ex.Message}");
125+
}
126+
}
127+
private static void Uninstall()
128+
{
129+
Directory.Delete(extractPath, true);
130+
Console.WriteLine($"Uninstalled EZCodeLanguage from: {extractPath}\\");
131+
132+
Console.WriteLine($"Adding directory to user PATH: {directoryToAddToPath}");
133+
134+
RemoveDirectoryFromPath(directoryToAddToPath);
135+
}
136+
private static async Task Install()
137+
{
138+
var latestRelease = await GetLatestReleaseAsync(owner, repo);
139+
var assetUrl = GetAssetDownloadUrl(latestRelease, assetName);
140+
141+
if (assetUrl == null)
142+
{
143+
Console.WriteLine($"Asset {assetName} not found in the latest release.");
144+
return;
145+
}
146+
147+
var downloadPath = Path.Combine(Path.GetTempPath(), assetName);
148+
await DownloadFileAsync(assetUrl, downloadPath);
149+
150+
ExtractZipFile(downloadPath, extractPath);
151+
152+
Console.WriteLine($"Extracted to: {extractPath}");
153+
Console.WriteLine("Installation completed successfully.");
154+
155+
Directory.CreateDirectory(Package.PackagesDirectory);
156+
Console.WriteLine("Created Package Directory.");
157+
Console.WriteLine("Installing Packages.");
158+
159+
string[] packages = ["main", "time", "windows-os"];
160+
161+
foreach (var package in packages)
162+
{
163+
var downloadFilePath = Path.Combine(Package.PackagesDirectory, package);
164+
var downloadUrl = $"https://github.com/EZCodeLanguage/Packages/releases/download/{package}-package/{package}.zip";
165+
166+
InstallAndExtract(downloadUrl, downloadFilePath);
167+
Console.WriteLine($"Installed package '{package}' to: {Package.PackagesDirectory}");
168+
}
169+
170+
Console.WriteLine($"Adding directory to user PATH: {directoryToAddToPath}");
171+
172+
AddDirectoryToPath(directoryToAddToPath);
173+
}
174+
175+
static void AddDirectoryToPath(string directory)
176+
{
177+
UpdateProcessPath(directory, true);
178+
UpdateUserPath(directory, true);
179+
180+
Console.WriteLine("successfully added directory to PATH.");
181+
}
182+
183+
static void RemoveDirectoryFromPath(string directory)
184+
{
185+
UpdateProcessPath(directory, false);
186+
UpdateUserPath(directory, false);
187+
188+
Console.WriteLine("Directory removed from PATH successfully.");
189+
}
190+
191+
static void UpdateProcessPath(string directory, bool add)
192+
{
193+
string currentPath = Environment.GetEnvironmentVariable("PATH") ?? "";
194+
string newPath = add ? AddDirectoryToPathString(currentPath, directory) : RemoveDirectoryFromPathString(currentPath, directory);
195+
Environment.SetEnvironmentVariable("PATH", newPath, EnvironmentVariableTarget.Process);
196+
}
197+
198+
static void UpdateUserPath(string directory, bool add)
199+
{
200+
const string userPathSubkey = @"Environment";
201+
const string pathVariableName = "Path";
202+
203+
using (RegistryKey key = Registry.CurrentUser.OpenSubKey(userPathSubkey, writable: true))
204+
{
205+
if (key == null)
206+
{
207+
throw new InvalidOperationException("Failed to open registry key.");
208+
}
209+
210+
string currentPath = key.GetValue(pathVariableName, "", RegistryValueOptions.DoNotExpandEnvironmentNames).ToString();
211+
string newPath = add ? AddDirectoryToPathString(currentPath, directory) : RemoveDirectoryFromPathString(currentPath, directory);
212+
key.SetValue(pathVariableName, newPath, RegistryValueKind.ExpandString);
213+
}
214+
}
215+
216+
static string AddDirectoryToPathString(string currentPath, string directory)
217+
{
218+
var pathParts = currentPath.Split(';');
219+
if (!pathParts.Contains(directory, StringComparer.OrdinalIgnoreCase))
220+
{
221+
currentPath += ";" + directory;
222+
}
223+
return currentPath;
224+
}
225+
226+
static string RemoveDirectoryFromPathString(string currentPath, string directory)
227+
{
228+
var pathParts = currentPath.Split(';')
229+
.Where(part => !part.Equals(directory, StringComparison.OrdinalIgnoreCase))
230+
.ToArray();
231+
return string.Join(";", pathParts);
232+
}
233+
234+
private static async Task<dynamic> GetLatestReleaseAsync(string owner, string repo)
235+
{
236+
using var client = new HttpClient();
237+
client.DefaultRequestHeaders.UserAgent.TryParseAdd("request");
238+
var url = $"https://api.github.com/repos/{owner}/{repo}/releases/latest";
239+
var response = await client.GetStringAsync(url);
240+
return Newtonsoft.Json.JsonConvert.DeserializeObject(response);
241+
}
242+
243+
private static string GetAssetDownloadUrl(dynamic release, string assetName)
244+
{
245+
foreach (var asset in release.assets)
246+
{
247+
if (asset.name == assetName)
248+
{
249+
return asset.browser_download_url;
250+
}
251+
}
252+
return null;
253+
}
254+
255+
private static async Task DownloadFileAsync(string url, string outputPath)
256+
{
257+
using var client = new HttpClient();
258+
var response = await client.GetAsync(url);
259+
response.EnsureSuccessStatusCode();
260+
await using var stream = await response.Content.ReadAsStreamAsync();
261+
await using var fileStream = new FileStream(outputPath, FileMode.Create, FileAccess.Write, FileShare.None);
262+
await stream.CopyToAsync(fileStream);
263+
}
264+
265+
private static void ExtractZipFile(string zipPath, string extractPath)
266+
{
267+
if (Directory.Exists(extractPath))
268+
{
269+
Directory.Delete(extractPath, true);
270+
}
271+
ZipFile.ExtractToDirectory(zipPath, extractPath);
272+
}
273+
274+
static void InstallAndExtract(string downloadUrl, string downloadFilePath)
275+
{
276+
using (WebClient webClient = new WebClient())
277+
{
278+
string tempDownloadFilePath = downloadFilePath + "_.zip";
279+
280+
webClient.DownloadFile(downloadUrl, tempDownloadFilePath);
281+
282+
ZipFile.ExtractToDirectory(tempDownloadFilePath, downloadFilePath, true);
283+
284+
File.Delete(tempDownloadFilePath);
285+
}
286+
}
287+
}

0 commit comments

Comments
 (0)