PowerShell Modules - Storing state for connections
05 Jun 2018Following on from my recent module writing work, i’ve been using a little trick in some of my PowerShell modules to store a small amount of state that persists as long as the module is loaded. I’ve been primarily using this strategy as a way to manage connections for SharePoint and REST services.
My example here is a small one derived loosely from a SharePoint Client-Side Object Model (CSOM) module I use and maintain. Essentially, in the module .psm1 file the variable is defined and then used by a couple of functions to set, get and clear the connection data using the $script:variable
scoping, as shown below:
Note: You need the SharePoint Online PowerShell module for the SharePoint DLLs!
$Assemblies = @(
"$env:ProgramFiles\SharePoint Online Management Shell\Microsoft.Online.SharePoint.PowerShell\Microsoft.SharePoint.Client.dll"
"$env:ProgramFiles\SharePoint Online Management Shell\Microsoft.Online.SharePoint.PowerShell\Microsoft.SharePoint.Client.Runtime.dll"
"$env:ProgramFiles\SharePoint Online Management Shell\Microsoft.Online.SharePoint.PowerShell\Microsoft.Online.SharePoint.Client.Tenant.dll"
)
Add-Type -Path $Assemblies -Verbose
# SharePoint connection states
[System.Diagnostics.CodeAnalysis.SuppressMessage('PSUseDeclaredVarsMoreThanAssigments', '')]
$Connection = New-Object System.Collections.ArrayList
Function Connect-SharePoint {
[CmdletBinding()]
Param (
[Parameter(Mandatory)]
[PSCredential]
$Credential,
[Parameter(Mandatory)]
[string]
$Uri,
[parameter()]
[switch]
$PassThru
)
# Login
$SPContext = New-Object Microsoft.SharePoint.Client.ClientContext($Uri)
$SPContext.Credentials = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials(
$Credential.UserName,
$Credential.Password
)
try {
$SPContext.ExecuteQuery()
$null = $Script:Connection.Add($SPContext)
if ($PassThru) {
$SPContext
}
}
catch {
Write-Error "Error connecting to SharePoint."
}
}
Function Get-SharePointConnection {
[CmdletBinding()]
Param (
[parameter()]
[string]
$Site
)
if ($Site) {
$Script:Connection | Where-Object -Property URL -eq -Value $Site
}
else {
$Script:Connection
}
}
Function Disconnct-SharePoint {
[CmdletBinding(DefaultParameterSetName = 'Site')]
Param (
[Parameter(
Mandatory,
ParameterSetName = 'Site'
)]
[string]
$Site,
[Parameter(
ParameterSetName = 'All'
)]
[switch]
$All
)
if ($PSCmdlet.ParameterSetName -eq 'Site') {
$Disconnect = Get-SharePointConnection -Site $Site
if ($Disconnect) {
$Script:Connection.Remove($Disconnect)
}
else {
throw "No connection for site $Site found."
}
}
if ($PSCmdlet.ParameterSetName -eq 'All') {
$Script:Connection = New-Object System.Collections.ArrayList
}
}
Anyways, hopefully this helps for managing connections, REST auth tokens and a few other little scenarios. I’d be wary of using this approach too often for things like modifying function or module states, as it’s not really the one function for a job (the UNIX way) most PowerShell users might expect.