Initial commit
lets build something awesome...
This commit is contained in:
1 parent
f30f280fb1
commit
335b6b4a70
23 files changed
+2728
No files matched your search
@@ -0,0 +1,345 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
|
||||
/*
|
||||
* NativePatcher class is responsible for automating the Windows 11 24H2 installation process.
|
||||
* It uses the Fido.ps1 script https://github.com/pbatard/Fido to download the ISO, mounts the ISO, and runs Server setupprep.exe
|
||||
*/
|
||||
|
||||
namespace FlybyScript
|
||||
{
|
||||
public class NativePatcher
|
||||
{
|
||||
private Logger _logger;
|
||||
private string _fidoScriptPath;
|
||||
|
||||
public NativePatcher(Logger logger)
|
||||
{
|
||||
this._fidoScriptPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "upgraider", "Fido.ps1");
|
||||
this._logger = logger;
|
||||
}
|
||||
|
||||
public async Task AutomateWindowsInstallation()
|
||||
{
|
||||
// Step 1: Download Windows 24H2 ISO using Fido.ps1
|
||||
await DownloadISO();
|
||||
|
||||
// Step 2: Allow user to select the ISO after download
|
||||
MessageBox.Show("Please select the ISO file to mount.", "ISO Selection", MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||||
|
||||
// Step 3: Mount the ISO and get the mounted drive letter
|
||||
string mountedDriveLetter = await MountISO();
|
||||
|
||||
if (string.IsNullOrEmpty(mountedDriveLetter))
|
||||
{
|
||||
_logger.Log("Failed to mount ISO. Exiting.", Color.Crimson);
|
||||
return;
|
||||
}
|
||||
|
||||
// Step 2: Run the setup process with the mounted drive letter
|
||||
await RunSetup(mountedDriveLetter);
|
||||
}
|
||||
|
||||
// Step 1: Download Windows 24H2 ISO by running the Fido.ps1 script
|
||||
private async Task DownloadISO()
|
||||
{
|
||||
try
|
||||
{
|
||||
_logger.Log("Starting the download of the Windows 24H2 ISO...", Color.Blue);
|
||||
|
||||
// Run Fido.ps1 to download the ISO (PowerShell script)
|
||||
string downloadCommand = $"& \"{_fidoScriptPath}\"";
|
||||
await ExecutePowerShellCommand(downloadCommand);
|
||||
|
||||
_logger.Log("Windows 24H2 ISO download completed.", System.Drawing.Color.Green);
|
||||
|
||||
MessageBox.Show("Please wait for the ISO file to download, and then select the ISO file.",
|
||||
"Information",
|
||||
MessageBoxButtons.OK,
|
||||
MessageBoxIcon.Information);
|
||||
|
||||
_logger.Log("Please wait for the ISO file to download, and then select the ISO file. " +
|
||||
"If you cancel the process here and wait for the ISO download, you will need to restart the patching process, " +
|
||||
"but you can skip the ISO download.", System.Drawing.Color.Black);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Log($"Error during ISO download: {ex.Message}", System.Drawing.Color.Crimson);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task<string> MountISO()
|
||||
{
|
||||
try
|
||||
{
|
||||
OpenFileDialog openFileDialog = new OpenFileDialog
|
||||
{
|
||||
Title = "Select Windows 24H2 ISO File",
|
||||
Filter = "ISO Files (*.iso)|*.iso|All Files (*.*)|*.*",
|
||||
InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyComputer)
|
||||
};
|
||||
|
||||
if (openFileDialog.ShowDialog() == DialogResult.OK)
|
||||
{
|
||||
string isoFilePath = openFileDialog.FileName;
|
||||
|
||||
MessageBox.Show($"Selected ISO file: {isoFilePath}. Now mounting the ISO.", "ISO Selected", MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||||
|
||||
_logger.Log($"Mounting ISO: {isoFilePath}...", System.Drawing.Color.Blue);
|
||||
|
||||
string mountCommand = $"Mount-DiskImage -ImagePath \"{isoFilePath}\"";
|
||||
await ExecutePowerShellCommand(mountCommand); // Run asynchronously for mounting
|
||||
|
||||
// After mounting, try to get the drive letter
|
||||
string mountedDriveLetter = await GetMountedDriveLetter();
|
||||
|
||||
if (string.IsNullOrEmpty(mountedDriveLetter))
|
||||
{
|
||||
_logger.Log("Failed to get mounted drive letter.", System.Drawing.Color.Crimson);
|
||||
return null;
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.Log($"ISO mounted successfully. Drive letter: {mountedDriveLetter}", System.Drawing.Color.Green);
|
||||
return mountedDriveLetter; // Return the mounted drive letter
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.Log("No ISO file selected.", System.Drawing.Color.Black);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Log($"Error mounting ISO: {ex.Message}", System.Drawing.Color.Crimson);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private async Task RunSetup(string mountedDriveLetter)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Check if the mounted drive is available
|
||||
if (string.IsNullOrEmpty(mountedDriveLetter))
|
||||
{
|
||||
_logger.Log("No mounted drive found. Exiting.", System.Drawing.Color.Crimson);
|
||||
return;
|
||||
}
|
||||
|
||||
// Log the drive letter
|
||||
_logger.Log($"Mounted drive letter: {mountedDriveLetter}", System.Drawing.Color.Gray);
|
||||
|
||||
// Build the path to the Sources folder
|
||||
string sourcesFolderPath = Path.Combine(mountedDriveLetter, "sources");
|
||||
|
||||
// Path correct?
|
||||
_logger.Log($"Checking Sources folder at: {sourcesFolderPath}", System.Drawing.Color.Gray);
|
||||
|
||||
// Check if Sources folder exists
|
||||
if (Directory.Exists(sourcesFolderPath))
|
||||
{
|
||||
_logger.Log($"Found Sources folder at {sourcesFolderPath}. Opening CMD and running setupprep.exe.", System.Drawing.Color.Green);
|
||||
|
||||
// Prepare the CMD command to open cmd, then run 'setupprep.exe /product server'
|
||||
string cmdCommand = $"/C \"cd /d {sourcesFolderPath} && start cmd /k setupprep.exe /product server\"";
|
||||
|
||||
// Execute the CMD command, which will open a new CMD window
|
||||
ProcessStart(cmdCommand);
|
||||
|
||||
MessageBox.Show("Follow the Windows Server Setup window now. You can close the command window and the Flyby11 app.",
|
||||
"Information",
|
||||
MessageBoxButtons.OK,
|
||||
MessageBoxIcon.Information);
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.Log($"Sources folder not found at {sourcesFolderPath}.", System.Drawing.Color.Crimson);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Log($"Error running setupprep.exe: {ex.Message}", System.Drawing.Color.Crimson);
|
||||
}
|
||||
}
|
||||
|
||||
// btnMountRunSetup_Click: Run setup.exe from a mounted ISO on the fly
|
||||
public async Task RunSetupFromMountedISO()
|
||||
{
|
||||
// Choose an ISO file
|
||||
string isoFilePath = SelectISOFile();
|
||||
if (isoFilePath == null) return;
|
||||
|
||||
try
|
||||
{
|
||||
// Mount the selected ISO
|
||||
await ExecutePowerShellCommand($"Mount-DiskImage -ImagePath \"{isoFilePath}\"");
|
||||
|
||||
// Get the mounted drive letter
|
||||
string mountedDriveLetter = await GetMountedDriveLetter();
|
||||
if (string.IsNullOrEmpty(mountedDriveLetter))
|
||||
{
|
||||
_logger.Log("Failed to get mounted drive letter.", Color.Crimson);
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if setup.exe exists and start it
|
||||
string setupPath = Path.Combine(mountedDriveLetter, "setup.exe");
|
||||
if (File.Exists(setupPath))
|
||||
{
|
||||
_logger.Log($"Found setup.exe at {setupPath}. Launching setup.", Color.Green);
|
||||
|
||||
Process.Start(new ProcessStartInfo
|
||||
{
|
||||
FileName = setupPath,
|
||||
UseShellExecute = true,
|
||||
CreateNoWindow = false
|
||||
});
|
||||
|
||||
MessageBox.Show("Windows Setup has started. Follow the on-screen instructions.", "Information", MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.Log($"setup.exe not found at {setupPath}.", Color.Crimson);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Log($"Error running setup.exe: {ex.Message}", Color.Crimson);
|
||||
}
|
||||
}
|
||||
|
||||
private void ProcessStart(string command)
|
||||
{
|
||||
try
|
||||
{
|
||||
using (var process = new Process())
|
||||
{
|
||||
process.StartInfo.FileName = "cmd.exe";
|
||||
process.StartInfo.Arguments = command;
|
||||
process.StartInfo.UseShellExecute = true;
|
||||
process.StartInfo.CreateNoWindow = false;
|
||||
|
||||
// Start the process
|
||||
process.Start();
|
||||
|
||||
// Wait for the process to finish
|
||||
process.WaitForExit();
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Log($"Error executing CMD command: {ex.Message}", System.Drawing.Color.Crimson);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task<string> ExecutePowerShellCommand(string command)
|
||||
{
|
||||
try
|
||||
{
|
||||
using (var process = new Process())
|
||||
{
|
||||
process.StartInfo.FileName = "powershell.exe";
|
||||
process.StartInfo.Arguments = $"-NoProfile -ExecutionPolicy Bypass -Command \"{command}\"";
|
||||
process.StartInfo.RedirectStandardOutput = true;
|
||||
process.StartInfo.RedirectStandardError = true;
|
||||
process.StartInfo.UseShellExecute = false;
|
||||
process.StartInfo.CreateNoWindow = true;
|
||||
|
||||
// Output and error handlers
|
||||
var outputBuilder = new StringBuilder();
|
||||
var errorBuilder = new StringBuilder();
|
||||
|
||||
process.OutputDataReceived += (sender, args) =>
|
||||
{
|
||||
if (args.Data != null)
|
||||
{
|
||||
outputBuilder.AppendLine(args.Data); // Collect output data
|
||||
_logger.Log(args.Data, System.Drawing.Color.LightPink);
|
||||
}
|
||||
};
|
||||
|
||||
process.ErrorDataReceived += (sender, args) =>
|
||||
{
|
||||
if (args.Data != null)
|
||||
{
|
||||
errorBuilder.AppendLine(args.Data); // Collect error data
|
||||
_logger.Log(args.Data, System.Drawing.Color.Crimson);
|
||||
}
|
||||
};
|
||||
|
||||
// Start the process
|
||||
process.Start();
|
||||
process.BeginOutputReadLine();
|
||||
process.BeginErrorReadLine();
|
||||
|
||||
// Wait for the process to exit
|
||||
await Task.Run(() => process.WaitForExit());
|
||||
|
||||
// Combine the full output and error logs
|
||||
string output = outputBuilder.ToString();
|
||||
string error = errorBuilder.ToString();
|
||||
|
||||
if (!string.IsNullOrEmpty(error))
|
||||
{
|
||||
_logger.Log(error, System.Drawing.Color.Crimson);
|
||||
}
|
||||
|
||||
// Return the entire output of ps command
|
||||
return output;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Log($"PowerShell command execution failed: {ex.Message}", System.Drawing.Color.Crimson);
|
||||
return string.Empty; // Return an empty string if an error occurs
|
||||
}
|
||||
}
|
||||
|
||||
// Get the mounted drive letter
|
||||
private async Task<string> GetMountedDriveLetter()
|
||||
{
|
||||
try
|
||||
{
|
||||
// List all the drives to find the mounted drive letter
|
||||
var drives = DriveInfo.GetDrives();
|
||||
|
||||
foreach (var drive in drives)
|
||||
{
|
||||
// Check if the drive is a CD/DVD and if it's mounted
|
||||
if (drive.DriveType == DriveType.CDRom && drive.IsReady)
|
||||
{
|
||||
// Return the letter of the mounted drive
|
||||
return drive.Name.Substring(0, 2);
|
||||
}
|
||||
}
|
||||
|
||||
return null; // Return null if no mounted drive is found
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Log($"Error getting mounted drive letter: {ex.Message}", System.Drawing.Color.Crimson);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
private string SelectISOFile()
|
||||
{
|
||||
using (var openFileDialog = new OpenFileDialog
|
||||
{
|
||||
Title = "Select Windows 11 ISO File",
|
||||
Filter = "ISO Files (*.iso)|*.iso|All Files (*.*)|*.*",
|
||||
InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyComputer)
|
||||
})
|
||||
{
|
||||
return openFileDialog.ShowDialog() == DialogResult.OK ? openFileDialog.FileName : null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
using FlybyScript;
|
||||
|
||||
public class PSPatcher
|
||||
{
|
||||
public void LoadPowerShellPlugins(TreeView treeView)
|
||||
{
|
||||
var scriptDirectory = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "upgraider");
|
||||
|
||||
if (!Directory.Exists(scriptDirectory))
|
||||
{
|
||||
MessageBox.Show("upgraider directory does not exist.");
|
||||
return;
|
||||
}
|
||||
|
||||
// Create a Dependencies category in the TreeView
|
||||
TreeNode dependencyCategory = new TreeNode("Dependencies");
|
||||
treeView.Nodes.Add(dependencyCategory);
|
||||
|
||||
var scriptFiles = Directory.GetFiles(scriptDirectory, "*.ps1");
|
||||
|
||||
foreach (var file in scriptFiles)
|
||||
{
|
||||
var scriptName = Path.GetFileNameWithoutExtension(file);
|
||||
|
||||
// Create a TreeNode for each ps script
|
||||
var scriptNode = new TreeNode
|
||||
{
|
||||
ToolTipText = file,
|
||||
Text = $"{scriptName} [PS]",
|
||||
Tag = file // Store the file path as the Tag
|
||||
};
|
||||
|
||||
// Add the script node to the Dependecy category
|
||||
dependencyCategory.Nodes.Add(scriptNode);
|
||||
}
|
||||
}
|
||||
|
||||
// Execute the selected PowerShell script
|
||||
public async Task ExecutePlugin(string pluginPath, Logger logger)
|
||||
{
|
||||
try
|
||||
{
|
||||
using (var process = new Process())
|
||||
{
|
||||
process.StartInfo.FileName = "powershell.exe";
|
||||
process.StartInfo.Arguments = $"-NoProfile -ExecutionPolicy Bypass -File \"{pluginPath}\"";
|
||||
process.StartInfo.RedirectStandardOutput = true;
|
||||
process.StartInfo.RedirectStandardError = true;
|
||||
process.StartInfo.UseShellExecute = false;
|
||||
process.StartInfo.CreateNoWindow = true;
|
||||
|
||||
var outputBuilder = new StringBuilder();
|
||||
var errorBuilder = new StringBuilder();
|
||||
|
||||
// Handle output from PowerShell script
|
||||
process.OutputDataReceived += (sender, e) =>
|
||||
{
|
||||
if (!string.IsNullOrEmpty(e.Data))
|
||||
{
|
||||
outputBuilder.AppendLine(e.Data);
|
||||
logger.Log($"PowerShell script output: {e.Data}", System.Drawing.Color.Black);
|
||||
}
|
||||
};
|
||||
|
||||
// Handle error from PowerShell script
|
||||
process.ErrorDataReceived += (sender, e) =>
|
||||
{
|
||||
if (!string.IsNullOrEmpty(e.Data))
|
||||
{
|
||||
errorBuilder.AppendLine(e.Data);
|
||||
logger.Log($"PowerShell script error: {e.Data}", System.Drawing.Color.Crimson);
|
||||
}
|
||||
};
|
||||
|
||||
process.Start();
|
||||
process.BeginOutputReadLine();
|
||||
process.BeginErrorReadLine();
|
||||
|
||||
await Task.Run(() =>
|
||||
{
|
||||
process.WaitForExit();
|
||||
});
|
||||
|
||||
logger.Log($"PowerShell script executed successfully: {pluginPath}", System.Drawing.Color.Green);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
logger.Log($"Error executing PowerShell script: {pluginPath}. Exception: {ex.Message}", System.Drawing.Color.Crimson);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,238 @@
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
|
||||
/*
|
||||
* Imported from my xd-AntiSpy app https://github.com/builtbybel/xd-AntiSpy
|
||||
*/
|
||||
|
||||
namespace FlybyScript
|
||||
{
|
||||
public class ScriptPatcher
|
||||
{
|
||||
public string PlugID { get; set; }
|
||||
public string PlugInfo { get; set; }
|
||||
public string[] PlugCheck { get; set; }
|
||||
public string[] PlugDo { get; set; }
|
||||
public string[] PlugUndo { get; set; }
|
||||
public string PlugCategory { get; set; }
|
||||
|
||||
private Logger logger;
|
||||
|
||||
public ScriptPatcher(Logger logger)
|
||||
{
|
||||
this.logger = logger;
|
||||
}
|
||||
|
||||
public bool PlugCheckFeature()
|
||||
{
|
||||
bool isFeatureActive = true;
|
||||
foreach (var command in PlugCheck)
|
||||
{
|
||||
if (!ExecuteCommandAndCheckResult(command))
|
||||
{
|
||||
isFeatureActive = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
logger.Log($"Feature '{PlugID}' is {(isFeatureActive ? "active" : "inactive")}", System.Drawing.Color.Black);
|
||||
return isFeatureActive;
|
||||
}
|
||||
|
||||
// PlugCheck Helper to execute commands and check the result
|
||||
private bool ExecuteCommandAndCheckResult(string command)
|
||||
{
|
||||
try
|
||||
{
|
||||
var process = new Process
|
||||
{
|
||||
StartInfo = new ProcessStartInfo
|
||||
{
|
||||
FileName = "cmd.exe",
|
||||
Arguments = $"/c {command}",
|
||||
RedirectStandardOutput = true,
|
||||
UseShellExecute = false,
|
||||
CreateNoWindow = true,
|
||||
}
|
||||
};
|
||||
process.Start();
|
||||
process.WaitForExit();
|
||||
|
||||
// Read the output of the command
|
||||
string output = process.StandardOutput.ReadToEnd();
|
||||
|
||||
// Check if output contains "1" (indicating active) or "0" (indicating inactive)
|
||||
bool isActive = output.Contains("1");
|
||||
|
||||
// logger.Log($"Plugin executed successfully: {command}. Result: {(isActive ? "active" : "inactive")}", System.Drawing.Color.Black);
|
||||
return isActive;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
logger.Log($"Error executing plugin: {command}. Exception: {ex.Message}", System.Drawing.Color.Crimson);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public async void PlugDoFeature()
|
||||
{
|
||||
await ExecuteFeatureCommands(PlugDo);
|
||||
}
|
||||
|
||||
public async void PlugUndoFeature()
|
||||
{
|
||||
await ExecuteFeatureCommands(PlugUndo);
|
||||
}
|
||||
|
||||
private async Task ExecuteFeatureCommands(string[] commands)
|
||||
{
|
||||
foreach (var command in commands)
|
||||
{
|
||||
await ExecuteCommand(command);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task ExecuteCommand(string command)
|
||||
{
|
||||
try
|
||||
{
|
||||
var process = new Process
|
||||
{
|
||||
StartInfo = new ProcessStartInfo
|
||||
{
|
||||
FileName = IsPowerShellCommand(command) ? "powershell.exe" : "cmd.exe",
|
||||
Arguments = IsPowerShellCommand(command) ? $"-Command \"{command}\"" : $"/c \"{command}\"",
|
||||
RedirectStandardOutput = true,
|
||||
RedirectStandardError = true,
|
||||
UseShellExecute = false,
|
||||
CreateNoWindow = true,
|
||||
}
|
||||
};
|
||||
|
||||
// Event handler for handling output data
|
||||
process.OutputDataReceived += (sender, e) =>
|
||||
{
|
||||
if (!string.IsNullOrEmpty(e.Data))
|
||||
{
|
||||
logger.Log($"Output: {e.Data}", System.Drawing.Color.Green);
|
||||
}
|
||||
};
|
||||
|
||||
// Event handler for handling error data
|
||||
process.ErrorDataReceived += (sender, e) =>
|
||||
{
|
||||
if (!string.IsNullOrEmpty(e.Data))
|
||||
{
|
||||
logger.Log($"Error: {e.Data}", System.Drawing.Color.Crimson);
|
||||
}
|
||||
};
|
||||
|
||||
process.Start();
|
||||
|
||||
// Begin asynchronous reading of the output and error streams
|
||||
process.BeginOutputReadLine();
|
||||
process.BeginErrorReadLine();
|
||||
|
||||
// Wait for the process to exit
|
||||
await process.WaitForExitAsync();
|
||||
|
||||
// Log command execution
|
||||
logger.Log($"Plugin executed command: {command}", System.Drawing.Color.Green);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
logger.Log($"Error executing plugin: {command}. Exception: {ex.Message}", System.Drawing.Color.Crimson);
|
||||
}
|
||||
}
|
||||
|
||||
// Determine if our command should be run with PowerShell
|
||||
private bool IsPowerShellCommand(string command)
|
||||
{
|
||||
return command.StartsWith("powershell.exe") || command.Contains("Get-") || command.Contains("Set-");
|
||||
}
|
||||
|
||||
// Get plugin information
|
||||
public string GetPluginInformation()
|
||||
{
|
||||
return $"{PlugInfo.Replace("\\n", Environment.NewLine)}";
|
||||
}
|
||||
|
||||
private static void AddToPluginCategory(TreeNodeCollection pluginCategory, TreeNode node, string category)
|
||||
{
|
||||
if (pluginCategory == null)
|
||||
throw new ArgumentNullException(nameof(pluginCategory));
|
||||
var existingCategory = pluginCategory.Cast<TreeNode>().FirstOrDefault(n => n.Text == category);
|
||||
|
||||
if (existingCategory == null)
|
||||
{
|
||||
existingCategory = new TreeNode(category)
|
||||
{
|
||||
BackColor = System.Drawing.Color.LightBlue,
|
||||
ForeColor = System.Drawing.Color.Black
|
||||
};
|
||||
pluginCategory.Add(existingCategory);
|
||||
}
|
||||
|
||||
existingCategory.Nodes.Add(node);
|
||||
}
|
||||
|
||||
public static async Task LoadPlugins(string pluginDirectory, TreeNodeCollection pluginCategory, Logger logger)
|
||||
{
|
||||
if (Directory.Exists(pluginDirectory))
|
||||
{
|
||||
var pluginFiles = Directory.GetFiles(pluginDirectory, "*.json");
|
||||
|
||||
foreach (var file in pluginFiles)
|
||||
{
|
||||
// Exclude JSON files of our DLL Plugins as they are loaded separately
|
||||
if (Path.GetFileName(file).IndexOf("Plugin", StringComparison.OrdinalIgnoreCase) >= 0)
|
||||
continue;
|
||||
|
||||
try
|
||||
{
|
||||
var json = File.ReadAllText(file);
|
||||
var plugin = JsonConvert.DeserializeObject<ScriptPatcher>(json);
|
||||
|
||||
if (plugin != null)
|
||||
{
|
||||
plugin.logger = logger; // Set logger for the plugin
|
||||
|
||||
// Execute all commands for the plugin to check its feature
|
||||
bool isActive = plugin.PlugCheckFeature();
|
||||
|
||||
var pluginNode = new TreeNode(plugin.PlugID)
|
||||
{
|
||||
ToolTipText = plugin.PlugInfo,
|
||||
Checked = isActive,
|
||||
Tag = plugin // Store plugin object in Tag property
|
||||
};
|
||||
|
||||
// Add to the appropriate category
|
||||
AddToPluginCategory(pluginCategory, pluginNode, plugin.PlugCategory);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
logger.Log($"Error loading plugin from file '{file}': {ex.Message}", System.Drawing.Color.Crimson);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Extension method to make WaitForExit async in ExecuteCommand
|
||||
public static class ProcessExtensions
|
||||
{
|
||||
public static async Task WaitForExitAsync(this Process process)
|
||||
{
|
||||
var tcs = new TaskCompletionSource<bool>();
|
||||
process.EnableRaisingEvents = true;
|
||||
process.Exited += (sender, args) => tcs.TrySetResult(true);
|
||||
await tcs.Task;
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user