feat: add Cake build to produce powershell module (#2)
- Add Cake build project - Change to CPM - Package bumps for security bumps - Reorganise solution structure to group harness projects
This commit is contained in:
parent
274d279732
commit
ecb0a20cbb
27 changed files with 267 additions and 58 deletions
145
src/PowershellHarness/Program.cs
Normal file
145
src/PowershellHarness/Program.cs
Normal file
|
|
@ -0,0 +1,145 @@
|
|||
using System.Management.Automation;
|
||||
using System.Management.Automation.Runspaces;
|
||||
using System.Text;
|
||||
using PowershellModule.Calendar;
|
||||
|
||||
namespace PowershellHarness;
|
||||
|
||||
// https://github.com/FuseCP/FuseCP/blob/278a19dc06949600f25a1b4ed74d0419a8fa3fc2/FuseCP/Sources/FuseCP.Providers.HostedSolution.SfB2015/SfBBase.cs#L224
|
||||
// some useful code in here tbh
|
||||
class Program
|
||||
{
|
||||
static void Main(string[] args)
|
||||
{
|
||||
// I've gotta work out how to get the rider terminal to act closer to powershell because .PadLeft in powershell
|
||||
// will correctly output lines when output with WriteOutput, but the Jetbrains debug worker (or whatever
|
||||
// it is that rider spawns), has none of that and operates in its own world.
|
||||
// Which is fine if you never want new lines.
|
||||
// Ideally you'd just launch pwsh.exe and attach to that, but _that_ has its own issues as well.
|
||||
// The new line issue might be related to how I've set up the host seeing as I just did a bunch of copy paste shit
|
||||
// from something I found on github to get it across the line so I could debug it.
|
||||
// I'll eventually revisit those hosts and rewrite them properly once I start adding more commands, and if I care.
|
||||
// Threads & variables has all the visuals I need after all.
|
||||
#if DEBUG
|
||||
if (!System.Diagnostics.Debugger.IsAttached)
|
||||
{
|
||||
Console.BackgroundColor = ConsoleColor.Yellow;
|
||||
Console.WriteLine(CenterText("Running without a debugger attached may result in lines not being output correctly"));
|
||||
Console.ResetColor();
|
||||
}
|
||||
#endif
|
||||
Console.WriteLine(CenterText(" PowerShell Debug Harness "));
|
||||
Console.WriteLine($"Reported console window size: {Console.WindowWidth}x{Console.WindowHeight}");
|
||||
Console.WriteLine($"Reported console buffer size: {Console.BufferWidth}x{Console.BufferHeight}");
|
||||
Console.WriteLine(CenterText(" WIDTH ", '-'));
|
||||
|
||||
var host = new CustomHost(Console.WindowWidth);
|
||||
var runspace = InitialisePowershellHost(host);
|
||||
|
||||
// InvokeCommand(runspace, GetCalendarCommand.FullName);
|
||||
|
||||
foreach (var day in Enum.GetValues<DayOfWeek>())
|
||||
{
|
||||
InvokeCommand(runspace, GetCalendarCommand.FullName, [
|
||||
CreateCommand(nameof(GetCalendarCommand.MarkedDaySymbol), "faker"),
|
||||
CreateCommand(nameof(GetCalendarCommand.StartOfWeek), day.ToString()),
|
||||
CreateCommand(nameof(GetCalendarCommand.Date), "22/6/26"),
|
||||
// CreateCommand(nameof(GetCalendarCommand.AlignRight))
|
||||
]);
|
||||
}
|
||||
|
||||
// InvokeCommand(runspace, GetCalendarCommand.FullName, [
|
||||
// new CommandParameter(nameof(GetCalendarCommand.MarkedDaySymbol), "🤫"),
|
||||
// new CommandParameter(nameof(GetCalendarCommand.StartOfWeek), DayOfWeek.Saturday)
|
||||
// ]);
|
||||
// InvokeCommand(runspace, GetCalendarCommand.FullName, [new CommandParameter(nameof(GetCalendarCommand.StartOfWeek), "Sunday")]);
|
||||
}
|
||||
|
||||
private static CommandParameter CreateCommand(string name, string? argument = null)
|
||||
{
|
||||
if (argument is not null)
|
||||
{
|
||||
return new CommandParameter(name, argument);
|
||||
}
|
||||
|
||||
return new CommandParameter(name);
|
||||
}
|
||||
|
||||
static string CenterText(string text, char paddingChar = ' ')
|
||||
{
|
||||
return text.PadLeft((Console.WindowWidth + text.Length) / 2, paddingChar).PadRight(Console.WindowWidth, paddingChar);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initialises a PowerShell session and returns an open Runspace
|
||||
/// </summary>
|
||||
/// <param name="host"></param>
|
||||
/// <returns></returns>
|
||||
static Runspace InitialisePowershellHost(CustomHost host)
|
||||
{
|
||||
// Create the initial session state for the host. Yes, that 2 on the end does indicate that the underlying
|
||||
// implementation for this is C++
|
||||
// Welcome to the lands of fuck all documentation and figuring shit out from an increasingly shit internet
|
||||
// where finding non-slop answers gets harder by the day as people close sources of information to prevent
|
||||
// scraping. Fuck every single person involved modern AI.
|
||||
// It wasn't much better finding documentation about the System.Management.* namespace before that, but it's
|
||||
// definitely a lot worse because of it
|
||||
var initialSessionState = InitialSessionState.CreateDefault2();
|
||||
|
||||
|
||||
// No idea what the helpFileName should be. As is common with _a lot_ of the System.Management.* namespace,
|
||||
// fuck all is actually documented with comments, or documented at all!
|
||||
// From https://learn.microsoft.com/en-us/powershell/scripting/developer/hosting/creating-a-constrained-runspace?view=powershell-7.6
|
||||
// (which yes, this section _is_ under a legacy category!), it's perfectly fine to leave it as null.
|
||||
// We also don't really care as we're just doing this so we can test commands without having to deal with Rider
|
||||
// and it's quirks around runnning a powershell terminal and attaching to it. Yeah it technically works, but
|
||||
// it's way too common to end up with Rider refusing to build correctly or ensure the right dll is used for the module
|
||||
var getCalendarCommand = new SessionStateCmdletEntry(GetCalendarCommand.FullName, typeof(GetCalendarCommand), null);
|
||||
initialSessionState.Commands.Add(getCalendarCommand);
|
||||
|
||||
// Create a runspace from the state, open and return it
|
||||
var runspace = RunspaceFactory.CreateRunspace(host, initialSessionState);
|
||||
|
||||
// A runspace is technically disposable, but we're not reimplementing a full host and we won't be doing anything
|
||||
// that would require a fresh runspace multiple times over (yet), so we can just treat the lifetime of the
|
||||
// disposable as application lifetime
|
||||
runspace.Open();
|
||||
|
||||
return runspace;
|
||||
}
|
||||
|
||||
static void InvokeCommand(Runspace runspace, string command, IEnumerable<CommandParameter>? parameters = null)
|
||||
{
|
||||
// Not too sure on the difference of runspace vs PowerShell here. Doesn't seem to make a difference either way
|
||||
// and this is just a debug harness so it doesn't really matter for now
|
||||
using var pipeline = runspace.CreatePipeline();
|
||||
// using var powershell = PowerShell.Create(runspace);
|
||||
|
||||
var cmd = new Command(command);
|
||||
if (parameters is not null)
|
||||
{
|
||||
foreach (var commandParameter in parameters)
|
||||
{
|
||||
cmd.Parameters.Add(commandParameter);
|
||||
}
|
||||
}
|
||||
|
||||
pipeline.Commands.Add(cmd);
|
||||
// powershell.Commands.AddCommand(cmd);
|
||||
|
||||
try
|
||||
{
|
||||
var results = pipeline.Invoke();
|
||||
// var results = powershell.Invoke();
|
||||
foreach (var result in results)
|
||||
{
|
||||
Console.Write(result);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.Error.WriteLine($"Unable to execute command {command}");
|
||||
Console.Error.WriteLine(ex.GetBaseException().Message);
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue