PowerShell cmdlets can be written in C# by inheriting either form the Cmdlet
class or the PSCmdlet
class. In short, the difference between both classes are the level of dependence to the PowerShell runspace. The Cmdlet
-class is less tighly coupled to the PowerShell runspace, than the PSCmdlet
class. A more in-depth comparison between both classes can be found here.
One important difference between both classes are the requirements for automated testing. The Cmdlet
class can be easily invoked in C#, while the PSCmdlet
class requires to be run in a PowerShell runspace. A great description about the two testing variations can be found in the course by Nathan Honeycutt "PowerShell Cmdlet Development in C# - The Ins and Outs".
In general, I use for automated testing the XUnit framework.
[Fact]
public void ConvertJWTTest()
{
//-- Arrange
var jwt = "{imaging long JWT string}";
# You create a variable containing the Cmdlet.
var cmdlet = new ConvertFromJWTCmdlet()
{
JWT = jwt
};
//-- Act
# When invoking the cmdlet, the return will always be an IEnumerable.
var actual = cmdlet.Invoke().OfType<Hashtable>().ToList();
//-- Assert
Assert.IsType<Hashtable>(actual[0]);
}
The PSCmdlet
class requires a PowerShell runspace to run the commands.
[Fact]
public void NewJWTHMAC()
{
//-- Arrange
var secret = "GQDstcKsx0NHjPOuXOYg5MbeJ1XT0uFiwDVvVBrk";
var claim = new Hashtable()
{
{ "name", "DigitalAXPP" },
{ "age", 21},
{ "date", DateTimeOffset.Now.AddHours(3).ToUnixTimeSeconds() }
};
var regex = @"(^[\w-]*\.[\w-]*\.[\w-]*$)";
# Creating your initial session, plus adding the to-be tested cmdlet
var initialSessionState = InitialSessionState.CreateDefault();
initialSessionState.Commands.Add(
new SessionStateCmdletEntry("New-JWT", typeof(NewJWTCmdlet), null)
);
# Creating the runspace and opening a PowerShell session
using (var runspace = RunspaceFactory.CreateRunspace(initialSessionState))
{
runspace.Open();
using (var powershell = PowerShell.Create())
{
powershell.Runspace = runspace;
//-- Act
# Starting the command and adding all required arguments, plus eventually invoking the cmdlet
var newJWTCommand = new Command("New-JWT");
newJWTCommand.Parameters.Add("Secret", secret);
newJWTCommand.Parameters.Add("Payload", claim);
newJWTCommand.Parameters.Add("Algorithm", Algorithm.HS512);
powershell.Commands.AddCommand(newJWTCommand);
var result = powershell.Invoke<string>();
//-- Assert
Assert.IsType<string>(result[0]);
Assert.Matches(regex, result[0]);
}
}
}