2022-03-09 22:42:40 +01:00
|
|
|
|
using System.Diagnostics;
|
|
|
|
|
using Cocona;
|
|
|
|
|
using Spectre.Console;
|
|
|
|
|
|
2022-03-11 16:32:53 +01:00
|
|
|
|
const int ScriptListSize = 15;
|
|
|
|
|
const int ErrorExitCode = 1;
|
|
|
|
|
|
2022-03-09 22:42:40 +01:00
|
|
|
|
var app = CoconaLiteApp.Create();
|
|
|
|
|
|
|
|
|
|
app.AddCommand(RootCommand);
|
|
|
|
|
app.Run();
|
|
|
|
|
|
|
|
|
|
static void RootCommand(
|
2022-03-11 16:32:53 +01:00
|
|
|
|
[Option("extensions", new char[] { 'e' }, Description = "Comma separated list of script extensions to search")] string extensions = "*",
|
|
|
|
|
[Option("depth", new char[] { 'd' }, Description = "Folder depth of the search")] int depth = 0,
|
|
|
|
|
[Option("elevated", new char[] { 'E' }, Description = "Run the script with elevated privileges")] bool elevated = false,
|
|
|
|
|
[Option("multiple", new char[] { 'm' }, Description = "Execute multiple scripts")] bool multiple = false,
|
|
|
|
|
[Argument(Name = "Directory", Description = "Directory from which search the scripts")] string directory = ".")
|
2022-03-09 22:42:40 +01:00
|
|
|
|
{
|
|
|
|
|
if (!Directory.Exists(directory))
|
|
|
|
|
{
|
2022-03-11 16:32:53 +01:00
|
|
|
|
AnsiConsole.Markup($"[red]The directory '{directory}' does not exist.[/]");
|
|
|
|
|
Environment.ExitCode = ErrorExitCode;
|
|
|
|
|
return;
|
2022-03-09 22:42:40 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var fileExtensions = extensions.Split(new[] { ',', ' ' }, StringSplitOptions.RemoveEmptyEntries)
|
|
|
|
|
.ToHashSet()
|
|
|
|
|
.ToArray();
|
|
|
|
|
|
2022-03-11 16:32:53 +01:00
|
|
|
|
var finder = new ScriptFinder
|
2022-03-09 22:42:40 +01:00
|
|
|
|
{
|
|
|
|
|
Extensions = fileExtensions,
|
|
|
|
|
RootFolder = directory,
|
2022-03-11 16:32:53 +01:00
|
|
|
|
Depth = depth
|
2022-03-09 22:42:40 +01:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
var files = finder.GetScriptFiles(fileExtensions);
|
|
|
|
|
|
|
|
|
|
if (files.Length == 0)
|
|
|
|
|
{
|
2022-03-11 16:32:53 +01:00
|
|
|
|
AnsiConsole.Markup($"[red]No scripts script files found in '{directory}' with extensions '{string.Join("|", fileExtensions)}'[/]");
|
|
|
|
|
Environment.ExitCode = ErrorExitCode;
|
|
|
|
|
return;
|
2022-03-09 22:42:40 +01:00
|
|
|
|
}
|
|
|
|
|
|
2022-03-11 16:32:53 +01:00
|
|
|
|
if (multiple)
|
|
|
|
|
{
|
|
|
|
|
var prompt = new MultiSelectionPrompt<FileInfo>()
|
|
|
|
|
.Title("Select scripts")
|
|
|
|
|
.NotRequired()
|
|
|
|
|
.PageSize(ScriptListSize)
|
|
|
|
|
.MoreChoicesText("[grey]Move up and down to reveal more options[/]")
|
|
|
|
|
.InstructionsText("[grey](Press [blue]<space>[/] to toggle a script, [green]<enter>[/] to accept)[/]")
|
|
|
|
|
.AddChoices(files);
|
|
|
|
|
|
|
|
|
|
var scripts = AnsiConsole.Prompt(prompt);
|
|
|
|
|
|
|
|
|
|
scripts.ForEach(ScriptExecutor.Exec);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
var prompt = new SelectionPrompt<FileInfo>()
|
2022-03-09 22:42:40 +01:00
|
|
|
|
.Title("Select a script")
|
2022-03-11 16:32:53 +01:00
|
|
|
|
.PageSize(ScriptListSize)
|
|
|
|
|
.MoreChoicesText("[grey]Move up and down to reveal more options[/]")
|
|
|
|
|
.AddChoices(files);
|
2022-03-09 22:42:40 +01:00
|
|
|
|
|
2022-03-11 16:32:53 +01:00
|
|
|
|
var script = AnsiConsole.Prompt(prompt);
|
2022-03-09 22:42:40 +01:00
|
|
|
|
|
2022-03-11 16:32:53 +01:00
|
|
|
|
ScriptExecutor.Exec(script);
|
|
|
|
|
}
|
2022-03-09 22:42:40 +01:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static class ScriptExecutor
|
|
|
|
|
{
|
2022-03-11 16:32:53 +01:00
|
|
|
|
internal static void Exec(FileInfo file)
|
2022-03-09 22:42:40 +01:00
|
|
|
|
{
|
|
|
|
|
var info = new ProcessStartInfo
|
|
|
|
|
{
|
|
|
|
|
FileName = "powershell.exe",
|
2022-03-11 16:32:53 +01:00
|
|
|
|
Arguments = $"-File {file.FullName}",
|
2022-03-09 22:42:40 +01:00
|
|
|
|
UseShellExecute = false,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
Exec(info);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
internal static void Exec(ProcessStartInfo info) => Process.Start(info)?.WaitForExit();
|
|
|
|
|
}
|
|
|
|
|
|
2022-03-11 16:32:53 +01:00
|
|
|
|
readonly struct ScriptFinder
|
2022-03-09 22:42:40 +01:00
|
|
|
|
{
|
2022-03-11 16:32:53 +01:00
|
|
|
|
public string RootFolder { get; init; } = ".";
|
|
|
|
|
public string[] Extensions { get; init; } = new[] { "ps1", "*sh", "bat", "cmd" };
|
|
|
|
|
public int Depth { get; init; } = 0;
|
2022-03-09 22:42:40 +01:00
|
|
|
|
|
|
|
|
|
private readonly EnumerationOptions _options;
|
|
|
|
|
|
|
|
|
|
public ScriptFinder()
|
|
|
|
|
{
|
|
|
|
|
_options = new EnumerationOptions
|
|
|
|
|
{
|
|
|
|
|
IgnoreInaccessible = true,
|
|
|
|
|
RecurseSubdirectories = Depth > 0,
|
|
|
|
|
MaxRecursionDepth = Depth,
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
2022-03-11 16:32:53 +01:00
|
|
|
|
internal readonly FileInfo[] GetScriptFiles(string extension)
|
2022-03-09 22:42:40 +01:00
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
var filenames = Directory.GetFiles(RootFolder, $"*.{extension}", _options);
|
|
|
|
|
return filenames.Select(x => new FileInfo(x)).ToArray();
|
|
|
|
|
}
|
|
|
|
|
catch (UnauthorizedAccessException)
|
|
|
|
|
{
|
|
|
|
|
return Array.Empty<FileInfo>();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-03-11 16:32:53 +01:00
|
|
|
|
internal readonly FileInfo[] GetScriptFiles() =>
|
|
|
|
|
Extensions.Select(GetScriptFiles).SelectMany(x => x).ToArray();
|
2022-03-09 22:42:40 +01:00
|
|
|
|
}
|