PowerShell Activities: First impressions
The first thing I noticed was that I couldn't do anything because the Licensing App wouldn't even see that there was a PowerShell App to license. Then once I updated to the newest Licensing App, it wouldn't pull the PowerShell App license with a Renew All I had to Renew Selected that license individually. After that it worked. Huzzah!
Script Object:
General Tab:
Published Checkbox: This controls whether a script is selectable when adding one manually to a P$A.
Activity Object:
Visual Notes:
Overall: This activity class window size is locked (unable to resize or maximize). This makes it difficult to see the parameter mapping table and generally feels a little clunky.
There is a Task in the Task Pane labeled "Run Activity PowerShell" perhaps this is intended for manual execution. I couldn't get this to work.
General Tab:
- Area field is mapped to the Activity Area enum list.
- Stage field is mapped to Activity Stage enum list.
- Assigned To uses the Assigned To User relationship class. There is not functionality in the Notify Analyst Settings for this assignment, though I can't imagine why there would need to be as the whole point of these seems to be automation.
- You can only select the script before the record is created.
- PowerShell field: Line numbers! Well done, that's great!
- Parameter table: This is hard to see!
- If you create a P$A template, then change the script it's linked to/based on, the template will show and run the script as it looked when the template was created. You can open and re-select the same script and it will update with any changes. In creating a template, it writes the text from the Script Object to the management pac.
# Management Pack XML <Property Path="$Context/Property[Type='CustomCireson_Powershell_Activity_Library!Cireson.Powershell.Activity.Script']/PowershellScript$">$Environment = Get-ChildItem -Path ENV:\ | % { $_.Name.tostring() +" - "+ $_.Value.ToString() } $PSVersionTable.PSVersion $Environment</Property>PowerShell Output Tab:
- The output works just like you would expect something to write to a screen. So don't Write-Host (bad practice anyway), just output whatever you have e.g.:
# Some Code $SomeText = 'This is some text' $SomeText # Will output This is some text
Actual Scripting:
This should be intuitive, but for those of us who are spoons in the knife drawer of life, you cannot use powershell interactively. Meaning: you cannot ask for input (things like Read-Host). Thankfully, Read-Host will cause the activity to fail and have a log entry like:
"A command that prompts the user failed because the host program or the command type does not support user interaction. The host was attempting to request confirmation with the following message:
Things like the following will just hang:
Get-Process | Out-GridView Get-Help -Name Get-Member -ShowWindow
- When you have object parameters, do not leave any space between parameters, i.e. Param([Parameter(Mandatory=$True)],[string]$Description)
- For SCSM 2012, you have to write the parameters on a single line
Error handling:
You are going to need to handle errors. If your script would (or could) result in red text in a console (raise an error to the error stream), then your activity will show as failed and be handled by SCSM as such (aka failing the parent request and not executing subsequent activities). This seems to work with the -ErrorAction parameter, but I would really like to know how Cireson is detecting errors. Presumably if your console wouldn't be bleeding red text, your activity won't fail.
Note: When I get the chance, and if I remember (harder) I'll upload my UserInput parser that breaks the Question/Answers into a hash table for ease of use.
Comments
That there is another license key is a bit frustrating. I have only just performed this activity (we have to use the offline method) and my keys are not in the list.
Is it possible to invoke another script from the library through a P$A? I'd like to be able to keep my scripts as modular as possible and this would be tricky if we're forced do duplicate code or resort to sequential P$As in a single WI.
Can you trigger a script from an SCSM Workflow Event? We used to insert scripts into the workflow and have it invoked by this trigger.
@Leigh_Kilday
I thought I would be able to update my original post with more information, but I'll put it here instead.
You can trigger other scripts, but unless you specify credentials it will run as the Local System account (see below). What you'll lose by doing this is the ability in the context of the Work Item to detect error\failure conditions.
I'm not confident I know what you're referring to regarding workflow events. There is a workflow event that fires when scripts are run manually or automatically, but it isn't specific to a script, it's to the activity. The Activity contains the PowerShellScript property and via the Cireson.Powershell.Activity.ActivityRelatesToScript you can access the source.
Security Context:
The scripts run using the Local System account of the workflow server (SERVERNAME$) This has a few implications. First, it means that you won't be able to use a PowerShell profile for that account. This is a highly privileged account in the machine context, and effectively unable to reach out by itself on the domain. It can't initiate PSSessions because (AFAIK) you can't grant that account access on other computers. It's possible to pass credentials to anything, the problem is how to store those credentials. I'm not aware of a secure way to store credentials in PowerShell scripts or files:
- Cleartext is obviously unacceptable.
- While possible to ConvertTo-SecureString and leave an encrypted version of the password in a file, it's a simple thing to ConvertFrom-SecureString and you're tied to one machine and one account.
- When not converted to secure string, the System.Security.SecureString class can be fed into the constructor for System.Management.Automation.PSCredential objects and written back as plain text.
- I won't go down the security rabbit hole. It's possible to manage this with keys, but now we're talking about potentially adding process and infrastructure.
- Pay attention, tread carefully.
Objects:Writing objects will not always write the properties you would see in a console. Running:
Output:
Modules:
Loading modules seems to work fine. I loaded smlets without issue from both the System Environment Variable and directly using local file path and UNC.
Protip for those who might load SMLets and the Micro$oft SCSM cmdlets:
Add the Module name as a prefix to any cmdlet in the event of name collisions (Get-SCSMClass does this).
This would look like:
Since we're running as the local machine account two options come to mind for loading modules automatically.
1. Loading them using the PSModulePath system environment variable (You'd set these manually in the system properties dialog pane or use .NET. This means changing the environment variables for the whole machine, not per account.
2. Farm the execution out to other scripts or services like Task Scheduler. Depending on how you do it, this solves the credentials issue, and allows account level PSProfile use, but incurs the penalty of requiring manual password maintenance on the scheduled tasks. If your environment uses service accounts with passwords that don't change and you've already accepted the risk associated there, that's an easy solution. It's also possible to script changing the password on scheduled tasks. I'm uneasy creating automation to maintain automation.
Wish List:
Templates need to reference the source script and not cache the script. The more I play with it, the more annoying it is that activity templates don't update when the script changes. This is a problem.
Oddly, the system struggles to resolve parameter sets when you don't specify the parameter directly. For example:
It takes pipeline input fine, or you can feed it the ID of a workitem. It does need SMLets. I usually keep this function in my utility module so I can just load that in the P$A. This outputs the Question, Answer, Live Objects, and the type.
@Billy_Wilson
You probably wouldn't get the SCSM Workflow granularity of an individual job, but it feels like a fair trade off having a PowerShell script workflow job that just encapsulates all scheduled jobs made through this. If a feature request for this hasn't been raised, I'll certainly submit.
https://community.cireson.com/discussion/2557/powershell-activity-enable-scheduling-of-activities/p1?new=1