diff --git a/ForceOps.Benchmarks/ForceOps.Benchmarks.csproj b/ForceOps.Benchmarks/ForceOps.Benchmarks.csproj
index 6e7e282..16322a9 100644
--- a/ForceOps.Benchmarks/ForceOps.Benchmarks.csproj
+++ b/ForceOps.Benchmarks/ForceOps.Benchmarks.csproj
@@ -4,7 +4,7 @@
-
+
diff --git a/ForceOps.Lib/ForceOps.Lib.csproj b/ForceOps.Lib/ForceOps.Lib.csproj
index 9979817..dcb8b83 100644
--- a/ForceOps.Lib/ForceOps.Lib.csproj
+++ b/ForceOps.Lib/ForceOps.Lib.csproj
@@ -15,7 +15,7 @@
-
-
+
+
\ No newline at end of file
diff --git a/ForceOps.Test/ForceOps.Test.csproj b/ForceOps.Test/ForceOps.Test.csproj
index be89e41..4127f47 100644
--- a/ForceOps.Test/ForceOps.Test.csproj
+++ b/ForceOps.Test/ForceOps.Test.csproj
@@ -5,11 +5,11 @@
-
-
-
+
+
+
-
+
runtime; build; native; contentfiles; analyzers
all
diff --git a/ForceOps/ForceOps.csproj b/ForceOps/ForceOps.csproj
index f9b46ef..7eced39 100644
--- a/ForceOps/ForceOps.csproj
+++ b/ForceOps/ForceOps.csproj
@@ -26,7 +26,7 @@
-
+
diff --git a/ForceOps/src/Program.cs b/ForceOps/src/Program.cs
index 24d98bc..ea1f8b4 100644
--- a/ForceOps/src/Program.cs
+++ b/ForceOps/src/Program.cs
@@ -1,6 +1,5 @@
-using System.CommandLine;
-using System.CommandLine.Builder;
-using System.CommandLine.Parsing;
+using System.CommandLine;
+using System.CommandLine.Help;
using System.Runtime.Versioning;
namespace ForceOps;
@@ -21,48 +20,46 @@ public ForceOpsRunner(ForceOps forceOps)
internal int Run()
{
- var rootCommand = new RootCommand("By hook or by crook, perform operations on files and directories. If they are in use by a process, kill the process.")
- {
- Name = "forceops"
- };
- rootCommand.AddCommand(CreateDeleteCommand());
- rootCommand.AddCommand(CreateListCommand());
+ // A named Command is used instead of RootCommand so the usage text shows
+ // "forceops" rather than the executable name ("ForceOps").
+ var rootCommand = new Command("forceops", "By hook or by crook, perform operations on files and directories. If they are in use by a process, kill the process.");
+ rootCommand.Options.Add(new HelpOption());
+ rootCommand.Options.Add(new VersionOption());
+ rootCommand.Subcommands.Add(CreateDeleteCommand());
+ rootCommand.Subcommands.Add(CreateListCommand());
- var parser = new CommandLineBuilder(rootCommand)
- .UseDefaults()
- .AddMiddleware(async (context, next) =>
+ try
+ {
+ return rootCommand.Parse(_forceOps.args).Invoke(new InvocationConfiguration
{
- try
- {
- await next(context);
- }
- catch (Exception ex)
- {
- _forceOps.caughtException = ex;
-
- if (ex is FileNotFoundException fileNotFoundEx)
- {
- _forceOps.forceOpsContext.environmentExit.Exit((int)ExitCode.FileNotFound, ex.Message);
- }
- throw;
- }
- })
- .Build();
+ EnableDefaultExceptionHandler = false
+ });
+ }
+ catch (Exception ex)
+ {
+ _forceOps.caughtException = ex;
- return parser.Invoke(_forceOps.args);
+ if (ex is FileNotFoundException)
+ {
+ _forceOps.forceOpsContext.environmentExit.Exit((int)ExitCode.FileNotFound, ex.Message);
+ }
+ Console.Error.WriteLine(ex.ToString());
+ return 1;
+ }
}
Command CreateDeleteCommand()
{
- var filesToDeleteArgument = new Argument("files", "Files or directories to delete.")
+ var filesToDeleteArgument = new Argument("files")
{
+ Description = "Files or directories to delete.",
Arity = ArgumentArity.OneOrMore
};
- var forceOption = new Option(["-f", "--force"], "Ignore nonexistent files and arguments.");
- var disableElevate = new Option(["-e", "--disable-elevate"], "Do not attempt to elevate if the file can't be deleted.");
- var retryDelay = new Option(["-d", "--retry-delay"], () => 50, "Delay when retrying to delete a file, after deleting processes holding a lock.");
- var maxRetries = new Option(["-n", "--max-retries"], () => 10, "Number of retries when deleting a locked file.");
+ var forceOption = new Option("--force", "-f") { Description = "Ignore nonexistent files and arguments." };
+ var disableElevate = new Option("--disable-elevate", "-e") { Description = "Do not attempt to elevate if the file can't be deleted." };
+ var retryDelay = new Option("--retry-delay", "-d") { DefaultValueFactory = _ => 50, Description = "Delay when retrying to delete a file, after deleting processes holding a lock." };
+ var maxRetries = new Option("--max-retries", "-n") { DefaultValueFactory = _ => 10, Description = "Number of retries when deleting a locked file." };
var deleteCommand = new Command("delete", "Delete files or a directories recursively.")
{
@@ -73,20 +70,28 @@ Command CreateDeleteCommand()
maxRetries
};
- deleteCommand.AddAlias("rm");
- deleteCommand.AddAlias("remove");
- deleteCommand.SetHandler(_forceOps.DeleteCommand, filesToDeleteArgument, forceOption, disableElevate, retryDelay, maxRetries);
+ deleteCommand.Aliases.Add("rm");
+ deleteCommand.Aliases.Add("remove");
+ deleteCommand.SetAction(parseResult => _forceOps.DeleteCommand(
+ parseResult.GetValue(filesToDeleteArgument)!,
+ parseResult.GetValue(forceOption),
+ parseResult.GetValue(disableElevate),
+ parseResult.GetValue(retryDelay),
+ parseResult.GetValue(maxRetries)));
return deleteCommand;
}
Command CreateListCommand()
{
- var fileOrDirectoryArgument = new Argument("fileOrDirectory", "File or directory to get the locks of.");
+ var fileOrDirectoryArgument = new Argument("fileOrDirectory")
+ {
+ Description = "File or directory to get the locks of."
+ };
var listCommand = new Command("list", "Uses LockCheck to output processes using a file or directory.")
{
fileOrDirectoryArgument
};
- listCommand.SetHandler(_forceOps.ListCommand, fileOrDirectoryArgument);
+ listCommand.SetAction(parseResult => _forceOps.ListCommand(parseResult.GetValue(fileOrDirectoryArgument)!));
return listCommand;
}
}