Keb
Keb

Reputation: 113

Custom Powershell Cmdlet - Create hidden accessible variable

I'm working on a custom Powershell Cmdlet for accessing a REST webservice.
The webservice requires me to authenticate, and when i do it returns a authenticaton-token that i have to include in every request after that.

The problem I am facing is that I am unable to store the token in a desired manner so i can use it with ease in commands after the authentication.

I would like if it could work in the same way as Connect-MSOLService work.
For those unfamiliar with the Office 365 cmdlets i will give some examples.

Office 365 Cmdlets

$Credentials = Get-Credential
Connect-MSOLService -Credential $Credentials
Get-MSOLUser

In this example the Get-MSOLUser will return every Office 365 user, because the Connect-MSOLService have been called before hand.

My Cmdlet

$Credentials = Get-Credential
$token = Connect-WebService -Credential $Credentials
Get-Server -token $token
Get-Client -token $token

As you can see, I have to return the token and store it in a variable and use it in every call i do after the authentication.

So that leads me to my question, how can i "inject" the token into the Powershell session and use it "under-the-hood" on every command in my cmdlet/module after that?

Thank you for your time.

Upvotes: 2

Views: 1664

Answers (3)

hsimah
hsimah

Reputation: 1303

If using the PowerShell 5.0 assembly you can inherit from PSCmdlet and use SessionState to store variables.

private string const variableName = "MyVar";
private Token token = new Token("your token");
SessionState.PSVariable.Set(new PSVariable(variableName, token, ScopedItemOptions.Private));

You then use GetValue() to retrieve it.

Token storedToken = (Token)SessionState.PSVariable.GetValue(variableName);

This variable is not available to the PowerShell session but will persist between cmdlet calls. I use it to store an API token on the first query, and to reuse it until it expires or the session is closed.

Upvotes: 1

Keith Hill
Keith Hill

Reputation: 201622

You have to be careful about storing the token in a process wide variable as it is possible to have multiple PowerShell runspaces running in the same process. However, what you could do is create a static reference to a Dictionary that stashes the token for the runspace in which the cmdlet is running. You can get the runspace ID like so:

Guid runspaceId = Guid.Empty;
using (var ps = PowerShell.Create(RunspaceMode.CurrentRunspace))
{
    runspaceId = ps.Runspace.InstanceId;
}

Then create a static class with a static readonly field like so:

public static class TokenUtil {
    public static readonly Dictionary<Guid,PSObject> Tokens = new Dictionary<Guid,PSObject>();
}

Check for existing token for this runspace like so:

PSObject token = null;
if (TokenUtil.Tokens.ContainsKey(runspaceId))
{
    token = TokenUtil.Tokens[runspaceId];
}

Upvotes: 2

Stanley De Boer
Stanley De Boer

Reputation: 5241

I don't know how Microsoft does it, but I think one way to do it is like this:

function Connect-WebService {
   param($credential)

   #Do all of the connection here


   #Set the global variable so it will be available outside of this function
   $script:token = ...
}

function Get-Server {
   param(
      $token = $script:token # By default use the globally set $token variable
  )
}

This way would work if you are doing everything in a PowerShell module.

Upvotes: 0

Related Questions