Skip to content

Commit

Permalink
Add driver update middleware
Browse files Browse the repository at this point in the history
  • Loading branch information
JusterZhu committed Nov 17, 2023
1 parent 472d612 commit 6d9fe39
Show file tree
Hide file tree
Showing 10 changed files with 241 additions and 0 deletions.
5 changes: 5 additions & 0 deletions src/c#/GeneralUpdate.Core/Domain/Entity/VersionInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,5 +41,10 @@ public VersionInfo(long pubTime, string name, string mD5, string version, string
/// Remote service url address.
/// </summary>
public string Url { get; set; }

public override string ToString()
{
return Version;
}
}
}
28 changes: 28 additions & 0 deletions src/c#/GeneralUpdate.Core/Driver/BackupDriverCommand.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
using System.Collections.Generic;
using System.Text;

namespace GeneralUpdate.Core.Driver
{

/// <summary>
/// When the /export-driver command backs up a driver, it backs up the driver package along with all its dependencies, such as associated library files and other related files.
/// </summary>
public class BackupDriverCommand : IDriverCommand
{
private DriverInformation _information;

public BackupDriverCommand(DriverInformation information)
{
_information = information;
}

public void Execute()
{
var command = new StringBuilder("/c dism /online /export-driver /destination:\"")
.Append(_information.OutPutDirectory)
.Append("\"")
.ToString();
CommandExecutor.ExecuteCommand(command);
}
}
}
46 changes: 46 additions & 0 deletions src/c#/GeneralUpdate.Core/Driver/CommandExecutor.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
using System;
using System.Diagnostics;

namespace GeneralUpdate.Core.Driver
{
/// <summary>
/// When the process starts, PnPUtil is used to execute driver processing commands.
/// </summary>
public class CommandExecutor
{
public static void ExecuteCommand(string command)
{
/*
*Problems may occur, including:
Permission issues: PnPUtil requires administrator rights to run. If you try to run it without the proper permissions, the backup or restore may fail.
Driver compatibility: Although the backed up drivers work properly at backup time, if the operating system is upgraded, the backed up drivers may no longer be compatible with the new operating system version.
Hardware problems: If the hardware device fails or the hardware configuration changes, the backup driver may not work properly.
To minimize these risks, the following measures are recommended:
Before doing anything, create a system restore point so that it can be restored to its previous state if something goes wrong.
Update the driver regularly to ensure that the driver is compatible with the current operating system version.
If possible, use pre-tested drivers that are proven to work.
*
*/

var processStartInfo = new ProcessStartInfo
{
FileName = "cmd.exe",
Arguments = command,
UseShellExecute = false,
RedirectStandardOutput = true,
CreateNoWindow = true,
Verb = "runas"
};

using (var process = new Process { StartInfo = processStartInfo })
{
process.Start();
process.WaitForExit();

if (process.ExitCode != 0)
throw new Exception("Operation failed: " + process.StandardOutput.ReadToEnd());
}
}
}
}
45 changes: 45 additions & 0 deletions src/c#/GeneralUpdate.Core/Driver/DriverInformation.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
using System;
using System.Collections.Generic;
using System.Linq;

namespace GeneralUpdate.Core.Driver
{
/// <summary>
/// Driver information object.
/// </summary>
public class DriverInformation
{
public string InstallDirectory { get; private set; }
public string OutPutDirectory { get; private set; }

private DriverInformation(){}

public class Builder
{
private DriverInformation _information = new DriverInformation();

public Builder SetInstallDirectory(string installDirectory)
{
_information.InstallDirectory = installDirectory;
return this;
}

public Builder SetOutPutDirectory(string outPutDirectory)
{
_information.OutPutDirectory = outPutDirectory;
return this;
}

public DriverInformation Build()
{
if (string.IsNullOrWhiteSpace(_information.InstallDirectory) ||
string.IsNullOrWhiteSpace(_information.OutPutDirectory))
{
throw new InvalidOperationException("Cannot create DriverInformation, not all fields are set.");
}

return _information;
}
}
}
}
24 changes: 24 additions & 0 deletions src/c#/GeneralUpdate.Core/Driver/DriverProcessor.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
using System.Collections.Generic;

namespace GeneralUpdate.Core.Driver
{
public class DriverProcessor
{
private List<IDriverCommand> _commands = new List<IDriverCommand>();

public void AddCommand(IDriverCommand command)
{
_commands.Add(command);
}

public void ProcessCommands()
{
foreach (var command in _commands)
{
command.Execute();
}

_commands.Clear();
}
}
}
7 changes: 7 additions & 0 deletions src/c#/GeneralUpdate.Core/Driver/IDriverCommand.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
namespace GeneralUpdate.Core.Driver
{
public interface IDriverCommand
{
void Execute();
}
}
32 changes: 32 additions & 0 deletions src/c#/GeneralUpdate.Core/Driver/InstallDriverCommand.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
using System;
using System.Text;

namespace GeneralUpdate.Core.Driver
{
public class InstallDriverCommand : IDriverCommand
{
private DriverInformation _information;

public InstallDriverCommand(DriverInformation information)
{
_information = information;
}

public void Execute()
{
try
{
var command = new StringBuilder("/c pnputil /add-driver \"")
.Append(_information.InstallDirectory)
.Append("\"")
.ToString();
CommandExecutor.ExecuteCommand(command);
}
catch (Exception ex)
{
new RestoreDriverCommand(_information).Execute();
throw new Exception($"Failed to execute install command for {_information.InstallDirectory}", ex);
}
}
}
}
23 changes: 23 additions & 0 deletions src/c#/GeneralUpdate.Core/Driver/RestoreDriverCommand.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
using System.Text;

namespace GeneralUpdate.Core.Driver
{
public class RestoreDriverCommand : IDriverCommand
{
private DriverInformation _information;

public RestoreDriverCommand(DriverInformation information)
{
_information = information;
}

public void Execute()
{
var command = new StringBuilder("/c pnputil /add-driver \"")
.Append(_information.OutPutDirectory)
.Append("\"")
.ToString();
CommandExecutor.ExecuteCommand(command);
}
}
}
30 changes: 30 additions & 0 deletions src/c#/GeneralUpdate.Core/Pipelines/Middleware/DriveMiddleware.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
using System.IO;
using System.Threading.Tasks;
using GeneralUpdate.Core.Driver;
using GeneralUpdate.Core.Pipelines.Context;

namespace GeneralUpdate.Core.Pipelines.Middleware
{
/// <summary>
/// Drive file processing class.
/// </summary>
public class DriveMiddleware : IMiddleware
{
public async Task InvokeAsync(BaseContext context, MiddlewareStack stack)
{
var information = new DriverInformation.Builder()
.SetInstallDirectory(Path.Combine(context.SourcePath,context.Version.ToString()))
.SetOutPutDirectory(Path.Combine(context.TargetPath,context.Version.ToString()))
.Build();

var processor = new DriverProcessor();
// Backup driver.
processor.AddCommand(new BackupDriverCommand(information));
// Install the new driver, and if the installation fails, the backup is automatically restored.
processor.AddCommand(new InstallDriverCommand(information));
processor.ProcessCommands();
var node = stack.Pop();
if (node != null) await node.Next.Invoke(context, stack);
}
}
}
1 change: 1 addition & 0 deletions src/c#/GeneralUpdate.Differential/DifferentialCore.cs
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,7 @@ public bool Restore(string targetDirectory)
}
}


#endregion Public Methods

#region Private Methods
Expand Down

0 comments on commit 6d9fe39

Please sign in to comment.