From a29fb096dc5f4b41b34535cdf20571b60eca55ce Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 12 Jan 2026 04:01:01 +0000 Subject: [PATCH 1/3] Initial plan From e85867495bdfd20e5e8a6efbf581383ab1fa6778 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 12 Jan 2026 04:04:38 +0000 Subject: [PATCH 2/3] Add UAC script command support to driver upgrade functionality Co-authored-by: JusterZhu <11714536+JusterZhu@users.noreply.github.com> --- .../Driver/DisableUACCommand.cs | 13 ++++ .../Driver/DriverInformation.cs | 22 ++++++ .../Driver/RestoreUACCommand.cs | 13 ++++ .../Driver/ScriptCommand.cs | 68 +++++++++++++++++++ .../Pipeline/DriverMiddleware.cs | 26 ++++++- 5 files changed, 139 insertions(+), 3 deletions(-) create mode 100644 src/c#/GeneralUpdate.Core/Driver/DisableUACCommand.cs create mode 100644 src/c#/GeneralUpdate.Core/Driver/RestoreUACCommand.cs create mode 100644 src/c#/GeneralUpdate.Core/Driver/ScriptCommand.cs diff --git a/src/c#/GeneralUpdate.Core/Driver/DisableUACCommand.cs b/src/c#/GeneralUpdate.Core/Driver/DisableUACCommand.cs new file mode 100644 index 00000000..7eb324d7 --- /dev/null +++ b/src/c#/GeneralUpdate.Core/Driver/DisableUACCommand.cs @@ -0,0 +1,13 @@ +namespace GeneralUpdate.Core.Driver +{ + /// + /// Command to disable User Account Control (UAC) via script execution. + /// The script content is not managed by this class; only the script entry point is provided. + /// + public class DisableUACCommand : ScriptCommand + { + public DisableUACCommand(string scriptPath) : base(scriptPath) + { + } + } +} diff --git a/src/c#/GeneralUpdate.Core/Driver/DriverInformation.cs b/src/c#/GeneralUpdate.Core/Driver/DriverInformation.cs index e396e2a6..ea9424e8 100644 --- a/src/c#/GeneralUpdate.Core/Driver/DriverInformation.cs +++ b/src/c#/GeneralUpdate.Core/Driver/DriverInformation.cs @@ -18,6 +18,16 @@ public class DriverInformation public string OutPutDirectory { get; private set; } public string DriverDirectory { get; private set; } + + /// + /// Path to the script that disables UAC. + /// + public string DisableUACScriptPath { get; private set; } + + /// + /// Path to the script that restores UAC. + /// + public string RestoreUACScriptPath { get; private set; } /// /// A collection of driver files to be backed up. @@ -54,6 +64,18 @@ public Builder SetFieldMappings(Dictionary fieldMappings) _information.FieldMappings = fieldMappings; return this; } + + public Builder SetDisableUACScriptPath(string scriptPath) + { + _information.DisableUACScriptPath = scriptPath; + return this; + } + + public Builder SetRestoreUACScriptPath(string scriptPath) + { + _information.RestoreUACScriptPath = scriptPath; + return this; + } public DriverInformation Build() { diff --git a/src/c#/GeneralUpdate.Core/Driver/RestoreUACCommand.cs b/src/c#/GeneralUpdate.Core/Driver/RestoreUACCommand.cs new file mode 100644 index 00000000..1b7e2a82 --- /dev/null +++ b/src/c#/GeneralUpdate.Core/Driver/RestoreUACCommand.cs @@ -0,0 +1,13 @@ +namespace GeneralUpdate.Core.Driver +{ + /// + /// Command to restore User Account Control (UAC) via script execution. + /// The script content is not managed by this class; only the script entry point is provided. + /// + public class RestoreUACCommand : ScriptCommand + { + public RestoreUACCommand(string scriptPath) : base(scriptPath) + { + } + } +} diff --git a/src/c#/GeneralUpdate.Core/Driver/ScriptCommand.cs b/src/c#/GeneralUpdate.Core/Driver/ScriptCommand.cs new file mode 100644 index 00000000..b888fd82 --- /dev/null +++ b/src/c#/GeneralUpdate.Core/Driver/ScriptCommand.cs @@ -0,0 +1,68 @@ +using System; +using System.Diagnostics; +using GeneralUpdate.Common.Shared; + +namespace GeneralUpdate.Core.Driver +{ + /// + /// Base class for executing script commands. + /// + public abstract class ScriptCommand : DriverCommand + { + protected string ScriptPath { get; } + + protected ScriptCommand(string scriptPath) + { + if (string.IsNullOrWhiteSpace(scriptPath)) + throw new ArgumentNullException(nameof(scriptPath), "Script path cannot be null or empty."); + + ScriptPath = scriptPath; + } + + public override void Execute() + { + ExecuteScript(ScriptPath); + } + + /// + /// Execute a script file. + /// + /// Path to the script file to execute. + protected virtual void ExecuteScript(string scriptPath) + { + var processStartInfo = new ProcessStartInfo + { + WindowStyle = ProcessWindowStyle.Hidden, + FileName = scriptPath, + UseShellExecute = false, + RedirectStandardOutput = true, + RedirectStandardError = true, + Verb = "runas" + }; + + var process = new Process(); + try + { + process.StartInfo = processStartInfo; + process.Start(); + process.WaitForExit(); + + var output = process.StandardOutput.ReadToEnd(); + GeneralTracer.Info($"Script execution output: {output}"); + + var error = process.StandardError.ReadToEnd(); + if (!string.IsNullOrEmpty(error)) + { + GeneralTracer.Error($"Script execution error: {error}"); + } + + if (process.ExitCode != 0) + throw new ApplicationException($"Script execution failed with exit code: {process.ExitCode}"); + } + finally + { + process.Dispose(); + } + } + } +} diff --git a/src/c#/GeneralUpdate.Core/Pipeline/DriverMiddleware.cs b/src/c#/GeneralUpdate.Core/Pipeline/DriverMiddleware.cs index c96ce6b0..5fb1d7b7 100644 --- a/src/c#/GeneralUpdate.Core/Pipeline/DriverMiddleware.cs +++ b/src/c#/GeneralUpdate.Core/Pipeline/DriverMiddleware.cs @@ -29,17 +29,37 @@ public Task InvokeAsync(PipelineContext context) if (fieldMappings == null || fieldMappings.Count == 0) return; - var information = new DriverInformation.Builder() + var disableUACScriptPath = context.Get("DisableUACScriptPath"); + var restoreUACScriptPath = context.Get("RestoreUACScriptPath"); + + var builder = new DriverInformation.Builder() .SetDriverFileExtension(FileExtension) .SetOutPutDirectory(outPutPath) .SetDriverDirectory(patchPath) - .SetFieldMappings(fieldMappings) - .Build(); + .SetFieldMappings(fieldMappings); + + if (!string.IsNullOrWhiteSpace(disableUACScriptPath)) + builder.SetDisableUACScriptPath(disableUACScriptPath); + + if (!string.IsNullOrWhiteSpace(restoreUACScriptPath)) + builder.SetRestoreUACScriptPath(restoreUACScriptPath); + + var information = builder.Build(); var processor = new DriverProcessor(); + + // Disable UAC before driver operations if script path is provided + if (!string.IsNullOrWhiteSpace(information.DisableUACScriptPath)) + processor.AddCommand(new DisableUACCommand(information.DisableUACScriptPath)); + processor.AddCommand(new BackupDriverCommand(information)); processor.AddCommand(new DeleteDriverCommand(information)); processor.AddCommand(new InstallDriverCommand(information)); + + // Restore UAC after driver operations if script path is provided + if (!string.IsNullOrWhiteSpace(information.RestoreUACScriptPath)) + processor.AddCommand(new RestoreUACCommand(information.RestoreUACScriptPath)); + processor.ProcessCommands(); }); } From b3981f9ade1c243d04f44876e543691fec4d677d Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 12 Jan 2026 04:05:50 +0000 Subject: [PATCH 3/3] Fix UAC script execution and add security validations Co-authored-by: JusterZhu <11714536+JusterZhu@users.noreply.github.com> --- .../Driver/ScriptCommand.cs | 20 +++++++------------ 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/src/c#/GeneralUpdate.Core/Driver/ScriptCommand.cs b/src/c#/GeneralUpdate.Core/Driver/ScriptCommand.cs index b888fd82..7251ced7 100644 --- a/src/c#/GeneralUpdate.Core/Driver/ScriptCommand.cs +++ b/src/c#/GeneralUpdate.Core/Driver/ScriptCommand.cs @@ -30,13 +30,14 @@ public override void Execute() /// Path to the script file to execute. protected virtual void ExecuteScript(string scriptPath) { + if (!System.IO.File.Exists(scriptPath)) + throw new ApplicationException($"Script file not found: {scriptPath}"); + var processStartInfo = new ProcessStartInfo { WindowStyle = ProcessWindowStyle.Hidden, FileName = scriptPath, - UseShellExecute = false, - RedirectStandardOutput = true, - RedirectStandardError = true, + UseShellExecute = true, Verb = "runas" }; @@ -47,17 +48,10 @@ protected virtual void ExecuteScript(string scriptPath) process.Start(); process.WaitForExit(); - var output = process.StandardOutput.ReadToEnd(); - GeneralTracer.Info($"Script execution output: {output}"); - - var error = process.StandardError.ReadToEnd(); - if (!string.IsNullOrEmpty(error)) - { - GeneralTracer.Error($"Script execution error: {error}"); - } - if (process.ExitCode != 0) - throw new ApplicationException($"Script execution failed with exit code: {process.ExitCode}"); + throw new ApplicationException($"Script execution failed for '{scriptPath}' with exit code: {process.ExitCode}"); + + GeneralTracer.Info($"Script executed successfully: {scriptPath}"); } finally {