A few months back I was part of creating a new course for the Microsoft Virtual Academy which is an introduction course for Service Manager. My contribution to the course was to present the “Automated Service Manager-” and “Extending Service Manager” modules when we did the recording in Las Vegas during MMS. I had a great time presenting and I hope you guys will have good use of the content!

The topics for the “System Center 2012 Service Manager: Planning, Deploying, Managing” course are:

  1. Architecture & Design
  2. Connectors
  3. Incident Management
  4. Problem Management
  5. Knowledge Management
  6. Automated Service Manager
  7. Extending Service Manager
  8. Change Management
  9. Release Management
  10. Service Requests
  11. Reporting & Data Warehouse

Go take the free course at: http://j.mp/scsm-mva

Categories : Service Manager
Comments (0)

Yesterday I found an email saying that I’ve been renewed as a System Center Cloud and Datacenter Management MVP. I just want take to opportunity to say THANK YOU to all the people at Microsoft and fellow MVPs that makes being an MVP so much fun and inspiring! Go MVP13!

Categories : MVP
Comments (2)

If you like me upgraded your Lync client to 2013 a while back and started to run into annoying freezes in the Service Manager console read this!

If you have a Lync client installed Service Manager provides some integration with Lync to show status of a user and provide a way of initiating e.g. an IM session with the affected user of an incident. Since installing Lync 2013 several people have reported that the Service Manager console started to freeze on opening a form where there was a user declared (Affected User, Primary User etc.). Seems like the problem only occurred if the old Lync client was left uninstalled!! So, if you’re experiencing freezes like the one described above, make sure you uninstall the old Lync client and give it a go. Hopefully this helps!

Categories : Service Manager
Comments (0)

From time to time I see questions regarding the use of “SendEmail” with Service Requests. For those not familiar with SendEmail it’s a console task for Service Manager that can be used by an analyst to send emails to other users regarding an incident. A common usage scenario is to request additional information from the affected user of an incident. In combination with the Exchange Connector this results in a really nice solution that documents the communication between the two parties in the action log of the incident.

Since the original version of SendEmail (part of the Exchange Connector download that can be found here) didn’t support usage with Service Requests I’ve now created a dialect of the solution that’s made for usage with Service Requests.

image

image

You can find the solution at the TechNet Gallery here: TechNet Gallery – SendEmail for Service Request Fulfillment

If you like the solution please rate it at the Gallery!

A couple of weeks ago one of my customers were asking if it was possible to get a console task that was bound to a specific incident template. They wanted to avoid the step where they have to go search/browse for the template in the “Template Picker” when creating a new incident. I came to think about the “Incident Quick Templates” solution which gives you a “fly-out-menu” of templates when you need to apply a frequently used template on an existing incident, but that solution can’t be used to create new incidents. So I went ahead and created a custom console task that solves the problem. Here it is, my “Quick Create Incident” console task.

image

The solution allows you to specify any number of templates you want to be able to pick from a “fly-out-menu” when creating a new incident.

Download: TechNet Gallery: Quick Create Incident

Setting up the solution

To be able to use your preferred templates in the “fly-out-menu” you need to know the internal Id of the templates you want to use.

Locate a Template ID

To locate the ID of a template, follow these steps:

  1. Start the “Service Manager Shell” (within the Service Manager Console go to AdministrationStart PowerShell Session)
  2. Use the following command to locate the ID of a template (replace “incident” with any word that is part of the display name of the template you’re looking for, *=wildcard)

Get-SCSMObjectTemplate -DisplayName *Incident*|ft DisplayName,Id

  1. Make a note of the Id  for the templates you want to have access to in the “fly-out-menu”
Wiring up your templates to the “fly-out-menu”

To add menu items (which are actually separate console tasks) wired to your templates, download the solution from here: TechNet Gallery: Quick Create Incident . Extract the zip archive to “C:\Temp\QuickCreateIncident”. Now, to define which templates you want to have access to in the “fly-out-menu”, open “C:\Temp\QuickCreateIncident\Litware.IncidentManagement.QuickCreate.Library.xml” in your favorite XML editor.

In the management pack I’ve wired-up two templates as examples to the “fly-out-menu”, the “Hardware Incident Template” and the “Network Incident Template”. Each of these menu items are defined as a <ConsoleTask> in the MP, see example below.

<ConsoleTask ID="Litware.Incident.QuickCreate.Network.Task" Accessibility="Public" Enabled="true" Target="Litware.Incident.QuickCreate.GroupTask" RequireOutput="false">
        <Assembly>EnterpriseManagement!SdkDataAccessAssembly</Assembly>
        <Handler>Microsoft.EnterpriseManagement.UI.SdkDataAccess.ConsoleTaskHandler</Handler>
        <Parameters>
          <Argument Name="Assembly">Litware.SCSM.QuickCreate</Argument>
          <Argument Name="Type">Litware.SCSM.QuickCreate.TaskHandlers.QuickCreateIncidentCommand</Argument>
          <Argument Name="TemplateId">4cf10508-c474-94fd-55df-28cb7a6f3fb3</Argument>
        </Parameters>
      </ConsoleTask>

Each menu item is actually defined as separate Console Tasks that has the same Target, which is a parent Console Task. There are three important things to notice in the example above:

  • The Console Task ID needs to be unique
  • The Target needs to be Litware.Incident.QuickCreate.GroupTask
  • The TemplateID is the reference used to define which template that will be used to create the new incident
To add your own menu items
  1. Copy the XML for one of the example <ConsoleTasks> (“Network” or “Hardware”)
  2. Give the new Console Task a new Console Task ID (which is uniqe)
  3. Change the TemplateId value to the Id the template you want to use (that you located using the Get-SCSMObjectTemplate command earlier)
Setting the display name of a menu item

To add a display name of a console task, follow these steps.

  1. Locate the Console Task ID for which Console Task you want to set the display name
  2. Make sure there is a <DisplayString> defined, as below, where the Console Task ID matches the ElementID

<LanguagePack ID="ENU" IsDefault="true">
      <DisplayStrings>
        …
        <DisplayString ElementID="Litware.Incident.QuickCreate.Network.Task">
            <Name>Network Incident</Name>
            <Description />
        </DisplayString>
        …
      </DisplayStrings>
</LanguagePack>

  1. The value of the <Name> tag will be the name shown in the Service Manager console

Note: In the example above we’ve added/updated the English display string. To add display strings for other languages. See the following blog post: Localizing Management Pack Content. Also, if you delete a console task, make sure you delete the <DisplayString> as well since you will not be able to import the MP if it contains display strings that refers to deleted elements.

Setting the icon of a menu item

To specify an icon for a menu item, in the <ImageReferences> section, add a line as the example below but make sure the ElementID matches the Console Task ID of your Console Task (menu item) that you want to set the icon for.

<ImageReference ElementID="Litware.Incident.QuickCreate.Network.Task" ImageID="SMIncident!IncidentMgmt_CreateIncidentFromTemplate_16" />

Finalizing

To be able to use the custom Console Task you need to bundle the provided assembly file with Management Pack. Before doing this though, you should seal the Management Pack (otherwise an annoying confirmation dialog will show up each time you click one of the menu items).

  1. Start the “Service Manager Shell”, within the Service Manager Console go to AdministrationStart PowerShell Session)
  2. Execute the following command:

cd C:\Temp\QuickCreateIncident

  1. Execute the following command to Seal the Management Pack:

Protect-SCManagementPack  -ManagementPackFile .\Litware.IncidentManagement.QuickCreate.Library.xml -KeyFilePath .\QuickCreateKey.snk -CompanyName Litware -OutputDirectory ./

  1. Execute the following command to bundle the sealed Management Pack with the assembly containing the custom Console Task:

New-SCManagementPackBundle -ManagementPack .\Litware.IncidentManagement.QuickCreate.Library.mp -Name Litware.IncidentManagement.QuickCreate.Library.mpb -Resource .\Litware.SCSM.QuickCreate.dll

  1. Finally, import the Management Pack Bundle using the console or using the following command:

Import-SCSMManagementPack .\Litware.IncidentManagement.QuickCreate.Library.mpb

You’re done! If you like the solution rate it at the gallery: TechNet Gallery: Quick Create Incident

Note: The example menu items “Hardware Incident” and the “Network Incident” are bound to out-of-the-box templates. If you’ve deleted the templates these examples are refering to since installing Service Manager these examples will not work and should be deleted. If you decide to delete them (the ConsoleTask elements), remember to delete all elements refering to them as well (display strings and image references).

In Service Manager 2012 the console tasks used to change the status of an Incident are grouped in a parent task called "Change Incident Status". Some people I’ve talked to actually prefer the way the console tasks were presented in Service Manager 2010 where they were presented as separate tasks instead of a group, the reason mainly being that it saves one mouse click.

I’ve addressed the wish of having things the way they were by creating a management pack that hides the group and re-wires each of the child tasks to make them appear as separate tasks outside of the group.

Before importing the management pack:
image

After importing the management pack:
image

Download the management pack at TechNet Gallery: http://gallery.technet.microsoft.com/Service-Manager-2012-b558f3ac

Enjoy!

PS: After writing this post I found another post with the same topic, check out this great blog post by Dieter Gasser: “Moving the Resolve task out of the “Change Incident Status” group”

Comments (2)

In Part 1: Custom Form Templates for Service Manager 2012 I showed you how to make use of the custom form templates, this time I’ll show you how the templates were created. This blog post will not only be useful to those that wants to create templates that can be used with the Service Manager Authoring Tool, but this is also a good start for those who want to build their complete form within Visual Studio.

In the previous post I shared two templates that re-used Service Manager controls to equipe custom forms with the Related Items Tab and the History Tab. This is how they were created.

Setting up the development environment

This guide was developed on a machine that had the following components installed:

  • Visual Studio 2012
  • Service Manager 2012 Console
  • Service Manager 2012 Authoring Tool
  • Service Manager 2012 Update Rollup 2

Note: You should without any problems be able to use any version of Visual Studio 2010/2012 when following this guide.

Setting up the Visual Studio Project

  1. Fire up Visual Studio 2010/2012 and create a new “WPF User Control Library”
    Important: You need to make use of .Net Framework 3.5
    SNAGHTML2bfe415
  2. Add the following references to the project
?View Code CSHARP
Microsoft.EnterpriseManagement.UI.Control.dll 
Microsoft.EnterpriseManagement.UI.SMControls.dll 
Microsoft.EnterpriseManagement.ServiceManager.Application.Common.dll 
Microsoft.EnterpriseManagement.ServiceManager.SharedResources.dll

All but the “SharedResources” assembly can be found in the installation directory of the Service Manager console. The “SharedResources” assembly can be found in a sub directory of the “Authoring Tool installation directory” called PackagesToLoad.

Creating the Form Templates

This section will guide you in how to build a custom form template which will contain two special Service Manager controls, the RelatedItemsPane control (Related Items tab) and the History control (History tab).

  1. Delete UserControl1 and add a new user control called MyTemplate (for Part 1 of this blog post I created two templates, CITemplate and WITemplate)
  2. In the XAML code for the user control, in the UserControl tag, set the Height and Width to something like 600 to make it easier to work with the control in the Authoring Tool.
  3. In the XAML code for the user control, add the following reference
?View Code CSHARP
xmlns:smcontrols="clr-namespace:Microsoft.EnterpriseManagement.UI.WpfControls;assembly=Microsoft.EnterpriseManagement.UI.SMControls"
  1. Drag a TabControl onto the design surface.
  2. Name the existing tab item “tabItemGeneral
  3. Add two tab items – tabItemRelItems for “Related items” and tabItemHistory for “History”.
  4. Add a Grid control inside the “General Tab”

Step 4-7 should give you a TabControl XAML representation as below:

<TabControl HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
    <TabItem Header="General" x:Name="tabItemGeneral">
        <Grid />
    </TabItem>
    <TabItem Header="Related Items" x:Name="tabItemRelItems">
    </TabItem>
    <TabItem Header="History" x:Name="tabItemHistory">
        <smcontrols:HistoryTab></smcontrols:HistoryTab>
    </TabItem>
</TabControl>

Note: The Authoring Tool doesn’t support adding controls directly inside a TabItem, that’s the reason for adding a Grid control in step 7.

Adding the “Related Items Tab”

To re-use the “Related Items” control in your custom form template you need to make use of the RelatedItemsPane control. To add the “Related Items” control simply declare the control in your code behind:

?View Code CSHARP
private RelatedItemsPane _relatedItemsPane;

Depending on if you’re going to use the form template to create forms for Work Item classes or Configuration Item classes there’s a difference:

Alt.1 – Related Items Tab in Configuration Item Forms

Add the following two lines to the constructor (“MyTemplate()”) method of your user control:

?View Code CSHARP
_relatedItemsPane = new RelatedItemsPane(new ConfigItemRelatedItemsConfiguration());
tabItemRelItems.Content = _relatedItemsPane;

Alt.2 – Related Items Tab in Work Item Forms

Add the following lines to the constructor (“MyTemplate()”) method of your user control:

?View Code CSHARP
var paneConfig = new WorkItemRelatedItemsConfiguration("RelatedWorkItems", "RelatedWorkItemSource","RelatedConfigItems","RelatedKnowledgeArticles","FileAttachments");
_relatedItemsPane = new RelatedItemsPane(paneConfig);
tabItemRelItems.Content = _relatedItemsPane;

Note: When using the “Related Items” control you need to provide the form with a binding source that contains the required relationships (components) used by the “Related Items” control. If the form isn’t bound to a type projection that includes the relationships used by the “Related Items” control the “Related Items” control will be “disabled”. In the section called “Wiring up a working binding source” in Part 1 of this blog post there’s examples of two type projections that contains the required components, one for work item forms and one for configuration item forms.

Adding the “History Tab”

To add the “History” control to a tab item you simply add the control in the XAML code for the tab item as below:

?View Code CSHARP
<TabItem Header="History" x:Name="tabItemHistory">
	<smcontrols:HistoryTab></smcontrols:HistoryTab>
</TabItem>

Wrapping it up!

Compile the project in (Release Mode) and use the output assembly (e.g. Litware.SCSM.CustomFormTemplates.dll) as described in Part 1: Custom Form Templates for Service Manager 2012.

In this example I did’t go all the way and add localization support, for more information on localization support in custom forms see: Localizing Forms – Service Request Example

For reference, here’s the XAML code and code beind of the CITemplate and WITemplate I created in Part 1 of the blog post:

CITemplate.xaml

<UserControl x:Class="Litware.SCSM.CustomFormTemplates.CITemplate"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:smcontrols="clr-namespace:Microsoft.EnterpriseManagement.UI.WpfControls;assembly=Microsoft.EnterpriseManagement.UI.SMControls"
             mc:Ignorable="d" 
             Height="600" Width="600">
    <Grid>
        <TabControl HorizontalAlignment="Stretch" VerticalAlignment="Stretch" >
            <TabItem Header="General" x:Name="tabItemGeneral">
                <Grid/>
            </TabItem>
            <TabItem Header="Related Items" x:Name="tabItemRelItems">
            </TabItem>
            <TabItem Header="History" x:Name="tabItemHistory">
                <smcontrols:HistoryTab></smcontrols:HistoryTab>
            </TabItem>
        </TabControl>
    </Grid>
</UserControl>

CITemplate.xaml.cs

?View Code CSHARP
using Microsoft.EnterpriseManagement.ServiceManager.Application.Common;
 
namespace Litware.SCSM.CustomFormTemplates
{
    /// <summary>
    /// Interaction logic for CITemplate.xaml
    /// </summary>
    public partial class CITemplate
    {
        private readonly RelatedItemsPane _relatedItemsPane;
 
        public CITemplate()
        {
            InitializeComponent();
 
            _relatedItemsPane = new RelatedItemsPane(new ConfigItemRelatedItemsConfiguration());
            tabItemRelItems.Content = _relatedItemsPane;
        }
    }
}

WITemplate.xaml

<UserControl x:Class="Litware.SCSM.CustomFormTemplates.WITemplate"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:smcontrols="clr-namespace:Microsoft.EnterpriseManagement.UI.WpfControls;assembly=Microsoft.EnterpriseManagement.UI.SMControls"
             mc:Ignorable="d" 
             Height="600" Width="600">
    <Grid>
        <TabControl HorizontalAlignment="Stretch" VerticalAlignment="Stretch" >
            <TabItem Header="General" x:Name="tabItemGeneral">
                <Grid/>
            </TabItem>
            <TabItem Header="Related Items" x:Name="tabItemRelItems">
            </TabItem>
            <TabItem Header="History" x:Name="tabItemHistory">
                <smcontrols:HistoryTab></smcontrols:HistoryTab>
            </TabItem>
        </TabControl>
    </Grid>
</UserControl>

WITemplate.xaml.cs

?View Code CSHARP
using Microsoft.EnterpriseManagement.ServiceManager.Application.Common;
 
namespace Litware.SCSM.CustomFormTemplates
{
    /// <summary>
    /// Interaction logic for CITemplate.xaml
    /// </summary>
    public partial class WITemplate
    {
        private readonly RelatedItemsPane _relatedItemsPane;
 
        public WITemplate()
        {
            InitializeComponent();
 
            var paneConfig = new WorkItemRelatedItemsConfiguration("RelatedWorkItems", "RelatedWorkItemSource",
                                                               "RelatedConfigItems", "RelatedKnowledgeArticles",
                                                               "FileAttachments");
            _relatedItemsPane = new RelatedItemsPane(paneConfig);
            tabItemRelItems.Content = _relatedItemsPane;
        }
    }
}
Comments (7)

A while back I created some “custom form templates” to be used with the Service Manager Authoring Tool (2010). The purpose was to enable “authors” to re-use some of the existing controls in Service Manager like the “Related Items Tab” and the “History Tab” when creating new forms in the Authoring Tool. By request I’ve updated these to support Service Manager 2012. So far I’ve just added two templates that contain the “Related Items Tab” and the “History Tab”. One template is for Work Items and one is for Configuration Items.

SNAGHTMLc125cb

If you just want to try the templates out you can go ahead and download this example bundle: Litware.SCSM.FormsExample.mpb. After importing it you can use any of the following two views to try out the forms using the Create MyWorkItem or Create MyConfigItem task:

  • Work Items > My Work Items > All My Work Items
  • Configuration Items > My Config Items > All My Config Items

To learn how to use the custom templates in the Service Manager Authoring Tool let’s create two simple classes and a form for each of them (based on the templates).

Creating the Example Manangement Pack

  1. Create a folder called C:\Temp\MyCustomForms
  2. Copy Litware.SCSM.CustomFormTemplates.dll to C:\Temp\MyCustomForms
  3. Start the Service Manager Authoring Tool
  4. Create a new Management Pack called “Litware.SCSM.FormsExample.xml” in “C:\Temp\MyCustomForms

Creating a custom Configuration Item class

  1. Right click Classes and select “Create Configuration Item Class…
    image
  2. In the Create Class dialog, name the class “MyConfigItem” and click Create.
  3. Add a new property by clicking “Create Property…”, name the property “PrincipalName”.
  4. While having the new property selected, mark it as Key in the Details pane.
    image
  5. Delete the property that was automatically added (called something like Property_…) when you created the class.
    image
  6. In the confirmation dialog, click yes to delete the property.

Creating a custom Work Item class

  1. Right click Classes and select “Create Work Item Class…
  2. In the Create Class dialog, name the class “MyWorkItem” and click Create.
  3. Delete the property that was automatically added (called something like Property_…) when you created the class.

We don’t have to add a new key property to the custom Work Item class since we’re already inheriting a key property.

Using the Configuration Item Form Template

  1. Right click Forms in the Management Pack explorer, select Add Custom
    image
  2. In the Base Class dialog, select your custom class called MyConfigItem and click OK
  3. In the Add custom fom dialog, name your form MyConfigItemForm, select the following assembly C:\Temp\MyCustomForms\Litware.SCSM.CustomFormTemplates.dll
  4. Still in the Add custom form dialog, in the type selection drop down select CITemplate (which contains both a related items and the history tab) and click Create
    SNAGHTML74e66a
  5. In the the “Form Designer”, add a Label and a TextBox to General tab.
  6. Change the Content of the Label to “Principal Name”
  7. Change the Binding Path of the TextBox to PrincipalName
    image

Using the Work Item Form Template

  1. Right click Forms in the Management Pack explorer, select Add Custom
  2. In the Base Class dialog, select your custom class called MyWorkItem and click OK
  3. In the Add custom fom dialog, name your form MyWorkItemForm, select the following assembly C:\Temp\MyCustomForms\Litware.SCSM.CustomFormTemplates.dll
  4. Still in the Add custom form dialog, in the type selection drop down select WITemplate (which contains both a related items and the history tab) and click Create
  5. In the the “Form Designer”, add a Label and a TextBox to General tab.
  6. Change the Content of the Label to “Title”
  7. Change the Binding Path of the TextBox to Title
  8. Save all changes and exit the Service Manager Authoring Tool

Wiring up a working binding source

Since the control used for the Related Items tab requires a type projection with specific components to work, let’s go through the steps required to make sure we provide that.

  1. Open up C:\Temp\MyCustomForms\Litware.SCSM.FormsExample.xml in an XML editor
  2. In the <References> section, make sure you have the following references:

    <Reference Alias="WorkItem">
            <ID>System.WorkItem.Library</ID>
            <Version>7.5.1561.0</Version>
            <PublicKeyToken>31bf3856ad364e35</PublicKeyToken> 
    </Reference> 
    <Reference Alias="SupportingItem">
            <ID>System.SupportingItem.Library</ID>
            <Version>7.5.1561.0</Version>
            <PublicKeyToken>31bf3856ad364e35</PublicKeyToken> 
    </Reference> 
    <Reference Alias="CoreKnowledge">
            <ID>System.Knowledge.Library</ID>
            <Version>7.5.1561.0</Version>
            <PublicKeyToken>31bf3856ad364e35</PublicKeyToken> 
    </Reference> 
    <Reference Alias="ConfigurationManagement">
            <ID>ServiceManager.ConfigurationManagement.Library</ID>
            <Version>7.5.1561.0</Version>
            <PublicKeyToken>31bf3856ad364e35</PublicKeyToken> 
    </Reference>

    Note: If you already have references to any of these Management Packs, make sure the alias of the existing reference matches the alias in the XML above.

  3. In the <EntityTypes> section (below the <ClassTypes> section) add the following two type projections encapsulated in the <TypeProjections> tag
  4. <TypeProjections>
            <TypeProjection ID="MyConfigItem.Projection" Accessibility="Public" Type="MyConfigItem">
              <Component Path="$Context/Path[Relationship='WorkItem!System.WorkItemRelatesToConfigItem' SeedRole='Target']$" Alias="ImpactedWorkItem" />
              <Component Path="$Context/Path[Relationship='WorkItem!System.WorkItemAboutConfigItem' SeedRole='Target']$" Alias="RelatedWorkItem" />
              <Component Path="$Context/Path[Relationship='SupportingItem!System.ConfigItemHasFileAttachment']$" Alias="FileAttachment" />
              <Component Path="$Context/Path[Relationship='System!System.ConfigItemRelatesToConfigItem']$" Alias="RelatedConfigItem" />
              <Component Path="$Context/Path[Relationship='System!System.ConfigItemRelatesToConfigItem' SeedRole='Target']$" Alias="RelatedConfigItemSource" />
              <Component Path="$Context/Path[Relationship='CoreKnowledge!System.EntityLinksToKnowledgeDocument']$" Alias="RelatedKnowledgeArticles" />
    </TypeProjection>

    <TypeProjection ID="MyWorkItem.Projection" Accessibility="Public" Type="MyWorkItem">
              <Component Path="$Target/Path[Relationship='WorkItem!System.WorkItemHasFileAttachment']$" Alias="FileAttachments">
                <Component Path="$Target/Path[Relationship='SupportingItem!System.FileAttachmentAddedByUser']$" Alias="FileAttachmentAddedBy" />
              </Component>
              <Component Path="$Target/Path[Relationship='WorkItem!System.WorkItemRelatesToWorkItem']$" Alias="RelatedWorkItems">
                <Component Path="$Target/Path[Relationship='WorkItem!System.WorkItemAffectedUser']$" Alias="RWIAffectedUser" />
                <Component Path="$Target/Path[Relationship='WorkItem!System.WorkItemAssignedToUser']$" Alias="RWIAssignedUser" />
              </Component>
              <Component Path="$Target/Path[Relationship='WorkItem!System.WorkItemRelatesToWorkItem' SeedRole='Target']$" Alias="RelatedWorkItemSource">
                <Component Path="$Target/Path[Relationship='WorkItem!System.WorkItemAssignedToUser']$" Alias="RelatedWorkItemAssignedTo" />
              </Component>
              <Component Path="$Target/Path[Relationship='WorkItem!System.WorkItemAboutConfigItem']$" Alias="RelatedConfigItems" />
              <Component Path="$Target/Path[Relationship='WorkItem!System.WorkItemAboutConfigItem' TypeConstraint='CoreKnowledge!System.Knowledge.Article']$" Alias="RelatedKnowledgeArticles" />
            </TypeProjection>
    </TypeProjections>

  5. Now let’s wire up the forms to each of the type projections. For the Config Item form, find the <Form> with ID="MyConfigItemForm" and replace Target="MyConfigItem" with Target="MyConfigItem.Projection"
  6. For the Work Item form, find the <Form> with ID="MyWorkItemForm" and replace Target="MyWorkItem" with Target="MyWorkItem.Projection"
  7. Save the file and exit the XML editor.

Creating the Management Pack Bundle

Before we’re ready to go we need to create a Management Pack Bundle which contains the Management Pack and the dll that contains the form templates.

  1. Open up a PowerShell command prompt
  2. Execute the following commands:
    import-module smlets
    cd C:\Temp\MyCustomForms
    New-MPBFile.ps1 .\Litware.SCSM.FormsExample.xml .\Litware.SCSM.FormsExample –computername SCSMComputerName

Note: I just loaded up smlets to get access to New-MPBFile.ps1, nothing else. Smlets can be found at http://smlets.codeplex.com

Taking the custom forms for a spin

  1. Import the Management Pack Bundle: Litware.SCSM.FormsExample.mpb
  2. Restart the console
  3. Create views for the custom classes (in the example files available as download in the top of the blog post I’ve already added the views)
  4. Use the console tasks Create MyConfigItem or Create MyWorkItem to try out the forms.

In Part 2 I’ll show you how the templates were created!

Important: Throughout this blog post I’m storing date model resources like managment pack classes in unseald management packs. You should always avoid this in production scenarios but since this is just to demo the templates I didn’t go through the extra steps required. Normally I would have created a separate managment pack with all data model resources within and selad that before starting up the creation of forms.

A couple of days ago Anders Bengtsson over at contoso.se asked me if I could help out and create a solution that could be used to help automate the task of saving file attachments to the file system. After spending some time messing around with memory streams in PowerShell I’ve managed to come up with a script that can be used to save all files “attached” to a work item or configuration item in Service Manager.

#
#Author: Patrik Sundqvist, www.litware.se
#Description: Can be used to archive attached files
#
 
param([Guid] $Id = $(throw "Parameter `$Id is required. This should be the internal id of a work item or config item which attached files you want to archive."),
[string]$ArchiveRootPath = $(throw "Parameter `$ArchiveRootPath is required. A folder containing all file attachments will be created in this folder."),
[string]$ComputerName = "localhost")
 
$WIhasAttachMent = "aa8c26dc-3a12-5f88-d9c7-753e5a8a55b4"
$CIhasAttachMent = "095ebf2a-ee83-b956-7176-ab09eded6784"
 
#Adjust path
$ArchiveRootPath = $ArchiveRootPath.TrimEnd("\")
 
#Make sure path exists
if(!(Test-Path $ArchiveRootPath))
{
    Write-Error "Provided archive path $ArchiveRootPath doesn't exists" -ErrorAction Stop
}
 
#Making sure smlets is loaded
if(!(get-module smlets))
{
    import-module smlets -Force -ErrorAction Stop    
}
 
#Get Emo
$Emo = Get-SCSMObject -Id $Id -ComputerName $ComputerName
 
 
#Check if this is a work item or config item
$WIhasAttachMentClass = Get-SCSMRelationshipClass -Id $WIhasAttachMent -ComputerName $ComputerName
$WIClass = Get-SCSMClass System.WorkItem$ -ComputerName $ComputerName
#Figure out if this is a work item or a config item to make sure we use the correct relationship
if($Emo.IsInstanceOf($WIClass))
{
    $files = Get-SCSMRelatedObject -SMObject $Emo -Relationship $WIhasAttachMentClass -ComputerName $ComputerName
}
else
{
    $CIhasAttachMentClass = Get-SCSMRelationshipClass -Id $CIhasAttachMent -ComputerName $ComputerName
    $CIClass = Get-SCSMClass System.ConfigItem$ -ComputerName $ComputerName
    if($Emo.IsInstanceOf($CIClass))
    {
        $files = Get-SCSMRelatedObject -SMObject $Emo -Relationship $CIhasAttachMentClass -ComputerName $ComputerName
    }
    else
    {
        Write-Error "Instance isn't of supported type" -ErrorAction Stop
    }
}
 
#For each file, archive to entity folder
if($files -ne $Null)
{
    #Create archive folder
    $nArchivePath = $ArchiveRootPath + "\" + $Emo.Id
    New-Item -Path ($nArchivePath) -ItemType "directory" -Force|Out-Null
 
    $files|%{
            Try
            {
                $_.DisplayName
                $fs = [IO.File]::OpenWrite(($nArchivePath + "\" + $_.DisplayName))
                $memoryStream = New-Object IO.MemoryStream
                $buffer = New-Object byte[] 8192
                [int]$bytesRead|Out-Null
                while (($bytesRead = $_.Content.Read($buffer, 0, $buffer.Length)) -gt 0)
                {
                    $memoryStream.Write($buffer, 0, $bytesRead)
                }        
                $memoryStream.WriteTo($fs)
            }
            Finally
            {
                $fs.Close()
                $memoryStream.Close()
            }
    }
}

Get-FileAttachments.ps1 requires “smlets” which can be downloaded at smlets.codeplex.com.

Remember to unblock the script after downloading, if you want to be able to run it that is :)

Using smlets you can simply search for configuration items or work items and pass on their internal ids to the script to have all their attachments archived nice and easy in a folder of your choice. In the example below I’m searching for all incidents in Service Manager that has a title containing the word “computer”. I pass on their internal id, a folder to use for archiving and the computer name of my Service Manager management server to the script. The script then checks for attachments and, in the case of finding attachments, creates a folder for each incident that has attachments and save the files in them.

?View Code POWERSHELL
Import-module smlets
$class = get-scsmclass system.workitem.incident$ -ComputerName sm2
$incidents = Get-SCSMObject -Class $class -Filter "DisplayName -like '*test*'" -computerName sm2
foreach ($incident in $incidents)
{
    .\Get-FileAttachments.ps1 -Id $incident.Get_Id() -ArchiveRootPath "C:\SCSM\Archive" -computername sm2    
}
Comments (10)

A few weeks back I was awarded the “System Center Cloud and Datacenter Management” MVP Award. I just wanted to shout out a big thanks to Microsoft, my wife (for putting up with all the late hours), colleagues, fellow community contributors and Anders Bengtsson (www.contoso.se, for all the fun work we’ve done together on collaborating posts).

logo_mvp

Categories : MVP, Service Manager
Comments (4)