Home Advanced Request Offering

grabbing inputs that are generated from @autocomplete queries

alex_kokinalex_kokin Member IT Monkey ✭
edited July 2020 in Advanced Request Offering

I have hit this hurdle several times now where my runbook cannot see the data from a field using the @autocomplete.

what exactly needs to be done so the runbook can see the data in the input.

in this case I created a new class to get all the Collections from SCCM. The query work perfectly providing the collections. When you select a collection and save, the runbook fails because there is no collection passed to it from the field.




Answers

  • Justin_WorkmanJustin_Workman Cireson Support Super IT Monkey ✭✭✭✭✭

    @alex_kokin - You have 2 options. Either fetch the Related Item(or Affected Item depending on which relationship you configure the Query Result prompt to use), or have a step in the runbook that parses the UserInput property of the SR and pulls out the answer to the SCCM Collection prompt.

  • James_JohnsonJames_Johnson Customer Advanced IT Monkey ✭✭✭

    Hi @alex_kokin

    I just recently ran into this problem myself. I wrote this powershell to grab the data out from the user input field. In this script I have an example of the data at the top saved to a string which parses it out and puts it in variables I return from the runbook activity to use in other steps. Let me know if you have any questions about it.

    $UserInput = '<UserInputs><UserInput Question="Department" Answer="&lt;Values Count=&quot;1&quot;&gt;&lt;Value DisplayName=&quot;Research Tech Support&quot; Id=&quot;97204c95-bf98-3f76-63cb-a0c0e23fb92f&quot;/&gt;&lt;/Values&gt;" Type="System.SupportingItem.PortalControl.InstancePicker" /><UserInput Question="Display Name" Answer="test 1 2 3" Type="string" /></UserInputs>'
    
    
    
    
    
    
    function ParseInput($inputString){
        $UserInputs = ((($inputString | Select-String '(?<=<UserInputs>)(.*)(?=</UserInputs>)').Matches.Value).Split('<*>') | Select-String '(?<=UserInput )(.*)(?=/)').Matches.Value
        $parsedAnswers = @()
        foreach($inpt in $UserInputs){
            $question = ($inpt | Select-String -Pattern '(?<=Question=")([^"]*)(?=")').Matches.Value
            $answer = ($inpt | Select-String -Pattern '(?<=Answer=")([^"]*)(?=")').Matches.Value
            $type = ($inpt | Select-String -Pattern '(?<=Type=")([^"]*)(?=")').Matches.Value
            $tempObj = [PSCustomObject] @{
                Question = $question
                Answer = ParseAnswer $answer
                Type = $type
            }
    
    
            $parsedAnswers = $parsedAnswers + $tempObj
    
    
        }
        return $parsedAnswers
    }
    
    
    function ParseAnswer($inputString){
        
        $clean = $inputString.Replace('&quot;','"').replace('&gt;', '>').replace('&lt;','<')
        [System.Collections.ArrayList]$split = $clean.split('<*>', [System.StringSplitOptions]::RemoveEmptyEntries) 
        
        if($split.count -le 1){
            return $split
        }
    
    
        $split.Remove("/Values")
        $count = ($split[0] | Select-String -Pattern '(?<=Count=")([^"]*)(?=")').Matches.Value
        $split.RemoveAt(0)
    
    
        $vals = @()
        foreach($s in $split){
            $dict = @{}
            $props = ($s | Select-String -pattern '(?<=\s)([\w\d]*)(?==")' -AllMatches).Matches.Value
            foreach($p in $props){
                $pattern = '(?<=' + $p + '=")([^"]*)(?=")'
                $val = ($s | Select-String -Pattern $pattern).Matches.Value
                $dict.Add($p, $val)
    
    
            }
            $vals = $vals + $dict
        }
        return $vals
    }
    
    
    
    
    $parsedData = ParseInput $UserInput
    
    
    $DisplayName = $parsedData[1].Answer
    $Department = $parsedData[0].Answer["DisplayName"]
    $UserName = ($parsedData[1].Answer).Replace(" ","_")
    
    
    
  • Brian_WiestBrian_Wiest Customer Super IT Monkey ✭✭✭✭✭

    I also have a similar PS script.

    This script will take the user input and break it down by types to return a question and answer array.

    but when needed to pull specifics out I create the variable in the specific section. The script pulls out the CI user GUID that you can then pass to the next step of the runbook to Get-Object AD user to pull all their CI data. Also have the User input in @" "@ to account for users typing weird stuff into the free form txt boxes.

    HTH

    [xml]$UserInput = @"
    XXXXXXXXXXXXXX
    "@
    
    ## Create empty Question and Answer Array
    $QAArray = @()
    
    ## Define variables for each of the Node Types
    $StringNodes = $UserInput.Userinputs.Userinput | Where-Object {$_.Type -eq "string"}
    $IntNodes = $UserInput.Userinputs.Userinput | Where-Object {$_.Type -eq "int"}
    $EnumNodes = $UserInput.Userinputs.Userinput | Where-Object {$_.Type -eq "enum"}
    $DateNodes = $UserInput.Userinputs.Userinput | Where-Object {$_.Type -eq "datetime"}
    $QueryNodes = $UserInput.Userinputs.Userinput | Where-Object {$_.Type -eq "System.SupportingItem.PortalControl.InstancePicker"}
    $BoolNodes = $UserInput.Userinputs.Userinput | Where-Object {$_.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 String-type Questions and Answers, then add to the Array
    if (($IntNodes | Measure-Object).Count -gt 0) {
        foreach ($IntNode in $IntNodes) {
            [string]$IntQuestion = $IntNode.Question
            [string]$IntAnswer = $IntNode.Answer
            $QAArray += ("$IntQuestion = $IntAnswer")
        }
    }
    
    ## 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
    
    
Sign In or Register to comment.