Home Self-Service Portal - Community

Custom PS Script Issue - User Input to Activity Description

Ozge_OzkayaOzge_Ozkaya Member Adept IT Monkey ✭✭
Dears,

I am using SCSM 2012 R2 with the latest 2012 version of Cireson Community Portal. Our Silverlight portal is still in use as part of our transition period.

A very good solution has been provided by Gabrial Taylor for writing the user inputs into each SR activity.

https://model-technology.com/blog/scsm-workflow-populate-work-item-data-to-child-activities/

I have been using this solution without any issues in Silverlight Portal. However with the Cireson Portal, the solution is not working as expected and I don't know the reason. The user inputs are successfully captured in SR but the PowerShell script cannot populate them into the activities even though there is no error logged when the script runs.

I really appreciate if you have any idea where the problem might be or any alternative solution that can be used with Cireson Portal.

Here is the JS:

$WorkItemID

PowerShell {
    param(
        [parameter(Mandatory=$true)]$WorkItemID
    )

    #region Variables
    $SMLetsModule = "SMLets"
    [guid]$RelClassGUID_AffectedUser = "dff9be66-38b0-b6d6-6144-a412a3ebd4ce"
    [guid]$RelClassGUID_AssignedToUser = "15e577a3-6bf9-6713-4eac-ba5a5b7c4722"
    [guid]$RelClassGUID_ContainsActivity = "2da498be-0485-b2b2-d520-6ebd1698e61b"
    $VerbosePreference = "Continue"
    #endregion

    #region Functions
    function processUserInput {
        [CmdletBinding()]
        param(
            [parameter(Mandatory=$true)][xml]$UserInput
        )

        ## Create empty Question and Answer Array
        $QAArray = @()

        ## Define variables for each of the Node Types
        $StringNodes = $UserInput.Userinputs.Userinput | where {$_.Type -eq "string"}
        $EnumNodes = $UserInput.Userinputs.Userinput | where {$_.Type -eq "enum"}
        $DateNodes = $UserInput.Userinputs.Userinput | where {$_.Type -eq "datetime"}
        $QueryNodes = $UserInput.Userinputs.Userinput | where {$_.Type -eq "System.SupportingItem.PortalControl.InstancePicker"}
        $BoolNodes = $UserInput.Userinputs.Userinput | where {$_.Type -eq "bool"}

        ## Process String-type Questions and Answers, then add to the Array
        if (($StringNodes | Measure-Object).Count -gt 0) {
            foreach ($strnode in $StringNodes) {
                [string]$StringQuestion = $strnode.Question
                [string]$StringAnswer = $strnode.Answer
                $QAArray += ("$StringQuestion = $StringAnswer")
            }
        }

        ## Process Bool-type Questions and Answers, then add to the Array
        if (($BoolNodes | Measure-Object).Count -gt 0) {
            foreach ($boolnode in $BoolNodes) {
                [string]$BoolQuestion = $boolnode.Question
                [string]$BoolAnswer = $boolnode.Answer
                $QAArray += ("$BoolQuestion = $BoolAnswer")
            }
        }
    
        ## Process Date-type Questions and Answers, then add to the Array
        if (($DateNodes | Measure-Object).Count -gt 0) {
            foreach ($datenode in $DateNodes) {
                [string]$DateQuestion = $datenode.Question
                $RawDateAnswer = [datetime]$datenode.Answer
                [string]$DateAnswer = $RawDateAnswer.ToString("d")
                $QAArray += ("$DateQuestion = $DateAnswer")
            }
        }

        ## Process Enum-type Questions and Answers, then add to the Array
        if (($EnumNodes | Measure-Object).Count -gt 0) {
            foreach ($enumnode in $EnumNodes) {
                    [string]$EnumQuestion = $enumnode.Question
                    $EnumAnswer = $enumnode.Answer
                    $EnumAnswerDetails = Get-SCSMEnumeration -Id $EnumAnswer
                    [string]$AnswerDisplayName = $EnumAnswerDetails.displayname
                    $QAArray += ("$EnumQuestion = $AnswerDisplayName")
                }
        }

        ## Process Query-type Questions and Answers, then add to the Array
        if (($QueryNodes | Measure-Object).Count -gt 0) {
            foreach ($querynode in $QueryNodes) {
                [string]$QueryQuestion = $querynode.question
                [xml]$QueryAnswerXML = $querynode.answer
                if ($QueryAnswerXML.Values.Count -gt 1) {
                    [string]$QueryAnswerDS = ($QueryAnswerXML.Values.Value.DisplayName) -join "; "
                }
                else {
                    [string]$QueryAnswerDS = $QueryAnswerXML.Values.Value.DisplayName
                }
                $QAArray += ("$QueryQuestion = $QueryAnswerDS")
            }
        }

        ## Format the Array into a Multi-Line String
        $QAString = ""
        foreach ($ArrayEntry in $QAArray) {
            $QAString += "$ArrayEntry`n"
        }
        $QAString = $QAString.Substring(0,$QAString.Length-1)

        ## Output the Result
        $QAString
    }

    #endregion

    #region Import SMLets
    ## Set the identity of the default management server for SMLets cmdlets to target to the local computer
    ## Since this script will be running from a workflow, this value will always be the identity of the management server hosting the workflows
    $smdefaultcomputer = $env:COMPUTERNAME

    ## Check whether or not SMLets module has been imported and, if not, import it
    Write-Verbose "[$(Get-Date)] Loading SMLets PowerShell module ..."
    $ExistingModules = (Get-Module | ForEach-Object{$_.name}) -join " "
    If(!$ExistingModules.Contains($SMLetsModule)) {
        Import-Module $SMLetsModule -Force -Verbose:$false
    }
    #endregion

    #region Get Work Item, Assigned To User, and Affected User information
    $WorkItem = Get-SCSMObject -Id $WorkItemID

    $AffectedUserRelObj = $null
    $AffectedUserRelObj = Get-SCSMRelationshipObject -BySource $WorkItem | ?{$_.SourceObject -eq $WorkItem -and $_.IsDeleted -eq $false -and $_.RelationshipId -eq $RelClassGUID_AffectedUser}
    if ($AffectedUserRelObj -ne $null) {
        $AffectedUser = Get-SCSMObject -Id ($AffectedUserRelObj.TargetObject).PSObject.ImmediateBaseObject.Id
    }
    Else {
        $AffectedUser = $null
    }

    $AssignedToUserRelObj = $null
    $AssignedToUserRelObj = Get-SCSMRelationshipObject -BySource $WorkItem | ?{$_.SourceObject -eq $WorkItem -and $_.IsDeleted -eq $false -and $_.RelationshipId -eq $RelClassGUID_AssignedToUser}
    if ($AssignedToUserRelObj -ne $null) {
        $AssignedToUser = Get-SCSMObject -Id ($AssignedToUserRelObj.TargetObject).PSObject.ImmediateBaseObject.Id
    }
    Else {
        $AssignedToUser = $null
    }
    #endregion

    #region Enumerate Child Activities

    ## Get all child activities and store in the array
    $ChildActivities = @()
    [guid[]]$ChildActivityGUIDs = ((Get-SCSMRelationshipObject -BySource $WorkItem | ?{$_.RelationshipID -eq $RelClassGUID_ContainsActivity -and $_.IsDeleted -eq $false}).TargetObject).get_Id()
    if ($ChildActivityGUIDs.count -gt 0) {
        foreach ($GUID in $ChildActivityGUIDs) {
         $ChildActivities += Get-SCSMObject -Id $GUID
        }
    }
    #endregion

    #region Process User Input
    if ($ChildActivities.count -gt 0) {
        $UserInputStr = processUserInput -UserInput $WorkItem.UserInput
    }
    #endregion

    #region Format Parent Work Item Information
    if ($ChildActivities.count -gt 0) {
        $ParentWorkItemInfo = ""
        $LineBreak = "`n"

        $ParentWorkItemInfo += "###### Parent Request Information ######" + $LineBreak
        $ParentWorkItemInfo += "Request Id:   " + $WorkItem.Id + $LineBreak
        If ($AffectedUser -ne $null) {
            $ParentWorkItemInfo += "Requestor:   " + $AffectedUser.DisplayName + " `($($AffectedUser.Domain)\$($AffectedUser.Username)`)" + $LineBreak
        }
        Else {
            $ParentWorkItemInfo += "Requestor:   (None)" + $LineBreak + $LineBreak
        }
        $ParentWorkItemInfo += "Request Description:   " + $WorkItem.Description + $LineBreak + $LineBreak
        $ParentWorkItemInfo += "Currently Assigned Support Group:   " + $WorkItem.SupportGroup.DisplayName + $LineBreak
        If ($AssignedToUser -ne $null) {
            $ParentWorkItemInfo += "Currently Assigned Technician:   " + $AssignedToUser.DisplayName + " `($($AssignedToUser.Domain)\$($AssignedToUser.Username)`)" + $LineBreak + $LineBreak
        }
        Else {
            $ParentWorkItemInfo += "Currently Assigned Technician:   (None)" + $LineBreak + $LineBreak
        }
        $ParentWorkItemInfo += "Request Questions and User Answers:" + $LineBreak + $UserInputStr + $LineBreak
        $ParentWorkItemInfo += "###### End Parent Request Information ######"
    }
    #endregion

    #region Update Activity Descriptions
    if ($ChildActivities.count -gt 0) {
        foreach ($Activity in $ChildActivities) {
            $UpdatedDescription = $Activity.Description + $LineBreak + $ParentWorkItemInfo
            Set-SCSMObject -SMObject $Activity -Property Description -Value $UpdatedDescription
        }
    }
    #endregion

    #region Clean Up
    Remove-Module SMLets -Force
    #endregion
} -args $WorkItemID

Answers

  • Matt_MedleyMatt_Medley Member Advanced IT Monkey ✭✭✭
    Dears,

    I am using SCSM 2012 R2 with the latest 2012 version of Cireson Community Portal. Our Silverlight portal is still in use as part of our transition period.

    A very good solution has been provided by Gabrial Taylor for writing the user inputs into each SR activity.

    https://model-technology.com/blog/scsm-workflow-populate-work-item-data-to-child-activities/

    I have been using this solution without any issues in Silverlight Portal. However with the Cireson Portal, the solution is not working as expected and I don't know the reason. The user inputs are successfully captured in SR but the PowerShell script cannot populate them into the activities even though there is no error logged when the script runs.

    I really appreciate if you have any idea where the problem might be or any alternative solution that can be used with Cireson Portal.

    Here is the JS:

    $WorkItemID

    PowerShell {
        param(
            [parameter(Mandatory=$true)]$WorkItemID
        )

        #region Variables
        $SMLetsModule = "SMLets"
        [guid]$RelClassGUID_AffectedUser = "dff9be66-38b0-b6d6-6144-a412a3ebd4ce"
        [guid]$RelClassGUID_AssignedToUser = "15e577a3-6bf9-6713-4eac-ba5a5b7c4722"
        [guid]$RelClassGUID_ContainsActivity = "2da498be-0485-b2b2-d520-6ebd1698e61b"
        $VerbosePreference = "Continue"
        #endregion

        #region Functions
        function processUserInput {
            [CmdletBinding()]
            param(
                [parameter(Mandatory=$true)][xml]$UserInput
            )

            ## Create empty Question and Answer Array
            $QAArray = @()

            ## Define variables for each of the Node Types
            $StringNodes = $UserInput.Userinputs.Userinput | where {$_.Type -eq "string"}
            $EnumNodes = $UserInput.Userinputs.Userinput | where {$_.Type -eq "enum"}
            $DateNodes = $UserInput.Userinputs.Userinput | where {$_.Type -eq "datetime"}
            $QueryNodes = $UserInput.Userinputs.Userinput | where {$_.Type -eq "System.SupportingItem.PortalControl.InstancePicker"}
            $BoolNodes = $UserInput.Userinputs.Userinput | where {$_.Type -eq "bool"}

            ## Process String-type Questions and Answers, then add to the Array
            if (($StringNodes | Measure-Object).Count -gt 0) {
                foreach ($strnode in $StringNodes) {
                    [string]$StringQuestion = $strnode.Question
                    [string]$StringAnswer = $strnode.Answer
                    $QAArray += ("$StringQuestion = $StringAnswer")
                }
            }

            ## Process Bool-type Questions and Answers, then add to the Array
            if (($BoolNodes | Measure-Object).Count -gt 0) {
                foreach ($boolnode in $BoolNodes) {
                    [string]$BoolQuestion = $boolnode.Question
                    [string]$BoolAnswer = $boolnode.Answer
                    $QAArray += ("$BoolQuestion = $BoolAnswer")
                }
            }
        
            ## Process Date-type Questions and Answers, then add to the Array
            if (($DateNodes | Measure-Object).Count -gt 0) {
                foreach ($datenode in $DateNodes) {
                    [string]$DateQuestion = $datenode.Question
                    $RawDateAnswer = [datetime]$datenode.Answer
                    [string]$DateAnswer = $RawDateAnswer.ToString("d")
                    $QAArray += ("$DateQuestion = $DateAnswer")
                }
            }

            ## Process Enum-type Questions and Answers, then add to the Array
            if (($EnumNodes | Measure-Object).Count -gt 0) {
                foreach ($enumnode in $EnumNodes) {
                        [string]$EnumQuestion = $enumnode.Question
                        $EnumAnswer = $enumnode.Answer
                        $EnumAnswerDetails = Get-SCSMEnumeration -Id $EnumAnswer
                        [string]$AnswerDisplayName = $EnumAnswerDetails.displayname
                        $QAArray += ("$EnumQuestion = $AnswerDisplayName")
                    }
            }

            ## Process Query-type Questions and Answers, then add to the Array
            if (($QueryNodes | Measure-Object).Count -gt 0) {
                foreach ($querynode in $QueryNodes) {
                    [string]$QueryQuestion = $querynode.question
                    [xml]$QueryAnswerXML = $querynode.answer
                    if ($QueryAnswerXML.Values.Count -gt 1) {
                        [string]$QueryAnswerDS = ($QueryAnswerXML.Values.Value.DisplayName) -join "; "
                    }
                    else {
                        [string]$QueryAnswerDS = $QueryAnswerXML.Values.Value.DisplayName
                    }
                    $QAArray += ("$QueryQuestion = $QueryAnswerDS")
                }
            }

            ## Format the Array into a Multi-Line String
            $QAString = ""
            foreach ($ArrayEntry in $QAArray) {
                $QAString += "$ArrayEntry`n"
            }
            $QAString = $QAString.Substring(0,$QAString.Length-1)

            ## Output the Result
            $QAString
        }

        #endregion

        #region Import SMLets
        ## Set the identity of the default management server for SMLets cmdlets to target to the local computer
        ## Since this script will be running from a workflow, this value will always be the identity of the management server hosting the workflows
        $smdefaultcomputer = $env:COMPUTERNAME

        ## Check whether or not SMLets module has been imported and, if not, import it
        Write-Verbose "[$(Get-Date)] Loading SMLets PowerShell module ..."
        $ExistingModules = (Get-Module | ForEach-Object{$_.name}) -join " "
        If(!$ExistingModules.Contains($SMLetsModule)) {
            Import-Module $SMLetsModule -Force -Verbose:$false
        }
        #endregion

        #region Get Work Item, Assigned To User, and Affected User information
        $WorkItem = Get-SCSMObject -Id $WorkItemID

        $AffectedUserRelObj = $null
        $AffectedUserRelObj = Get-SCSMRelationshipObject -BySource $WorkItem | ?{$_.SourceObject -eq $WorkItem -and $_.IsDeleted -eq $false -and $_.RelationshipId -eq $RelClassGUID_AffectedUser}
        if ($AffectedUserRelObj -ne $null) {
            $AffectedUser = Get-SCSMObject -Id ($AffectedUserRelObj.TargetObject).PSObject.ImmediateBaseObject.Id
        }
        Else {
            $AffectedUser = $null
        }

        $AssignedToUserRelObj = $null
        $AssignedToUserRelObj = Get-SCSMRelationshipObject -BySource $WorkItem | ?{$_.SourceObject -eq $WorkItem -and $_.IsDeleted -eq $false -and $_.RelationshipId -eq $RelClassGUID_AssignedToUser}
        if ($AssignedToUserRelObj -ne $null) {
            $AssignedToUser = Get-SCSMObject -Id ($AssignedToUserRelObj.TargetObject).PSObject.ImmediateBaseObject.Id
        }
        Else {
            $AssignedToUser = $null
        }
        #endregion

        #region Enumerate Child Activities

        ## Get all child activities and store in the array
        $ChildActivities = @()
        [guid[]]$ChildActivityGUIDs = ((Get-SCSMRelationshipObject -BySource $WorkItem | ?{$_.RelationshipID -eq $RelClassGUID_ContainsActivity -and $_.IsDeleted -eq $false}).TargetObject).get_Id()
        if ($ChildActivityGUIDs.count -gt 0) {
            foreach ($GUID in $ChildActivityGUIDs) {
             $ChildActivities += Get-SCSMObject -Id $GUID
            }
        }
        #endregion

        #region Process User Input
        if ($ChildActivities.count -gt 0) {
            $UserInputStr = processUserInput -UserInput $WorkItem.UserInput
        }
        #endregion

        #region Format Parent Work Item Information
        if ($ChildActivities.count -gt 0) {
            $ParentWorkItemInfo = ""
            $LineBreak = "`n"

            $ParentWorkItemInfo += "###### Parent Request Information ######" + $LineBreak
            $ParentWorkItemInfo += "Request Id:   " + $WorkItem.Id + $LineBreak
            If ($AffectedUser -ne $null) {
                $ParentWorkItemInfo += "Requestor:   " + $AffectedUser.DisplayName + " `($($AffectedUser.Domain)\$($AffectedUser.Username)`)" + $LineBreak
            }
            Else {
                $ParentWorkItemInfo += "Requestor:   (None)" + $LineBreak + $LineBreak
            }
            $ParentWorkItemInfo += "Request Description:   " + $WorkItem.Description + $LineBreak + $LineBreak
            $ParentWorkItemInfo += "Currently Assigned Support Group:   " + $WorkItem.SupportGroup.DisplayName + $LineBreak
            If ($AssignedToUser -ne $null) {
                $ParentWorkItemInfo += "Currently Assigned Technician:   " + $AssignedToUser.DisplayName + " `($($AssignedToUser.Domain)\$($AssignedToUser.Username)`)" + $LineBreak + $LineBreak
            }
            Else {
                $ParentWorkItemInfo += "Currently Assigned Technician:   (None)" + $LineBreak + $LineBreak
            }
            $ParentWorkItemInfo += "Request Questions and User Answers:" + $LineBreak + $UserInputStr + $LineBreak
            $ParentWorkItemInfo += "###### End Parent Request Information ######"
        }
        #endregion

        #region Update Activity Descriptions
        if ($ChildActivities.count -gt 0) {
            foreach ($Activity in $ChildActivities) {
                $UpdatedDescription = $Activity.Description + $LineBreak + $ParentWorkItemInfo
                Set-SCSMObject -SMObject $Activity -Property Description -Value $UpdatedDescription
            }
        }
        #endregion

        #region Clean Up
        Remove-Module SMLets -Force
        #endregion
    } -args $WorkItemID

    Hey Ozge, did you find a solution to this issue with the script and the Cireson portal?
Sign In or Register to comment.