I've always wanted to create my own PowerShell cmdlets. I don't know why – it's just the geek inside of me demanding to be let out. :)

So – here goes. I've created a set of cmdlets around announcements. These cmdlets could now be used in PowerShell, as part of a console task, or even in a workflow in SCSM to create, update, and list announcements. I can't wait to demo this in a workflow at some point – imagine having some workflow that does some magic but before you start the magic work you want to post an announcment to the self-service portal to notify users you are busy doing magic. Then, when the workflow is done, you can automtaiacally update the announceent so that the expiration date occurs in the past so it no longer shows up on the portal. Nice!

But more importantly, I hope this serves as a good example of how to create PowerShell cmdlets for Service Manager.

I followed the instructions at this blog post to get started with creating PowerShell cmdlets. He also provides a really nice Visual Studio project template for C# and one for VB.Net that makes it even easier to get started. Make sure you choose the output framework version to be 3.5. Do this by right clicking on the project in the Solution Explorer and choosing properties. Then in the dialog select '.Net Framework 3.5':

Next I just neeeded to do the usual adding of a Reference to the Microsoft.EnterpriseManagement.Core.dll assembly located in the C:\Program Files\Microsoft System Center\Service Manager 2010\SDK Binaries directory on the Service Manager management server.

Then add the following using statements:

using Microsoft.EnterpriseManagement;

using Microsoft.EnterpriseManagement.Common;

using Microsoft.EnterpriseManagement.Configuration;

 

Now we are ready to start writing PowerShell cmdlet code! First, declare the cmdlet:

[Cmdlet(VerbsCommon.New, "SCSMAnnouncement", SupportsShouldProcess = true)]

public class AddAnnouncement : Cmdlet

{

Then specify the parameters

#region Parameters

private String _Name = null;

private String _Body = null;

private String _Priority = null;

private DateTime _ExpirationDate;

private String _ComputerName = "localhost";

 

[Parameter(Position = 0,

Mandatory = true,

ValueFromPipelineByPropertyName = true,

HelpMessage = "The title of the annoucncement.")]

[ValidateNotNullOrEmpty]

public string Name

{

get{return _Name;}

set{_Name = value;}

}

 

[Parameter(Position = 1,

Mandatory = true,

ValueFromPipelineByPropertyName = true,

HelpMessage = "The body of the announcement")]

[ValidateNotNullOrEmpty]

public string Body

{

get{return _Body;}

set{_Body = value;}

}

 

[Parameter(Position = 2,

Mandatory = false,

ValueFromPipelineByPropertyName = true,

HelpMessage = "The priority of the announcement. Must be exactly 'Low', 'Medium', or 'Critical'.")]

[ValidateNotNullOrEmpty]

public string Priority

{

get { return _Priority; }

set { _Priority = value; }

}

 

[Parameter(Position = 3,

Mandatory = true,

ValueFromPipelineByPropertyName = true,

HelpMessage = "The expiration date of the announcement. Pass a datetime object. Convert to UTC time first. Required.")]

[ValidateNotNullOrEmpty]

public DateTime ExpirationDate

{

get { return _ExpirationDate; }

set { _ExpirationDate = value; }

}

 

[Parameter(Position = 4,

Mandatory = false,

ValueFromPipelineByPropertyName = true,

HelpMessage = "The SCSM Management Server to connect to.")]

[ValidateNotNullOrEmpty]

public String ComputerName

{

get { return _ComputerName; }

set { _ComputerName = value; }

}

 

#endregion

 

PowerShell cmdlets have just one method you need to override to do the work – the ProcessRecord() method:

protected override void ProcessRecord()

{

try

{

In my example here we are just going to do the usual by creating an EnterpriseManagementGroup object to connect to the SCSM server.

EnterpriseManagementGroup emg = new EnterpriseManagementGroup(_ComputerName);

 

Then we get the Announcement class

ManagementPackClass clsAnnouncement = emg.EntityTypes.GetClass(new Guid("EF8A786A-5D22-F035-32D7-D0B60D9284AD")); //System.Announcement.Item

 

Now we need to handle the string Priority input the user provided and map that to the correct enumeration object

ManagementPackEnumeration enumPriority = null;

switch (_Priority)

{

case "Low":

enumPriority = emg.EntityTypes.GetEnumeration(new Guid("9CB0E9C2-4012-C30B-1E91-5E1272083D7B")); //System.Announcement.PriorityEnum.Low

break;

case "Critical":

enumPriority = emg.EntityTypes.GetEnumeration(new Guid("13A0D2E7-26AC-081B-AA59-E09F78ADB7C9")); //System.Announcement.PriorityEnum.Critical

break;

case "Medium":

enumPriority = emg.EntityTypes.GetEnumeration(new Guid("4C02D027-2991-73EB-F8CA-F0123BE92705")); //System.Announcement.PriorityEnum.Medium

break;

default:

enumPriority = emg.EntityTypes.GetEnumeration(new Guid("4C02D027-2991-73EB-F8CA-F0123BE92705")); //System.Announcement.PriorityEnum.Medium

break;

}

 

Next we get a CreatableEnterpriseManagementObject object of the Announcement class, set the properites according to the user's input and Commit(). That's it!

CreatableEnterpriseManagementObject emo = new CreatableEnterpriseManagementObject(emg, clsAnnouncement);

 

emo[clsAnnouncement, "Id"].Value = System.Guid.NewGuid().ToString();

if(_Name != null)

emo[clsAnnouncement, "DisplayName"].Value = _Name;

emo[clsAnnouncement, "Title"].Value = _Name;

 

if(_Body != null)

emo[clsAnnouncement, "Body"].Value = _Body;

emo[clsAnnouncement, "Priority"].Value = enumPriority.Id;

emo[clsAnnouncement, "ExpirationDate"].Value = _ExpirationDate;

 

emo.Commit();

 

}

catch (Exception)

{

}

}

 

The other Announcement examples are pretty self-explanatory and you can check the source code out for them in the downloadable project linked to at the end of this post.

Let's check these cmdlets out in action now.

First, you'll need to install the cmdlets snapin. Do this by:

  1. Download the package (link at the end)
  2. Open a PowerShell window AS ADMINISTRATOR!!
  3. cd to the …..\Release folder
  4. run InstallUtil.exe .\ServiceManagerCmdlets.dll
  5. run Add-PSSnapin ServiceManagerCmdlets

image

Now we can run the cmdlets. First, create a new announcement using New-SCSMAnnouncement. Note – body, name and expirationDate are all required parameters.

image

Now, you can run Get-SCSMAnnouncement and see a list of all the announcement objects in the database, including the one we just created.

image

Now run Set-SCSMAnnouncement to update some values.

image

Then run Get-SCSMAnnouncement again to see the changes.

 image

AWESOME!! But wait, there's more!! :)

Awhile back when we were prioritizing which cmdlets we would provide out of the box for SCSM 2010, I made the decision to prioritize Remove-SCSMManagementPack lower and eventually it was cut due to lack of time. After spending lots of time editing and testing management packs lately, I'm realizing this is an essential cmdlets for any MP author! So – as penance, I have also created a Remove-SCSMManagementPack cmdlet. You can use it to uninstall a management pack by providing the name, version, and keytoken (if it is sealed).

In this example, I add the out of the box cmdlet snapin, import a test MP, and then remove it.

image

Nice! This is going to be a huge timesaver for me and other MP authors out there!

Please put requests for new cmdlets in the comments below and I'll try to keep adding to the snapin.

Project file download is available here:

http://cid-17faa48294add53f.skydrive.live.com/self.aspx/.Public/Tools/ServiceManagerCmdlets.zip