What do all Connect- Cmdlets have in common?

Writing a PowerShell Connect- Cmdlet

There are a lot of custom system integrations here at my new workplace, and almost all of them are written as .NET apps running either from the command line or in one of several Hangfire instances. It's kind of opaque and feels like overkill for the simpler stuff, so I've been working on migrating them to simple PowerShell scripts.

One of the services we integrate with is Moodle, an open-source learning management system (LMS). It has some pretty nice web service endpoints that we can call with Invoke-RestMethod, but I didn't want to have to pass a URI and token to every single PowerShell command that talks to a Moodle instance.

Enter the Connect-Moodle Cmdlet.

Those of you who have worked with PowerShell modules that connect to services will recognise the Connect-* Cmdlet syntax. For example, the Azure Active Directory module has a Connect-AzureAD Cmdlet. You call it once and it prompts for credentials, then saves them away so that every subsequent call to the same module can use those credentials.

So how do they work? How do you persist credentials inside of a PowerShell module so that all the other Cmdlets can access them? I asked on the TechNet PowerShell forum and was told by a rather unhelpful moderator that Connect- Cmdlets are all unique and have nothing in common, but that's simply not true.

The secret is PowerShell's PSCmdLet.SessionState property. It's basically somewhere you can store state so that other Cmdlets in the same module can access it. From a script module, you can get to it using $PsCmdlet.SessionState.

So here's an example. In my Connect-Moodle Cmdlet, one of the parameter sets I can accept is a URL and a raw Token to use in subsequent calls. I make an arbitrary call to the Moodle instance to verify that the token is valid, then save them away like this:

$PsCmdlet.SessionState.PSVariable.Set("_MoodleUrl", $Url)
$PsCmdlet.SessionState.PSVariable.Set("_MoodleToken", $Token)

Then in other Cmdlets I can do this at the top of the function:

$Url = $PsCmdlet.SessionState.PSVariable.GetValue("_MoodleUrl")
$Token = $PsCmdlet.SessionState.PSVariable.GetValue("_MoodleToken")

Hopefully this helps point someone else in the right direction if they're trying to create a PowerShell module that connects to a service and persists state.

Posted by: Matt Hamilton
Last revised: 15 Dec, 2019 11:55 PM History

Comments

No comments yet. Be the first!

No new comments are allowed on this post.