Automation–Service Management Automation Tip/Trick–Leveraging InlineScript and $Using:Variable with PowerShell Workflow

Automation–Service Management Automation Tip/Trick–Leveraging InlineScript and $Using:Variable with PowerShell Workflow

  • Comments 6
  • Likes

A question came up on a recent SMA blog post Automation–Service Management Automation Runbook Spotlight–Exchange Distribution List Creation and the answer deserves its own blog post. Understanding the underlying moving parts of why we do what we do in SMA is just as important as the development of knowledge we provide through examples.  Some concepts were taken for granted in the post referenced above that I wanted to dive into a little bit and provide more reading for those that need further detail.


What Question are we Trying to Answer?

Q: Stijn asks: I was wondering why you use the $pscomputername and $pscredential parameters of the inline script. In the inlinescript activity you use the $using scope modifier to access the variables exchangeserver and credentials.

Could you elaborate? thanks

And more specifically

Why use remoting twice?

Once for executing the inlinescript on the exchange server and then creating a session to the same exchange server?

Well, first – thank you!  Since PowerShell Workflow is so new and the details on how you use it are not always obvious, and since SMA uses PowerShell workflow, our examples are all about how you can use workflow within the realms of SMA to get your automation done from end to end. These types of questions are great and key to pushing the envelope of understanding. 

A: In this post, we’re going to dive into some of the specifics around why we use InlineScript and $Using:Variable configurations in our examples to get the data we need.  I’ll use this post Automation–Service Management Automation Runbook Spotlight–Exchange Distribution List Creation as a reference to explain these details so we close the gap on the initial question that came up.

Initialize the Variables

At our top level process Runbook (Build-Exchange-Distribution-List) we instantiate a handful of variables that can be used throughout the processing of subroutine Runbooks. The two variables referenced below are leveraged for making connections directly to the Exchange server via an InlineScript for our example solution. 

001
002
$PSCredName = "Contoso Creds"
$ExchangeServer = "EX01"

Note      $PSCredName is actually referencing a string "Contoso Creds" which is a name of an SMA Credential object that has been created/stored in the SMA database and can be leveraged by name within our SMA Runbooks to make credential management easier.  $ExchangeServer is obviously the Exchange server we'll be connecting to (EX01).

Leveraging the Initialized Variables when Calling Sub Runbooks

Following the example provided in the post, we execute a subroutine Runbook called Create-Exchange-Distribution-List to execute the logic for the creation of our DL from our process Runbook Build-Exchange-Distribution-List.

001
002
003
$DLCreated = Create-Exchange-Distribution-ListDistributionListName `
    $DistributionListName -DLOU $DLOU -DomainFQDN $DomainFQDN `
    -ExchangeServer $ExchangeServer -PSCredName $PSCredName

Parameters in Subroutine Runbooks within SMA

Skipping way ahead and diving into a subroutine Runbook (Get-Exchange-Distribution-List), we then leverage the top level variables defined as parameters sent to the subroutine Runbooks similar to the below example:

001
002
003
004
005
006
 param(
 [string]$ExchangeServer,
 [string]$DomainFQDN,
 [string]$DistributionListName,
 [string]$PSCredName
 )

Then within the subroutine Runbook we leverage the SMA cmdlet Get-AutomationPSCredential leveraging (by name) the $PSCredName to retrieve the credentials and store them in a credential variable to be used by this Runbook for this session.

001
$PSUserCred = Get-AutomationPSCredential -Name $PSCredName

Now, using the subroutine Runbook Get-Exchange-Distribution-List as an example, we need to determine if an Exchange DL actually exists (that is the function of this Runbook at least).  In order to do this, we are making a connection to the Exchange server ($ExchangeServer) leveraging the stored credentials ($PSUserCred) to do a quick check and then return those results to the calling Runbook.

Leveraging InlineScript in an SMA Runbook to Run a Non-Workflow Script

This is where the InlineScript comes in. We need to leverage an InlineScript so we can run a non-workflow execution to get results and return back that data back to the workflow.  We do this to make a remote connection to the system (Exchange server in our example), process our request, get our data, and bring it back to the workflow.

001
002
003
004
005
006
007
008
009
010
011
012
workflow Get-Exchange-Distribution-List
{
    .
    .
    $DLData = InlineScript{
    .
    .
    } -psComputerName $ExchangeServer -psCredential $PSUserCred
    $DLData
}

Note     We are leveraging the workflow variables as parameters for the InlineScript

What about the $Using:Variable – What is that all about?

While in the InlineScript, if we want to use workflow variables (parameters, credentials) we need to leverage the $Using:Variable option which tells the InlineScript to use the variable from the workflow.

The example below is leveraging the $Using:PSUserCred to access the stored credential variable for reuse in the connection to the Exchange server within the InlineScript.

001
002
003
$GetDLConn = New-PSSession -ConfigurationName Microsoft.Exchange `
 -ConnectionUri $ConnectionURI -Authentication Kerberos `
 -Credential $Using:PSUserCred

Note     Pay attention to where the $ is defined.  It moves to before Using instead of with the PSUserCred portion of the string.

Remote management of Microsoft Exchange required us to create a PSSession that had a configuration name of "Microsoft.Exchange".  We found that the InlineScript does not allow for this type of PSSession,  so we created a remote InlineScript connection to the Exchange server, and then leveraged a Microsoft.Exchange PSSession to execute the cmdlets within an Invoke-Command.

To ensure we don't leave anything behind, we clean up the session with a Remove-PSSession before we return to the InlineScript and then back to workflow.

001
Remove-PSSession $GetDLConn

All of that, to be able to return the following Open-mouthed smile

001
$DLData

This returns an object with information (we execute  Get-ExchangeDistributionGroup Exchange PowerShell CMDLET and if it finds our distribution list, we have data, if it doesn't, the return data returns a NULL).


Conclusion

I elaborated quite a bit in the weeds on some of this.  Hopefully you got your answer in there :) if not, please ask for more clarification.  URLs for great reference since SMA is literally consuming PowerShell v3 Workflow:

Running Windows PowerShell Commands in a Workflow
Hey, Scripting Guy! Blog (PowerShell Workflow Posts)

That’s it!  For more information, tips/tricks, and example solutions for SMA, be sure to watch for future blog posts in the Automation Track!

Till next time, Happy Automating


Your comment has been posted.   Close
Thank you, your comment requires moderation so it may take a while to appear.   Close
Leave a Comment
  • Hello Jim,

    Thanks for the dedicated post ;-)

    Hopefully I got the use of using 2 'hops' (1 for the inlinescript and 1 for the pssession):

    The PSCredentials automatically adds 'localhost' to the PSComputer property unless PSComputerName or PSConnectionUri are present.

    This allows the to reuse of the pscredential in the new-pssession cmdlet by specifying the -credential parameter and referring to the psUserCred defined in the workflow by making use of the $using scope. And because the inlinescript did not allow to create an Exchange configuration

    But the following draw my attention:

    "Remote management of Microsoft Exchange required us to create a PSSession that had a configuration name of "Microsoft.Exchange".  We found that the InlineScript does not allow for this type of PSSession...."

    Funny thing, as I do not have SMA installed just yet nor have access to an on-premise Exchange, when adding the credentials as a parameter and the PSConnectionUri (as they are linked) the use of the inlinescript parameters just works, so omitting the session creation in the inlinescript (tested against O365).

    Workflow Get-Exchange-Distribution-List

    {

    param([string]$name)

        $result = inlinescript

           {

               get-distributionGroup $using:name

           } -psConfigurationName Microsoft.Exchange `

             -psAuthentication Basic `

             -psallowRedirection `

             -DisplayName "Get Dirstribution list Exchange online"

          $result

    }

    Get-Exchange-Distribution-List -Name "Something" -PSCredential $cred -PSConnecionUri "ps.outlook.com/powershell"

    As the get-Exchange-Distribution-List is a 'sub-runbook' the parent 'runbook' can easily call the workflow providing the PS parameters.

  • @Stijn C, thanks for the follow up here.  This will also help others as they look at different ways to build out their solutions.  I do really appreciate the extra set of eyes and feedback helps improve adoption!  Have a great weekend!