Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions ConsoleApp/src/ArgumentParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down
35 changes: 35 additions & 0 deletions WindowsInstallerLib/src/InstallerManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

/// <summary>
Expand All @@ -61,6 +62,40 @@ public sealed class InstallerManager
/// <exception cref="InvalidDataException">Thrown if the firmware type cannot be determined or is invalid.</exception>
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))
Expand Down
27 changes: 26 additions & 1 deletion WindowsInstallerLib/src/ProcessManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@ internal static int StartCmdProcess(string fileName, string args)
process.Start();
process.WaitForExit();
ExitCode = process.ExitCode;

}
catch (InvalidOperationException)
{
Expand Down Expand Up @@ -144,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;
}

/// <summary>
/// Starts a new process to execute the Deployment Image Servicing and Management (DISM) tool with the specified
/// arguments.
Expand Down Expand Up @@ -188,6 +195,15 @@ internal static int StartDismProcess(string args)
return ExitCode;
}

internal static int StartDismProcessThreaded(string args)
{
ThreadManager.CreateThread(
() => StartDismProcess(args)
);

return ExitCode;
}

/// <summary>
/// Starts a process with the specified executable file and arguments, waits for it to exit, and returns the
/// process's exit code.
Expand Down Expand Up @@ -235,5 +251,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;
}
}
}
117 changes: 117 additions & 0 deletions WindowsInstallerLib/src/ThreadManager.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
using System;
using System.Threading;

namespace WindowsInstallerLib
{
/// <summary>
/// This class handles the priority, the state, etcetera of threads.
/// </summary>
internal sealed class ThreadManager
{
/// <summary>
/// Gets the current priority of the thread.
/// </summary>
/// <param name="thread"></param>
/// <returns>
/// BelowNormal, Normal, AboveNormal or Highest
/// </returns>
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;
}
}
}