Tuesday, October 25, 2011

SCSM Workflow Date Time Token Error in the Authoring Console

The Authoring Tool workflow has an option of "relative" when using date fields. However, when you check the checkbox and enter a relative token such as [now] the authoring console doesn't like it and will not save. I haven't seen anyone else complain about this, so maybe it is just my environment. Either way, I had to find a workaround. It is pretty simple.

First what might happen is you are creating an on update trigger. You select a date field and select the relate checkbox.


















You might be able to click okay, but later down the road when you save you might get this token error.













If this is happening to you, specify the expression that you want, except do not use "relative." For now, insert a static date. Save the management pack and open the xml. Go find your expression. You can see mine below.
<Expression>     <SimpleExpression>         <ValueExpression>              <Property State="Post">$Context/Property[Type='CustomSystem_WorkItem_Library!System.WorkItem']/ScheduledStartDate$</Property>                            </ValueExpression>                            <Operator>LessEqual</Operator>                            <ValueExpression>                              <Value>2011-09-25T05:00:00</Value>                            </ValueExpression>                          </SimpleExpression>                        </Expression>

Replace <Value>2011-09-25T05:00:00</Value> with <Token>[now]</Token>


That's it.

SCSM Tokens

[me]
[mygroups]

[now] +|- # s|m|h|d

where:

s => seconds
m => minutes
h => hours
d => days

for example:
[now] + 2 h is now + 2 hours
[now ]+ 3 m is now + 3 minutes
[now] - 2 h is now - 2 hours

Monday, September 12, 2011

Quickly find the SCSM Management Group Name

I always assumed the SCSM management group name was in the title of the console until I actually needed one day, then I realized it wasn't there. It seems like you would see the Management Group name every where, but it is not. Use the registry on a SCSM server to find it.

Open regedit:
HKEY_LOCAL_Machine\SOFTWARE\Microsoft\Microsoft Operations Manager\3.0\Server Management Groups 

Monday, August 29, 2011

Here are some useful SCSM DataMart Views

Create Announcements view from The CMDB


USE [DWDataMart]
GO
/****** Object:  View [dbo].[Custom_Announcements]    Script Date: 08/29/2011 13:16:37 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
Create View [dbo].[Custom_Announcements]
As
Select BaseManagedEntityId,
ExpirationDate_DDB905FF_A923_F97D_D00B_6430C2CD5E95 as Expiration,
P.DisplayName as Priority,
Title_A24FDDD9_5BC0_B3D0_E014_1F98C0B9143E Announcement,
Left(Substring(Body_3D226BC1_0528_14EA_F3FB_3823A132B4F8,Charindex('\ltrch',Body_3D226BC1_0528_14EA_F3FB_3823A132B4F8)+7,250),Charindex('}',Substring(Body_3D226BC1_0528_14EA_F3FB_3823A132B4F8,Charindex('\ltrch',Body_3D226BC1_0528_14EA_F3FB_3823A132B4F8)+7,250))-1) Body
 FROM ServiceManager.dbo.MTV_System$Announcement$Item a
 Join ServiceManager.dbo.DisplayStringView P on a.Priority_6986BA50_58CF_ABCA_FB58_8FCAB694E6C9 = P.LTStringId and LanguageCode = 'ENU'
GO


Review Activities

/****** Object:  View [dbo].[Custom_ReviewActivityList]    Script Date: 08/29/2011 13:16:37 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

CREATE VIEW [dbo].[Custom_ReviewActivityList]
 AS


Select
RA.Id + Coalesce(Cast(R.ReviewerDimKey as varchar(255)),'') As ActivityandReviewer_Key,
RA.BaseManagedEntityId as ActivityGUID,
RA.Id as ActivityId,
Cast('https://servicemanagerdev/analyst/ReviewActivityDetails.aspx?AID=' + RA.Id AS varchar(255)) ViewActivity,
RA.CreatedDate,
RA.Title,
DecString.DisplayName,
R.DecisionDate,
R.Comments as DecisionComments,
U.FirstName as ReviewerFirstName, U.LastName as ReviewerLastName, U.DisplayName as ReviewerDisplayName, U.UserName as ReviewerUserName,
WI.BaseManagedEntityId as ParentWorkItemGUId,
WI.Id as ParentWorkItemId,
WI.Title as ParentWorkitemTitle,
Cast('https://servicemanagerdev/analyst/ChangeRequestDetails.aspx?CRID=' + WI.Id  AS varchar(255)) ViewParent
FROM ActivityDimvw A
Join ReviewActivityDimvw RA on A.BaseManagedEntityId = RA.BaseManagedEntityId
Left Join ReviewActivityhasReviewerFactvw RARF on A.ActivityDimKey = RARF.ActivityDimKey
LEFT Join ReviewerDimvw R on RARF.ReviewActivityHasReviewer_ReviewerDimKey = R.ReviewerDimKey
LEFT Join ReviewerDecisionvw RD ON R.Decision_ReviewerDecisionId = RD.ReviewerDecisionId
Left Join dbo.DisplayStringDimvw as DecString on RD.EnumTypeId = DecString.BaseManagedEntityId and DecString.LanguageCode = 'ENU'

LEFT Join ReviewerIsUserFactvw RU on R.ReviewerDimKey = RU.ReviewerDimKey
LEFT Join UserDimvw U on RU.ReviewerIsUser_UserDimKey = U.UserDimKey

Left Join ActivityAreavw AA  With (NOLOCK) on RA.Area_ActivityAreaId= AA.ActivityAreaId
Left Join dbo.DisplayStringDimvw as AAString on AA.EnumTypeId = AAString.BaseManagedEntityId and AAString.LanguageCode = 'ENU'

Left Join ActivityPriorityvw AP  With (NOLOCK) on RA.Priority_ActivityPriorityId = AP.ActivityPriorityId
Left Join dbo.DisplayStringDimvw as APString on AP.EnumTypeId = APString.BaseManagedEntityId and APString.LanguageCode = 'ENU'

Left Join ActivityStagevw AStage  With (NOLOCK) on RA.Stage_ActivityStageId = AStage.ActivityStageId
Left Join dbo.DisplayStringDimvw as AStageString on AStage.EnumTypeId = AStageString.BaseManagedEntityId and AStageString.LanguageCode = 'ENU'

Left Join ActivityStatusvw AStatus  With (NOLOCK) on RA.Status_ActivityStatusId = AStatus.ActivityStatusId
Left Join dbo.DisplayStringDimvw as AStatusString on AStatus.EnumTypeId = AStatusString.BaseManagedEntityId and AStatusString.LanguageCode = 'ENU'

Left Join WorkItemContainsActivityFactvw WICA on A.ActivityDimKey = WICA.WorkItemContainsActivity_ActivityDimKey
Left Join WorkItemDimvw WI on WICA.WorkItemDimKey = WI.WorkItemDimKey
GO

Incidents 


/****** Object:  View [dbo].[Custom_IncidentList_with_HL]    Script Date: 08/29/2011 13:16:37 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE VIEW [dbo].[Custom_IncidentList_with_HL]
 AS

Select
I.BaseManagedEntityId as IncidentGUID,
I.Id as IncidentId,
'https://servicemanagerdev/enduser/RequestDetails.aspx?RequestsId=' + Convert(varchar(50),I.BaseManagedEntityId) + '&RequestType=incident'
AS IncidentLink,
I.CreatedDate,
IncidentStatusString.DisplayName as 'Status',
IncidentClassString.DisplayName  as 'Classification',
I.Title, I.Description, Escalated,
IncidentImpactString.DisplayName as Impact,
IncidentUrgencyString.DisplayName as Urgency,
Priority,
IncidentResCatString.DisplayName as ResolutionCategory,
ResolutionDescription,
TargetResolutionTime,
AffectedUser.FirstName as AffectedUserFirstName, AffectedUser.LastName as AffectedUserLastName, AffectedUser.DisplayName as AffectedUserDisplayName, AffectedUser.UserName as AffectedUserName,
ContactMethod as AffectedUserContactMethod,
AssignedUser.FirstName as AssignedUserFirstName, AssignedUser.LastName as AssignedUserLastName, AssignedUser.DisplayName as AssignedUserDisplayName, AssignedUser.UserName as AssignedUserName,
CreatedByUser.FirstName as CreatedByUserFirstName, CreatedByUser.LastName as CreatedByUserLastName, CreatedByUser.DisplayName as CreatedByUserDisplayName, CreatedByUser.UserName as CreatedByUserName
FROM dbo.IncidentDimvw I With (NOLOCK)
Join WorkItemDimvw WI  With (NOLOCK) on I.BaseManagedEntityId = WI.BaseManagedEntityId

LEFT Join IncidentStatusvw S  With (NOLOCK) on I.Status_IncidentStatusId = s.IncidentStatusId
LEFT Join dbo.DisplayStringDimvw as IncidentStatusString on S.EnumTypeId = IncidentStatusString.BaseManagedEntityId and IncidentStatusString.LanguageCode = 'ENU'

LEFT Join IncidentClassificationvw C on I.Classification_IncidentClassificationId = C.IncidentClassificationId
LEFT Join dbo.DisplayStringDimvw as IncidentClassString on C.EnumTypeId = IncidentClassString.BaseManagedEntityId and IncidentClassString.LanguageCode = 'ENU'

LEFT Join IncidentImpactvw Impact on I.Impact_IncidentImpactId = Impact.IncidentImpactId
LEFT Join dbo.DisplayStringDimvw as IncidentImpactString on Impact.EnumTypeId = IncidentImpactString.BaseManagedEntityId and IncidentImpactString.LanguageCode = 'ENU'

LEFT Join IncidentUrgencyvw Urgency on I.Urgency_IncidentUrgencyId = Urgency.IncidentUrgencyId
LEFT Join dbo.DisplayStringDimvw as IncidentUrgencyString on Urgency.EnumTypeId = IncidentUrgencyString.BaseManagedEntityId and IncidentUrgencyString.LanguageCode = 'ENU'

LEFT Join IncidentResolutionCategoryvw ResCat on I.ResolutionCategory_IncidentResolutionCategoryId = ResCat.IncidentResolutionCategoryId
LEFT Join dbo.DisplayStringDimvw as IncidentResCatString on ResCat.EnumTypeId = IncidentResCatString.BaseManagedEntityId and IncidentResCatString.LanguageCode = 'ENU'

Left Join WorkItemAffectedUserFactvw WIAF on WI.WorkItemDimKey = WIAF.WorkItemDimKey and WIAF.DeletedDate IS NULL
Left Join UserDimvw AffectedUser on WIAF.WorkItemAffectedUser_UserDimKey = AffectedUser.UserDimKey

Left Join WorkItemAssignedToUserFactvw WIAT on WI.WorkItemDimKey = WIAT.WorkItemDimKey and WIAT.DeletedDate IS NULL
Left Join UserDimvw AssignedUser on WIAT.WorkItemAssignedToUser_UserDimKey = AssignedUser.UserDimKey

Left Join WorkItemCreatedByUserFactvw WICB on WI.WorkItemDimKey = WICB.WorkItemDimKey and WICB.DeletedDate IS NULL
Left Join UserDimvw CreatedByUser on WICB.WorkItemCreatedByUser_UserDimKey = CreatedByUser.UserDimKey

Where 1=1

and Status <> ('IncidentStatusEnum.Closed')
GO

Another Incident List without a Hyperlink

/****** Object:  View [dbo].[Custom_IncidentList]    Script Date: 08/29/2011 13:16:37 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE VIEW [dbo].[Custom_IncidentList]
 AS

Select
I.BaseManagedEntityId as IncidentGUID,
I.Id as IncidentId,
I.CreatedDate,
IncidentStatusString.DisplayName as 'Status',
IncidentClassString.DisplayName  as 'Classification',
I.Title, I.Description, Escalated,
IncidentImpactString.DisplayName as Impact,
IncidentUrgencyString.DisplayName as Urgency,
Priority,
IncidentResCatString.DisplayName as ResolutionCategory,
ResolutionDescription,
TargetResolutionTime,
AffectedUser.FirstName as AffectedUserFirstName, AffectedUser.LastName as AffectedUserLastName, AffectedUser.DisplayName as AffectedUserDisplayName, AffectedUser.UserName as AffectedUserName,
ContactMethod as AffectedUserContactMethod,
AssignedUser.FirstName as AssignedUserFirstName, AssignedUser.LastName as AssignedUserLastName, AssignedUser.DisplayName as AssignedUserDisplayName, AssignedUser.UserName as AssignedUserName,
CreatedByUser.FirstName as CreatedByUserFirstName, CreatedByUser.LastName as CreatedByUserLastName, CreatedByUser.DisplayName as CreatedByUserDisplayName, CreatedByUser.UserName as CreatedByUserName
FROM dbo.IncidentDimvw I With (NOLOCK)
Join WorkItemDimvw WI  With (NOLOCK) on I.BaseManagedEntityId = WI.BaseManagedEntityId

LEFT Join IncidentStatusvw S  With (NOLOCK) on I.Status_IncidentStatusId = s.IncidentStatusId
LEFT Join dbo.DisplayStringDimvw as IncidentStatusString on S.EnumTypeId = IncidentStatusString.BaseManagedEntityId and IncidentStatusString.LanguageCode = 'ENU'

LEFT Join IncidentClassificationvw C on I.Classification_IncidentClassificationId = C.IncidentClassificationId
LEFT Join dbo.DisplayStringDimvw as IncidentClassString on C.EnumTypeId = IncidentClassString.BaseManagedEntityId and IncidentClassString.LanguageCode = 'ENU'

LEFT Join IncidentImpactvw Impact on I.Impact_IncidentImpactId = Impact.IncidentImpactId
LEFT Join dbo.DisplayStringDimvw as IncidentImpactString on Impact.EnumTypeId = IncidentImpactString.BaseManagedEntityId and IncidentImpactString.LanguageCode = 'ENU'

LEFT Join IncidentUrgencyvw Urgency on I.Urgency_IncidentUrgencyId = Urgency.IncidentUrgencyId
LEFT Join dbo.DisplayStringDimvw as IncidentUrgencyString on Urgency.EnumTypeId = IncidentUrgencyString.BaseManagedEntityId and IncidentUrgencyString.LanguageCode = 'ENU'

LEFT Join IncidentResolutionCategoryvw ResCat on I.ResolutionCategory_IncidentResolutionCategoryId = ResCat.IncidentResolutionCategoryId
LEFT Join dbo.DisplayStringDimvw as IncidentResCatString on ResCat.EnumTypeId = IncidentResCatString.BaseManagedEntityId and IncidentResCatString.LanguageCode = 'ENU'

Left Join WorkItemAffectedUserFactvw WIAF on WI.WorkItemDimKey = WIAF.WorkItemDimKey and WIAF.DeletedDate IS NULL
Left Join UserDimvw AffectedUser on WIAF.WorkItemAffectedUser_UserDimKey = AffectedUser.UserDimKey

Left Join WorkItemAssignedToUserFactvw WIAT on WI.WorkItemDimKey = WIAT.WorkItemDimKey and WIAT.DeletedDate IS NULL
Left Join UserDimvw AssignedUser on WIAT.WorkItemAssignedToUser_UserDimKey = AssignedUser.UserDimKey

Left Join WorkItemCreatedByUserFactvw WICB on WI.WorkItemDimKey = WICB.WorkItemDimKey and WICB.DeletedDate IS NULL
Left Join UserDimvw CreatedByUser on WICB.WorkItemCreatedByUser_UserDimKey = CreatedByUser.UserDimKey

Where 1=1
--and I.Id = 'IR124'
--and (

-- AffectedUser.UserName = 'Brody_Kilpatrick' OR
-- Assigneduser.UserName = 'Brody_Kilpatrick' OR
-- CreatedByUser.UserName = 'Brody_Kilpatrick'
-- )

and Status <> ('IncidentStatusEnum.Closed')
GO

Change Requests

/****** Object:  View [dbo].[Custom_ChangeList]    Script Date: 08/29/2011 13:16:37 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE VIEW [dbo].[Custom_ChangeList]
 AS
 Select
CR.BaseManagedEntityId ChangeGUID,
CR.ID ChangeRequestId,
'https://servicemanagerdev/enduser/RequestDetails.aspx?RequestsId=' + Convert(varchar(50),CR.BaseManagedEntityId) + '&RequestType=changeRequest'
AS EndUserPortalLink,
'https://servicemanagerdev/analyst/ChangeRequestDetails.aspx?CRID=' + CONVERT(varchar(50),CR.ID)
AS AnalystPortalLink,
CR.ActualStartDate,
CR.ActualEndDate,
CR.CreatedDate,
CR.Description,
CR.Notes,
CR.PostImplementationReview,
CR.Reason,
CR.RequiredByDate,
CR.Title,
CAString.DisplayName Area,
CCString.DisplayName Category,
CIString.DisplayName Impact,
CImpString.DisplayName ImplementationResults,
CPString.DisplayName Priority,
CRiskString.DisplayName Risk,
CSString.DisplayName 'Status',

AffectedUser.FirstName as AffectedUserFirstName, AffectedUser.LastName as AffectedUserLastName, AffectedUser.DisplayName as AffectedUserDisplayName, AffectedUser.UserName as AffectedUserName,
ContactMethod as AffectedUserContactMethod,
AssignedUser.FirstName as AssignedUserFirstName, AssignedUser.LastName as AssignedUserLastName, AssignedUser.DisplayName as AssignedUserDisplayName, AssignedUser.UserName as AssignedUserName,
CreatedByUser.FirstName as CreatedByUserFirstName, CreatedByUser.LastName as CreatedByUserLastName, CreatedByUser.DisplayName as CreatedByUserDisplayName, CreatedByUser.UserName as CreatedByUserName


FROM dbo.ChangeRequestDimvw CR
Join dbo.WorkItemDimvw WI on CR.BaseManagedEntityId = WI.BaseManagedEntityId

Left Join WorkItemAffectedUserFactvw WIAF on WI.WorkItemDimKey = WIAF.WorkItemDimKey and WIAF.DeletedDate IS NULL
Left Join UserDimvw AffectedUser on WIAF.WorkItemAffectedUser_UserDimKey = AffectedUser.UserDimKey

Left Join WorkItemAssignedToUserFactvw WIAT on WI.WorkItemDimKey = WIAT.WorkItemDimKey and WIAT.DeletedDate IS NULL
Left Join UserDimvw AssignedUser on WIAT.WorkItemAssignedToUser_UserDimKey = AssignedUser.UserDimKey

Left Join WorkItemCreatedByUserFactvw WICB on WI.WorkItemDimKey = WICB.WorkItemDimKey and WICB.DeletedDate IS NULL
Left Join UserDimvw CreatedByUser on WICB.WorkItemCreatedByUser_UserDimKey = CreatedByUser.UserDimKey


Left Join ChangeAreavw CA  With (NOLOCK) on CR.Area_ChangeAreaId = CA.ChangeAreaId
Left Join dbo.DisplayStringDimvw as CAString on CA.EnumTypeId = CAString.BaseManagedEntityId and CAString.LanguageCode = 'ENU'

Left Join ChangeCategoryvw CC  With (NOLOCK) on CR.Category_ChangeCategoryId = CC.ChangeCategoryId
Left Join dbo.DisplayStringDimvw as CCString on CC.EnumTypeId = CCString.BaseManagedEntityId and CCString.LanguageCode = 'ENU'

Left Join ChangeImpactvw CI  With (NOLOCK) on CR.Impact_ChangeImpactId = CI.ChangeImpactId
Left Join dbo.DisplayStringDimvw as CIString on CI.EnumTypeId = CIString.BaseManagedEntityId and CIString.LanguageCode = 'ENU'

Left Join ChangeImplementationResultsvw CImp  With (NOLOCK) on CR.ImplementationResults_ChangeImplementationResultsId = CImp.ChangeImplementationResultsId
Left Join dbo.DisplayStringDimvw as CImpString on CImp.EnumTypeId = CImpString.BaseManagedEntityId and CImpString.LanguageCode = 'ENU'

Left Join ChangePriorityvw CP  With (NOLOCK) on CR.Priority_ChangePriorityId = CP.ChangePriorityId
Left Join dbo.DisplayStringDimvw as CPString on CP.EnumTypeId = CPString.BaseManagedEntityId and CPString.LanguageCode = 'ENU'

Left Join ChangeRiskvw CRisk  With (NOLOCK) on CR.Risk_ChangeRiskId = CRisk.ChangeRiskId
Left Join dbo.DisplayStringDimvw as CRiskString on CRisk.EnumTypeId = CRiskString.BaseManagedEntityId and CRiskString.LanguageCode = 'ENU'

Left Join ChangeStatusvw CS  With (NOLOCK) on CR.Status_ChangeStatusId = CS.ChangeStatusId
Left Join dbo.DisplayStringDimvw as CSString on CS.EnumTypeId = CSString.BaseManagedEntityId and CSString.LanguageCode = 'ENU'
GO


All Activity List

/****** Object:  View [dbo].[Custom_ActivityList]    Script Date: 08/29/2011 13:16:37 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE VIEW [dbo].[Custom_ActivityList]
 AS
 Select
A.BaseManagedEntityId ActivityGUID,
A.Id ActivityId,
Case When ra.ActivityId IS NULL
Then 'https://servicemanagerdev/analyst/ManualActivityDetails.aspx?AID=' + CONVERT(varchar(50),A.Id)
Else 'https://servicemanagerdev/analyst/ReviewActivityDetails.aspx?AID=' + CONVERT(varchar(50),A.Id)
End ActivityLink,
A.Title,
ActualStartDate,
ActualEndDate,
A.CreatedDate,
A.Description,
A.Notes,
ScheduledStartDate,
ScheduledEndDate,

AssignedUser.FirstName as AssignedUserFirstName, AssignedUser.LastName as AssignedUserLastName, AssignedUser.DisplayName as AssignedUserDisplayName, AssignedUser.UserName as AssignedUserName,
CreatedByUser.FirstName as CreatedByUserFirstName, CreatedByUser.LastName as CreatedByUserLastName, CreatedByUser.DisplayName as CreatedByUserDisplayName, CreatedByUser.UserName as CreatedByUserName,

AAString.DisplayName Area,
APString.DisplayName Priority,
AStageString.DisplayName Stage,
AStatusString.DisplayName 'Status'

FROM dbo.ActivityDimvw A
Join WorkItemDimvw WI on A.BaseManagedEntityId = WI.BaseManagedEntityId

Left Join WorkItemAssignedToUserFactvw WIAT on WI.WorkItemDimKey = WIAT.WorkItemDimKey and WIAT.DeletedDate IS NULL
Left Join UserDimvw AssignedUser on WIAT.WorkItemAssignedToUser_UserDimKey = AssignedUser.UserDimKey

Left Join WorkItemCreatedByUserFactvw WICB on WI.WorkItemDimKey = WICB.WorkItemDimKey and WICB.DeletedDate IS NULL
Left Join UserDimvw CreatedByUser on WICB.WorkItemCreatedByUser_UserDimKey = CreatedByUser.UserDimKey


Left Join ActivityAreavw AA  With (NOLOCK) on A.Area_ActivityAreaId= AA.ActivityAreaId
Left Join dbo.DisplayStringDimvw as AAString on AA.EnumTypeId = AAString.BaseManagedEntityId and AAString.LanguageCode = 'ENU'

Left Join ActivityPriorityvw AP  With (NOLOCK) on A.Priority_ActivityPriorityId = AP.ActivityPriorityId
Left Join dbo.DisplayStringDimvw as APString on AP.EnumTypeId = APString.BaseManagedEntityId and APString.LanguageCode = 'ENU'

Left Join ActivityStagevw AStage  With (NOLOCK) on A.Stage_ActivityStageId = AStage.ActivityStageId
Left Join dbo.DisplayStringDimvw as AStageString on AStage.EnumTypeId = AStageString.BaseManagedEntityId and AStageString.LanguageCode = 'ENU'

Left Join ActivityStatusvw AStatus  With (NOLOCK) on A.Status_ActivityStatusId = AStatus.ActivityStatusId
Left Join dbo.DisplayStringDimvw as AStatusString on AStatus.EnumTypeId = AStatusString.BaseManagedEntityId and AStatusString.LanguageCode = 'ENU'

Left Join Custom_ReviewActivityList ra on A.Id = ra.ActivityId
GO




Friday, August 5, 2011

Backing up Management packs when they're modified

(Courtesy of my Co-worker and friend Thomas Bianco) 


So i'm warping up the SCSM project at my client, and one of the value add deliverables i wanted to include was an automatic way to backup their configuration in case they modifiy it later and break something. googling around i found This script to backup management packs, but that's not really what I wanted to do. Some quick modifications and I ended up with this script:


Import-module SMLets

#discover if anything is modified today
$today = Get-Date("{0} 00:00:00" -f (get-date).ToShortDateString()); 
if (Get-SCSMManagementPack | where-object {$_.LastModified -ge $today}) {
    
    #Inscope Definitions
    $OutPutDir = "C:\Management Packs\UnsealedBackups\";
    $UnsealedMPs = Get-SCSMManagementPack | ?{ ! $_.Sealed };
    [string]$CurrentDate = Get-Date -uformat "%Y\%m\%d-%A";
    $CompletePath = ($OutPutDir + $CurrentDate);

    if ( ! (test-path  $CompletePath)) {
        $output = New-Item -Type Directory -Name $CurrentDate -Path $OutPutDir;
    };
    
    $UnsealedMPs | Foreach-Object {
        "   Exporting: {0}" -f $_.Name;
        $_ | Export-SCSMManagementPack -targetdirectory "$CompletePath";
    };
};
Remove-module SMLets -force;
Then i scheduled a task to run it every night at 9:00 PM Local time.

powershell.exe -command "& 'C:\Windows\System32\WindowsPowerShell\v1.0\Examples\Backup-SCSMUnsealedMPs.ps1' "
The bonus on this is that the backup will only be created if any pack was changed today, and you get a nice sorted tree by year\month\date-day
2011\08\05-Friday

Wednesday, July 20, 2011

Four SCSM Self-Service Portal Solutions (certificate, redirect, alias)

When accessing the Self-Service Portal, typing https://servername/enduser into the browser address isn't acceptable for most organizations. This blog posts addresses 4 concerns of the self-service portal and how to resolve them. The information may be common to many IT Professionals; however, it was not common to me, as I have rarely been required to set up IIS sites in the past. I must also mention and thank the source for most of this information, Thomas Bianco, who has challenged me with (I think uncommon) Service Manager questions and answers.

1. Creating a DNS entry for your Self-Service portal
2. Properly creating a certificate to access the Self-Service Portal
3. Automatically redirecting to the end-user portal when typing in that alias
4.  Preventing the need to type in https in front of the site name

For each of these steps, we are going to assume the following:
Self-Service Portal Server Name: SCSM01
Website Name we want to use: ServiceManager.domain.local


1. Creating a DNS entry for your Self-Service portal
  1. Log into DNS for your Active Directory Domain
  2. Go to Forward Lookup Zones
  3. Select you domain
  4. Right click on your domain
  5. Select New Alias (CNAME)
  6. In the Alias Name box type "ServiceManager" (Without the quotes)
  7. In the Fully Qualified Domain Box Type "ServiceManager.domain.local" (Without the quotes)
  8. Click Ok
  9. To test, Browse to https://servicemanager/enduser
  10. You will still receive a certificate error, but should be able to click on to the site

2. Properly creating a certificate to access the Self-Service Portal
  1. Log onto you SCSM Self-Service Portal Server
  2. Start > Run > MMC > File > Add/Remove Snap-in
  3. In the list of snap-ins, select Certificates
  4. Click Add
  5. A window should pop up stating "This snap-in will always maange certificates for:"
  6. Select Computer Account > Next
  7. Select "Local Computer" > Next
  8. Finish
  9. Ok
  10. Expand Certificate (Local Computer) > Personal > Certificates
  11. Right Click > Request New Certificate
  12. Select the Certificate Enrollment Policy
  13. Next
  14. On the enrollment policy click the link labeled "More information is required to enroll for this certificate. Click here to configure settings."
  15. On the Subject tab, on the dropdown box under Type: Populate each field and add them as necessary
  16. Under Alternative name, under Type:  Select DNS
  17. Type in all the names that could be used to access the SSP. For example servicemanager, servicemanager.domain.local, SCSM01, SCSM01.domain.local
  18. Click Add
  19. Select the General Tab and populate the fields
  20. Select the Private Key Tab > Key Options Check the box "Make private key exportable
  21. Select the Certificate Authority Tab
  22. Select the correct certificate authority for your organization
  23. OK
  24. Back on the Certificate Enrollment Window check the "Web Server" box
  25. Click Enroll
Update the SSP with the new certificate
  1. Go to IIS Manager
  2. Select SCSMPortal
  3. Select Bindings
  4. On the HTTPS binding, click edit
  5. In the SSL certificate box, select you new certificate
  6. Click OK
  7. Click Close
The Certificate Error on the Self-Service Portal should no longer exist.


3. Automatically redirecting to the end-user portal when typing in that alias
  1. Open IIS Manager
  2. Select SCSMPortal
  3. Double Click HTTP Redirect (If HTTP Redirect in not installed, go to Roles, Add Features, Select HTTP Redirect)
  4. Check the box "Redirect requests to this destination"
  5. Type in "enduser\" (Without the quotes)
  6. Under redirect behavior make sure "Redirect all requests to exact destination" is UNCHECKED
  7. Under redirect behavior make sure "Only redirect requests to content in the directory" is CHECKED
  8. In the Status Code Select "Found (302)"
  9. Click Apply
  10. Go to the Analyst and enduser vitual directories under SCSMPortal
  11. Select HTTP Redirect
  12. Make sure "redirect requests to this destination" is UNCHECKED
  13. To Test type in https://servicemanager
  14. You should automatically be redirected to https://servicemanager/enduser

4.  Preventing the need to type in https in front of the site name

From Thomas:
[A Client] had a requirement to silently redirect users from their HTTP support site to the new HTTPS. It took me a few hours, but I found out an easy way to do this without redirecting to an absolute path that would break outside access through the firewall. First, I’m using the same redirect we worked out at [Client], then adding in the URL rewrite add-in from http://www.iis.net/download/URLRewrite. The HTTP redirect moves users who hit the website root down to the enduser virtual directory, and the rewrite directives moves connections from HTTP to HTTPS. The only downside is that people going to the root with HTTP get redirected twice, which takes about 1-4 seconds...Feel free to steal this for your blog.

Here's how:
  1. Open IIS Manager
  2. Select SCSMPortal
  3. Select bindings
  4. Click Add
  5. Type: http
  6. IP address: All unassigned
  7. Port: 80
  8. Host Name: Leave Blank
  9. Click OK
  10. If you get a warning about Port 80 being using on the default website, you may want to stop the default website or remove the binding from the default website
  11. Click Close
  12. Install the URL Rewrite utility from http://www.iis.net/download/URLRewrite
  13. Browse to the directory of the SCSM Portal
  14. Backup the web.config file
  15. Open the Web.config file
  16. Paste in the following and save the web.config file:
    <?xml version="1.0" encoding="UTF-8"?>
    <configuration>
    <system.webServer>
    <httpRedirect enabled="true" destination="enduser/" childOnly="true" />
    <rewrite>
    <rules>
    <rule name="HTTP to HTTPS redirect" stopProcessing="true">
    <match url="(.*)" /> <!-- Require SSL must be OFF in the site settings -->
    <conditions>
    <add input="{HTTPS}" pattern="off" ignoreCase="true" />
    </conditions>
    <action type="Redirect" redirectType="Found" url="https://{HTTP_HOST}{REQUEST_URI}" />
    </rule>
    </rules>
    </rewrite>
    </system.webServer>
    </configuration> 

To test, simply type servicemanager into your browser. You should be redirected. 

Monday, July 11, 2011

Changing SCSM Portal Address

Great article on changing the SCSM portal Address
http://memoexp.wordpress.com/2011/03/30/changing-scsm-portal-address/



Ever have a customer request that they want the Self Service Portal to be a specific address, different from the one you’ve initially setup? Well, its not possible to change the URL. However what you can do is set up a CNAME in your DNS to accomplish this goal. Here is how to do it.

1. Go to the DC. Open up DNS under Administrative Tools. Under the DC, expand Forward Lookup Zones, then right click the folder with the domain name, select New Alias (CNAME).
image

2. Under Alias Name, type in the portal URL that you want. Then under target host, drill down and browse to your portal host name, which in my case is SCSM. Click Ok.
image

3. Go to the server which the Portal is installed. Launch IIS Manager, go to the Portal Sites, in my case, SCSMPortal, click onBindings on the right panel.
image

4. Click Add.
image

5. Select Type as httpsIP address as All UnassignedPort as 443. Then select the SSL certificate. Click Ok.
image

6. While highlighting your portal on the left pane, in my case SCSMPortal, Double click HTTP Redirect.
Note! HTTP Redirect is not installed by default for IIS7. To install it, go to Server Manager > Roles > Web Server (IIS), look for Add Role Services, you’ll find that you will have the option to install HTTP Redirection.
image

7. Check Redirect requests to this destination. Key in the full address of the Portal Site, click Apply on the right pane. If you’re not sure, its https:// + Full Computer Name + /enduser. So for my case it is https://scsm.systemcenter.local/enduser
(To get your Full Computer Name, Right click My Computer > Properties. You’ll see it there.)
image

8. Browse to the new URL which in my case is https://servicemanager, the portal should launch without problems.

P/s If you’re getting password prompts when using the new URL, then highlight the portal on the left pane, and double click onAuthentication. Select Basic Authentication and click on Enable on the right pane. Try using the new URL again, you shouldn’t get any prompts now.
image

Tuesday, June 28, 2011

Data warehouse failure concerns answered

I have been having some concerns for the lack of failover options and documentation for the Service Manager data warehouse. I created a forum post which can be seen at http://social.technet.microsoft.com/Forums/en-US/systemcenterservicemanager/thread/1479d2c4-25eb-4aaf-bd0d-9f95618d1a4a/.


If the DW goes down, Service Manager will continue grooming old work items but changes to existing or the creation of new work items won't be copied to the DW. The grooming job will delete any closed work item that has existed for more then your grooming policy setting. (Default settings is 90 days for IR and 365 days for CR and PR).
That means that if your DW goes down on Day 1, it could be down for another 89 days before any incidents created after day 1 will be groomed from your database. And that is if the incidents is closed. When you get your DW back up and running, any work item that was created or changed during the DW downtime will be copied to the DW.
Take a look at this blogpost:http://blogs.technet.com/b/servicemanager/archive/2009/09/18/data-retention-policies-aka-grooming-in-the-servicemanager-database.aspx
Regards//Anders
Anders Asp | Lumagate | www.lumagate.com | Sweden | My blog: www.scsm.se


Monday, June 27, 2011

Attaching Email Screenshots with Service Manager

I am not sure if many people realize this until SCSM is actually installed. But the SCSM out-of-the-box email solution will automatically attach pictures in the body of an email to an incident. I have had people ask me in the past if this is possible, and I would always say, "probably, but it isn't native."

This feature is not available with the Exchange connector, so you might want to use both solutions.

Monday, June 13, 2011

Microsoft Authorization Manager Hotfix is not Need for Server 2008 R2 with SP1

I came across a problem attempting to install the SCSM prerequisite "Authorization Manager Hotfix" when installing SCSM on Server 2008 R2 with SP1. It said that it is not applicable, but it still shows a warning.
IT IS NOT NEEDED. What is my source? Well, unfortunately, a comment made by Travis Wright. But it is good enough for me, and it seems to work fine without it.

I quote "The Authorization Manager hotfix is not required on Win2k8 R2 SP1"


Source: Look in the comments section
http://blogs.technet.com/b/servicemanager/archive/2011/03/04/service-manager-2010-sp1-now-supports-windows-server-2008-r2-windows-7-sp1-and-sql-server-2008-sp2.aspx 

Sunday, June 12, 2011

Service Manager role based security scoping

The below post isn't real new, but it is highly informational. A lot of questions tend to arise around security scoping, and I found a great post, which I wanted to duplicate. The below text was taken from http://scug.be/blogs/scsm/archive/2010/03/21/service-manager-role-based-security-scoping.aspx.


An important aspect in the overall configuration of the Service Manager environment is providing access to the SCSM environment to perform operations. This in a controlled way, so End Users, Operators, Resolvers, Change Owners… can easily access SCSM and perform the their tasks in a controlled environment.
With Role based security scoping in SCSM there is the possibility to configure a controlled environment for different service roles. A SCSM role profile is a configuration set to define access to objects, views in the console, operations they can perform and members of the role (AD User/Group). SCSM components of a User role are:
  • The security scope: Is the security boundary in SCSM. Boundaries can be set on Group/queue, Class, Property & relationships.
  • UI filter scope: This filter is for defining what an operator can see in the SCSM console. Limiting the options visible in the console improves the usability. UI filters can be set on console tasks, templates and views.
  • User role profile: SCSM includes some predefined user profiles who include a set of allowed operations with a class/property/relationship scope over objects.
  • User Assignment: The members of the user role in SCSM. This can be set for users or groups. (Always recommended to use groups)
When configuring role based security scoping we have to think about the profiles that have to be defined in SCSM with the corresponding operations. The different profiles for an implementation is specific and is something that needs to be defined upfront.
The following example “runs” through the creation of the Mail incident resolver role.
Example info:
  • Only incidents from the “Email problem" category need to be visible for the role.
  • The mgmt console Views access is limited.
  • User roles can be controlled with AD security group.

Preparing the Security Scope

As specified above, Security Scope for a user profile can be specified on different levels. This preparation step goes through the creation of the group and the incident queue for further use in the user profile creation.

Create a group in SCSM

Creating a group in the SCSM console is a straightforward task. In this example the
  • In the Service Manager console, click Library, expand Library, and then click Groups.
  • In the Tasks pane, click Create Group.
    • On the Before You Begin page, click Next.
    • On the General page, do the following:
      • Provide a name for the group, such as Email Servers.
      • In the Description text box, type a description for the group.
      • Under Management pack, make sure that an unsealed management pack is selected. In our example we store the information in a dedicated custom mgmt pack.
      • Click Next.
    image
    • On the Included Members page, click Add.
      • In the Select Objects dialog box, select a class such as “Windows Computer”. (Groups can includes members of the same class or from different classes.)
      • In our example select all the Exchange servers in the organization.
      • Click OK, click Next
image
    • On the Dynamic members page, click Next.
    • On the Subgroups page, click Next.
    • On the Excluded Members page, click Next.
    • On the Summary page, confirm the group settings that you made, and then click Create.
    • On the Completion page, make sure that you receive the following confirmation message, and then click Close.

Create the incident queue

Next step in the preparation of the User Role profile configuration is to create a Queue for incidents.
  • In the Library pane, expand Library, and then click Queues.
  • In the Tasks pane, click Create Queue.
  • On the Before You Begin page, click Next.
  • On the General page,
    • type a name in the Queue name box. (In our example, Mail incidents Queue)
    • Work item type box, in the Select a Class dialog box, select a class. In our case “Incident”, and then click OK.
    • In the Management pack list, select the same “roles” mgmt pack that is used to create the group. (keeping the thing together)
    • Click Next.
image
  • On the Criteria page, build the criteria that you want to use to filter work items for the queue, and then click Next
    • In our example, select the Classification Category property in the “Available Properties” area, click Add.
    • In the list, select Email Problems, and then click Next.
    • (more the one criteria can be specified on this page)
image
  • On the Summary page, click Create to create the queue.
  • On the Completion page, click Close.

Create a User role Profile in SCSM

Group and queue are created in the SCSM console, the User Role Profile creation can start. Groups and queues are two configuration items of a User Profile. Mgmt Pack access, Views, templates & tasks are other configuration items in the wizard. If there is a need to limit access to these items then this information needs to be available before the creation of the profile.
Example step-by-step for the email incident resolver user profile:
  • In the Administration pane of the SCSM console, expand Security, and then selectUser Roles.
  • In the Tasks pane under User Roles, select Create User Role, and then select the user role profile.
    • In our example we select the Incident Resolver role.
image
  • On the Before You Begin page, click Next.
  • On the General page, enter a name and description for this user role, and then clickNext.
    • Important Info: on the general page of each predefined role there is a clear description of the rights of the selected role profile.
image
  • On the Management Packs page, select the management packs that contain the data that you want to assigned access to. In our example “select all” and click Next.
image
  • On the Queues page, select the Queues that this user role will have access to, and click Next. Here we use the just created Queue for our Email Incident Resolvers role.
image
  • On the Groups page, select the Groups that this user role will have access to, and clickNext. Here we use the just created Group for our Email Incident Resolvers role.
image
  • On the Tasks page, select the Tasks that this user role will have access to, and clickNext. In our example I don’t limit the available tasks.
image
  • On the Views page, select the Views that this user role will have access to, and clickNext. In our example I want to limit the view in the mgmt console and selected only items from Incident management and configuration management.
image
  • On the Form Templates page, select the Templates that this user role will have access to, and click Next. In our example I don’t limit the available templates.
image
  • On the Users page, click Add, and use the Select Users or Groups dialog box to select users and user groups from Active Directory Domain Services for this user role, and click Next.
image
  • On the Summary page, review settings and click Create.
  • On the Completion page, click Close.

To validate the creation of a user role

  • In the Service Manager console, verify that the newly created user role appears in the middle pane.
  • Log on to the Service Manager console as one of the users assigned to the user role.
    • Verify the access in the mgmt console
    • Verify the Views in the mgmt console
image
  • Only the “Work Items” and “Configuration Items” pane are visible for the user. “Work Items” pane is limited by the Views filter in the configuration of the profile.
  • Only Incidents from the Email queue are visible in the console
  • Read-only access to the configuration items in the console
This is just an example how you can setup a user profile. There are a lot of different roles with different configuration items that can be set in SCSM, all depends on the requirements of the environment. Keep in mind that each additional role profile that is created will have an additional load on the server.
I hope this gives you an idea how to configure role based security scoping for your environment.

Have fun!

Kurt

Wednesday, May 25, 2011

BOOK: System Center Service Manager 2010: Unleashed

System Center Service Manager 2010 is available for pre-order on Amazon. Get it now!

Saturday, May 7, 2011

Move the database in Service Manager 2010

2010-10-16 16:30:00Stefan Allansson

Move the database in Service Manager 2010

If you want to move the SQL database for SCSM to another SQL server, you can do like this:
Start with taking backup of your SCSM database on the first SQL server. 
In SQL server Manager, right click the Service Manager database and choose Tasks\Backup. 
Default choices are ok.
Backup DB SCSM2010
Copy the database backup file to your new SQL server. You can put the file where you want on the server. Open the SQL Manager on the new SQL server and right click “Databases” and choose Restore Database. Fill in the database name and choose “from device” and specify the location for the backup file that you have copied to the new SQL server.
Restore DB SCSM2010
Next step is to do some changes in the registry on the Service Manager Management Server. 
Change the “DatabaseServerName” to your new SQL server under:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\System Center\2010\Common\Database
If you have changed the name on your database when you restored it on the new server you have to change the “DatabaseName” in the registry. Restart the service “System Center Data Access Service” on the Service Manager Management Server and then open the SCSM console. 
Now your Console is connected to your new SQL server.

Sunday, February 13, 2011

Strange issues with the SCSM Mangement Server

I sometimes find strange issues with the SCSM management server. For example, my connectors have not synchronized in several days. Performing a manual synchronization does nothing. When I look in the event log, there are no errors, but there is a sync start/end immediately.

I have found that a restart of all the SCSM services will clear this up. If services restarts do not work, a server restart usually does work.

Tuesday, February 8, 2011

Export all unsealed MPs

http://www.scsm.se/?p=227


Here’s a little powershell script that I use for exporting all unsealed MPs. It’s really useful to run once in a while so you have a backup of all unsealed MPs.
The script will create a new folder with the current date and store all MPs in that folder. Change the $OutPutDir variable to a folder of your choice.
[powershell]
Add-PSSnapin SMCMDLetSnapIn

$OutPutDir = “C:\Unsealed MPs\”
$UnsealedMPs = Get-SCSMManagementPack | ?{ ! $_.Sealed }
$CurrentDate = Get-Date
$CurrentDate = $CurrentDate.ToShortDateString()
$CompletePath = ($OutPutDir + $CurrentDate)

if ( ! (test-path $CompletePath))
{
$output = New-Item -Type Directory -Name $CurrentDate -Path $OutPutDir
}

$UnsealedMPs | %{
” Exporting: {0}” -f $_.Name
$_ | Export-SCSMManagementPack -directory “$CompletePath”
}
[/powershell]

Sunday, February 6, 2011

SharePoint Surveys with SCSM

http://blogs.technet.com/b/servicemanager/archive/2009/12/08/incident-resolution-satisfaction-surveys-on-sharepoint.aspx

SCSM Portal is Slow - I got a suggestion from Travis Wright


I got some more information from one of our devs today.  Try this:
  • Open IIS
  • Select the Application Pools view
  • Select the SM_AppPool application pool (unless your portal is using a different app pool for some reason)
  • Click the Advanced Settings... link in the Actions pane on the right (or in the context menu)
  • Scroll down to the bottom to the Recycling section
  • Change the Regular Time Interval (minutes) option to 0 (never recycle)
That will make sure the portal doesnt just recycle the app pool and require a rebuild just because a certain amount of time has passed.

Monday, January 31, 2011

Enabling Users to Take Action from Email Using Web Pages/Web Services




Travis Wright [MSFT] 
25 Jan 2011 2:22 PM 
4
This is a guest blog post from a Microsoft Consulting Services Senior Consultant – Andreas Rynes.  He has become a Service Manager expert lately and has come up with a really innovative solution I wanted to share with you all.  The scenario that Andreas writes about in this blog post is a way to enable an end user to receive an email notification when his incident is resolved and then to click a link to either reactivate or close the incident.  The link passes the work item ID on the query string and the web page the user is directed to by clicking on the link either updates the incident status to closed or active depending on the link the user clicked.  The exciting thing about this is not just this particular solution but the pattern which can be followed to enable many other types of scenarios for SCSM.  Some other scenarios I could see working with this pattern are: change request approval/reject, going to a web page to provide additional information about an incident, viewing the status of a change request, etc. 
This solution is similar to some of these that we have already published if you are interested in looking at other examples of doing this kind of thing:
Incident Resolution Satisfaction Surveys on SharePoint
Automatically Sending Notifications to Reviewers
Inserting links to Review/Manual Activities in notifications
Thanks for writing this up Andreas and sharing with the community!
====================================================================================================================
During a SCSM session with my customer, while we gathering requirements for their implementation of SCSM, they asked me for the following requirement: whenever an incident is resolved by an analyst the affected end user should be notified with an email. This is nothing special and can be done easily with SCSM workflow features out of the box. So I thought: “yes, of course”, but then they continue with their requirements, that this email should include an option to close or reactivate an incident. The idea behind that requirement is that the end user is the one that can decide if the topic described within the incident was resolved or needs further attention by an analyst.
So the solution is not that complex, but it needs some very different parts to fulfill the requirement. First you need to use the SDK from Service Manager to define methods to close and activate an incident, the second part is the mail template, which can be defined within the Service Manager console and the third part is the workflow that triggers the notification, also managed within the console.
Part I – Visual Studio
1) First I’ve created a solution within Visual Studio. I’ve decided to create a Web Service to implement the functionality for the simple reason that a web service gives you the flexibility to use it both from a web and rich client application.
Start Visual Studio, click on File – New – Web Site … and choose ASP.NET Web Service and give it a meaningful name like SCSMIncidentService
VS creates a template for a asmx web service with three important files called service.cs, service.asmx and a web.config file. I won’t go into detail about SOA architecture or web services and how to implement that within Visual Studio. So I just mention all the details needed for this specific solution.
1) Now go on and remove the already generated first web method “HelloWorld” and implement the SCSM functionality.
2) After that you need to add references to the SDK, for that switch to the Solution Explorer, click on the right mouse button at the project and choose Add Referenceand go to the tab Browse and go to the Service Manager installation folder (normally on C:\Program Files\Microsoft System Center\Service Manager 2010\SDK Binaries and choose all three files there.

3) Then add these using statements in the service.cs file by adding the following lines at the very top:
using Microsoft.EnterpriseManagement;
using Microsoft.EnterpriseManagement.Configuration;
using Microsoft.EnterpriseManagement.Common;

You can also add another namespace, System.Configuration (as shown in the screenshot). I’ll describe later why we could use this one as well.
4) We first start implementing a constructor for the service that initiates all the required classes like the ManagementGroup with either an FQDN or localhost (I’m hosting that service on the same server as the Service Manager Data Access Service) of the Service Manager.
In the second line you’ll see the usage of ConfigurationSettings.AppSettings, which is why we add the System.Configuration namespace to the service. This uses the AppSettings section of the web.config file to gather the Version and PublicKeyToken for the Management Pack. The advantage of using the web.config is that you don’t have to hardcode those values in the code and with every change you would have to re-compile it everytime. If you put those values in the web.config you can just change the xml file.
Then we need the ManagementPack for the Incident class and the enumeration of the status of incidents. We put all these in the constructor of the service class.

5) Then we are going forward to implement the two web methods, I’ve called them CloseIncident and ActivateIncident. Those methods accept the ID from the incident (e.g. IR10) and a string for the current user, who called the method. That mechanism is needed to avoid closing or activating incidents by accident from other users (I’ll describe that feature in a moment). Both methods call another private method called UpdateIncident. That method does the real work and accepts three parameters - those two from the Webmethods and another one that defines if the incident needs to be closed or activated.

6) UpdateIncident has some more lines, but not that much. It initiates another MP that hosts a TypeProjection. This is required to get the Affected User (as this is not part of the Incident class, but is a relationship to a user instance) to compare it with the actual user (we’ll get the user from the security principial context of the webpage).
From that MP we initiate the TypeProjection and with the help of a criteria string that defines the search criteria for the TypeProjection (in this case the incident class is the seed of the TypeProjection) we can use GetObjectProjectionReader to receive the specific incident. If the incident with the specified ID was not found then the method return false. If there is a record found we use a ManagementPackRelationship instance to get the Affected User. Then we compare it with the activeUser string and make sure that the incident is not closed already (because from an ITIL process view a closed incident should not be re-activated again).
The real work is done within two lines of code, set the status to the string that is passed in the UpdateIncident method (close or active) and overwrite the instance.

7) The last thing we need to clarify for the service is the CreateIncidentCriteriaXml method that just returns the criteria that is needed to receive the correct incident. For that we just use a simple expression that uses the ID attribute of the WorkItem as the left part and the searchString as the right part and the equal operator.

So with that, we’ve finished the service.
8) You would be able to test that asmx service already, just press F5. You will get an interface in the browser to test your two webmethod.
Next, we need to create two aspx websites that calls the service and give the user some sort of feedback, if the call was successful or not.
After adding those aspx webpages to your solution go and add a method to each of both, one for activateIncident and one for closeIncident. There are two parameters that we need to get to call the service, the ID of the incident and the name of the current user. For the first parameter we just crawl the QueryString (so we have to set the ID in the URL in the email template later) and for the current user we call the WindowsIdentity.GetCurrent() method. Then initiate the service and call one method per each aspx webpage.
9) After that you’re absolutely free to design the webpage and customize it that it fits your needs and UI definitions and requirements. In my case I’ve just added some positive text if the method returns 0 or some negative text for the value 1.

Part II – eMail Template
Now it’s time to create the email template
Before you create the email template, the second part of our solution, it’s time to configure the notification channels within the SCSM console. Go to Administration – Notifications – Channels and choose the e-Mail Notification Channel and double click it or click on Properties in the task pane. There you need to configure your SMTP server, a return email address and enable the e-mail notification.

After that click on the templates within Administration – Notifications to create your new template.
i) General
Give the template a name and describe it. The most important part on that first page of the wizard is to choose the correct target class, which is Incident in this case and put it in your own management pack.
ii) Template Design
In the Template Design tab you can design your mail, if it’s old-style text email or a HTML formatted mail, the mail subject and the body. For me, I’ve decided to generate an HTML-formatted mail with some fancy stuff like images and different font-styles. The result could looks like this or even better if you like:

You can define your own CSS styles and arrange the text and images where you want them to be. The best way it works for me was using an editor outside of the console and create the entire look and feel there. Then the HTML source can just be copy/pasted into Service Manager’s notification template wizard textbox.
You can see more information about how to create notification templates in this blog post:
http://blogs.technet.com/servicemanager/archive/2009/09/28/creating-notification-templates-in-system-center-service-manager.aspx
The most importing thing is the URL of those two hyperlinks, as we defined two webpages we need to use those and add the incident ID with ?ID=IR10 (we need to replace that in the console with dynamic data from the incident)

Then just paste the complete HTML code to the console template wizard and replace the dynamic text parts with those items from the incident instance with theInsert… button (don’t try to just type the value in – that won’t work. Use the Insert… button).
From there you can choose the attributes from the incident and related entities, which are then placed within the template (both body and subject field). For example you have to replace the URL with <a href="http://atssm/ServiceManagerSample/CloseIncident.aspx?ID=$Context/Property[Type='CustomSystem_WorkItem_Library!System.WorkItem']/Id$">Incident wieder eröffnen</a> (Please note that you have to customize the URL to your own webserver and webapplication!)
The result looks like the screenshot below:

After that you’re done with the template, just click on Next for the Summary tab and finish the wizard.
Part III – Workflow
Now we have the web services/site pages and the email template, now we need the workflow that triggers the entire solution.
Open the console and go to the workflow configuration view that can be found under Administration – Workflow – Configuration. There are some already defined workflow configurations that can be used and we go with the Incident Event Workflow Configuration. After selecting that entry click on Properties in the task pane.

Now you can setup a new workflow that runs whenever an Incident is updated or created.
So click on Add and fill out the Workflow Information that are asked, take care to choose “When an incident is updated” in our case and choose also the correct Management Pack (it makes sense to choose the same as for the template, so that the solution is built in one single MP). And of course, enabling the workflow with the checkbox makes a lot of sense here J

Now we have to define the criteria when the workflow should be triggered. For now we just said whenever an incident is updates (which would be true, if someone just updates a description or any other field on the incident form). So we need to define that this should run only if the Status is changed to Resolved.

So keep the “Changed from” empty as this is not important to us, but add the Status in the “Changed To” tab and enter resolved to the textbox next to it.
So now it’s time to tell the workflow configuration what to do, when it is triggered. In our solution we’d like to Select People to Notify. So in the specific tab make sure the checkbox Enable notification is set and choose Affected User in the ComboBox and choose the new created mail template a couple of minutes before. And don’t forget to click the Add button (I did this from time to time J).

After that setup we are all set and done. Finish the wizard and see if the window for the Incident Event Workflows is updated with your new workflow definition.

Now it’s time to test the complete solution by resolving an incident in the console. Make sure that you have an incident that has an Affected User filled out and that this user has an email-address in the Active Directory and in the Service Manager database, otherwise there will no email be generated. If that’s a test lab environment like it was in my case, you can enter an email address in the CMBD on the user entity form, but make sure that you disable the AD Connector for a test, as it might overwrite the email-address with a blank value again J
In my template, I’m using also the Resolution Category and Comments from the analyst, so I put some more or less useful text in those fields and resolve the incident.

A couple of seconds later the email is generated and showing the correct values from the incident and the option to close or re-activate the incident with a simple click on the specific link.

The user gets a response that his/her incident was closed now (or re-activated) with the HTML page I designed before.
The source files for this solution are attached.
 EMailIncidentSample.zip