SMA – Migrating SMA Runbooks (SMART Toolkit) Annoying Confirmation

blocked

To migrate SMA runbooks from one environment to another you probably want to use SMA Runbook Toolkit to export and import the runbooks and assets, you can find the download here. This toolkit is a collection of PowerShell scripts which are few years old but still work perfectly with SMA 2016. After you downloaded the toolkit and extracted it, there is e.g. the SMART\Import and Export Tool\SMART-IE-GUI.ps1 to export and import your runbooks with a PowerShell GUI…

image

…and the GUI looks like this…

image

One problem you might encounter is, that you would have to confirm the execution of a child script Import-SMARunbookfromXMLorPS1.ps1 for each script you want to import…

image

…to circumvent this annoying step, you need to unblock the files in PowerShell. How can you do it? Well you just need to get all files in the SMART directory and use Unblock-File cmdlet to unblock the script….

2

…after this step the import runs without interruption. This problem happens not only to the SMART tools, but also could happen to any other module you download from an external source.

SMA Authoring Toolkit – Some Runbooks Are Not Showing Up

untitled

When you are creating runbooks in SMA (Service Management Automation) and you are using the SMA Authoring Toolkit available on PowerShell Gallery, you might have also have faced a very annoying bug. If you have a certain amount of runbooks in SMA and you are browsing through the runbook list in ISE you simply cannot find certain runbooks. Trying to refresh the list does not work at all.

image

If you open SMA to browse the runbook list you can see them all published and in a “healthy” state. So there is no reason not to show up.

Continue reading

SMA – ISE Add-On Editing Runbooks

powershell-whatsnew

A couple of month ago Microsoft released the latest (updated) version of PowerShell 5.0 . Why is this worth writing about? Well, with every new release there are some fantastic goodies included, you just need to discover them :). One of these goodies is (my) long awaited runbook editing capability for ISE. In this post I would like to show you how to get it installed and how to work with it.

First we need to get the module which is called SMAAuthoringToolkit. Because my lab environment does not have internet access, I will just download the module to my notebook and copy it to the lab machine.

Save-Module  SMAAuthoringToolkit -Path C:\Temp

This command will save the module from the PowerShell Gallery in C:\Temp…

image

Next, I copy the module to the lab server to my user path C:\Users\[user]\Documents\WindowsPowerShell\Modules

image

Next type…

Install-SMAIseAddOn

This will install the add-on so that it will be automatically loaded next time you start your ISE.

If you have internet connection on your system you don’t need to do the above “offline” copy steps, instead you just need to type…

Install-Module SMAAuthoringToolkit -Scope CurrentUser

If you add the -Scope CurrentUser parameter, the module is installed to…

$env:USERPROFILE\Documents\WindowsPowerShell\Modules

Then, if you want the PowerShell ISE to always automatically load the add-on, run…

Install-SMAIseAddOn

Otherwise, whenever you want to load the add-on, just run the following in the PowerShell ISE…

Import-Module SMAAuthoringToolkit   

No let’s start ISE and see what we got…

Continue reading

SMA – Invoke Runbook Error “Cannot find the ‘’command.”

error

This is just a quick post about SMA. I bumped many times in this error while writing PowerShell workflows in SMA …

SMASpaceError

At line:3497 char:21 + PAT000287-RelateAppSetSR -AppSetID $AppSet -SRID $Applicatio ... + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Cannot find the 'PAT000287-RelateAppSetSR' command. If this command is defined as a workflow, ensure it is defined before the workflow 
that calls it. If it is a command intended to run directly within Windows PowerShell (or is not available on this system),
place it in an InlineScript: 'InlineScript { PAT000287-RelateAppSetSR }'

…and I figured out that there are many reasons for this error.

If you are nesting runbooks like this…

workflow ParentWorkflow 
{
	ChildWorkflow -Param1 "Test" 	#Calling child workflow
}

Several reasons could lead to this problem:

  • The child workflow does not exist in SMA.
  • The child workflow has not been published.
  • The naming of the child workflow name does not match the invoke command.
  • There is a space in front of the child workflow. Just edit the line, where you call the child runbook and check in the parent runbook again.
  • Before you check in the parent workflow, you must check in the child workflow. This applies only when the runbook itself did not exist before. If the child runbook was created any time before the parent workflow, this error will not happen.

I hope this will help you this quite common error to eliminate during development.

SMA – Database Grooming Some Things You Should Know

know

SMA is Microsoft’s on-premise automation engine and the successor of Opalis / Orchestrator. We have utilized this engine quite a lot and have lots of experience developing PowerShell workflows for SMA. But as every system your need to maintain and pamper it, otherwise it will strike back at some point. We recently experienced such an issue, which also could happen in your environment.

When a runbook is executed it generates a job, see more details here. A job can have different status either be failed, stopped, suspended or running. So, if you decide you want to debug a runbook because it fails all the time, you can turn on different log levels or also known as runbook streams. There is an excellent post on System Center: Orchestrator Engineering Blog explaining how you turn on one of the six different streams like Output, Progress, Warning, Error, Verbose, and Debug. Depending on the type you receive different information levels.

What happens is, as soon you turn on e.g. verbose stream you will see it in the job output like this…

image

A best practice is to keep these streams turned off and only enabling it if you really need them. But why is that? Well, this output has to stay “somewhere” otherwise it would not be “persistent”. In SMA this output gets stored in the Stream.JobStreams table. If you run a select query against this table you will see something like this…

image

If you have a closer look at the Stream TypeName column you figure out the stream type like Verbose, Output, Progress etc. If you see Output, this does not mean it is only data from Write-Output, instead it is also data returned by a runbook for passing as input for the next runbook. As a side note, you should never use Write-Output in your runbooks instead use Write-Verbose. Write-Output is only meant for output objects and consuming by other runbooks.

Continue reading

PowerShell – SCCM Cmdlet Library “Get-CMDeviceCollection : Specified cast is not valid.”

UPDATE: This issue has been resolved in the latest version here https://www.microsoft.com/en-us/download/details.aspx?id=46681

While doing some SCCM automation we bumped into an issue with the SCCM Cmdlet Library 5.0.8249.1128.

When you try to execute a workflow using PowerShell Remoting in SMA like this…

workflow test {

InlineScript{ $VerbosePreference = "Continue"

$ModuleName = (get-item $env:SMS_ADMIN_UI_PATH).parent.FullName + "\ConfigurationManager.psd1"

Import-Module $ModuleName

cd P01:

$DeviceCollection = Get-CMDeviceCollection -CollectionId "P010000C"

Return $DeviceCollection

} -PSComputerName "SERVERFQDN"

}
Get-CMDeviceCollection : Specified cast is not valid.
At test:3 char:3
+ 
+ CategoryInfo : NotSpecified: (:) [Get-CMDeviceCollection], InvalidCastException
+ FullyQualifiedErrorId : System.InvalidCastException,Microsoft.ConfigurationManagement.Cmdlets.Collections.Commands.GetDeviceCollectionCommand
+ PSComputerName : [SERVERFQDN]

After some investigation we could not determine the cause of it, so the last option was to rollback to Cmdlet Library Version 5.0.82.31.1004 and then everything worked fine. The problem exists if we provide a named parameter like -CollectionId or –Name the problem also exists in other Cmdlets and also in the latest version of SCCM 2016 (vNext). Microsoft has confirmed / fixed this issue and it will be available in the next version. I have filed this bug on connect.

I hope this helps!

PowerShell – Remote Desktop Cmdlets “A Remote Desktop Services deployment does not exist…”

PowerShellBanner

Recently while automating some cool stuff I needed to create a PowerShell workflow for deploying VDI clients using Windows Server 2012 R2 Remote Desktop Services. One of the first things I always do is checking the existing PowerShell support and I figured out there is a large number of cmdlets available for managing RDS services. So the first thoughts were, this is going to be an easy walk in the park. Well, not really…

One of the first things I wanted to know, which users are assigned to which client. The Get-RDPersonalVirtualDesktopAssignment cmdlet gives you this information by providing the connection broker and collection name…

Get-RDPersonalVirtualDesktopAssignment [-CollectionName] <String> [-ConnectionBroker <String> ]

Because I will execute the script in a PowerShell workflow from a remote machine (SMA) using WinRM, I did some tests and I used Invoke-Command to do some PowerShell Remoting just to get started. Usually we develop PowerShell workflows starting with its core part / functionality and then wrap all other stuff around it, like logging, error handling and PowerShell workflow structure.

My test command looks like this…

$ConnectionBroker = "ConnectionBroker.domain.com"
$VDICollection = "MyVDICollection"
$UserName = "domain\user"

Invoke-Command -ComputerName $ConnectionBroker -Credential (Get-Credential -UserName $UserName -Message "Enter credentials") -ScriptBlock `
{
Import-Module RemoteDesktop;`
Get-RDPersonalVirtualDesktopAssignment -CollectionName $Using:VDICollection -ConnectionBroker $Using:ConnectionBroker
} 

The specified user has administrator permission on the connection broker and VDI deployment itself, so it should be working just fine. Well, it did not and I received an error…

A Remote Desktop Services deployment does not exist on ComputerName. This operation can be performed after creating a deployment. For information about creating a deployment, run "Get-Help New-RDVirtualDesktopDeployment" or "Get-Help New-RDSessionDeployment".
+ CategoryInfo : NotSpecified: (:) [Write-Error], WriteErrorException
+ FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException,Get-RDPersonalVirtualDesktopAssignment
+ PSComputerName : ComputerName

To make it short it seems that the Get-RDPersonalVirtualDesktopAssignment connects to the connection broker doing another hop, so we run here into a second hop problem. What is a ”second hop problem”? Don Jones has published a nice post here explaining the second hop. In this paper on page 39 Ravikanth Chaganti explains our problem a bit more in detail and how to handle it.

Finally to solve the problem we need to use CredSSP for passing the authentication to the second hop. In order to do that we need to use the parameter “-Authentication CredSSP” which will delegate our credential to the “second” hop. Be aware that you also need to enable CredSSP either via GPO or via PowerShell using Enable-WSManCredSSP cmdlet and then it worked like a charm.

$ConnectionBroker = "ConnectionBroker.domain.com"
$VDICollection = "MyVDICollection"
$UserName = "domain\user"



Invoke-Command -ComputerName $ConnectionBroker -Credential (Get-Credential -UserName $UserName -Message "Enter credentials") -ScriptBlock `
{
Import-Module RemoteDesktop;`
Get-RDPersonalVirtualDesktopAssignment -CollectionName $Using:VDICollection -ConnectionBroker $Using:ConnectionBroker
} -Authentication CredSSP

I would like to thank my buddy Fulvio Ferrarini and Marc van Orsouw for helping troubleshooting this issue.

This is an old problem but it does not always present you with an “Access Denied” error or anything like that as you can see in this example. I hope it save you some time!