From a338f536a32042d1c6a2a650cb5c983a6aff2105 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Felipe=20Gonz=C3=A1lez=20Mart=C3=ADn?=
<158048821+felgmar@users.noreply.github.com>
Date: Thu, 8 May 2025 17:03:43 +0100
Subject: [PATCH 1/6] WindowsInstallerLib: implement ThreadManager
---
WindowsInstallerLib/src/ThreadManager.cs | 119 +++++++++++++++++++++++
1 file changed, 119 insertions(+)
create mode 100644 WindowsInstallerLib/src/ThreadManager.cs
diff --git a/WindowsInstallerLib/src/ThreadManager.cs b/WindowsInstallerLib/src/ThreadManager.cs
new file mode 100644
index 0000000..8e9c95e
--- /dev/null
+++ b/WindowsInstallerLib/src/ThreadManager.cs
@@ -0,0 +1,119 @@
+using System;
+using System.Collections;
+using System.Collections.Concurrent;
+using System.Threading;
+
+namespace WindowsInstallerLib
+{
+ ///
+ /// This class handles the priority, the state, etcetera of threads.
+ ///
+ internal sealed class ThreadManager
+ {
+ ///
+ /// Gets the current priority of the thread.
+ ///
+ ///
+ ///
+ /// BelowNormal, Normal, AboveNormal or Highest
+ ///
+ private static ThreadPriority GetThreadPriority(Thread thread) { return thread.Priority; }
+ private static ThreadPriority SetThreadPriority(Thread thread, ThreadPriority threadPriority) { return thread.Priority = threadPriority; }
+ private static ThreadState GetThreadState(Thread thread) { return thread.ThreadState; }
+ private static ApartmentState GetThreadApartmentState(Thread thread) { return thread.GetApartmentState(); }
+ private static bool TrySetThreadApartmentState(Thread thread, ApartmentState apartmentState)
+ {
+ try
+ {
+ return thread.TrySetApartmentState(apartmentState);
+ }
+ catch (PlatformNotSupportedException)
+ {
+ throw;
+ }
+ catch (ArgumentException)
+ {
+ throw;
+ }
+ catch (ThreadStateException)
+ {
+ throw;
+ }
+ }
+ private static Thread? GetCurrentThread() { return Thread.CurrentThread; }
+ internal static bool IsBackground(Thread thread) { return thread.IsBackground; }
+ internal static bool IsThreadAlive(Thread thread) { return thread.IsAlive; }
+
+ internal static Thread CreateThread(Action action)
+ {
+ Thread thread = new(() =>
+ {
+ action.Invoke();
+ }
+ );
+
+ if (GetThreadState(thread) == ThreadState.Running)
+ {
+ //throw new InvalidOperationException($"Cannot modify the state of a thread when it is already running.");
+ thread.Join();
+ }
+
+ try
+ {
+ thread.IsBackground = true;
+ }
+ catch (ThreadStateException ex)
+ {
+ if (ex.InnerException != null)
+ {
+ throw ex.InnerException;
+ }
+ }
+ catch
+ {
+ throw;
+ }
+
+ try
+ {
+ if (GetThreadPriority(thread) == ThreadPriority.Normal)
+ {
+ SetThreadPriority(thread, ThreadPriority.AboveNormal);
+ }
+ }
+ catch
+ {
+ throw;
+ }
+
+ try
+ {
+ TrySetThreadApartmentState(thread, ApartmentState.MTA);
+ }
+ catch
+ {
+ throw;
+ }
+
+ try
+ {
+ if (GetCurrentThread != null &&
+ GetThreadState(thread) == ThreadState.Unstarted)
+ {
+ thread.Start();
+ }
+ }
+ catch (Exception ex)
+ {
+ switch (ex.InnerException != null)
+ {
+ case true:
+ throw ex.InnerException;
+ case false:
+ throw;
+ }
+ }
+ return thread;
+ }
+ }
+}
From 6e257e1b0773ba2940ab42dbd53e4bcab87ac074 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Felipe=20Gonz=C3=A1lez=20Mart=C3=ADn?=
<158048821+felgmar@users.noreply.github.com>
Date: Thu, 8 May 2025 17:04:59 +0100
Subject: [PATCH 2/6] WindowsInstallerLib: add threaded wrappers for existing
functions
Add wrappers to the originals functions and call them by wrapping them around ThreadManager
---
WindowsInstallerLib/src/ProcessManager.cs | 36 ++++++++++++++++++++++-
1 file changed, 35 insertions(+), 1 deletion(-)
diff --git a/WindowsInstallerLib/src/ProcessManager.cs b/WindowsInstallerLib/src/ProcessManager.cs
index 9f93231..9a54a11 100644
--- a/WindowsInstallerLib/src/ProcessManager.cs
+++ b/WindowsInstallerLib/src/ProcessManager.cs
@@ -22,7 +22,6 @@ internal static int StartCmdProcess(string fileName, string args)
process.Start();
process.WaitForExit();
ExitCode = process.ExitCode;
-
}
catch (InvalidOperationException)
{
@@ -40,6 +39,14 @@ internal static int StartCmdProcess(string fileName, string args)
return ExitCode;
}
+ internal static int StartCmdProcessThreaded(string fileName, string args)
+ {
+ ThreadManager.CreateThread(
+ () => StartCmdProcess(fileName, args)
+ );
+ return ExitCode;
+ }
+
internal static int StartDiskPartProcess(int DiskNumber, string EfiDrive, string DestinationDrive)
{
Process process = new();
@@ -108,6 +115,15 @@ internal static int StartDiskPartProcess(int DiskNumber, string EfiDrive, string
return ExitCode;
}
+ internal static int StartDiskPartProcessThreaded(int DiskNumber, string EfiDrive, string DestinationDrive)
+ {
+ ThreadManager.CreateThread(
+ () => StartDiskPartProcess(DiskNumber, EfiDrive, DestinationDrive)
+ );
+
+ return ExitCode;
+ }
+
internal static int StartDismProcess(string args)
{
Process process = new();
@@ -141,6 +157,15 @@ internal static int StartDismProcess(string args)
return ExitCode;
}
+ internal static int StartDismProcessThreaded(string args)
+ {
+ ThreadManager.CreateThread(
+ () => StartDismProcess(args)
+ );
+
+ return ExitCode;
+ }
+
internal static int StartProcess(string filename, string args)
{
Process process = new();
@@ -177,5 +202,14 @@ internal static int StartProcess(string filename, string args)
return ExitCode;
}
+
+ internal static int StartProcessThreaded(string filename, string args)
+ {
+ ThreadManager.CreateThread(
+ () => StartProcess(filename, args)
+ );
+
+ return ExitCode;
+ }
}
}
From 01caad30f6765b84b259950bf6d2a3e95b508d32 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Felipe=20Gonz=C3=A1lez=20Mart=C3=ADn?=
<158048821+felgmar@users.noreply.github.com>
Date: Tue, 20 May 2025 14:09:27 +0100
Subject: [PATCH 3/6] WindowsInstallerLib: remove unused usings
---
WindowsInstallerLib/src/ThreadManager.cs | 2 --
1 file changed, 2 deletions(-)
diff --git a/WindowsInstallerLib/src/ThreadManager.cs b/WindowsInstallerLib/src/ThreadManager.cs
index 8e9c95e..7302964 100644
--- a/WindowsInstallerLib/src/ThreadManager.cs
+++ b/WindowsInstallerLib/src/ThreadManager.cs
@@ -1,6 +1,4 @@
using System;
-using System.Collections;
-using System.Collections.Concurrent;
using System.Threading;
namespace WindowsInstallerLib
From 76e8b87b7c16e292c759d659766429093c86b843 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Felipe=20Gonz=C3=A1lez=20Mart=C3=ADn?=
<158048821+felgmar@users.noreply.github.com>
Date: Tue, 20 May 2025 14:09:40 +0100
Subject: [PATCH 4/6] WindowsInstaller: add new threaded diskpart function
---
WindowsInstallerLib/src/ProcessManager.cs | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/WindowsInstallerLib/src/ProcessManager.cs b/WindowsInstallerLib/src/ProcessManager.cs
index dd46d2a..8e46d52 100644
--- a/WindowsInstallerLib/src/ProcessManager.cs
+++ b/WindowsInstallerLib/src/ProcessManager.cs
@@ -143,6 +143,14 @@ internal static int StartDiskPartProcess(int DiskNumber, string EfiDrive, string
return ExitCode;
}
+ internal static int StartDiskPartProcessThreaded(int DiskNumber, string EfiDrive, string DestinationDrive)
+ {
+ ThreadManager.CreateThread(
+ () => StartDiskPartProcess(DiskNumber, EfiDrive, DestinationDrive)
+ );
+ return ExitCode;
+ }
+
///
/// Starts a new process to execute the Deployment Image Servicing and Management (DISM) tool with the specified
/// arguments.
From 7eb42d080440ef8944d2920dec540802b7e22388 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Felipe=20Gonz=C3=A1lez=20Mart=C3=ADn?=
<158048821+felgmar@users.noreply.github.com>
Date: Fri, 20 Jun 2025 13:25:05 +0100
Subject: [PATCH 5/6] WindowsInstallerLib: add UseMultiThreading parameter
---
WindowsInstallerLib/src/InstallerManager.cs | 35 +++++++++++++++++++++
1 file changed, 35 insertions(+)
diff --git a/WindowsInstallerLib/src/InstallerManager.cs b/WindowsInstallerLib/src/InstallerManager.cs
index 18a9e6d..712e8d2 100644
--- a/WindowsInstallerLib/src/InstallerManager.cs
+++ b/WindowsInstallerLib/src/InstallerManager.cs
@@ -37,6 +37,7 @@ public struct Parameters(string DestinationDrive,
public string ImageFilePath { get; set; } = ImageFilePath;
public bool InstallExtraDrivers { get; set; } = InstallExtraDrivers;
public string FirmwareType { get; set; } = FirmwareType;
+ public bool UseMultiThreading { get; set; } = false;
}
///
@@ -61,6 +62,40 @@ public sealed class InstallerManager
/// Thrown if the firmware type cannot be determined or is invalid.
public static void Configure(ref Parameters parameters)
{
+ #region UseMultiThreading
+ Console.WriteLine("\nDo you want to enable multithreading?: ");
+ string? p_UseMultiThreading = Console.ReadLine();
+
+ if (!string.IsNullOrWhiteSpace(p_UseMultiThreading))
+ {
+ try
+ {
+ parameters.UseMultiThreading = p_UseMultiThreading.ToLowerInvariant() switch
+ {
+ "yes" or "y" or "true" => true,
+ "no" or "n" or "false" => false,
+ _ => throw new ArgumentException("Invalid input for multithreading option. Please type 'yes' or 'no'.")
+ };
+ }
+ catch (Exception)
+ {
+ throw;
+ }
+ }
+
+ switch (parameters.UseMultiThreading)
+ {
+ case true:
+ parameters.UseMultiThreading = true;
+ Console.WriteLine($"\nMultithreading is enabled.", ConsoleColor.Yellow);
+ break;
+ case false:
+ parameters.UseMultiThreading = false;
+ Console.WriteLine($"\nMultithreading is disabled.", ConsoleColor.Yellow);
+ break;
+ }
+ #endregion
+
#region DestinationDrive
if (string.IsNullOrEmpty(parameters.DestinationDrive) ||
string.IsNullOrWhiteSpace(parameters.DestinationDrive))
From 7e7902cd8172dee4a6f719d800712412311caa18 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Felipe=20Gonz=C3=A1lez=20Mart=C3=ADn?=
<158048821+felgmar@users.noreply.github.com>
Date: Fri, 20 Jun 2025 13:31:48 +0100
Subject: [PATCH 6/6] ConsoleApp: add "/multithreaded" argument
---
ConsoleApp/src/ArgumentParser.cs | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/ConsoleApp/src/ArgumentParser.cs b/ConsoleApp/src/ArgumentParser.cs
index 68f5c51..621e566 100644
--- a/ConsoleApp/src/ArgumentParser.cs
+++ b/ConsoleApp/src/ArgumentParser.cs
@@ -64,6 +64,9 @@ internal static void ParseArgs(ref Parameters parameters, string[] args)
case "/firmwaretype":
parameters.FirmwareType = args[Array.IndexOf(args, arg) + 1].ToUpperInvariant();
continue;
+ case "/multithreaded":
+ parameters.UseMultiThreading = args[Array.IndexOf(args, arg) + 1].Equals("TRUE", StringComparison.OrdinalIgnoreCase);
+ continue;
}
}
#if DEBUG
@@ -76,6 +79,7 @@ internal static void ParseArgs(ref Parameters parameters, string[] args)
Console.WriteLine($" Image File Path: {parameters.ImageFilePath}");
Console.WriteLine($" Install Extra Drivers: {parameters.InstallExtraDrivers}");
Console.WriteLine($" Firmware Type: {parameters.FirmwareType}");
+ Console.WriteLine($" Multithreaded: {parameters.UseMultiThreading}");
Console.WriteLine("Press any key to continue...");
Console.ReadKey();
#endif