From 58392d01600b35c0ba10ec5ec5b4ecfe03197970 Mon Sep 17 00:00:00 2001 From: catgwalker <78571293+CATgwalker@users.noreply.github.com> Date: Mon, 12 Jan 2026 12:10:28 -0600 Subject: [PATCH 1/5] Add -IncludeMRVS parameter and functionality to return multi-row variable sets from Get-ServiceNowRecord --- ServiceNow/Public/Get-ServiceNowRecord.ps1 | 101 +++++++++++++++++++-- 1 file changed, 95 insertions(+), 6 deletions(-) diff --git a/ServiceNow/Public/Get-ServiceNowRecord.ps1 b/ServiceNow/Public/Get-ServiceNowRecord.ps1 index 23f88f5..e605e20 100644 --- a/ServiceNow/Public/Get-ServiceNowRecord.ps1 +++ b/ServiceNow/Public/Get-ServiceNowRecord.ps1 @@ -55,6 +55,13 @@ A property named 'CustomVariable' will be added to the return object. You can get the value with $return.CustomVariable.CustomVarName.Value. +.PARAMETER IncludeMRVS + Include custom variables in the return object. + Some records may have associated custom variables, some may not. + For instance, an RITM may have custom variables, but the associated tasks may not. + A property named 'MRVS' will be added to the return object. + You can get the value with $return.MRVS. + .PARAMETER AsValue Return the underlying value instead of pscustomobject. Only valid when the Property parameter is set to 1 item. @@ -171,7 +178,7 @@ function Get-ServiceNowRecord { [CmdletBinding(DefaultParameterSetName = 'Id', SupportsPaging)] [Alias('gsnr')] - Param ( + param ( [Parameter(ParameterSetName = 'Table', Mandatory)] [Parameter(ParameterSetName = 'TableId', Mandatory)] [Parameter(ParameterSetName = 'TableParentId')] @@ -230,6 +237,9 @@ function Get-ServiceNowRecord { [Parameter()] [switch] $IncludeCustomVariable, + [Parameter()] + [switch] $IncludeMRVS, + [Parameter()] [switch] $AsValue, @@ -343,6 +353,85 @@ function Get-ServiceNowRecord { $result | Add-Member @{'sys_class_name' = $Table } } + if ( $IncludeMRVS) { + foreach ($record in $result) { + + $recordSysId = if ($DisplayValue -eq 'all') { $record.sys_id.value } else { $record.sys_id } + + $MRVSParams = @{ + Table = 'sc_multi_row_question_answer' + Filter = @('parent_id', '-eq', $recordSysId) + Property = 'row_index', 'sc_item_option.item_option_new.sys_name', 'sc_item_option.item_option_new.name', 'value', 'sc_item_option.sys_id', 'sc_item_option.item_option_new.type', 'sc_item_option.item_option_new.question_text', 'sc_item_option.item_option_new.reference', 'sc_item_option.item_option_new.variable_set' + IncludeTotalCount = $true + ServiceNowSession = $ServiceNowSession + } + + # suppress warning when getting total count + $MRVSOut = Get-ServiceNowRecord @MRVSParams -WarningAction SilentlyContinue + $MRVSOut = $MRVSOut | Group-Object row_index + + $record | Add-Member @{ + 'MRVS' = @() + } + + foreach ($MRVSRow in $MRVSOut) { + $flattenMRVSresult = [pscustomobject] @{ + 'row_index' = $MRVSRow.name + } + + $MRVSRow.group | ForEach-Object { + if ($_.'sc_item_option.item_option_new.name') { + $flattenMRVSresult | Add-Member -Name $_.'sc_item_option.item_option_new.name' -Value $_.value -member NoteProperty + } else { + $flattenMRVSresult | Add-Member -Name $_.'sc_item_option.item_option_new.sys_name' -Value $_.value -member NoteProperty + } + + $flattenMRVSresult | Add-Member -Name 'variable_set' -Value $_.'sc_item_option.item_option_new.variable_set' -member NoteProperty -Force + + # show the underlying value if the option is a reference type + if ($_.'sc_item_option.item_option_new.type' -eq 'Reference') { + #do not do any further lookup when the value is blank or null + #resolves #234 and #262 + if ($_.'value' -eq "" -or $null -eq $_.'value') { + continue + } + $sysidPattern = "[0-9a-fA-F]{32}" + $sysid = [Regex]::Matches($_.'value', $sysidPattern).Value + if ($sysid) { + Write-Verbose "Custom variable lookup for $($flattenMRVSresult.name) from table '$($_.'sc_item_option.item_option_new.reference')' sysid:'$($_.'value')'" + # issue 234. ID might not be sysid or number for reference...odd + $refValue = Get-ServiceNowRecord -Table $_.'sc_item_option.item_option_new.reference' -ID $_.'value' -Property name -AsValue -ServiceNowSession $ServiceNowSession -ErrorAction SilentlyContinue + if ($refValue) { + if ($_.'sc_item_option.item_option_new.name') { + # Prefix the name onto the ReferenceTable/ReferenceID values when there are multiple references used in an MRVS + $flattenMRVSresult | Add-Member @{"$($_.'sc_item_option.item_option_new.name')_ReferenceTable" = $_.'sc_item_option.item_option_new.reference' } + $flattenMRVSresult | Add-Member @{"$($_.'sc_item_option.item_option_new.name')_ReferenceID" = $_.'value' } + # Rewrite the value to be the retrieved name from the reference ID + $flattenMRVSresult | Add-Member -Name $_.'sc_item_option.item_option_new.name' -Value $refValue -member NoteProperty -Force + } else { + # Prefix the name onto the ReferenceTable/ReferenceID values when there are multiple references used in an MRVS + $flattenMRVSresult | Add-Member @{"$($_.'sc_item_option.item_option_new.sys_name')_ReferenceTable" = $_.'sc_item_option.item_option_new.reference' } + $flattenMRVSresult | Add-Member @{"$($_.'sc_item_option.item_option_new.sys_name')_ReferenceID" = $_.'value' } + # Rewrite the value to be the retrieved name from the reference ID + $flattenMRVSresult | Add-Member -Name $_.'sc_item_option.item_option_new.sys_name' -Value $refValue -member NoteProperty -Force + } + } + } + + } + } + + $record.MRVS += $flattenMRVSresult + } + + if ( $addedSysIdProp ) { + $record | Select-Object -Property * -ExcludeProperty sys_id + } else { + $record + } + } + } + if ( $IncludeCustomVariable ) { # for each record, get the variable names and then get the variable values @@ -391,11 +480,11 @@ function Get-ServiceNowRecord { $newVar | Add-Member @{'ReferenceID' = $var.'sc_item_option.value' } # issue 234. ID might not be sysid or number for reference...odd $refValue = Get-ServiceNowRecord -Table $var.'sc_item_option.item_option_new.reference' -ID $var.'sc_item_option.value' -Property name -AsValue -ServiceNowSession $ServiceNowSession -ErrorAction SilentlyContinue - if ( $refValue ) { - $newVar.Value = $refValue - } - } - + if ( $refValue ) { + $newVar.Value = $refValue + } + } + } if ( $var.'sc_item_option.item_option_new.name' ) { From d23ef85a7476d1ee79e5aa60c1cb9edc1ffc6be0 Mon Sep 17 00:00:00 2001 From: catgwalker <78571293+CATgwalker@users.noreply.github.com> Date: Mon, 12 Jan 2026 12:30:06 -0600 Subject: [PATCH 2/5] Corrections to Parameter documentation. --- ServiceNow/Public/Get-ServiceNowRecord.ps1 | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ServiceNow/Public/Get-ServiceNowRecord.ps1 b/ServiceNow/Public/Get-ServiceNowRecord.ps1 index e605e20..58d065c 100644 --- a/ServiceNow/Public/Get-ServiceNowRecord.ps1 +++ b/ServiceNow/Public/Get-ServiceNowRecord.ps1 @@ -56,9 +56,9 @@ You can get the value with $return.CustomVariable.CustomVarName.Value. .PARAMETER IncludeMRVS - Include custom variables in the return object. - Some records may have associated custom variables, some may not. - For instance, an RITM may have custom variables, but the associated tasks may not. + Include variable sets in the return object. + Some records may have associated variable sets, some may not. + For instance, an RITM may have variable sets, but the associated tasks may not. A property named 'MRVS' will be added to the return object. You can get the value with $return.MRVS. From e52381c524fad767ca9ccadb5b4bc5515bde09c6 Mon Sep 17 00:00:00 2001 From: CATgwalker <78571293+CATgwalker@users.noreply.github.com> Date: Mon, 8 Jun 2026 16:35:26 -0500 Subject: [PATCH 3/5] Correct syntax to prevent duplicate record returns --- ServiceNow/Public/Get-ServiceNowRecord.ps1 | 160 +++++++++++---------- 1 file changed, 82 insertions(+), 78 deletions(-) diff --git a/ServiceNow/Public/Get-ServiceNowRecord.ps1 b/ServiceNow/Public/Get-ServiceNowRecord.ps1 index 58d065c..a902539 100644 --- a/ServiceNow/Public/Get-ServiceNowRecord.ps1 +++ b/ServiceNow/Public/Get-ServiceNowRecord.ps1 @@ -343,6 +343,7 @@ function Get-ServiceNowRecord { } [array]$result = Invoke-ServiceNowRestMethod @thisParams + Write-Verbose "Received $(($result | Measure-Object).count) records`r`n" if ( -not $result ) { return @@ -353,7 +354,82 @@ function Get-ServiceNowRecord { $result | Add-Member @{'sys_class_name' = $Table } } - if ( $IncludeMRVS) { + if ( $IncludeCustomVariable ) { + + # for each record, get the variable names and then get the variable values + foreach ($record in $result) { + + Write-Verbose "Checking $($result.IndexOf($record)) record of results for custom variables`r`n" + $recordSysId = if ($DisplayValue -eq 'all') { $record.sys_id.value } else { $record.sys_id } + + # YES_NO = 1; MULTI_LINE_TEXT = 2; MULTIPLE_CHOICE = 3; NUMERIC_SCALE = 4; SELECT_BOX = 5; SINGLE_LINE_TEXT = 6; CHECKBOX = 7; REFERENCE = 8; DATE = 9; DATE_TIME = 10; LABEL = 11; BREAK = 12; MACRO = 14; UI_PAGE = 15; WIDE_SINGLE_LINE_TEXT = 16; MACRO_WITH_LABEL = 17; LOOKUP_SELECT_BOX = 18; CONTAINER_START = 19; CONTAINER_END = 20; LIST_COLLECTOR = 21; LOOKUP_MULTIPLE_CHOICE = 22; HTML = 23; SPLIT = 24; MASKED = 25; + + $customVarParams = @{ + Table = 'sc_item_option_mtom' + Filter = @('request_item', '-eq', $recordSysId), 'and', @('sc_item_option.item_option_new.type', '-in', '1,2,3,4,5,6,7,8,9,10,16,18,21,22,26') + Property = 'sc_item_option.item_option_new.sys_name', 'sc_item_option.item_option_new.name', 'sc_item_option.value', 'sc_item_option.sys_id', 'sc_item_option.item_option_new.type', 'sc_item_option.item_option_new.question_text', 'sc_item_option.item_option_new.reference' + IncludeTotalCount = $true + ServiceNowSession = $ServiceNowSession + } + + # suppress warning when getting total count + $customVarsOut = Get-ServiceNowRecord @customVarParams -WarningAction SilentlyContinue + + if ($customVarsOut) { + Write-Verbose "Received $(($customVarsOut | Measure-Object).count) CustomVariable results`r`n" + $record | Add-Member @{ + 'CustomVariable' = [pscustomobject]@{} + } + + foreach ($var in $customVarsOut) { + $newVar = [pscustomobject] @{ + Name = if ($var.'sc_item_option.item_option_new.name') { $var.'sc_item_option.item_option_new.name' } else { $var.'sc_item_option.item_option_new.sys_name' } + Value = $var.'sc_item_option.value' + DisplayName = $var.'sc_item_option.item_option_new.question_text' + Type = $var.'sc_item_option.item_option_new.type' + SysId = $var.'sc_item_option.sys_id' + } + + # show the underlying value if the option is a reference type + if ( $newVar.Type -eq 'Reference' ) { + #do not do any further lookup when the value is blank or null + #resolves #234 and 262 + if ($var.'sc_item_option.value' -eq "" -or $null -eq $var.'sc_item_option.value') { + continue + } + $sysidPattern = "[0-9a-fA-F]{32}" + $sysid = [Regex]::Matches($var.'sc_item_option.value', $sysidPattern).Value + if ($sysid) { + Write-Verbose "Custom variable lookup for $($newvar.name) from table '$($var.'sc_item_option.item_option_new.reference')' sysid:'$($var.'sc_item_option.value')'" + $newVar | Add-Member @{'ReferenceTable' = $var.'sc_item_option.item_option_new.reference' } + $newVar | Add-Member @{'ReferenceID' = $var.'sc_item_option.value' } + # issue 234. ID might not be sysid or number for reference...odd + $refValue = Get-ServiceNowRecord -Table $var.'sc_item_option.item_option_new.reference' -ID $var.'sc_item_option.value' -Property name -AsValue -ServiceNowSession $ServiceNowSession -ErrorAction SilentlyContinue + if ( $refValue ) { + $newVar.Value = $refValue + } + } + } + + if ( $var.'sc_item_option.item_option_new.name' ) { + $record.CustomVariable | Add-Member @{ $var.'sc_item_option.item_option_new.name' = $newVar } + } else { + $record.CustomVariable | Add-Member @{ $var.'sc_item_option.item_option_new.question_text' = $newVar } + } + } + + if ( $addedSysIdProp ) { + $record | Select-Object -Property * -ExcludeProperty sys_id + } else { + $record + } + } else { + Write-Verbose "No CustomVariable results`r`n" + } + } + } + + if ( $IncludeMRVS ) { foreach ($record in $result) { $recordSysId = if ($DisplayValue -eq 'all') { $record.sys_id.value } else { $record.sys_id } @@ -371,7 +447,7 @@ function Get-ServiceNowRecord { $MRVSOut = $MRVSOut | Group-Object row_index $record | Add-Member @{ - 'MRVS' = @() + 'MRVS' = [pscustomobject]@{} } foreach ($MRVSRow in $MRVSOut) { @@ -380,12 +456,6 @@ function Get-ServiceNowRecord { } $MRVSRow.group | ForEach-Object { - if ($_.'sc_item_option.item_option_new.name') { - $flattenMRVSresult | Add-Member -Name $_.'sc_item_option.item_option_new.name' -Value $_.value -member NoteProperty - } else { - $flattenMRVSresult | Add-Member -Name $_.'sc_item_option.item_option_new.sys_name' -Value $_.value -member NoteProperty - } - $flattenMRVSresult | Add-Member -Name 'variable_set' -Value $_.'sc_item_option.item_option_new.variable_set' -member NoteProperty -Force # show the underlying value if the option is a reference type @@ -432,76 +502,10 @@ function Get-ServiceNowRecord { } } - if ( $IncludeCustomVariable ) { - - # for each record, get the variable names and then get the variable values - foreach ($record in $result) { - - $recordSysId = if ($DisplayValue -eq 'all') { $record.sys_id.value } else { $record.sys_id } - - # YES_NO = 1; MULTI_LINE_TEXT = 2; MULTIPLE_CHOICE = 3; NUMERIC_SCALE = 4; SELECT_BOX = 5; SINGLE_LINE_TEXT = 6; CHECKBOX = 7; REFERENCE = 8; DATE = 9; DATE_TIME = 10; LABEL = 11; BREAK = 12; MACRO = 14; UI_PAGE = 15; WIDE_SINGLE_LINE_TEXT = 16; MACRO_WITH_LABEL = 17; LOOKUP_SELECT_BOX = 18; CONTAINER_START = 19; CONTAINER_END = 20; LIST_COLLECTOR = 21; LOOKUP_MULTIPLE_CHOICE = 22; HTML = 23; SPLIT = 24; MASKED = 25; - - $customVarParams = @{ - Table = 'sc_item_option_mtom' - Filter = @('request_item', '-eq', $recordSysId), 'and', @('sc_item_option.item_option_new.type', '-in', '1,2,3,4,5,6,7,8,9,10,16,18,21,22,26') - Property = 'sc_item_option.item_option_new.sys_name', 'sc_item_option.item_option_new.name', 'sc_item_option.value', 'sc_item_option.sys_id', 'sc_item_option.item_option_new.type', 'sc_item_option.item_option_new.question_text', 'sc_item_option.item_option_new.reference' - IncludeTotalCount = $true - ServiceNowSession = $ServiceNowSession - } - - # suppress warning when getting total count - $customVarsOut = Get-ServiceNowRecord @customVarParams -WarningAction SilentlyContinue - - $record | Add-Member @{ - 'CustomVariable' = [pscustomobject]@{} - } - - foreach ($var in $customVarsOut) { - $newVar = [pscustomobject] @{ - Name = if ($var.'sc_item_option.item_option_new.name') { $var.'sc_item_option.item_option_new.name' } else { $var.'sc_item_option.item_option_new.sys_name' } - Value = $var.'sc_item_option.value' - DisplayName = $var.'sc_item_option.item_option_new.question_text' - Type = $var.'sc_item_option.item_option_new.type' - SysId = $var.'sc_item_option.sys_id' - } - - # show the underlying value if the option is a reference type - if ( $newVar.Type -eq 'Reference' ) { - #do not do any further lookup when the value is blank or null - #resolves #234 and 262 - if ($var.'sc_item_option.value' -eq "" -or $null -eq $var.'sc_item_option.value') { - continue - } - $sysidPattern = "[0-9a-fA-F]{32}" - $sysid = [Regex]::Matches($var.'sc_item_option.value', $sysidPattern).Value - if ($sysid) { - Write-Verbose "Custom variable lookup for $($newvar.name) from table '$($var.'sc_item_option.item_option_new.reference')' sysid:'$($var.'sc_item_option.value')'" - $newVar | Add-Member @{'ReferenceTable' = $var.'sc_item_option.item_option_new.reference' } - $newVar | Add-Member @{'ReferenceID' = $var.'sc_item_option.value' } - # issue 234. ID might not be sysid or number for reference...odd - $refValue = Get-ServiceNowRecord -Table $var.'sc_item_option.item_option_new.reference' -ID $var.'sc_item_option.value' -Property name -AsValue -ServiceNowSession $ServiceNowSession -ErrorAction SilentlyContinue - if ( $refValue ) { - $newVar.Value = $refValue - } - } - - } - - if ( $var.'sc_item_option.item_option_new.name' ) { - $record.CustomVariable | Add-Member @{ $var.'sc_item_option.item_option_new.name' = $newVar } - } else { - $record.CustomVariable | Add-Member @{ $var.'sc_item_option.item_option_new.question_text' = $newVar } - } - } - - if ( $addedSysIdProp ) { - $record | Select-Object -Property * -ExcludeProperty sys_id - } else { - $record - } - } - } else { - + if (-not ($IncludeCustomVariable.IsPresent -or $IncludeMRVS.IsPresent) ) { + Write-Verbose "IncludeCustomVariable: $($IncludeCustomVariable.IsPresent)" + Write-Verbose "IncludeMRVS: $($IncludeMRVS.IsPresent)" + Write-Verbose 'IncludeCustomVariable or IncludeMRVS params not passed' # format the results if ( $Property ) { if ( $Property.Count -eq 1 -and $AsValue ) { From 87bd9bd7b99a3ad033cfde964e840ea067f908e1 Mon Sep 17 00:00:00 2001 From: CATgwalker <78571293+CATgwalker@users.noreply.github.com> Date: Mon, 8 Jun 2026 16:41:54 -0500 Subject: [PATCH 4/5] Restore MRVS result values --- ServiceNow/Public/Get-ServiceNowRecord.ps1 | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/ServiceNow/Public/Get-ServiceNowRecord.ps1 b/ServiceNow/Public/Get-ServiceNowRecord.ps1 index a902539..aa20789 100644 --- a/ServiceNow/Public/Get-ServiceNowRecord.ps1 +++ b/ServiceNow/Public/Get-ServiceNowRecord.ps1 @@ -456,6 +456,12 @@ function Get-ServiceNowRecord { } $MRVSRow.group | ForEach-Object { + if ($_.'sc_item_option.item_option_new.name') { + $flattenMRVSresult | Add-Member -Name $_.'sc_item_option.item_option_new.name' -Value $_.value -member NoteProperty + } else { + $flattenMRVSresult | Add-Member -Name $_.'sc_item_option.item_option_new.sys_name' -Value $_.value -member NoteProperty + } + $flattenMRVSresult | Add-Member -Name 'variable_set' -Value $_.'sc_item_option.item_option_new.variable_set' -member NoteProperty -Force # show the underlying value if the option is a reference type From 717c600569133ca966b2099603a66298dba70c7f Mon Sep 17 00:00:00 2001 From: CATgwalker <78571293+CATgwalker@users.noreply.github.com> Date: Mon, 8 Jun 2026 17:08:34 -0500 Subject: [PATCH 5/5] Revert MRVS initialization to array to support addition. --- ServiceNow/Public/Get-ServiceNowRecord.ps1 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ServiceNow/Public/Get-ServiceNowRecord.ps1 b/ServiceNow/Public/Get-ServiceNowRecord.ps1 index aa20789..a389be3 100644 --- a/ServiceNow/Public/Get-ServiceNowRecord.ps1 +++ b/ServiceNow/Public/Get-ServiceNowRecord.ps1 @@ -59,7 +59,7 @@ Include variable sets in the return object. Some records may have associated variable sets, some may not. For instance, an RITM may have variable sets, but the associated tasks may not. - A property named 'MRVS' will be added to the return object. + A property named will be added to the return object. You can get the value with $return.MRVS. .PARAMETER AsValue @@ -447,7 +447,7 @@ function Get-ServiceNowRecord { $MRVSOut = $MRVSOut | Group-Object row_index $record | Add-Member @{ - 'MRVS' = [pscustomobject]@{} + 'MRVS' = @() } foreach ($MRVSRow in $MRVSOut) {