diff --git a/ConsoleApp/ConsoleApp.csproj b/ConsoleApp/ConsoleApp.csproj index da2b86d..c8aea25 100644 --- a/ConsoleApp/ConsoleApp.csproj +++ b/ConsoleApp/ConsoleApp.csproj @@ -12,7 +12,7 @@ none latest-recommended ConsoleApp.Program - 0.0.7.0 + 0.0.8.0 true app.manifest diff --git a/ConsoleApp/src/ArgumentParser.cs b/ConsoleApp/src/ArgumentParser.cs index 7deb9bb..4ca2def 100644 --- a/ConsoleApp/src/ArgumentParser.cs +++ b/ConsoleApp/src/ArgumentParser.cs @@ -59,7 +59,7 @@ internal static void ParseArgs(ref Parameters parameters, string[] args) parameters.ImageFilePath = args[Array.IndexOf(args, arg) + 1].ToLowerInvariant(); continue; case "/additionaldriversdrive": - parameters.AdditionalDriversDrive = args[Array.IndexOf(args, arg) + 1].ToLowerInvariant(); + parameters.AdditionalDrive = args[Array.IndexOf(args, arg) + 1].ToLowerInvariant(); continue; case "/firmwaretype": parameters.FirmwareType = args[Array.IndexOf(args, arg) + 1].ToUpperInvariant(); @@ -80,7 +80,7 @@ internal static void ParseArgs(ref Parameters parameters, string[] args) Console.WriteLine($" Source Drive: {parameters.SourceDrive}"); Console.WriteLine($" Image Index: {parameters.ImageIndex}"); Console.WriteLine($" Image File Path: {parameters.ImageFilePath}"); - Console.WriteLine($" Additional Drivers Drive: {parameters.AdditionalDriversDrive}"); + Console.WriteLine($" Additional Drivers Drive: {parameters.AdditionalDrive}"); Console.WriteLine($" Firmware Type: {parameters.FirmwareType}"); Console.WriteLine("Press any key to continue..."); Console.ReadKey(); diff --git a/ConsoleApp/src/Program.cs b/ConsoleApp/src/Program.cs index 30d1231..aba4735 100644 --- a/ConsoleApp/src/Program.cs +++ b/ConsoleApp/src/Program.cs @@ -30,36 +30,45 @@ internal static int Main(string[] args) Console.WriteLine($"Created by {ProgramInfo.GetAuthor()}"); #endif } - catch (Exception) + catch (Exception ex) { - throw; + Console.WriteLine($"An error has occurred: {ex.Message}"); } try { ArgumentParser.ParseArgs(ref parameters, args); } - catch (Exception) + catch (Exception ex) { - throw; + Console.WriteLine($"An error has occurred: {ex.Message}"); } try { InstallerManager.Configure(ref parameters); } - catch (Exception) + catch (Exception ex) { - throw; + Console.WriteLine($"An error has occurred: {ex.Message}"); + } + + try + { + InstallerManager.Prepare(ref parameters); + } + catch (Exception ex) + { + Console.WriteLine($"An error has occurred: {ex.Message}"); } try { InstallerManager.InstallWindows(ref parameters); } - catch (Exception) + catch (Exception ex) { - throw; + Console.WriteLine($"An error has occurred: {ex.Message}"); } return 0; diff --git a/GUIApp/GUIApp.csproj b/GUIApp/GUIApp.csproj new file mode 100644 index 0000000..c2fcb04 --- /dev/null +++ b/GUIApp/GUIApp.csproj @@ -0,0 +1,54 @@ + + + + WinExe + net10.0-windows + enable + true + wit.Program + latest + x64 + none + true + en-US + latest-recommended + wit + wit + x64 + app.manifest + SystemAware + + + + 0 + True + none + True + 1.0.0.0 + $(Version) + $(Version) + + + + 9999 + True + full + testing + True + 0.0.3.0 + testing + $(Version) + $(Version) + + + + + + + + + + + + + diff --git a/GUIApp/app.manifest b/GUIApp/app.manifest new file mode 100644 index 0000000..180aa93 --- /dev/null +++ b/GUIApp/app.manifest @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/GUIApp/src/AboutWindow.Designer.cs b/GUIApp/src/AboutWindow.Designer.cs new file mode 100644 index 0000000..863d6b2 --- /dev/null +++ b/GUIApp/src/AboutWindow.Designer.cs @@ -0,0 +1,187 @@ +namespace wit +{ + partial class AboutWindow + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + tableLayoutPanel = new System.Windows.Forms.TableLayoutPanel(); + logoPictureBox = new System.Windows.Forms.PictureBox(); + labelProductName = new System.Windows.Forms.Label(); + labelVersion = new System.Windows.Forms.Label(); + labelCopyright = new System.Windows.Forms.Label(); + labelCompanyName = new System.Windows.Forms.Label(); + textBoxDescription = new System.Windows.Forms.TextBox(); + okButton = new System.Windows.Forms.Button(); + tableLayoutPanel.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)logoPictureBox).BeginInit(); + SuspendLayout(); + // + // tableLayoutPanel + // + tableLayoutPanel.ColumnCount = 2; + tableLayoutPanel.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 33F)); + tableLayoutPanel.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 67F)); + tableLayoutPanel.Controls.Add(logoPictureBox, 0, 0); + tableLayoutPanel.Controls.Add(labelProductName, 1, 0); + tableLayoutPanel.Controls.Add(labelVersion, 1, 1); + tableLayoutPanel.Controls.Add(labelCopyright, 1, 2); + tableLayoutPanel.Controls.Add(labelCompanyName, 1, 3); + tableLayoutPanel.Controls.Add(textBoxDescription, 1, 4); + tableLayoutPanel.Controls.Add(okButton, 1, 5); + tableLayoutPanel.Dock = System.Windows.Forms.DockStyle.Fill; + tableLayoutPanel.Location = new System.Drawing.Point(10, 10); + tableLayoutPanel.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); + tableLayoutPanel.Name = "tableLayoutPanel"; + tableLayoutPanel.RowCount = 6; + tableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 10F)); + tableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 10F)); + tableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 10F)); + tableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 10F)); + tableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 50F)); + tableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 10F)); + tableLayoutPanel.Size = new System.Drawing.Size(487, 307); + tableLayoutPanel.TabIndex = 0; + // + // logoPictureBox + // + logoPictureBox.Dock = System.Windows.Forms.DockStyle.Fill; + logoPictureBox.Location = new System.Drawing.Point(4, 3); + logoPictureBox.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); + logoPictureBox.Name = "logoPictureBox"; + tableLayoutPanel.SetRowSpan(logoPictureBox, 6); + logoPictureBox.Size = new System.Drawing.Size(152, 301); + logoPictureBox.SizeMode = System.Windows.Forms.PictureBoxSizeMode.StretchImage; + logoPictureBox.TabIndex = 12; + logoPictureBox.TabStop = false; + // + // labelProductName + // + labelProductName.Dock = System.Windows.Forms.DockStyle.Fill; + labelProductName.Location = new System.Drawing.Point(167, 0); + labelProductName.Margin = new System.Windows.Forms.Padding(7, 0, 4, 0); + labelProductName.MaximumSize = new System.Drawing.Size(0, 20); + labelProductName.Name = "labelProductName"; + labelProductName.Size = new System.Drawing.Size(316, 20); + labelProductName.TabIndex = 19; + labelProductName.Text = "Product Name"; + labelProductName.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; + // + // labelVersion + // + labelVersion.Dock = System.Windows.Forms.DockStyle.Fill; + labelVersion.Location = new System.Drawing.Point(167, 30); + labelVersion.Margin = new System.Windows.Forms.Padding(7, 0, 4, 0); + labelVersion.MaximumSize = new System.Drawing.Size(0, 20); + labelVersion.Name = "labelVersion"; + labelVersion.Size = new System.Drawing.Size(316, 20); + labelVersion.TabIndex = 0; + labelVersion.Text = "Version"; + labelVersion.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; + // + // labelCopyright + // + labelCopyright.Dock = System.Windows.Forms.DockStyle.Fill; + labelCopyright.Location = new System.Drawing.Point(167, 60); + labelCopyright.Margin = new System.Windows.Forms.Padding(7, 0, 4, 0); + labelCopyright.MaximumSize = new System.Drawing.Size(0, 20); + labelCopyright.Name = "labelCopyright"; + labelCopyright.Size = new System.Drawing.Size(316, 20); + labelCopyright.TabIndex = 21; + labelCopyright.Text = "Copyright"; + labelCopyright.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; + // + // labelCompanyName + // + labelCompanyName.Dock = System.Windows.Forms.DockStyle.Fill; + labelCompanyName.Location = new System.Drawing.Point(167, 90); + labelCompanyName.Margin = new System.Windows.Forms.Padding(7, 0, 4, 0); + labelCompanyName.MaximumSize = new System.Drawing.Size(0, 20); + labelCompanyName.Name = "labelCompanyName"; + labelCompanyName.Size = new System.Drawing.Size(316, 20); + labelCompanyName.TabIndex = 22; + labelCompanyName.Text = "Company Name"; + labelCompanyName.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; + // + // textBoxDescription + // + textBoxDescription.Dock = System.Windows.Forms.DockStyle.Fill; + textBoxDescription.Location = new System.Drawing.Point(167, 123); + textBoxDescription.Margin = new System.Windows.Forms.Padding(7, 3, 4, 3); + textBoxDescription.Multiline = true; + textBoxDescription.Name = "textBoxDescription"; + textBoxDescription.ReadOnly = true; + textBoxDescription.ScrollBars = System.Windows.Forms.ScrollBars.Both; + textBoxDescription.Size = new System.Drawing.Size(316, 147); + textBoxDescription.TabIndex = 23; + textBoxDescription.TabStop = false; + textBoxDescription.Text = "Description"; + // + // okButton + // + okButton.Anchor = System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right; + okButton.DialogResult = System.Windows.Forms.DialogResult.Cancel; + okButton.Location = new System.Drawing.Point(395, 277); + okButton.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); + okButton.Name = "okButton"; + okButton.Size = new System.Drawing.Size(88, 27); + okButton.TabIndex = 24; + okButton.Text = "&OK"; + // + // AboutWindow + // + AcceptButton = okButton; + AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F); + AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + ClientSize = new System.Drawing.Size(507, 327); + Controls.Add(tableLayoutPanel); + FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; + Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); + MaximizeBox = false; + MinimizeBox = false; + Name = "AboutWindow"; + Padding = new System.Windows.Forms.Padding(10); + ShowIcon = false; + ShowInTaskbar = false; + StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; + Text = "AboutWindow"; + tableLayoutPanel.ResumeLayout(false); + tableLayoutPanel.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)logoPictureBox).EndInit(); + ResumeLayout(false); + } + + #endregion + + private System.Windows.Forms.TableLayoutPanel tableLayoutPanel; + private System.Windows.Forms.PictureBox logoPictureBox; + private System.Windows.Forms.Label labelProductName; + private System.Windows.Forms.Label labelVersion; + private System.Windows.Forms.Label labelCopyright; + private System.Windows.Forms.Label labelCompanyName; + private System.Windows.Forms.TextBox textBoxDescription; + private System.Windows.Forms.Button okButton; + } +} diff --git a/GUIApp/src/AboutWindow.cs b/GUIApp/src/AboutWindow.cs new file mode 100644 index 0000000..b4f9868 --- /dev/null +++ b/GUIApp/src/AboutWindow.cs @@ -0,0 +1,93 @@ +using System.Reflection; +using System.Windows.Forms; + +namespace wit +{ + sealed partial class AboutWindow : Form + { + public AboutWindow() + { + InitializeComponent(); + Text = "About: " + AssemblyTitle; + labelProductName.Text = "Program name: " + AssemblyProduct; + labelVersion.Text = $"Version: {AssemblyVersion}"; + labelCopyright.Text = "Copyright: " + AssemblyCopyright; + labelCompanyName.Text = "Company: " + AssemblyCompany; + textBoxDescription.Text = "Description: " + AssemblyDescription; + } + + #region Assembly Attribute Accessors + + public static string AssemblyTitle + { + get + { + object[] attributes = Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyTitleAttribute), false); + if (attributes.Length > 0) + { + AssemblyTitleAttribute titleAttribute = (AssemblyTitleAttribute)attributes[0]; + if (titleAttribute.Title != "") + { + return titleAttribute.Title; + } + } + return System.IO.Path.GetFileNameWithoutExtension(Assembly.GetExecutingAssembly().Location); + } + } + + public static string? AssemblyVersion => Assembly.GetExecutingAssembly().GetName().Version?.ToString(); + + public static string AssemblyDescription + { + get + { + object[] attributes = Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyDescriptionAttribute), false); + if (attributes.Length == 0) + { + return ""; + } + return ((AssemblyDescriptionAttribute)attributes[0]).Description; + } + } + + public static string AssemblyProduct + { + get + { + object[] attributes = Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyProductAttribute), false); + if (attributes.Length == 0) + { + return ""; + } + return ((AssemblyProductAttribute)attributes[0]).Product; + } + } + + public static string AssemblyCopyright + { + get + { + object[] attributes = Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyCopyrightAttribute), false); + if (attributes.Length == 0) + { + return ""; + } + return ((AssemblyCopyrightAttribute)attributes[0]).Copyright; + } + } + + public static string AssemblyCompany + { + get + { + object[] attributes = Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyCompanyAttribute), false); + if (attributes.Length == 0) + { + return ""; + } + return ((AssemblyCompanyAttribute)attributes[0]).Company; + } + } + #endregion + } +} diff --git a/GUIApp/src/AboutWindow.resx b/GUIApp/src/AboutWindow.resx new file mode 100644 index 0000000..6392ed1 --- /dev/null +++ b/GUIApp/src/AboutWindow.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/GUIApp/src/MainWindow.Designer.cs b/GUIApp/src/MainWindow.Designer.cs new file mode 100644 index 0000000..43e54f0 --- /dev/null +++ b/GUIApp/src/MainWindow.Designer.cs @@ -0,0 +1,306 @@ + +using System.Diagnostics.CodeAnalysis; +using System.Windows.Forms; + +namespace wit +{ + partial class MainWindow + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + [RequiresUnreferencedCode("Calls System.ComponentModel.ComponentResourceManager.ApplyResources(Object, String)")] + private void InitializeComponent() + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(MainWindow)); + InstallButton = new Button(); + tableLayoutPanel1 = new TableLayoutPanel(); + EfiDriveLabel = new Label(); + DiskNumber = new NumericUpDown(); + DestinationDriveLabel = new Label(); + DestinationDrive = new ComboBox(); + EfiDrive = new ComboBox(); + RescanDisks = new Button(); + WindowsEditionIndex = new NumericUpDown(); + ImageFileLabel = new Label(); + WindowsEditionIndexLabel = new Label(); + ImageFilePath = new Label(); + ChooseISOImage = new Button(); + SourceDrive = new ComboBox(); + DiskNumberLabel = new Label(); + SourceDrive_Label = new Label(); + SourceDrive_Scan = new Button(); + ImageList = new DataGridView(); + DiskList = new DataGridView(); + MenuBar = new MenuStrip(); + fileToolStripMenuItem = new ToolStripMenuItem(); + exitToolStripMenuItem = new ToolStripMenuItem(); + aboutToolStripMenuItem = new ToolStripMenuItem(); + aboutTheProgramToolStripMenuItem = new ToolStripMenuItem(); + saveFileDialog1 = new SaveFileDialog(); + tableLayoutPanel1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)DiskNumber).BeginInit(); + ((System.ComponentModel.ISupportInitialize)WindowsEditionIndex).BeginInit(); + ((System.ComponentModel.ISupportInitialize)ImageList).BeginInit(); + ((System.ComponentModel.ISupportInitialize)DiskList).BeginInit(); + MenuBar.SuspendLayout(); + SuspendLayout(); + // + // InstallButton + // + resources.ApplyResources(InstallButton, "InstallButton"); + InstallButton.Name = "InstallButton"; + InstallButton.UseVisualStyleBackColor = true; + InstallButton.Click += InstallButton_Click; + // + // tableLayoutPanel1 + // + resources.ApplyResources(tableLayoutPanel1, "tableLayoutPanel1"); + tableLayoutPanel1.Controls.Add(EfiDriveLabel, 0, 1); + tableLayoutPanel1.Controls.Add(DiskNumber, 1, 2); + tableLayoutPanel1.Controls.Add(DestinationDriveLabel, 0, 0); + tableLayoutPanel1.Controls.Add(DestinationDrive, 1, 0); + tableLayoutPanel1.Controls.Add(EfiDrive, 1, 1); + tableLayoutPanel1.Controls.Add(RescanDisks, 2, 2); + tableLayoutPanel1.Controls.Add(WindowsEditionIndex, 1, 5); + tableLayoutPanel1.Controls.Add(ImageFileLabel, 0, 4); + tableLayoutPanel1.Controls.Add(WindowsEditionIndexLabel, 0, 5); + tableLayoutPanel1.Controls.Add(ImageFilePath, 1, 4); + tableLayoutPanel1.Controls.Add(ChooseISOImage, 2, 4); + tableLayoutPanel1.Controls.Add(SourceDrive, 1, 3); + tableLayoutPanel1.Controls.Add(DiskNumberLabel, 0, 2); + tableLayoutPanel1.Controls.Add(SourceDrive_Label, 0, 3); + tableLayoutPanel1.Controls.Add(SourceDrive_Scan, 2, 3); + tableLayoutPanel1.Name = "tableLayoutPanel1"; + // + // EfiDriveLabel + // + resources.ApplyResources(EfiDriveLabel, "EfiDriveLabel"); + EfiDriveLabel.FlatStyle = FlatStyle.System; + EfiDriveLabel.Name = "EfiDriveLabel"; + // + // DiskNumber + // + DiskNumber.BorderStyle = BorderStyle.FixedSingle; + resources.ApplyResources(DiskNumber, "DiskNumber"); + DiskNumber.Name = "DiskNumber"; + // + // DestinationDriveLabel + // + resources.ApplyResources(DestinationDriveLabel, "DestinationDriveLabel"); + DestinationDriveLabel.FlatStyle = FlatStyle.System; + DestinationDriveLabel.Name = "DestinationDriveLabel"; + // + // DestinationDrive + // + resources.ApplyResources(DestinationDrive, "DestinationDrive"); + DestinationDrive.DropDownStyle = ComboBoxStyle.DropDownList; + DestinationDrive.FormattingEnabled = true; + DestinationDrive.Name = "DestinationDrive"; + // + // EfiDrive + // + resources.ApplyResources(EfiDrive, "EfiDrive"); + EfiDrive.DropDownStyle = ComboBoxStyle.DropDownList; + EfiDrive.FormattingEnabled = true; + EfiDrive.Name = "EfiDrive"; + // + // RescanDisks + // + resources.ApplyResources(RescanDisks, "RescanDisks"); + RescanDisks.Name = "RescanDisks"; + RescanDisks.UseVisualStyleBackColor = false; + RescanDisks.Click += RescanDisks_Click; + // + // WindowsEditionIndex + // + resources.ApplyResources(WindowsEditionIndex, "WindowsEditionIndex"); + WindowsEditionIndex.BorderStyle = BorderStyle.FixedSingle; + WindowsEditionIndex.Name = "WindowsEditionIndex"; + // + // ImageFileLabel + // + resources.ApplyResources(ImageFileLabel, "ImageFileLabel"); + ImageFileLabel.FlatStyle = FlatStyle.System; + ImageFileLabel.Name = "ImageFileLabel"; + // + // WindowsEditionIndexLabel + // + resources.ApplyResources(WindowsEditionIndexLabel, "WindowsEditionIndexLabel"); + WindowsEditionIndexLabel.FlatStyle = FlatStyle.System; + WindowsEditionIndexLabel.Name = "WindowsEditionIndexLabel"; + // + // ImageFilePath + // + resources.ApplyResources(ImageFilePath, "ImageFilePath"); + ImageFilePath.AutoEllipsis = true; + ImageFilePath.FlatStyle = FlatStyle.System; + ImageFilePath.Name = "ImageFilePath"; + // + // ChooseISOImage + // + resources.ApplyResources(ChooseISOImage, "ChooseISOImage"); + ChooseISOImage.Name = "ChooseISOImage"; + ChooseISOImage.UseVisualStyleBackColor = false; + ChooseISOImage.Click += ChooseImage_Click; + // + // SourceDrive + // + resources.ApplyResources(SourceDrive, "SourceDrive"); + SourceDrive.DropDownStyle = ComboBoxStyle.DropDownList; + SourceDrive.FormattingEnabled = true; + SourceDrive.Name = "SourceDrive"; + // + // DiskNumberLabel + // + resources.ApplyResources(DiskNumberLabel, "DiskNumberLabel"); + DiskNumberLabel.FlatStyle = FlatStyle.System; + DiskNumberLabel.Name = "DiskNumberLabel"; + // + // SourceDrive_Label + // + resources.ApplyResources(SourceDrive_Label, "SourceDrive_Label"); + SourceDrive_Label.FlatStyle = FlatStyle.System; + SourceDrive_Label.Name = "SourceDrive_Label"; + // + // SourceDrive_Scan + // + resources.ApplyResources(SourceDrive_Scan, "SourceDrive_Scan"); + SourceDrive_Scan.Name = "SourceDrive_Scan"; + SourceDrive_Scan.UseVisualStyleBackColor = false; + SourceDrive_Scan.Click += SourceDrive_Scan_Click; + // + // ImageList + // + ImageList.AllowUserToAddRows = false; + ImageList.AllowUserToDeleteRows = false; + ImageList.AllowUserToResizeColumns = false; + ImageList.AllowUserToResizeRows = false; + ImageList.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill; + ImageList.AutoSizeRowsMode = DataGridViewAutoSizeRowsMode.DisplayedCells; + ImageList.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.AutoSize; + resources.ApplyResources(ImageList, "ImageList"); + ImageList.Name = "ImageList"; + ImageList.ReadOnly = true; + // + // DiskList + // + DiskList.AllowUserToAddRows = false; + DiskList.AllowUserToDeleteRows = false; + DiskList.AllowUserToResizeColumns = false; + DiskList.AllowUserToResizeRows = false; + DiskList.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill; + DiskList.AutoSizeRowsMode = DataGridViewAutoSizeRowsMode.DisplayedCells; + DiskList.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.AutoSize; + resources.ApplyResources(DiskList, "DiskList"); + DiskList.Name = "DiskList"; + DiskList.ReadOnly = true; + DiskList.RowHeadersWidthSizeMode = DataGridViewRowHeadersWidthSizeMode.DisableResizing; + // + // MenuBar + // + MenuBar.BackColor = System.Drawing.Color.Transparent; + MenuBar.Items.AddRange(new ToolStripItem[] { fileToolStripMenuItem, aboutToolStripMenuItem }); + resources.ApplyResources(MenuBar, "MenuBar"); + MenuBar.Name = "MenuBar"; + MenuBar.RenderMode = ToolStripRenderMode.System; + // + // fileToolStripMenuItem + // + fileToolStripMenuItem.DropDownItems.AddRange(new ToolStripItem[] { exitToolStripMenuItem }); + fileToolStripMenuItem.Name = "fileToolStripMenuItem"; + resources.ApplyResources(fileToolStripMenuItem, "fileToolStripMenuItem"); + // + // exitToolStripMenuItem + // + exitToolStripMenuItem.Name = "exitToolStripMenuItem"; + resources.ApplyResources(exitToolStripMenuItem, "exitToolStripMenuItem"); + exitToolStripMenuItem.Click += CloseApplication; + // + // aboutToolStripMenuItem + // + aboutToolStripMenuItem.DropDownItems.AddRange(new ToolStripItem[] { aboutTheProgramToolStripMenuItem }); + aboutToolStripMenuItem.Name = "aboutToolStripMenuItem"; + resources.ApplyResources(aboutToolStripMenuItem, "aboutToolStripMenuItem"); + // + // aboutTheProgramToolStripMenuItem + // + aboutTheProgramToolStripMenuItem.Name = "aboutTheProgramToolStripMenuItem"; + resources.ApplyResources(aboutTheProgramToolStripMenuItem, "aboutTheProgramToolStripMenuItem"); + aboutTheProgramToolStripMenuItem.Click += AboutWindow_Click; + // + // MainWindow + // + resources.ApplyResources(this, "$this"); + AutoScaleMode = AutoScaleMode.Dpi; + Controls.Add(InstallButton); + Controls.Add(ImageList); + Controls.Add(tableLayoutPanel1); + Controls.Add(DiskList); + Controls.Add(MenuBar); + DoubleBuffered = true; + FormBorderStyle = FormBorderStyle.FixedDialog; + MaximizeBox = false; + Name = "MainWindow"; + Load += MainWindow_Load; + tableLayoutPanel1.ResumeLayout(false); + tableLayoutPanel1.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)DiskNumber).EndInit(); + ((System.ComponentModel.ISupportInitialize)WindowsEditionIndex).EndInit(); + ((System.ComponentModel.ISupportInitialize)ImageList).EndInit(); + ((System.ComponentModel.ISupportInitialize)DiskList).EndInit(); + MenuBar.ResumeLayout(false); + MenuBar.PerformLayout(); + ResumeLayout(false); + PerformLayout(); + } + + #endregion + private DataGridView DiskList; + private MenuStrip MenuBar; + private ToolStripMenuItem fileToolStripMenuItem; + private ToolStripMenuItem exitToolStripMenuItem; + private ToolStripMenuItem aboutToolStripMenuItem; + private Label DestinationDriveLabel; + private Label EfiDriveLabel; + private Button InstallButton; + private DataGridView ImageList; + private TableLayoutPanel tableLayoutPanel1; + private NumericUpDown WindowsEditionIndex; + private Label WindowsEditionIndexLabel; + private Button ChooseISOImage; + private Label ImageFilePath; + private Label DiskNumberLabel; + private NumericUpDown DiskNumber; + private Label ImageFileLabel; + private ToolStripMenuItem aboutTheProgramToolStripMenuItem; + private ComboBox DestinationDrive; + private ComboBox EfiDrive; + private Button RescanDisks; + private SaveFileDialog saveFileDialog1; + private Label SourceDrive_Label; + private Button SourceDrive_Scan; + private ComboBox SourceDrive; + } +} diff --git a/GUIApp/src/MainWindow.cs b/GUIApp/src/MainWindow.cs new file mode 100644 index 0000000..29f2f74 --- /dev/null +++ b/GUIApp/src/MainWindow.cs @@ -0,0 +1,228 @@ +using System; +using System.Diagnostics.CodeAnalysis; +using System.IO; +using System.Runtime.Versioning; +using System.Windows.Forms; +using WindowsInstallerLib; +using WindowsInstallerLib.Helpers; + +namespace wit +{ + [SupportedOSPlatform("windows")] + public partial class MainWindow : Form + { + Parameters parameters = new() + { + DiskNumber = -1, + ImageIndex = -1 + }; + + [RequiresUnreferencedCode("Calls System.ComponentModel.ComponentResourceManager.ApplyResources(Object, String)")] + public MainWindow() + { + InitializeComponent(); + } + + private void MainWindow_Load(object sender, EventArgs e) + { + try + { + GetDisksData(sender, e); + GetDiskLetters(sender, e); + + WindowsEditionIndex.Enabled = false; + InstallButton.Enabled = false; + + DestinationDrive.SelectedIndexChanged += ValidateDiskLetter; + EfiDrive.SelectedIndexChanged += ValidateDiskLetter; + SourceDrive.SelectedIndexChanged += ValidateDiskLetter; + } + catch (Exception) + { + throw; + } + } + + private void CloseApplication(object sender, EventArgs e) + { + Application.Exit(); + } + + private void ChooseImage_Click(object sender, EventArgs e) + { + SourceDrive_Scan.Enabled = false; + + if (ImageFilePath.Text == "No image file is selected.") + { + OpenFileDialog OpenFileDialog = new() + { + Filter = "ESD file (*.esd)|*.esd|WIM file (*.wim)|*.wim", + CheckFileExists = true, + CheckPathExists = true, + AddExtension = true, + }; + + DialogResult DialogResult = OpenFileDialog.ShowDialog(); + + if (DialogResult == DialogResult.Cancel) + { + SourceDrive_Label.Enabled = true; + return; + } + + if (string.IsNullOrWhiteSpace(OpenFileDialog.FileName)) + { + MessageBox.Show("No image file was selected.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); + SourceDrive_Scan.Enabled = true; + ImageFilePath.Text = "No image file is selected"; + return; + } + + if (!OpenFileDialog.FileName.Contains("install")) + { + MessageBox.Show("Invalid image file. It must be 'install.wim' or 'install.esd'.", "Invalid file", MessageBoxButtons.OK, MessageBoxIcon.Error); + SourceDrive_Scan.Enabled = true; + throw new InvalidDataException("Invalid image file. It must be 'install.wim' or 'install.esd'."); + } + + parameters.ImageFilePath = OpenFileDialog.FileName; + ImageFilePath.Text = parameters.ImageFilePath; + SourceDrive.SelectedItem = Path.GetPathRoot(ImageFilePath.Text?.TrimEnd('\\')); + } + + if (ImageList.Columns.Count >= 1) + { + ImageList.Columns.Clear(); + } + + try + { + GetImageInfo(sender, e); + } + catch + { + throw; + } + } + + private void SourceDrive_Scan_Click(object sender, EventArgs e) + { + try + { + if (SourceDrive.Text.Length > 0) + { + foreach (string file in Directory.EnumerateFiles(SourceDrive.Text + @"\sources\")) + { + if (file.Contains("install") && file.EndsWith(".esd", StringComparison.CurrentCulture) || + file.Contains("install") && file.EndsWith(".wim", StringComparison.CurrentCulture)) + { + ImageFilePath.Text = file; + parameters.ImageFilePath = ImageFilePath.Text; + ChooseISOImage.Enabled = false; + break; + } + } + } + else + { + MessageBox.Show("Please select a source drive.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); + return; + } + + if (ImageList.Columns.Count >= 1) + { + ImageList.Columns.Clear(); + } + + GetImageInfo(sender, e); + } + catch (Exception) + { + throw; + } + } + + private void InstallButton_Click(object sender, EventArgs e) + { + try + { + parameters.DestinationDrive = DestinationDrive.Text; + parameters.EfiDrive = EfiDrive.Text; + parameters.DiskNumber = Convert.ToInt32(DiskNumber.Value); + parameters.ImageFilePath = ImageFilePath.Text; + parameters.ImageIndex = Convert.ToInt32(WindowsEditionIndex.Value); + + if (string.IsNullOrWhiteSpace(parameters.FirmwareType)) + { + switch (SystemInfo.SystemSupportsEFI()) + { + case true: + parameters.FirmwareType = "UEFI"; + break; + case false: + parameters.FirmwareType = "BIOS"; + break; + } + } + } + catch + { + throw; + } + + try + { + InstallButton.Text = "Please wait..."; + Deployment.FormatDisk(ref parameters); + Deployment.ApplyImage(ref parameters); + Deployment.InstallBootloader(ref parameters); + InstallButton.Text = "Installation complete"; + } + catch + { + throw; + } + } + + private void AboutWindow_Click(object sender, EventArgs e) + { + try + { + new AboutWindow().ShowDialog(this); + } + catch (ArgumentException) + { + throw; + } + catch (InvalidOperationException) + { + throw; + } + catch + { + throw; + } + } + + private void RescanDisks_Click(object sender, EventArgs e) + { + try + { + RescanDisks.Text = "Please wait..."; + RescanDisks.Enabled = false; + DiskList.Columns.Clear(); + DiskList.Rows.Clear(); + GetDisksData(sender, e); + } + catch + { + throw; + } + finally + { + RescanDisks.Text = "Rescan disks"; + RescanDisks.Enabled = true; + } + } + } +} diff --git a/GUIApp/src/MainWindow.resx b/GUIApp/src/MainWindow.resx new file mode 100644 index 0000000..df2c877 --- /dev/null +++ b/GUIApp/src/MainWindow.resx @@ -0,0 +1,813 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + True + + + + System + + + NoControl + + + + 668, 206 + + + 104, 27 + + + 4 + + + Install Windows + + + InstallButton + + + System.Windows.Forms.Button, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 0 + + + True + + + Single + + + 3 + + + Top, Bottom, Left, Right + + + True + + + 4, 31 + + + 96, 29 + + + 3 + + + Bootloader drive + + + EfiDriveLabel + + + System.Windows.Forms.Label, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tableLayoutPanel1 + + + 0 + + + 107, 64 + + + 41, 23 + + + 7 + + + DiskNumber + + + System.Windows.Forms.NumericUpDown, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tableLayoutPanel1 + + + 1 + + + Top, Bottom, Left, Right + + + True + + + 4, 1 + + + 96, 29 + + + 2 + + + OS drive + + + DestinationDriveLabel + + + System.Windows.Forms.Label, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tableLayoutPanel1 + + + 2 + + + Left + + + System + + + 107, 4 + + + 41, 23 + + + 14 + + + DestinationDrive + + + System.Windows.Forms.ComboBox, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tableLayoutPanel1 + + + 3 + + + Left + + + System + + + 107, 34 + + + 41, 23 + + + 15 + + + EfiDrive + + + System.Windows.Forms.ComboBox, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tableLayoutPanel1 + + + 4 + + + Top, Bottom, Left, Right + + + GrowAndShrink + + + System + + + NoControl + + + 252, 64 + + + 118, 24 + + + 16 + + + Rescan devices + + + RescanDisks + + + System.Windows.Forms.Button, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tableLayoutPanel1 + + + 5 + + + True + + + 107, 157 + + + 41, 23 + + + 10 + + + WindowsEditionIndex + + + System.Windows.Forms.NumericUpDown, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tableLayoutPanel1 + + + 6 + + + True + + + Fill + + + NoControl + + + 4, 123 + + + 96, 30 + + + 8 + + + Image file + + + ImageFileLabel + + + System.Windows.Forms.Label, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tableLayoutPanel1 + + + 7 + + + True + + + NoControl + + + 4, 154 + + + 96, 15 + + + 11 + + + Windows edition + + + WindowsEditionIndexLabel + + + System.Windows.Forms.Label, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tableLayoutPanel1 + + + 8 + + + Top, Bottom, Left, Right + + + True + + + NoControl + + + 107, 123 + + + 138, 30 + + + 13 + + + No image file is selected. + + + MiddleCenter + + + ImageFilePath + + + System.Windows.Forms.Label, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tableLayoutPanel1 + + + 9 + + + Top, Bottom, Left, Right + + + GrowAndShrink + + + System + + + NoControl + + + 252, 126 + + + 118, 24 + + + 12 + + + Choose ISO image + + + ChooseISOImage + + + System.Windows.Forms.Button, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tableLayoutPanel1 + + + 10 + + + Left + + + System + + + 107, 95 + + + 41, 23 + + + 17 + + + SourceDrive + + + System.Windows.Forms.ComboBox, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tableLayoutPanel1 + + + 11 + + + Top, Bottom, Left, Right + + + True + + + NoControl + + + 4, 61 + + + 96, 30 + + + 6 + + + Storage device + + + DiskNumberLabel + + + System.Windows.Forms.Label, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tableLayoutPanel1 + + + 12 + + + True + + + Fill + + + NoControl + + + 4, 92 + + + 96, 30 + + + 18 + + + Source drive + + + SourceDrive_Label + + + System.Windows.Forms.Label, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tableLayoutPanel1 + + + 13 + + + Top, Bottom, Left, Right + + + GrowAndShrink + + + System + + + NoControl + + + 252, 95 + + + 118, 24 + + + 19 + + + Scan source drive + + + SourceDrive_Scan + + + System.Windows.Forms.Button, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tableLayoutPanel1 + + + 14 + + + 12, 27 + + + 6 + + + 374, 206 + + + 5 + + + tableLayoutPanel1 + + + System.Windows.Forms.TableLayoutPanel, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 2 + + + <?xml version="1.0" encoding="utf-16"?><TableLayoutSettings><Controls><Control Name="EfiDriveLabel" Row="1" RowSpan="1" Column="0" ColumnSpan="1" /><Control Name="DiskNumber" Row="2" RowSpan="1" Column="1" ColumnSpan="1" /><Control Name="DestinationDriveLabel" Row="0" RowSpan="1" Column="0" ColumnSpan="1" /><Control Name="DestinationDrive" Row="0" RowSpan="1" Column="1" ColumnSpan="1" /><Control Name="EfiDrive" Row="1" RowSpan="1" Column="1" ColumnSpan="1" /><Control Name="RescanDisks" Row="2" RowSpan="1" Column="2" ColumnSpan="1" /><Control Name="WindowsEditionIndex" Row="5" RowSpan="1" Column="1" ColumnSpan="1" /><Control Name="ImageFileLabel" Row="4" RowSpan="1" Column="0" ColumnSpan="1" /><Control Name="WindowsEditionIndexLabel" Row="5" RowSpan="1" Column="0" ColumnSpan="1" /><Control Name="ImageFilePath" Row="4" RowSpan="1" Column="1" ColumnSpan="1" /><Control Name="ChooseISOImage" Row="4" RowSpan="1" Column="2" ColumnSpan="1" /><Control Name="SourceDrive" Row="3" RowSpan="1" Column="1" ColumnSpan="1" /><Control Name="DiskNumberLabel" Row="2" RowSpan="1" Column="0" ColumnSpan="1" /><Control Name="SourceDrive_Label" Row="3" RowSpan="1" Column="0" ColumnSpan="1" /><Control Name="SourceDrive_Scan" Row="3" RowSpan="1" Column="2" ColumnSpan="1" /></Controls><Columns Styles="AutoSize,0,AutoSize,0,AutoSize,0" /><Rows Styles="AutoSize,0,AutoSize,0,AutoSize,0,Absolute,30,AutoSize,0,Absolute,20" /></TableLayoutSettings> + + + 12, 239 + + + Vertical + + + 760, 152 + + + 4 + + + ImageList + + + System.Windows.Forms.DataGridView, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 1 + + + 12, 397 + + + 760, 152 + + + 0 + + + DiskList + + + System.Windows.Forms.DataGridView, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 3 + + + 17, 17 + + + 92, 22 + + + Exit + + + 37, 20 + + + File + + + 176, 22 + + + About the program + + + 52, 20 + + + About + + + 0, 0 + + + 784, 24 + + + 1 + + + Menu + + + MenuBar + + + System.Windows.Forms.MenuStrip, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 4 + + + 119, 17 + + + True + + + 96, 96 + + + True + + + True + + + GrowAndShrink + + + 784, 561 + + + 800, 600 + + + 800, 600 + + + Windows Installer + + + fileToolStripMenuItem + + + System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + exitToolStripMenuItem + + + System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + aboutToolStripMenuItem + + + System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + aboutTheProgramToolStripMenuItem + + + System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + saveFileDialog1 + + + System.Windows.Forms.SaveFileDialog, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + MainWindow + + + System.Windows.Forms.Form, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/GUIApp/src/Program.cs b/GUIApp/src/Program.cs new file mode 100644 index 0000000..ee1952d --- /dev/null +++ b/GUIApp/src/Program.cs @@ -0,0 +1,22 @@ +using System; +using System.Diagnostics.CodeAnalysis; +using System.Windows.Forms; + +namespace wit +{ + internal static class Program + { + /// + /// The main entry point for the application. + /// + [STAThread] + [RequiresUnreferencedCode("Calls wit.MainWindow.MainWindow()")] + static void Main() + { + // To customize application configuration such as set high DPI settings or default font, + // see https://aka.ms/applicationconfiguration. + ApplicationConfiguration.Initialize(); + Application.Run(new MainWindow()); + } + } +} diff --git a/GUIApp/src/Utilities.cs b/GUIApp/src/Utilities.cs new file mode 100644 index 0000000..6f2c7a7 --- /dev/null +++ b/GUIApp/src/Utilities.cs @@ -0,0 +1,142 @@ +using Microsoft.Dism; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Windows.Forms; +using WindowsInstallerLib.Helpers; + +namespace wit +{ + public partial class MainWindow + { + private void GetDiskLetters(object sender, EventArgs e) + { + List DiskLetters = [ + "A:\\", + "B:\\", + "C:\\", + "D:\\", + "E:\\", + "F:\\", + "G:\\", + "H:\\", + "I:\\", + "J:\\", + "K:\\", + "L:\\", + "M:\\", + "N:\\", + "O:\\", + "P:\\", + "Q:\\", + "R:\\", + "S:\\", + "T:\\", + "U:\\", + "V:\\", + "W:\\", + "X:\\", + "Y:\\", + "Z:\\" + ]; + List DiskLettersToRemove = []; + List> Disks = Devices.GetDisks(); + + try + { + foreach (string DiskLetter in DiskLetters) + { + foreach (Tuple disk in Disks) + { + string Letter = disk.Item3 + @"\"; + + if (DiskLetter.Equals(Letter, StringComparison.Ordinal)) + { + DiskLettersToRemove.Add(Letter); + } + } + } + + foreach (string DiskLetter in DiskLettersToRemove) + { + DiskLetters.Remove(DiskLetter); + } + + DestinationDrive.Items.AddRange(DiskLetters.ToArray()); + EfiDrive.Items.AddRange(DiskLetters.ToArray()); + SourceDrive.Items.AddRange(DiskLetters.ToArray()); + } + catch (Exception) + { + throw; + } + } + + private void GetDisksData(object sender, EventArgs e) + { + DiskList.Columns.Add("DiskNumber", "Disk"); + DiskList.Columns.Add("Model", "Model"); + DiskList.Columns.Add("Label", "Label"); + + List> disks = Devices.GetDisks(); + + foreach (Tuple disk in disks) + { + try + { + DiskList.Rows.Add(disk.Item1, disk.Item2, disk.Item3); + } + catch (ArgumentNullException) + { + throw; + } + catch (InvalidOperationException) + { + throw; + } + catch + { + throw; + } + } + + DiskList.Sort(DiskList.Columns[0], ListSortDirection.Ascending); + DiskList.Columns[0].AutoSizeMode = DataGridViewAutoSizeColumnMode.ColumnHeader; + DiskNumber.Maximum = DiskList.Rows.Count - 1; + } + + private void GetImageInfo(object sender, EventArgs e) + { + try + { + DismImageInfoCollection imageInfoCollection = Deployment.GetImageInfo(ref parameters); + + WindowsEditionIndex.Minimum = 1; + WindowsEditionIndex.Maximum = imageInfoCollection.Count; + + WindowsEditionIndex.Enabled = true; + + ImageList.Columns.Add("Index", "Index"); + ImageList.Columns.Add("Edition", "Name"); + ImageList.Columns.Add("Version", "Version"); + + foreach (DismImageInfo DismImage in imageInfoCollection) + { + ImageList.Rows.Add(DismImage.ImageIndex, DismImage.ImageName, DismImage.ProductVersion); + } + } + catch (DismException) + { + throw; + } + catch (Exception) + { + throw; + } + finally + { + DismApi.Shutdown(); + } + } + } +} diff --git a/GUIApp/src/ValidateDiskLetter.cs b/GUIApp/src/ValidateDiskLetter.cs new file mode 100644 index 0000000..8e5be60 --- /dev/null +++ b/GUIApp/src/ValidateDiskLetter.cs @@ -0,0 +1,71 @@ +using System.Windows.Forms; +using System; + +namespace wit +{ + public partial class MainWindow + { + private static void ShowMessage(string text, string caption) + { + try + { + MessageBox.Show(text, caption, MessageBoxButtons.OK, MessageBoxIcon.Error); + } + catch + { + throw; + } + } + + private void ValidateDiskLetter(object? sender, EventArgs e) + { + if (DestinationDrive.Text.Length > 0) + { + if (DestinationDrive.Text == EfiDrive.Text) + { + ShowMessage("The OS drive letter cannot be the same as the bootloader drive.", "Duplicate letter"); + DestinationDrive.Text = null; + EfiDrive.Text = null; + } + else if (DestinationDrive.Text == SourceDrive.Text) + { + ShowMessage("The OS drive letter cannot be the same as the source drive.", "Duplicate letter"); + DestinationDrive.Text = null; + SourceDrive.Text = null; + } + } + + if (EfiDrive.Text.Length > 0) + { + if (EfiDrive.Text == DestinationDrive.Text) + { + ShowMessage("The bootloader drive letter cannot be the same as the OS drive.", "Duplicate letter"); + EfiDrive.Text = null; + DestinationDrive.Text = null; + } + else if (EfiDrive.Text == SourceDrive.Text) + { + ShowMessage("The bootloader drive letter cannot be the same as the source drive.", "Duplicate letter"); + EfiDrive.Text = null; + SourceDrive.Text = null; + } + } + + if (SourceDrive.Text.Length > 0) + { + if (SourceDrive.Text == DestinationDrive.Text) + { + ShowMessage("The source drive letter cannot be the same as the OS drive.", "Duplicate letter"); + SourceDrive.Text = null; + DestinationDrive.Text = null; + } + else if (SourceDrive.Text == EfiDrive.Text) + { + ShowMessage("The source drive letter cannot be the same as the bootloader drive.", "Duplicate letter"); + SourceDrive.Text = null; + EfiDrive.Text = null; + } + } + } + } +} diff --git a/Windows Installer.sln b/Windows Installer.sln index d2766a2..629e65d 100644 --- a/Windows Installer.sln +++ b/Windows Installer.sln @@ -7,6 +7,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ConsoleApp", "ConsoleApp\Co EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WindowsInstallerLib", "WindowsInstallerLib\WindowsInstallerLib.csproj", "{0621F1C4-7D92-4863-8BF3-39E2D8D0661C}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GUIApp", "GUIApp\GUIApp.csproj", "{DEB8CFC7-E65A-B638-0B78-5385B78C1865}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|x64 = Debug|x64 @@ -21,6 +23,10 @@ Global {0621F1C4-7D92-4863-8BF3-39E2D8D0661C}.Debug|x64.Build.0 = Debug|x64 {0621F1C4-7D92-4863-8BF3-39E2D8D0661C}.Release|x64.ActiveCfg = Release|x64 {0621F1C4-7D92-4863-8BF3-39E2D8D0661C}.Release|x64.Build.0 = Release|x64 + {DEB8CFC7-E65A-B638-0B78-5385B78C1865}.Debug|x64.ActiveCfg = Debug|x64 + {DEB8CFC7-E65A-B638-0B78-5385B78C1865}.Debug|x64.Build.0 = Debug|x64 + {DEB8CFC7-E65A-B638-0B78-5385B78C1865}.Release|x64.ActiveCfg = Release|x64 + {DEB8CFC7-E65A-B638-0B78-5385B78C1865}.Release|x64.Build.0 = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/WindowsInstallerLib/WindowsInstallerLib.csproj b/WindowsInstallerLib/WindowsInstallerLib.csproj index 3969d30..4965f4d 100644 --- a/WindowsInstallerLib/WindowsInstallerLib.csproj +++ b/WindowsInstallerLib/WindowsInstallerLib.csproj @@ -8,7 +8,7 @@ none $(AssemblyName) latest - 1.1.4.0 + 1.1.5.0 x64 true diff --git a/WindowsInstallerLib/src/DeployManager.cs b/WindowsInstallerLib/src/DeployManager.cs index 1b9e272..0f97d1f 100644 --- a/WindowsInstallerLib/src/DeployManager.cs +++ b/WindowsInstallerLib/src/DeployManager.cs @@ -1,5 +1,6 @@ using Microsoft.Dism; using System; +using System.Collections.Generic; using System.IO; using System.Runtime.Versioning; @@ -282,6 +283,60 @@ internal static void GetImageInfo(ref Parameters parameters) } } + /// + /// Gets all Windows editions available using DISM, if any, and returns them as a collection. + /// + /// + /// + /// + /// + /// + internal static DismImageInfoCollection GetImageInfoD(ref Parameters parameters) + { + List> TransitionalTuple = []; + + ArgumentException.ThrowIfNullOrEmpty(parameters.ImageFilePath, nameof(parameters.ImageFilePath)); + + if (!PrivilegesManager.IsAdmin()) + { + throw new UnauthorizedAccessException("You do not have enough privileges to initialize the DISM API."); + } + + try + { + DismApi.Initialize(DismLogLevel.LogErrorsWarnings); + + DismImageInfoCollection images = DismApi.GetImageInfo(parameters.ImageFilePath); + + switch (images.Count) + { + case > 1: + Console.WriteLine($"\nFound {images.Count} images in {parameters.ImageFilePath}, shown below.\n", ConsoleColor.Yellow); + break; + case 1: + Console.WriteLine($"\nFound {images.Count} image in {parameters.ImageFilePath}, shown below.\n", ConsoleColor.Yellow); + break; + case 0: + Console.WriteLine($"\nNo images were found in {parameters.ImageFilePath}\n", ConsoleColor.Red); + throw new InvalidDataException($"images.Count is {images.Count}. This is considered to be invalid, the program cannot continue."); + } + + return images; + } + catch (DismException) + { + throw; + } + catch (Exception) + { + throw; + } + finally + { + DismApi.Shutdown(); + } + } + /// /// Retrieves information about the images contained in the specified image file. /// @@ -337,49 +392,35 @@ internal static DismImageInfoCollection GetImageInfoT(ref Parameters parameters) /// internal static void InstallAdditionalDrivers(ref Parameters parameters) { + bool IS_ADMIN = PrivilegesManager.IsAdmin(); + DismSession? session = null; - ArgumentException.ThrowIfNullOrWhiteSpace(parameters.AdditionalDriversDrive, nameof(parameters)); + ArgumentException.ThrowIfNullOrWhiteSpace(parameters.AdditionalDrive, nameof(parameters)); - if (!PrivilegesManager.IsAdmin()) + switch (IS_ADMIN) { - throw new UnauthorizedAccessException("You do not have enough privileges to install additional drivers."); + case true: + try + { + DismApi.Initialize(DismLogLevel.LogErrorsWarnings); + } + catch (DismException) + { + throw; + } + catch (Exception) + { + throw; + } + break; + case false: + throw new UnauthorizedAccessException("You do not have enough privileges to initialize the DISM API."); } try { - switch (PrivilegesManager.IsAdmin()) - { - case true: - try - { - DismApi.Initialize(DismLogLevel.LogErrorsWarnings); - } - catch (DismException) - { - throw; - } - catch (Exception) - { - throw; - } - break; - case false: - throw new UnauthorizedAccessException("You do not have enough privileges to initialize the DISM API."); - } - - try - { - session ??= DismApi.OpenOfflineSession(parameters.DestinationDrive); - } - catch (DismException) - { - throw; - } - catch (Exception) - { - throw; - } + session ??= DismApi.OpenOfflineSession(parameters.DestinationDrive); } catch (DismException) { @@ -392,7 +433,7 @@ internal static void InstallAdditionalDrivers(ref Parameters parameters) try { - DismApi.AddDriversEx(session, parameters.AdditionalDriversDrive, false, true); + DismApi.AddDriversEx(session, parameters.AdditionalDrive, false, true); } finally { @@ -416,9 +457,11 @@ internal static void InstallAdditionalDrivers(ref Parameters parameters) /// Thrown if the current process does not have administrative privileges required to perform the installation. internal static int InstallBootloader(ref Parameters parameters) { - ArgumentException.ThrowIfNullOrWhiteSpace(parameters.DestinationDrive, nameof(parameters.DestinationDrive)); - ArgumentException.ThrowIfNullOrWhiteSpace(parameters.EfiDrive, nameof(parameters.EfiDrive)); - ArgumentException.ThrowIfNullOrWhiteSpace(parameters.FirmwareType, nameof(parameters.FirmwareType)); + ArgumentException.ThrowIfNullOrWhiteSpace(parameters.DestinationDrive, nameof(parameters)); + ArgumentException.ThrowIfNullOrWhiteSpace(parameters.EfiDrive, nameof(parameters)); + ArgumentException.ThrowIfNullOrWhiteSpace(parameters.FirmwareType, nameof(parameters)); + + bool IS_ADMIN = PrivilegesManager.IsAdmin(); string EFI_BOOT_PATH = Path.Join(parameters.EfiDrive, @"\EFI\Boot"); string EFI_MICROSOFT_PATH = Path.Join(parameters.EfiDrive, @"\EFI\Microsoft"); @@ -428,7 +471,7 @@ internal static int InstallBootloader(ref Parameters parameters) bool EFI_MICROSOFT_EXISTS = Directory.Exists(EFI_MICROSOFT_PATH); bool WINDIR_EXISTS = Directory.Exists(WINDIR_PATH); - if (!PrivilegesManager.IsAdmin()) + if (!IS_ADMIN) { throw new UnauthorizedAccessException($"You do not have enough privileges to install the bootloader to {parameters.EfiDrive}"); } @@ -445,9 +488,8 @@ internal static int InstallBootloader(ref Parameters parameters) throw new DirectoryNotFoundException(@$"The directory {WINDIR_PATH} does not exist!"); } - Console.WriteLine($"Firmware type is set to: {parameters.FirmwareType}"); Console.WriteLine($"\n==> Installing bootloader to drive {parameters.EfiDrive} in disk {parameters.DiskNumber}"); - ProcessManager.StartCmdProcess("bcdboot", @$"{WINDIR_PATH} /s {parameters.EfiDrive} /f {parameters.FirmwareType}"); + ProcessManager.StartCmdProcess("bcdboot.exe", @$"{WINDIR_PATH} /s {parameters.EfiDrive} /f {parameters.FirmwareType}"); } catch (IOException) { @@ -457,7 +499,6 @@ internal static int InstallBootloader(ref Parameters parameters) { throw; } - return ProcessManager.ExitCode; } } diff --git a/WindowsInstallerLib/src/DiskManager.cs b/WindowsInstallerLib/src/DiskManager.cs index 7f4780f..7b4cae6 100644 --- a/WindowsInstallerLib/src/DiskManager.cs +++ b/WindowsInstallerLib/src/DiskManager.cs @@ -1,7 +1,10 @@ using System; +using System.Collections.Generic; +using System.Globalization; using System.IO; using System.Linq; using System.Management; +using System.Runtime.CompilerServices; using System.Runtime.Versioning; namespace WindowsInstallerLib @@ -43,27 +46,22 @@ internal static int FormatDisk(ref Parameters parameters) } } - /// - /// Lists all disk drives on the system and displays their details, including disk number, model, and device ID. - /// - /// This method queries the system's disk drives using WMI (Windows Management - /// Instrumentation) and outputs the retrieved information to the console. The details include the disk number, - /// model, and device ID for each disk drive found. Note that this method is intended for internal use - /// and writes directly to the console. It does not return the retrieved data or provide a way to - /// programmatically access it. - internal static void ListAll() + internal static List> GetDisks() { + List> DisksList = []; try { WqlObjectQuery DeviceTable = new("SELECT * FROM Win32_DiskDrive"); ManagementObjectSearcher DeviceInfo = new(DeviceTable); foreach (ManagementObject o in DeviceInfo.Get().Cast()) { - Console.WriteLine("Disk number = " + o["Index"]); - Console.WriteLine("Model = " + o["Model"]); - Console.WriteLine("DeviceID = " + o["DeviceID"]); - Console.WriteLine(""); + int Index = Convert.ToInt32(o["Index"]); + string Model = o["Model"].ToString() ?? string.Empty; + string Letter = GetDiskLetter(o["DeviceID"]); + + DisksList.Add(new(Index, Model, Letter)); } + return DisksList; } catch (Exception) { @@ -71,30 +69,68 @@ internal static void ListAll() } } - /// - /// Retrieves an array of all available drive information on the system. - /// - /// An array of objects representing the drives available on the system. - internal static DriveInfo[] GetDisksT() + private static string GetDiskLetter(object DeviceID) { + string DriveLetter = string.Empty; + + ArgumentNullException.ThrowIfNull(DeviceID); + try { - DriveInfo[] drives = DriveInfo.GetDrives(); - - return drives; + WqlObjectQuery PartitionQuery = new($"ASSOCIATORS OF {{Win32_DiskDrive.DeviceID='{DeviceID}'}} WHERE AssocClass=Win32_DiskDriveToDiskPartition"); + ManagementObjectSearcher PartitionSearcher = new(PartitionQuery); + foreach (ManagementObject partition in PartitionSearcher.Get().Cast()) + { + WqlObjectQuery LogicalDiskQuery = new($"ASSOCIATORS OF {{Win32_DiskPartition.DeviceID='{partition["DeviceID"]}'}} WHERE AssocClass=Win32_LogicalDiskToPartition"); + ManagementObjectSearcher LogicalDiskSearcher = new(LogicalDiskQuery); + foreach (ManagementObject logicalDisk in LogicalDiskSearcher.Get().Cast()) + { + DriveLetter = logicalDisk["DeviceID"].ToString() ?? throw new ArgumentNullException("DeviceID cannot be null", DeviceID.ToString()); + } + } } - catch (IOException) + catch (Exception) { throw; } - catch (UnauthorizedAccessException) + return DriveLetter; + } + + + /// + /// Lists all disk drives on the system and displays their details, including disk number, model, and device ID. + /// + /// This method queries the system's disk drives using WMI (Windows Management + /// Instrumentation) and outputs the retrieved information to the console. The details include the disk number, + /// model, and device ID for each disk drive found. Note that this method is intended for internal use + /// and writes directly to the console. It does not return the retrieved data or provide a way to + /// programmatically access it. + internal static SortedDictionary GetDisks() + { + SortedDictionary SystemDisks = []; + + try { - throw; + WqlObjectQuery Query = new("SELECT * FROM Win32_DiskDrive"); + ManagementObjectSearcher ObjectSearcher = new(Query); + foreach (ManagementObject obj in ObjectSearcher.Get().Cast()) + { + int Index = Convert.ToInt32(obj["Index"], CultureInfo.CurrentCulture); + string? Model = obj["Model"].ToString(); + + if (Model != null) + { + SystemDisks.Add(Index, Model); + } + } + } catch (Exception) { throw; } + + return SystemDisks; } } } diff --git a/WindowsInstallerLib/src/Helpers.cs b/WindowsInstallerLib/src/Helpers.cs new file mode 100644 index 0000000..4364311 --- /dev/null +++ b/WindowsInstallerLib/src/Helpers.cs @@ -0,0 +1,33 @@ +using Microsoft.Dism; +using System; +using System.Collections.Generic; + +namespace WindowsInstallerLib +{ + namespace Helpers + { + public class Privileges + { + public static bool IsAdmin() { return PrivilegesManager.IsAdmin(); } + } + + public class Devices + { + public static List> GetDisks() { return DiskManager.GetDisks(); } + } + + public class SystemInfo + { + public static bool SystemSupportsEFI() { return SystemInfoManager.IsEFI(); } + } + + public class Deployment + { + public static int ExitCode { get; private set; } + public static DismImageInfoCollection GetImageInfo(ref Parameters parameters) { return DeployManager.GetImageInfoD(ref parameters); } + public static void FormatDisk(ref Parameters parameters) { DiskManager.FormatDisk(ref parameters); } + public static void ApplyImage(ref Parameters parameters) { DeployManager.ApplyImage(ref parameters); } + public static void InstallBootloader(ref Parameters parameters) { DeployManager.InstallBootloader(ref parameters); } + } + } +} diff --git a/WindowsInstallerLib/src/InstallerManager.cs b/WindowsInstallerLib/src/InstallerManager.cs index 5107214..228f0dc 100644 --- a/WindowsInstallerLib/src/InstallerManager.cs +++ b/WindowsInstallerLib/src/InstallerManager.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.Globalization; using System.IO; using System.Runtime.Versioning; @@ -17,7 +18,7 @@ namespace WindowsInstallerLib /// Gets or sets the source drive containing the data to be imaged. /// Gets or sets the index of the image within the image file to be applied. /// Gets or sets the file path of the image file to be used in the operation. - /// Gets or sets a value indicating whether additional drivers should be installed during the imaging process. + /// Gets or sets a value indicating whether additional drivers should be installed during the imaging process. /// Gets or sets the firmware type of the system being imaged. [SupportedOSPlatform("windows")] public struct Parameters(string DestinationDrive, @@ -26,7 +27,7 @@ public struct Parameters(string DestinationDrive, string SourceDrive, int ImageIndex, string ImageFilePath, - string AdditionalDriversDrive, + string AdditionalDrive, string FirmwareType) { public string DestinationDrive { get; set; } = DestinationDrive; @@ -35,7 +36,7 @@ public struct Parameters(string DestinationDrive, public string SourceDrive { get; set; } = SourceDrive; public int ImageIndex { get; set; } = ImageIndex; public string ImageFilePath { get; set; } = ImageFilePath; - public string AdditionalDriversDrive { get; set; } = AdditionalDriversDrive; + public string AdditionalDrive { get; set; } = AdditionalDrive; public string FirmwareType { get; set; } = FirmwareType; } @@ -62,15 +63,14 @@ public sealed class InstallerManager public static void Configure(ref Parameters parameters) { #region DestinationDrive - if (string.IsNullOrEmpty(parameters.DestinationDrive) || - string.IsNullOrWhiteSpace(parameters.DestinationDrive)) + if (string.IsNullOrWhiteSpace(parameters.DestinationDrive)) { - string p_DestinationDrive; - Console.Write("\n==> Type the mountpoint to use for deploying Windows (e.g. Z:): "); + try { - p_DestinationDrive = Console.ReadLine() ?? throw new ArgumentNullException(nameof(parameters), "DestinationDrive is null!"); + parameters.DestinationDrive = Console.ReadLine() ?? + throw new ArgumentException("A valid destination drive is required.", nameof(parameters)); } catch (IOException) { @@ -89,35 +89,28 @@ public static void Configure(ref Parameters parameters) throw; } - ArgumentException.ThrowIfNullOrWhiteSpace(p_DestinationDrive); - - if (p_DestinationDrive.Length != 2 || - p_DestinationDrive.Length > 2) + if (parameters.DestinationDrive.Length > 2 || + parameters.DestinationDrive.Length < 2) { - throw new ArgumentException(@$"Invalid source drive {p_DestinationDrive}. Too many characters."); + throw new ArgumentException($"Invalid destination drive {parameters.DestinationDrive}."); } - if (p_DestinationDrive.StartsWith(':') || - !p_DestinationDrive.EndsWith(':')) + if (parameters.DestinationDrive.StartsWith(':') || !parameters.DestinationDrive.EndsWith(':')) { - throw new InvalidDataException(@$"Invalid source drive {p_DestinationDrive}. A valid drive is for example: 'Z:'."); + throw new InvalidDataException($"Invalid source drive {parameters.DestinationDrive}."); } - - parameters.DestinationDrive = p_DestinationDrive; } #endregion #region EfiDrive - if (string.IsNullOrEmpty(parameters.EfiDrive) || - string.IsNullOrWhiteSpace(parameters.EfiDrive)) + if (string.IsNullOrWhiteSpace(parameters.EfiDrive)) { - string p_EfiDrive; - Console.Write("\n==> Type the mountpoint to use for the bootloader (e.g. Y:): "); try { - p_EfiDrive = Console.ReadLine() ?? throw new ArgumentNullException(nameof(parameters), "EfiDrive is null!"); ; + parameters.EfiDrive = Console.ReadLine() ?? + throw new ArgumentException("A valid EFI drive is required.", nameof(parameters)); } catch (IOException) { @@ -136,32 +129,31 @@ public static void Configure(ref Parameters parameters) throw; } - ArgumentException.ThrowIfNullOrWhiteSpace(p_EfiDrive); - - if (p_EfiDrive.StartsWith(':')) + if (parameters.EfiDrive.StartsWith(':')) { - throw new ArgumentException(@$"Invalid EFI drive {p_EfiDrive}, it must have a colon at the end not at the beginning. For example: 'Y:'."); + throw new ArgumentException(@$"Invalid EFI drive {parameters.EfiDrive}, it must have a colon at the end not at the beginning. For example: 'Y:'."); } - else if (!p_EfiDrive.EndsWith(':')) + + if (!parameters.EfiDrive.EndsWith(':')) { - throw new ArgumentException($"Invalid EFI drive {p_EfiDrive}, it must have a colon. For example: 'Y:'."); + throw new ArgumentException($"Invalid EFI drive {parameters.EfiDrive}, it must have a colon. For example: 'Y:'."); } - - parameters.EfiDrive = p_EfiDrive; } #endregion #region DiskNumber - if (string.IsNullOrEmpty(parameters.DiskNumber.ToString()) || - string.IsNullOrWhiteSpace(parameters.DiskNumber.ToString()) || - parameters.DiskNumber == -1) + if (string.IsNullOrWhiteSpace(parameters.DiskNumber.ToString()) || parameters.DiskNumber == -1) { - int p_DiskNumber; + Console.WriteLine("\n==> These are the disks available on your system:"); try { - Console.WriteLine("\n==> These are the disks available on your system:"); - DiskManager.ListAll(); + SortedDictionary Disks = DiskManager.GetDisks(); + + foreach (KeyValuePair Disk in Disks) + { + Console.WriteLine("Disk number: {0}\nDisk model: {1}\n", Disk.Key, Disk.Value); + } } catch (Exception) { @@ -171,7 +163,7 @@ public static void Configure(ref Parameters parameters) Console.Write("\n==> Please type the disk number to format (e.g. 0): "); try { - p_DiskNumber = Convert.ToInt32(Console.ReadLine(), CultureInfo.CurrentCulture); + parameters.DiskNumber = Convert.ToInt32(Console.ReadLine(), CultureInfo.CurrentCulture); } catch (FormatException) { @@ -189,21 +181,18 @@ public static void Configure(ref Parameters parameters) { throw; } - - parameters.DiskNumber = p_DiskNumber; } #endregion #region SourceDrive - if (string.IsNullOrEmpty(parameters.SourceDrive) || - string.IsNullOrWhiteSpace(parameters.SourceDrive)) + if (string.IsNullOrWhiteSpace(parameters.SourceDrive)) { - string? p_SourceDrive; + Console.Write("\n==> Specify the mount point where the source are mounted at (e.g. X:): "); - Console.Write("\n==> Specify the mountpount where the source are mounted at (e.g. X:): "); try { - p_SourceDrive = Console.ReadLine(); + parameters.SourceDrive = Console.ReadLine() ?? + throw new ArgumentException("A sourced drive is required.", nameof(parameters)); } catch (IOException) { @@ -222,74 +211,49 @@ public static void Configure(ref Parameters parameters) throw; } - ArgumentException.ThrowIfNullOrWhiteSpace(p_SourceDrive); + ArgumentException.ThrowIfNullOrWhiteSpace(parameters.SourceDrive); - if (p_SourceDrive.StartsWith(':')) + if (parameters.SourceDrive.StartsWith(':')) { - throw new ArgumentException(@$"Invalid source drive {p_SourceDrive}, it must have a colon at the end not at the beginning. For example: 'H:'."); + throw new ArgumentException(@$"Invalid source drive {parameters.SourceDrive}, it must have a colon at the end not at the beginning. For example: 'H:'."); } - else if (!p_SourceDrive.EndsWith(':')) + else if (!parameters.SourceDrive.EndsWith(':')) { - throw new ArgumentException($"Invalid source drive {p_SourceDrive}, it must have a colon. For example: 'H:'."); + throw new ArgumentException($"Invalid source drive {parameters.SourceDrive}, it must have a colon. For example: 'H:'."); } - - parameters.SourceDrive = p_SourceDrive; } #endregion #region ImageFilePath - if (string.IsNullOrEmpty(parameters.ImageFilePath) || - string.IsNullOrWhiteSpace(parameters.ImageFilePath)) + if (string.IsNullOrWhiteSpace(parameters.ImageFilePath)) { - string p_ImageFilePath = DeployManager.GetImageFile(ref parameters); + parameters.ImageFilePath = DeployManager.GetImageFile(ref parameters); - Console.WriteLine($"\nImage file path has been set to {p_ImageFilePath}."); - - parameters.ImageFilePath = p_ImageFilePath; + Console.WriteLine($"\nImage file path has been set to {parameters.ImageFilePath}."); } #endregion #region ImageIndex - if (string.IsNullOrEmpty(parameters.ImageIndex.ToString()) || - string.IsNullOrWhiteSpace(parameters.ImageIndex.ToString()) || - parameters.ImageIndex == -1) + if (parameters.ImageIndex == -1) { DeployManager.GetImageInfo(ref parameters); Console.Write("\n==> Type the index number of the Windows edition you wish to install (e.g. 1): "); - string? SelectedIndex = Console.ReadLine(); - - if (string.IsNullOrEmpty(SelectedIndex) || string.IsNullOrWhiteSpace(SelectedIndex)) - { - throw new ArgumentException("No Windows edition was specified."); - } - - parameters.ImageIndex = Convert.ToInt32(SelectedIndex, CultureInfo.CurrentCulture); + parameters.ImageIndex = Convert.ToInt32(Console.ReadLine() ?? + throw new ArgumentException("No Windows edition was specified."), CultureInfo.CurrentCulture); } #endregion #region FirmwareType - if (string.IsNullOrEmpty(parameters.FirmwareType) || - string.IsNullOrWhiteSpace(parameters.FirmwareType)) + if (string.IsNullOrWhiteSpace(parameters.FirmwareType)) { - switch (SystemInfoManager.IsEFI()) - { - case true: - parameters.FirmwareType = "UEFI"; - Console.WriteLine($"\nThe installer has set the firmware type to {parameters.FirmwareType}.", ConsoleColor.Yellow); - break; - case false: - parameters.FirmwareType = "BIOS"; - Console.WriteLine($"\nThe installer has set the firmware type to {parameters.FirmwareType}.", ConsoleColor.Yellow); - break; - default: - throw new InvalidDataException($"Invalid firmware type: {parameters.FirmwareType}"); - } + parameters.FirmwareType = SystemInfoManager.IsEFI() ? "UEFI" : "BIOS"; + Console.WriteLine($"\nThe installer has set the firmware type to {parameters.FirmwareType}.", ConsoleColor.Yellow); } #endregion - #region AdditionalDriversList - if (string.IsNullOrWhiteSpace(parameters.AdditionalDriversDrive)) + #region AdditionalDrive + if (string.IsNullOrWhiteSpace(parameters.AdditionalDrive)) { Console.Write("\n=> Do you want to add additional drivers to your installation?: [Y/N]: "); string? UserWantsExtraDrivers = Console.ReadLine()?.ToLower(CultureInfo.CurrentCulture); @@ -317,7 +281,7 @@ public static void Configure(ref Parameters parameters) throw new FileNotFoundException($"The directory {driversPath} does not exist"); } - parameters.AdditionalDriversDrive = driversPath; + parameters.AdditionalDrive = driversPath; break; default: return; @@ -340,7 +304,7 @@ public static void Configure(ref Parameters parameters) /// Thrown if the object contains invalid or missing values, such as: - Disk /// number is -1. - EFI drive is null, empty, or whitespace. [SupportedOSPlatform("windows")] - public static void InstallWindows(ref Parameters parameters) + public static void Prepare(ref Parameters parameters) { if (parameters.DiskNumber.Equals(-1)) { @@ -352,10 +316,11 @@ public static void InstallWindows(ref Parameters parameters) throw new InvalidDataException("No EFI drive was specified, required for the bootloader installation."); } - ArgumentException.ThrowIfNullOrWhiteSpace(parameters.DestinationDrive); - ArgumentException.ThrowIfNullOrWhiteSpace(parameters.ImageFilePath); + ArgumentException.ThrowIfNullOrWhiteSpace(parameters.DestinationDrive, parameters.DestinationDrive); + ArgumentException.ThrowIfNullOrWhiteSpace(parameters.EfiDrive, parameters.EfiDrive); + ArgumentException.ThrowIfNullOrWhiteSpace(parameters.ImageFilePath, parameters.ImageFilePath); ArgumentOutOfRangeException.ThrowIfEqual(parameters.ImageIndex, -1); - ArgumentException.ThrowIfNullOrWhiteSpace(parameters.FirmwareType); + ArgumentException.ThrowIfNullOrWhiteSpace(parameters.FirmwareType, parameters.FirmwareType); try { @@ -365,32 +330,35 @@ public static void InstallWindows(ref Parameters parameters) { Console.WriteLine($"An error occurred while formatting the disk: {ex}", ConsoleColor.Red); } + } + public static void InstallWindows(ref Parameters parameters) + { try { DeployManager.ApplyImage(ref parameters); } - catch (Exception ex) + catch { - Console.WriteLine($"An error occurred while applying the image: {ex}", ConsoleColor.Red); + throw; } try { DeployManager.InstallAdditionalDrivers(ref parameters); } - catch (Exception ex) + catch { - Console.WriteLine($"An error occurred when installing additional drivers: {ex}", ConsoleColor.Yellow); + throw; } try { DeployManager.InstallBootloader(ref parameters); } - catch (Exception ex) + catch { - Console.WriteLine($"An error occurred while installing the bootloader: {ex}", ConsoleColor.Red); + throw; } } } diff --git a/WindowsInstallerLib/src/ProcessManager.cs b/WindowsInstallerLib/src/ProcessManager.cs index f4859ce..9b5264d 100644 --- a/WindowsInstallerLib/src/ProcessManager.cs +++ b/WindowsInstallerLib/src/ProcessManager.cs @@ -86,20 +86,31 @@ internal static int StartDiskPartProcess(int DiskNumber, string EfiDrive, string process.StartInfo.UseShellExecute = false; process.StartInfo.RedirectStandardInput = true; process.StartInfo.RedirectStandardOutput = true; + process.StartInfo.CreateNoWindow = true; + process.Start(); Console.WriteLine($"Formatting disk {DiskNumber}, please wait..."); process.StandardInput.WriteLine($"select disk {DiskNumber}"); process.StandardInput.WriteLine("clean"); + Console.WriteLine($"Cleaning disk {DiskNumber}..."); process.StandardInput.WriteLine("convert gpt"); + Console.WriteLine($"Converting disk {DiskNumber} to GPT"); process.StandardInput.WriteLine("create partition efi size=100"); - process.StandardInput.WriteLine("create partition msr size=16"); + Console.WriteLine("Creating a 100MB EFI partition..."); process.StandardInput.WriteLine("format fs=fat32 quick"); + Console.WriteLine("Formatting EFI partition with FAT32..."); process.StandardInput.WriteLine($"assign letter {EfiDrive}"); + Console.WriteLine($"Assigning letter {EfiDrive} to EFI partition..."); + process.StandardInput.WriteLine("create partition msr size=16"); + Console.WriteLine("Creating MSR partition..."); process.StandardInput.WriteLine("create partition primary"); + Console.WriteLine($"Creating main partition..."); process.StandardInput.WriteLine("format fs=ntfs quick"); + Console.WriteLine($"Formatting main partition with NTFS..."); process.StandardInput.WriteLine($"assign letter {DestinationDrive}"); + Console.WriteLine($"Assigning letter {DestinationDrive} to main partition..."); process.StandardInput.WriteLine("exit"); process.WaitForExit();