command-line-api
command-line-api copied to clipboard
How to validate that an argument is a valid file path?
I need an argument use for file creation or appending (path parameter in File.AppendAllText function). As far as I know there are two functions available LegalFileNamesOnly and LegalFilePathsOnly. The problem is that LegalFileNamesOnly validates just file name and so doesn't allow path characters like '\' or ':'. On the other hand LegalFilePathsOnly allows (as expected) path characters ( '', ':'), but also allows wildcard characters like '*' or '?', which cause the file writing function exception. Also there is not path length validation.
The problem is more serious when net framework 4.x is used. Because new FileInfo("C:\\*.txt"), which is legal in .net 6.0 causes an exception and so when the type of argument is FileInfo (like in Tutorial: Get started with System.CommandLine ) the exception will be in return await rootCommand.InvokeAsync(args); and so difficult to be reasonably handled.
Full example
internal class Program
{
static async Task<int> Main(string[] args)
{
try
{
var fileOption = new Option<FileInfo>(
name: "--file",
description: "The file to read and display on the console.")
{ IsRequired = true };
fileOption.LegalFilePathsOnly();
var rootCommand = new RootCommand("Sample app for System.CommandLine");
rootCommand.AddOption(fileOption);
rootCommand.SetHandler((file) =>
{
WriteFile(file);
},
fileOption);
return await rootCommand.InvokeAsync("--file C:\\test*.txt");
//return await rootCommand.InvokeAsync("--file c:\\temp\\testForentitiesbeingtrackedbytheDbContextthevaluesofforeignkeypropertiesindependententitiesarenotchangedwhentherelatedprincipalentityisdeletedThiscanresultinaninconsistentgraphofentitieswherethevaluesofforeignkeypropertiesdonotmatchtherelationshipsinthegraph.txt");
}
finally
{
Console.ReadLine();
}
}
static void WriteFile(FileInfo file)
{
System.IO.File.AppendAllText(file.FullName, "testing text " + DateTime.Now.ToString() + "\n");
}
}
When running on .net 6.0 it fails on System.IO.File.AppendAllText.... and on framework 4.7.2 it fails on return await rootCommand...
in both case with System.ArgumentException: Illegal characters in path.
When the too long filename is used (the commented out line) we get "System.IO.IOException: 'The filename, directory name, or volume label syntax is incorrect. " on net 6.0 and on framework "System.IO.PathTooLongException" on the same lines.