Simple Simple Microsoft Crescendo Example Part II

The Microsoft.PowerShell.Crescendo module is mostly brand new. It’s still early on in its development. It’s currently at version 0.4.1. This isn’t my first discussion on this topic, so please read Part I on this topic. That’ll give you an idea of my first experience working with the module. In that post, we created a PowerShell module that contained a single command that wrapped the mstsc.exe Remote Desktop Connection executable. Although there are several, I only wrote it with a single parameter: a stand-in for /v. This parameter expects the name of the computer or IP address, such as mstsc /v Server01.

In that example I copied, pasted, and edited an existing *.Crescendo.json file. Today, we’ll wrap the same command (even though I alluded to using something else), however, we’ll do it using other cmdlets from the module. These will include New-CrescendoCommand, New-ParameterInfo, New-UsageInfo, and New-ExampleInfo. I had no idea what these were for as the help is limited, but I think I figured it out for now. If you know more, then of course you’re welcome to comment and participate.

In the first example, we invoked New-CrescendoCommand. The available parameters at the time of this writing are -Verb and -Noun. Knowing those parameters, it’s straightforward what this was about. This is the naming for our new PowerShell command. As you can see, I supplied Connect and RemoteComputer, respectively. These are the same values that we supplied in Part I of this series. As you can likely tell, the command creates an object (a [TypeName] Command object to be exact). We send that object to ConvertTo-Json, as we’ll need everything in JSON before creating our mstsc.Crescendo.json file. As you can also tell, the object — both the PowerShell object and JSON object — has several other properties. As best as I could determine, there was no way to include these when invoking the New-CrescendoCommand. Do notice that the OriginalName property is blank and that there wasn’t a way to include that when invoking the command. We’ll be back to discuss this later.

[PS7.1.0] $Command = New-CrescendoCommand -Verb Connect -Noun RemoteComputer
[PS7.1.0] $Command

Verb : Connect
Noun : RemoteComputer
OriginalName :
OriginalCommandElements :
Aliases :
DefaultParameterSetName :
SupportsShouldProcess : False
SupportsTransactions : False
NoInvocation : False
Description :
Usage :
Parameters : {}
Examples : {}
OriginalText :
HelpLinks :
OutputHandlers :

[PS7.1.0] $Command = $Command | ConvertTo-Json
[PS7.1.0] $Command
{
  "Verb": "Connect",
  "Noun": "RemoteComputer",
  "OriginalName": null,
  "OriginalCommandElements": null,
  "Aliases": null,
  "DefaultParameterSetName": null,
  "SupportsShouldProcess": false,
  "SupportsTransactions": false,
  "NoInvocation": false,
  "Description": null,
  "Usage": null,
  "Parameters": [],
  "Examples": [],
  "OriginalText": null,
  "HelpLinks": null,
  "OutputHandlers": null
}

In this code example, we essentially do the same thing. We create a PowerShell object and then convert it to JSON. This is the addition of a new parameter.

[PS7.1.0] $Parameter = New-ParameterInfo -Name ComputerName -OriginalName /v
[PS7.1.0] $Parameter

ParameterType                   : object
Position                        : 2147483647
Name                            : ComputerName
OriginalName                    : /v
OriginalText                    :
Description                     :
DefaultValue                    :
DefaultMissingValue             :
AdditionalParameterAttributes   :
Mandatory                       : False
ParameterSetName                :
Aliases                         :
OriginalPosition                : 0
ValueFromPipeline               : False
ValueFromPipelineByPropertyName : False
ValueFromRemainingArguments     : False
NoGap                           : False

[PS7.1.0] $Parameter = $Parameter | ConvertTo-Json
[PS7.1.0] $Parameter
{
  "ParameterType": "object",
  "Position": 2147483647,
  "Name": "ComputerName",
  "OriginalName": "/v",
  "OriginalText": null,
  "Description": null,
  "DefaultValue": null,
  "DefaultMissingValue": null,
  "AdditionalParameterAttributes": null,
  "Mandatory": false,
  "ParameterSetName": null,
  "Aliases": null,
  "OriginalPosition": 0,
  "ValueFromPipeline": false,
  "ValueFromPipelineByPropertyName": false,
  "ValueFromRemainingArguments": false,
  "NoGap": false
}

And in this code example, we essentially do the same thing, too. This PowerShell object converted to JSON has to do with Usage. I’m still working that one over in my mind, but we’ll take a closer look.

[PS7.1.0] $Usage = New-UsageInfo -usage 'Runs Remote Desktop Connection'
[PS7.1.0] $Usage

Synopsis                       SupportsFlags HasOptions
--------                       ------------- ----------
Runs Remote Desktop Connection False         False

[PS7.1.0] $Usage = $Usage | ConvertTo-Json
[PS7.1.0] $Usage
{
  "Synopsis": "Runs Remote Desktop Connection",
  "SupportsFlags": false,
  "HasOptions": false,
  "OriginalText": null
}

Finally, we create a comment-based help example and ensure it’s in the JSON format.

[PS7.1.0] $Example = New-ExampleInfo -command Connect-RemoteComputer -originalCommand 'C:\Windows\System32\mstsc.exe' -description 'Wraps Remote Desktop Connection' 
[PS7.1.0] $Example

Command                OriginalCommand               Description
-------                ---------------               -----------
Connect-RemoteComputer C:\Windows\System32\mstsc.exe Wraps Remote Desktop Connection

[PS7.1.0] $Example = $Example | ConvertTo-Json
[PS7.1.0] $Example
{
  "Command": "Connect-RemoteComputer",
  "OriginalCommand": "C:\\Windows\\System32\\mstsc.exe",
  "Description": "Wraps Remote Desktop Connection"
}

Next, we have to manually put these pieces of JSON together into our single, mstsc.Crescendo.json file. Let’s do that next. We’ll begin with the Parameter JSON we created and add to it the Command JSON. In the Command JSON section, we had an entry that said "Parameters": [], In between the square brackets, we have to add the Parameter JSON. This has been done below.

{
    "Verb": "Connect",
    "Noun": "RemoteComputer",
    "OriginalName": null,
    "OriginalCommandElements": null,
    "Aliases": null,
    "DefaultParameterSetName": null,
    "SupportsShouldProcess": false,
    "SupportsTransactions": false,
    "NoInvocation": false,
    "Description": null,
    "Usage": null,
    "Parameters": [
        {
            "ParameterType": "object",
            "Position": 2147483647,
            "Name": "ComputerName",
            "OriginalName": "/v",
            "OriginalText": null,
            "Description": null,
            "DefaultValue": null,
            "DefaultMissingValue": null,
            "AdditionalParameterAttributes": null,
            "Mandatory": false,
            "ParameterSetName": null,
            "Aliases": null,
            "OriginalPosition": 0,
            "ValueFromPipeline": false,
            "ValueFromPipelineByPropertyName": false,
            "ValueFromRemainingArguments": false,
            "NoGap": false
        }
    ],
    "Examples": [],
    "OriginalText": null,
    "HelpLinks": null,
    "OutputHandlers": null
}

Next, we’ll add our Usage JSON to its place in our mstsc.Crescendo.json file

{
    "Verb": "Connect",
    "Noun": "RemoteComputer",
    "OriginalName": null,
    "OriginalCommandElements": null,
    "Aliases": null,
    "DefaultParameterSetName": null,
    "SupportsShouldProcess": false,
    "SupportsTransactions": false,
    "NoInvocation": false,
    "Description": null,
    "Usage": {
        "Synopsis": "Runs Remote Desktop Connection",
        "SupportsFlags": false,
        "HasOptions": false,
        "OriginalText": null
    },
    "Parameters": [
        {
            "ParameterType": "object",
            "Position": 2147483647,
            "Name": "ComputerName",
            "OriginalName": "/v",
            "OriginalText": null,
            "Description": null,
            "DefaultValue": null,
            "DefaultMissingValue": null,
            "AdditionalParameterAttributes": null,
            "Mandatory": false,
            "ParameterSetName": null,
            "Aliases": null,
            "OriginalPosition": 0,
            "ValueFromPipeline": false,
            "ValueFromPipelineByPropertyName": false,
            "ValueFromRemainingArguments": false,
            "NoGap": false
        }
    ],
    "Examples": [],
    "OriginalText": null,
    "HelpLinks": null,
    "OutputHandlers": null
}

And finally, we’ll add our Example JSON.

{
    "Verb": "Connect",
    "Noun": "RemoteComputer",
    "OriginalName": null,
    "OriginalCommandElements": null,
    "Aliases": null,
    "DefaultParameterSetName": null,
    "SupportsShouldProcess": false,
    "SupportsTransactions": false,
    "NoInvocation": false,
    "Description": null,
    "Usage": {
        "Synopsis": "Runs Remote Desktop Connection",
        "SupportsFlags": false,
        "HasOptions": false,
        "OriginalText": null
    },
    "Parameters": [
        {
            "ParameterType": "object",
            "Position": 2147483647,
            "Name": "ComputerName",
            "OriginalName": "/v",
            "OriginalText": null,
            "Description": null,
            "DefaultValue": null,
            "DefaultMissingValue": null,
            "AdditionalParameterAttributes": null,
            "Mandatory": false,
            "ParameterSetName": null,
            "Aliases": null,
            "OriginalPosition": 0,
            "ValueFromPipeline": false,
            "ValueFromPipelineByPropertyName": false,
            "ValueFromRemainingArguments": false,
            "NoGap": false
        }
    ],
    "Examples": [
        {
            "Command": "Connect-RemoteComputer",
            "OriginalCommand": "C:\\Windows\\System32\\mstsc.exe",
            "Description": "Wraps Remote Desktop Connection"
        }
    ],
    "OriginalText": null,
    "HelpLinks": null,
    "OutputHandlers": null
}

I don’t think it’s there yet, but one day there will likely be a command that does all this for us. Maybe there already is and somehow I’ve overlooked it. With this JSON created and saved as mstsc.Crescendo.json, we can attempt to use it with Export-CrescendoModule as we did in Part I.

[PS7.1.0] Export-CrescendoModule -ConfigurationFile 'C:\Users\tommymaynard\Documents\PowerShell\Modules\Microsoft.PowerShell.Crescendo\0.4.1\Samples\mstsc.Crescendo.json' -ModuleName 'RemoteComputer.psm1'

If you try this, you’ll notice it fails.

This is because the New-CrescendoCommand didn’t include an OriginalName parameter and therefore our JSON didn’t include a much-needed value. Without it, the command doesn’t point to an existing command on the computer, which becomes the reason behind the above error message. Even though it throws an error, it still creates the file (although it’s missing much of the good stuff). You’ll have to remove the file or you’ll get another error about the file already existing.

Our JSON ends up with this: “OriginalName”: null, instead of this: “OriginalName”:”/Windows/System32/mstsc.exe”,. As you can see below, I’ve added this in, so the code here is complete.

{
    "Verb": "Connect",
    "Noun": "RemoteComputer",
    "OriginalName": "/Windows/System32/mstsc.exe",
    "OriginalCommandElements": null,
    "Aliases": null,
    "DefaultParameterSetName": null,
    "SupportsShouldProcess": false,
    "SupportsTransactions": false,
    "NoInvocation": false,
    "Description": null,
    "Usage": {
        "Synopsis": "Runs Remote Desktop Connection",
        "SupportsFlags": false,
        "HasOptions": false,
        "OriginalText": null
    },
    "Parameters": [
        {
            "ParameterType": "object",
            "Position": 2147483647,
            "Name": "ComputerName",
            "OriginalName": "/v",
            "OriginalText": null,
            "Description": null,
            "DefaultValue": null,
            "DefaultMissingValue": null,
            "AdditionalParameterAttributes": null,
            "Mandatory": false,
            "ParameterSetName": null,
            "Aliases": null,
            "OriginalPosition": 0,
            "ValueFromPipeline": false,
            "ValueFromPipelineByPropertyName": false,
            "ValueFromRemainingArguments": false,
            "NoGap": false
        }
    ],
    "Examples": [
        {
            "Command": "Connect-RemoteComputer",
            "OriginalCommand": "C:\\Windows\\System32\\mstsc.exe",
            "Description": "Wraps Remote Desktop Connection"
        }
    ],
    "OriginalText": null,
    "HelpLinks": null,
    "OutputHandlers": null
}

Have fun and keep watching for newer versions. I suspect I will.

2 thoughts on “Simple Simple Microsoft Crescendo Example Part II

  1. Ross Walker

    You can assign Usage, Parameters and Examples to the original Command object and then convert the whole thing to Json, and export it:

    $Command = New-CresendoCommand
    $Command.Usage = New-UsageInfo
    $Command.Parameters = New-ParameterInfo
    $Command.Examples = New-ExampleInfo

    $Command | ConvertTo-Json | Export-CresendoModule

    Reply
    1. tommymaynard Post author

      Hi Ross! I approved your comment long ago — thank you for writing it! As I may prepare some more content regarding Crescendo I ended up rereading it. I think it will be helpful. I will be sure to try it at least!

      Reply

Leave a Reply

Your email address will not be published. Required fields are marked *