Archive for Service Manager Customization

Best of MMS is approaching! Only a few of weeks away now!

I will deliver a session at Best of MMS 2010 in Stockholm/Sweden. My session “Hardcore customization of Service Manager 2010” is a level 400 session that will take place day one. Amongst other usefull things I’ll show how to make incident management more efficient using custom workflows and how to create automated activities for change management.

There will be a number of System Center experts speaking at the event so bring all your SC questions!

See you in Stockholm! More info about the event here

The question is out there – “How can we add Related Items and History controls to our custom forms as seen in the built in forms”. Now, if you’re a fully grown developer you might have been able to figure this out when building forms for Service Manager in Visual Studio. But wouldn’t it be nice to be able to do this in the Authoring Tool. Since you’re able to add custom forms in the Authoring Tool and then further customize these I came to think about creating form templates for the Authoring Tool that contains already implemented controls like the “Related Items” control. To aid those who ask I’ve created some example templates that make use of the “Related items” and “History” controls (you can download the templates, source code and documentation from here).

To try the templates out in the console you can import the Custom.Form.Examples.mpb and go to Configuration Items – Computers (Deployed) – All Computers (Deployed) and open one of the listed CIs.

To learn how to use the templates, please try the example described in the document called “Building a new form using custom template” provided in the download.

Enjoy!

Comments (22)

The PowerShell cmdlets for Service Manager has gone Beta 1. I would like to thank Jim Truher for joining the project and putting in a lot of effort in this release!

Release notes:
The snapin has been converted to a PowerShell version 2 module, so registration is not needed. To install extract the zip archive into the
C:\Windows\System32\WindowsPowerShell\v1.0\modules directory

and then run:

PS> Import-Module SMLets

This module now contains the following:

?View Code POWERSHELL
PS> get-command -module smlets |sort commandtype | ft commandtype,name -au
 
CommandType Name
----------- ----
      Alias load
      Alias new-mg
   Function New-ManagementGroup
   Function import-Assembly
   Function Get-SCSMClassProperty
   Function get-SCSMCommand
   Function get-SCSMproperty
     Cmdlet Get-SCSMTask
     Cmdlet Get-SCSMSubscription
     Cmdlet Get-SCSMTypeProjection
     Cmdlet Get-SCSMTaskResult
     Cmdlet Get-SCSMUserRole
     Cmdlet Get-SCSMTopLevelEnumeration
     Cmdlet Import-SCManagementPack
     Cmdlet Remove-SCSMSubscription
     Cmdlet Remove-SCSMObject
     Cmdlet Remove-SCManagementPack
     Cmdlet Set-SCSMObject
     Cmdlet Set-SCSMIncident
     Cmdlet Set-SCSMAnnouncement
     Cmdlet New-SCSealedManagementPack
     Cmdlet New-SCManagementPack
     Cmdlet Set-SCSMObjectProjection
     Cmdlet New-SCSMObject
     Cmdlet New-SCSMIncident
     Cmdlet New-SCSMAnnouncement
     Cmdlet Get-SCSMRunAsAccount
     Cmdlet Get-SCDWWarehouseModuleTypes
     Cmdlet Get-SCDWRelationshipFactTypes
     Cmdlet Get-SCManagementPack
     Cmdlet Get-SCSMAnnouncement
     Cmdlet Get-SCManagementPackElement
     Cmdlet Get-SCDWOutriggerTypes
     Cmdlet Get-DataWarehouseConfiguration
     Cmdlet Export-SCManagementPack
     Cmdlet Get-SCDWDimensionTypes
     Cmdlet Get-SCDWMeasureTypes
     Cmdlet Get-SCDWFactTypes
     Cmdlet Get-SCSMCategory
     Cmdlet Get-SCSMRelatedObject
     Cmdlet Get-SCSMObjectProjection
     Cmdlet Get-SCSMRelationshipClass
     Cmdlet Get-SCSMRule
     Cmdlet Get-SCSMResource
     Cmdlet Get-SCSMObject
     Cmdlet Get-SCSMClass
     Cmdlet Get-SCSMChildEnumeration
     Cmdlet Get-SCSMConfigItem
     Cmdlet Get-SCSMIncident
     Cmdlet Get-SCSMEnumeration

Grab the release over at codeplex!
http://smlets.codeplex.com

Jun
10

Custom console tasks: Part 2

Posted by: | Comments (6)

In the first part of the “Custom console tasks” series i described a very simple but powerful way to use the “Tasks” functionality in the Service Manager console to reboot an affected computer of an incident. This time I’m going to show you how we can use PowerShell scripting and some custom Cmdlets I’ve published on Codeplex to create a task that can re-activate (open) a closed incident, something that isn’t possible to do in the console out-of-the-box. Before we go on, please note that according to most process frameworks you shouldn’t re-open a closed incident.

Updated 2011-01-04 since there was a typo in step 6, parameters argument

  1. The first thing you need is the custom Service Manager Cmdlets i published on Codeplex (download here). You can follow the instructions here to install the Cmdlets. Using these cmdlets you’re able to update some incident properties, most importantly for this scenario the “Status” property.
  2. Secondly you need a powershell script that uses the Cmdlets to do all the magic. I’ve written a script that forces the status of an incident to “Active” (no matter previous Status). Since this is kind of hardcore, and should be considered as an override, I wanted to prompt the user for a “reason”. The script accomplishes this by running some C# code that renders a dialog where the user can provide a reason for running the task on the incident. If the user click the “Cancel” button I abort the action and leave the status “as is”. If the user click the “OK” button I go ahead and change status to “Active” (the reason is logged in the action log). 
  3. 2010-11-19 Updated script to work with SMLets Beta 1 or later

    ?View Code POWERSHELL
    param($ID)
    Import-module smlets -Force
     
    [void] [System.Reflection.Assembly]::LoadWithPartialName("System.Drawing")
    [void] [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms") 
     
    $objForm = New-Object System.Windows.Forms.Form
    $objForm.Text = "Force Incident Status"
    $objForm.Size = New-Object System.Drawing.Size(400,200)
    $objForm.StartPosition = "CenterScreen"
     
    $objForm.KeyPreview = $True
    $objForm.Add_KeyDown({if ($_.KeyCode -eq "Enter")
        {$x=$objTextBox.Text;$objForm.Close()}})
    $objForm.Add_KeyDown({if ($_.KeyCode -eq "Escape")
        {$objForm.Close()}})
     
    $OKButton = New-Object System.Windows.Forms.Button
    $OKButton.Location = New-Object System.Drawing.Size(125,120)
    $OKButton.Size = New-Object System.Drawing.Size(75,23)
    $OKButton.Text = "OK"
    $OKButton.Add_Click({$x=$objTextBox.Text;$objForm.Close();$result="OK"})
    $objForm.Controls.Add($OKButton)
     
    $CancelButton = New-Object System.Windows.Forms.Button
    $CancelButton.Location = New-Object System.Drawing.Size(200,120)
    $CancelButton.Size = New-Object System.Drawing.Size(75,23)
    $CancelButton.Text = "Cancel"
    $CancelButton.Add_Click({$objForm.Close()})
    $objForm.Controls.Add($CancelButton)
     
    $objLabel = New-Object System.Windows.Forms.Label
    $objLabel.Location = New-Object System.Drawing.Size(10,20)
    $objLabel.Size = New-Object System.Drawing.Size(360,20)
    $objLabel.Text = "Please enter a reason for forcing the incident status to Active:"
    $objForm.Controls.Add($objLabel) 
     
    $objTextBox = New-Object System.Windows.Forms.TextBox
    $objTextBox.Location = New-Object System.Drawing.Size(10,40)
    $objTextBox.Size = New-Object System.Drawing.Size(360,60)
    $objTextBox.Multiline = "True"
    $objForm.Controls.Add($objTextBox) 
     
    $objForm.Topmost = $True
     
    $objForm.Add_Shown({$objForm.Activate()})
    [void] $objForm.ShowDialog()
     
    if($result -eq "OK")
    {
        Set-SCSMIncident -ID $ID -Status Active
        Write-Host "Incident status forced to Active"
        if($x -gt 0)
        {
        	Write-Host "Reason for action: $x"
        }
        else
        {
        	Write-Host "No reason provided"
        }
    }
    else
    {
        Write-Host "Force to active status aborted"
    }
  4. Place the script in a local folder, I use “C:\PowerShell Scripts”
  5. Create a new task in the Service Manager console: Administration – Library – Tasks
    1. Name: Force Activate
    2. Description: Used to force status of incident to active, can be used on closed incidents!
    3. Target Class: Incident
    4. Category: Incident Management Folder Tasks
    5. Command Line: powershell.exe
    6. Parameters: &'.\ForceActivate.ps1' $Context/Property[Type='WorkItem!System.WorkItem']/Id$
    7. Working Directory: C:\PowerShell Scripts\
    8. Log in action log when this task is run: True
    9. Show output when this task is run: True

You’re done! You’re now able to break all the rules and open closed incidents…

This was an example of how powerful tasks can be built using PowerShell and the Service Manager SDK (used by the Cmdlets) to customize the console functionality in Service Manager. I plan to write a final part of this series where we go all the way and use managed code only to create a custom task including a custom WPF form.

May
11

Custom console tasks: Part 1

Posted by: | Comments (3)

In Service Manager 2010 there is a concept of console tasks. Using tasks you’re able to quickly perform actions while working in the console. An example of this could be launching remote desktop against a computer affected by an incident by just pressing a link within the incident form.

Console tasks are a great feature of Service Manager, but what’s even greater is that you can create your own. There are two different ways to add console tasks, in the console “Library – Tasks” or by defining console tasks in a management pack and importing this. The difference between these two entry points is that you can add much more advanced tasks in the latter one. In this first post of two I’m going to show you how to add a task directly in the console. To show you how to do this – here is how to add a task for rebooting the affected computer of an incident.

  1. Go to LibraryTasksNew Task
  2. Name the task “Reboot affected computer
  3. Choose the target class Incident
    (This associates the task with the incident form and enables us to use properties and related objects properties of the selected incident as arguments for the task command line)
  4. Choose the Incident management Folder Tasks category
    (This controls where the task will be available in the console)
  5. Full path to command: shutdown.exe
  6. On the Parameters section, click insert property and choose: IncidentAbout Config Item
    (“About Config Items” is called “Affected Items” in the form)
  7. Select the property called “NetBIOS Computer Name”
    (Locate it faster by using the search functionality)
  8. Working directory: “%windir%\system32” 
  9. Check: Log in action log when this task is run
  10. Check: Show output when this task is run

Note: You cannot use the option to “log in action log when this task is run”, without using the “show output when this task is run”. Doing so will cause the action to not get registered in the action log. This is a reported bug (not confirmed)!


Now you’ve created a task that can be used from the Incident Management part of the console to reboot an affected computer of an incident.

Some important things to remember here:

  • If the list of “Affected Items” (About Config Item) only contains one computer the task will be executed without prompting the user. In this case this would mean that, clicking the reboot task would instantly reboot the affected computer without asking questions like “Are you sure….?”. In the case of the list containing more than one computer, the user will get prompted to select which of the listed computer to reboot.
  • The file specified in the command, in this case shutdown.exe, needs to be available on each machine where the console will be used to launch the task (in this specific case this shouldn’t be a problem since shutdown.exe is distributed with the OS).
  • When executing a console task, the task will be executed in the context of the logged on user. You can still use roles in Service Manager to show/hide console tasks from different users, but remember that seeing a console task doesn’t automatically give a user the permission to execute the task successfully.

Related information: http://blogs.technet.com/servicemanager/archive/2010/02/11/tasks-part-1-tasks-overview.aspx

In the next part of “Custom console tasks” series I’ll show how to add more advanced console tasks using the SDK (some coding coming up!) and a custom management pack.

Comments (3)

A couple of days ago there was a blog post published on the official Service Manager blog that solves a really annoying problem. The problem was that it wasn’t possible to, out-of-the-box, run incident workflows based on SLA breaches in Service Manager. Using the blogged solution you are now able to do exactly that! This means that you are now able to do notification and apply templates on incidents about to or breaching their SLA. By applying templates you could for instance escalate an incident about to breach its SLA. Isn’t that sweet?!

The posted solution is a joint project that Travis Wright and I have been working on for a couple of weeks. I hope you like it!
http://blogs.technet.com/servicemanager/archive/2010/05/06/incident-sla-management-in-service-manager.aspx

Comments (0)

When developing extensions to Service Manager you want to be able to use the localization support of Service Manager. The strategy chosen by the product team of Service Manager is to store localized content primarily in management packs. When you’re creating new management packs you define the ”strings” that should be displayed in the Service Manager console depending on which language the console is currently running under. You do this in the LanguagePacks section of your management packs as shown in the picture below.

LanguagePacks

As you see in the picture you can define different language packs. Within these you add references to elements of your management packs. For instance you can specify what should be the displayed name of a list item defined in the management pack. You could specify different names for English, Swedish and all other languages that could be used by your Service Manager interacting users.

To be able to use these localized values in custom forms within the Service Manager console you do this by using data binding as explained in this post by Travis Wright. Now if you’re creating an application outside the console that needs to display data from Service Manager (using the SDK) you want to be able to reuse the localization made in Service Manager. Let’s say that you want to display, as it was in my case, a localized list. To retrieve the localized values from Service Manager you use an object called ManagementPackDisplayString. You simply retrieve a ManagementPackDisplayString from the element you want to get a localized value from using a specified CultureInfo. In the picture below I’m retrieving the localized name of a list.

DisplayString

As you see you’re also able to get a localized description of the object. The “CurrentCulture” as seen in the picture is the culture your application is currently running under. For more information regarding CultureInfo start here.

Important, you need to make sure that there is a localization of an element in the specified language before you try to retrive it. If you try to retrive a localized value in a culture that doesn’t exist as a LanguagePack the “GetDisplayString” method will throw an exception.

Comments (3)

In a collaborative project we, Patrik Sundqvist and Anders Bengtsson have created an embryo of an Asset Management extension for Service Manager. Our thoughts behind this management pack are to build a version one that we could extend in the future. It is not a feature complete asset management solution for enterprise organizations, but it is a foundation that could give you some ideas what you could do with Service Manager 2010.

Download management pack here and the management pack guide here.SMAsset02

 SMAsset01

Comments (1)

When creating a view in the Service Manager console you might want to filter the listed objects based on a related object’s property. Since I got a question last week regarding a scenarios like this, I thought I go ahead and describe how this could be done. In this example I’m creating a view tha lists all change requests that are assigned to a swedish user. Follow the instructions below to create such a view:

  1. Start by right clicking on the “Change Management” folder and click “Create view”.Adv_View_Query_1_CreateView
  2. Name the new view, provide a description and select in which management pack you want to store the view.Adv_View_Query_2_General
  3. Click browse in the criteria section and select “Combination classes” in the “View” drop down list. Select a the combination class called “Change Request (Advanced)” and press OK.
    This is the key to success since you want to be able the query a combination class (a type projection) instead of only a simple class. A combination class provides access to related objects and there properties.
    Adv_View_Query_3_ChooseClass
  4. Since you selected a combination class (a type projection) you can now have a search criteria that is based on properties of items that are related to the change request in your view.
    Adv_View_Query_4_Criteria_RelatedObjects
  5. Select the “Assigned To User” in the left pane of the criteria section. Then check the checkbox for the “Country” attribute in the right pane of the criteria section, click the add button and write “Sweden” in the textbox.
    Adv_View_Query_5_Criteria
  6. Select which columns to display in your view and close the wizard.

You’re done!

To test the view, make sure you have a user object with the country value “Sweden” and a change request with this user as the “Assigned To” user.
Note: The same method could be used to list all incidents that has affected user that speaks a certain language

Comments (2)

When naming the properties of a class in a management pack you should stay away from dots (“.”) in the property id. Some times you might feel tempted to include a dot after a prefix (maybe the company name or something) in the id property as you might do for the id of a custom management pack. Including a dot in the id of a property will mess upp the binding path of your forms which will result in your forms not storing the modified values in the instances.

Thanks for verifying Anders!

OK
<Property ID=MyDate Type=datetime” />
<Property ID=“Prefix_MyDate Type=datetime” />

Not OK!!!
<Property ID=Prefix.MyDate Type=datetime” />

Comments (0)