From 8206fe87b49f86ca44926a0913116f6565c33a17 Mon Sep 17 00:00:00 2001 From: he3als Date: Sat, 24 Feb 2024 21:49:30 +0000 Subject: [PATCH] feat(.NET): move Windows ISO mount to new class --- src/Actions/.NET.cs | 178 +++++------------- .../FolderPicker.cs | 2 +- src/Misc/SelectWindowsImage.cs | 119 ++++++++++++ src/Program.cs | 8 - src/amecs.csproj | 3 +- 5 files changed, 167 insertions(+), 143 deletions(-) rename src/{Misc.FolderPicker => Misc}/FolderPicker.cs (99%) create mode 100644 src/Misc/SelectWindowsImage.cs diff --git a/src/Actions/.NET.cs b/src/Actions/.NET.cs index e3c76a5..356e93d 100644 --- a/src/Actions/.NET.cs +++ b/src/Actions/.NET.cs @@ -7,8 +7,7 @@ using System.Runtime.InteropServices; using System.Security; using System.Text; using System.Threading; -using System.Windows.Forms; -using Misc.FolderPicker; +using amecs.Misc; using Ameliorated.ConsoleUtils; using Microsoft.Dism; @@ -16,103 +15,28 @@ namespace amecs.Actions { public class _NET { - private static string file; - private static bool CheckFileViolation(string inputFile) - { - try - { - file = inputFile; - } - catch (SecurityException e) - { - Console.WriteLine(); - ConsoleTUI.OpenFrame.Close("Security error: " + e.Message, ConsoleColor.Red, Console.BackgroundColor, new ChoicePrompt() { AnyKey = true, Text = "Press any key to return to the Menu: " }); - return true; - } + private static string isoPath; + private static string mountedPath; - return false; - } - - private static bool DismountImage() + private static void Unmount() { - ProcessStartInfo startInfo = new ProcessStartInfo(); - startInfo.CreateNoWindow = false; - startInfo.UseShellExecute = false; - startInfo.FileName = "PowerShell.exe"; - startInfo.WindowStyle = ProcessWindowStyle.Hidden; - startInfo.Arguments = $"-NoP -C \"Dismount-DiskImage '{file}'\""; - startInfo.RedirectStandardOutput = true; - - var proc = Process.Start(startInfo); - proc.WaitForExit(); - return true; + if (isoPath == "none") + return; + + SelectWindowsImage.DismountIso(isoPath); } public static bool Install() { - string letter; - - var choice = new ChoicePrompt() { Text = "To install .NET 3.5, Windows installation media is needed.\r\nDo you have a Windows USB instead of an ISO? (Y/N): " }.Start(); - if (choice == null) return false; - var usingFolder = choice == 0; - if (usingFolder) - { - var dlg = new FolderPicker(); - dlg.InputPath = Globals.UserFolder; - if (!dlg.ShowDialog(IntPtr.Zero, false).GetValueOrDefault()) - { - Console.WriteLine(); - ConsoleTUI.OpenFrame.Close("\r\nYou must select a folder or drive.", new ChoicePrompt() {AnyKey = true, Text = "Press any key to return to the Menu: "}); - return true; - } - if (CheckFileViolation(dlg.ResultPath)) return false; - letter = dlg.ResultPath; - } - else - { - var dialog = new System.Windows.Forms.OpenFileDialog(); - dialog.Filter = "ISO Files (*.ISO)| *.ISO"; // Filter files by extension - dialog.Multiselect = false; - dialog.InitialDirectory = Globals.UserFolder; + (mountedPath, isoPath) = SelectWindowsImage.GetMediaPath(); + if (mountedPath == null) return false; - NativeWindow window = new NativeWindow(); - window.AssignHandle(Process.GetCurrentProcess().MainWindowHandle); - if (dialog.ShowDialog(window) == DialogResult.OK) - { - if (CheckFileViolation(dialog.FileName)) return false; - Console.WriteLine(); - ConsoleTUI.OpenFrame.WriteCentered("\r\nMounting ISO"); - } - else - { - Console.WriteLine(); - ConsoleTUI.OpenFrame.Close("\r\nYou must select an ISO.", new ChoicePrompt() {AnyKey = true, Text = "Press any key to return to the Menu: "}); - return true; - } - - using (new ConsoleUtils.LoadingIndicator(true)) - { - ProcessStartInfo startInfo = new ProcessStartInfo(); - startInfo.CreateNoWindow = false; - startInfo.UseShellExecute = false; - startInfo.FileName = "PowerShell.exe"; - startInfo.WindowStyle = ProcessWindowStyle.Hidden; - startInfo.Arguments = - $"-NoP -C \"(Mount-DiskImage '{file}' -PassThru | Get-Volume).DriveLetter + ':\'\""; - startInfo.RedirectStandardOutput = true; - - var proc = Process.Start(startInfo); - proc.WaitForExit(); - - letter = proc.StandardOutput.ReadLine(); - } - } - - if (!Directory.Exists(letter + @"\sources\sxs") || !Directory.GetFiles(letter + @"\sources\sxs", "*netfx3*").Any()) + if (!Directory.Exists(mountedPath + @"\sources\sxs") || !Directory.GetFiles(mountedPath + @"\sources\sxs", "*netfx3*").Any()) { - DismountImage(); + Unmount(); Console.WriteLine(); - ConsoleTUI.OpenFrame.Close("ISO/USB/folder does not contain the required files.", ConsoleColor.Red, Console.BackgroundColor, new ChoicePrompt() { AnyKey = true, Text = "Press any key to return to the Menu: " }); + ConsoleTUI.OpenFrame.Close("ISO/USB/folder does not contain the required files.", + ConsoleColor.Red, Console.BackgroundColor, new ChoicePrompt() { AnyKey = true, Text = "Press any key to return to the Menu: " }); return false; } @@ -120,63 +44,52 @@ namespace amecs.Actions var topCache = Console.CursorTop; var leftCache = Console.CursorLeft; Console.WriteLine(); - bool inProgress = false; + var inProgress = false; try { - using (var indicator = new ConsoleUtils.LoadingIndicator()) + using var indicator = new ConsoleUtils.LoadingIndicator(); + DismApi.Initialize(DismLogLevel.LogErrors); + using (var session = DismApi.OpenOnlineSession()) { - DismApi.Initialize(DismLogLevel.LogErrors); - using (var session = DismApi.OpenOnlineSession()) + var stdout = GetStdHandle(-11); + bool indicatorStopped = false; + var maxHashTags = (ConsoleTUI.OpenFrame.DisplayWidth - 5); + DismApi.EnableFeatureByPackagePath(session, "NetFX3", null, true, true, new List() { mountedPath + @"\sources\sxs" }, delegate(DismProgress progress) { - var stdout = GetStdHandle(-11); - bool indicatorStopped = false; - var maxHashTags = (ConsoleTUI.OpenFrame.DisplayWidth - 5); - DismApi.EnableFeatureByPackagePath(session, "NetFX3", null, true, true, new List() { letter + @"\sources\sxs" }, delegate(DismProgress progress) + inProgress = true; + if (!indicatorStopped) { - inProgress = true; - if (!indicatorStopped) - { - indicator.Stop(); - Console.SetCursorPosition(leftCache, topCache); - Console.WriteLine(" "); - } + indicator.Stop(); + Console.SetCursorPosition(leftCache, topCache); + Console.WriteLine(" "); + } - indicatorStopped = true; - var progressPerc = progress.Current / 10; - var currentHashTags = (int)Math.Ceiling(Math.Min(((double)progressPerc / 100) * maxHashTags, maxHashTags)); - var spaces = maxHashTags - currentHashTags + (4 - progressPerc.ToString().Length); - var sb = new StringBuilder(new string('#', currentHashTags) + new string(' ', spaces) + progressPerc + "%"); - uint throwaway; - WriteConsoleOutputCharacter(stdout, sb, (uint)sb.Length, new Languages.COORD((short)ConsoleTUI.OpenFrame.DisplayOffset, (short)Console.CursorTop), out throwaway); - inProgress = false; - }); - session.Close(); - Thread.Sleep(100); - var sb = new StringBuilder(new string('#', maxHashTags) + " 100%"); + indicatorStopped = true; + var progressPerc = progress.Current / 10; + var currentHashTags = (int)Math.Ceiling(Math.Min(((double)progressPerc / 100) * maxHashTags, maxHashTags)); + var spaces = maxHashTags - currentHashTags + (4 - progressPerc.ToString().Length); + var sb = new StringBuilder(new string('#', currentHashTags) + new string(' ', spaces) + progressPerc + "%"); uint throwaway; WriteConsoleOutputCharacter(stdout, sb, (uint)sb.Length, new Languages.COORD((short)ConsoleTUI.OpenFrame.DisplayOffset, (short)Console.CursorTop), out throwaway); - } - - DismApi.Shutdown(); - if (!usingFolder) DismountImage(); + inProgress = false; + }); + session.Close(); + Thread.Sleep(100); + var sb = new StringBuilder(new string('#', maxHashTags) + " 100%"); + uint throwaway; + WriteConsoleOutputCharacter(stdout, sb, (uint)sb.Length, new Languages.COORD((short)ConsoleTUI.OpenFrame.DisplayOffset, (short)Console.CursorTop), out throwaway); } + + DismApi.Shutdown(); + Unmount(); } catch (Exception e) { while (inProgress) { Thread.Sleep(50); } - - if (!usingFolder) - { - try - { - DismountImage(); - } - catch (Exception ex) - { - } - } + + Unmount(); Console.WriteLine(); Console.WriteLine(); @@ -190,7 +103,6 @@ namespace amecs.Actions Console.WriteLine(); Console.WriteLine(); - if (!usingFolder) ConsoleTUI.OpenFrame.Close(".NET 3.5 installed successfully", ConsoleColor.Green, Console.BackgroundColor, new ChoicePrompt() { AnyKey = true, diff --git a/src/Misc.FolderPicker/FolderPicker.cs b/src/Misc/FolderPicker.cs similarity index 99% rename from src/Misc.FolderPicker/FolderPicker.cs rename to src/Misc/FolderPicker.cs index 12d04e6..c56d598 100644 --- a/src/Misc.FolderPicker/FolderPicker.cs +++ b/src/Misc/FolderPicker.cs @@ -5,7 +5,7 @@ using System.Linq; using System.Runtime.InteropServices; using System.Runtime.InteropServices.ComTypes; -namespace Misc.FolderPicker +namespace amecs.Misc { public class FolderPicker { diff --git a/src/Misc/SelectWindowsImage.cs b/src/Misc/SelectWindowsImage.cs new file mode 100644 index 0000000..9448efa --- /dev/null +++ b/src/Misc/SelectWindowsImage.cs @@ -0,0 +1,119 @@ +using System; +using System.Diagnostics; +using System.Security; +using System.Windows.Forms; +using Ameliorated.ConsoleUtils; + +// Asks user to select Windows installation media, and mounts it if applicable +// Returns path to where it's mounted + +namespace amecs.Misc +{ + /// + /// Asks user to select Windows installation media, and mounts it if applicable + /// Returns path to where it's mounted + /// + public class SelectWindowsImage + { + private static string file; + private static bool CheckFileViolation(string inputFile) + { + try + { + file = inputFile; + } + catch (SecurityException e) + { + Console.WriteLine(); + ConsoleTUI.OpenFrame.Close("Security exception: " + e.Message, ConsoleColor.Red, Console.BackgroundColor, new ChoicePrompt() { AnyKey = true, Text = "Press any key to return to the Menu: " }); + return true; + } + + return false; + } + + public static bool DismountIso(string path) + { + var startInfo = new ProcessStartInfo + { + CreateNoWindow = false, + UseShellExecute = false, + FileName = "PowerShell.exe", + WindowStyle = ProcessWindowStyle.Hidden, + Arguments = $"-NoP -C \"Dismount-DiskImage '{path}'\"", + RedirectStandardOutput = true + }; + + var proc = Process.Start(startInfo); + if (proc == null) return false; + proc.WaitForExit(); + return true; + } + + public static (string MountedPath, string IsoPath) GetMediaPath() + { + var choice = + new ChoicePrompt() { Text = "To continue, Windows installation media is needed.\r\nDo you have a Windows USB instead of an ISO file? (Y/N): " }.Start(); + if (choice == null) return (null, "none"); + + // Folder/drive chosen + var usingFolder = choice == 0; + if (usingFolder) + { + var dlg = new FolderPicker + { + InputPath = Globals.UserFolder + }; + + if (dlg.ShowDialog(IntPtr.Zero, false).GetValueOrDefault()) + return CheckFileViolation(dlg.ResultPath) ? (null, "none") : (dlg.ResultPath, "none"); + + Console.WriteLine(); + ConsoleTUI.OpenFrame.Close("\r\nYou must select a folder or drive containing Windows installation media.", + new ChoicePrompt() { AnyKey = true, Text = "Press any key to return to the Menu: " }); + return (null, "none"); + } + + // Mounting the ISO + var dialog = new OpenFileDialog(); + dialog.Filter = "ISO Files (*.ISO)| *.ISO"; + dialog.Multiselect = false; + dialog.InitialDirectory = Globals.UserFolder; + + NativeWindow window = new NativeWindow(); + window.AssignHandle(Process.GetCurrentProcess().MainWindowHandle); + if (dialog.ShowDialog(window) == DialogResult.OK) + { + if (CheckFileViolation(dialog.FileName)) return (null, "none"); + Console.WriteLine(); + ConsoleTUI.OpenFrame.WriteCentered("\r\nMounting ISO"); + } + else + { + Console.WriteLine(); + ConsoleTUI.OpenFrame.Close("\r\nYou must select an ISO.", + new ChoicePrompt() { AnyKey = true, Text = "Press any key to return to the Menu: " }); + return (null, "none"); + } + + using (new ConsoleUtils.LoadingIndicator(true)) + { + var startInfo = new ProcessStartInfo + { + CreateNoWindow = false, + UseShellExecute = false, + FileName = "PowerShell.exe", + WindowStyle = ProcessWindowStyle.Hidden, + Arguments = $"-NoP -C \"(Mount-DiskImage '{file}' -PassThru | Get-Volume).DriveLetter + ':\'\"", + RedirectStandardOutput = true + }; + + var proc = Process.Start(startInfo); + if (proc == null) return (null, "none"); + proc.WaitForExit(); + + return (proc.StandardOutput.ReadLine(), file); + } + } + } +} \ No newline at end of file diff --git a/src/Program.cs b/src/Program.cs index d722486..db070db 100644 --- a/src/Program.cs +++ b/src/Program.cs @@ -1,19 +1,11 @@ using System; -using System.Diagnostics; -using System.DirectoryServices; using System.DirectoryServices.AccountManagement; -using System.Globalization; using System.Linq; -using System.Management; using System.Runtime.InteropServices; -using System.Security; using System.Security.Principal; -using System.Threading; using System.Threading.Tasks; using Ameliorated.ConsoleUtils; using Microsoft.Win32; -using System.Windows.Forms; -using System.Windows.Forms.VisualStyles; using amecs.Actions; using Menu = Ameliorated.ConsoleUtils.Menu; diff --git a/src/amecs.csproj b/src/amecs.csproj index 8f9cdd8..1cfcbd5 100644 --- a/src/amecs.csproj +++ b/src/amecs.csproj @@ -206,11 +206,12 @@ - + +