[英]Powershell Data Malformed with Splatting
我正在使用自定義 function,它使用 API 導入數據。 function 需要幾個不同的參數,我目前正在使用一個 $Params 哈希表來定義這些參數。 從那里我添加其他參數,這些參數可能會或可能不會根據某些條件添加。 我注意到在哈希表中存儲所有參數不能正常工作,但只有在 function 調用中特別指定時才會工作。
當前不起作用的代碼的基本版本是:
$ExtraParam = 'ccc'
$Params = @{
Par1 = 'aaa'
Par2 = 'bbb'
}
$Params.Par3 = $ExtraParam
Import-APIData @Params
API 返回以下錯誤消息: {"errorId":"error.request.invalidRepresentation.malformed","errorCode":0,"message":"Invalid parameter value was specified."}
但是,如果我運行以下代碼,它可以正常工作:
$ExtraParam = 'abc'
$Params = @{
Par1 = '123'
Par2 = '456'
}
Import-APIData @Params -Par3 $ExtraParam
我已經驗證進入 function 的參數都是正確的類型。 我正在調用的自定義 function 是專有的,因此我無法共享整個 function,但我只是想知道是否有任何東西可以重新格式化哈希表中的參數,而不是在 ZC1C425268E68384F1A4Z 調用中顯式調用它。 鑒於這兩塊代碼本質上是相同的,我希望有人能指出一些可能導致頂部無法工作的根本區別。
根據評論者的要求,這里是實際的 function。 底部的 _CallAPI function 實際調用的是 API。 我將無法分享它,但使用它正上方的$Params
output(在代碼中注釋掉)可能足以解決問題。
function Update-ICUser {
<#
.SYNOPSIS
Updates user on a Gensys ICWS server.
.PARAMETER ICSession
string ICSession. ICSession to update a user.
.PARAMETER Id
string Id. Id of the user to update.
.PARAMETER InputObject
object InputObject. Full IC User is needed.
.PARAMETER Argument
string Argument. Any query string parameters associated with the Api call.
.Example
$ICSession = New-ICSession -ComputerName server1 -Credential $Credential
Get-ICUser -Id user1 -Full |Update-ICUser -ICSession $ICsession -Extension 1234
Example 1: Update a user's extension.
#>
[CmdletBinding()]
param (
[Parameter(Mandatory,
Position = 0)]
[ICSession]$ICSession,
[Parameter(Mandatory,
ValueFromPipeline,
ParameterSetName = 'InputObject',
Position = 1)]
[object]$InputObject,
[Parameter(Mandatory,
ParameterSetName = 'Manual',
Position = 2)]
[string]$Id,
[Parameter(ParameterSetName = 'Manual',
Position = 3)]
[Parameter(ParameterSetName = 'InputObject')]
[string]$DisplayName,
[Parameter(ParameterSetName = 'Manual',
Position = 4)]
[Parameter(ParameterSetName = 'InputObject')]
[string]$OutboundAni,
[Parameter(ParameterSetName = 'Manual',
Position = 5)]
[Parameter(ParameterSetName = 'InputObject')]
[string]$Title,
[Parameter(ParameterSetName = 'Manual',
Position = 6)]
[Parameter(ParameterSetName = 'InputObject')]
[string]$OfficeLocation,
[Parameter(ParameterSetName = 'Manual',
Position = 7)]
[Parameter(ParameterSetName = 'InputObject')]
[string]$Notes,
[Parameter(ParameterSetName = 'Manual',
Position = 8)]
[Parameter(ParameterSetName = 'InputObject')]
[int]$Cost = 0,
[Parameter(ParameterSetName = 'Manual',
Position = 9)]
[Parameter(ParameterSetName = 'InputObject')]
[bool]$AutoAnswerAcdInteractions = $false,
[Parameter(ParameterSetName = 'Manual',
Position = 10)]
[Parameter(ParameterSetName = 'InputObject')]
[bool]$AutoAnswerNonAcdInteractions = $true,
[Parameter(ParameterSetName = 'Manual',
Position = 11)]
[Parameter(ParameterSetName = 'InputObject')]
[string]$ApplicationId = 'InteractionDesktop',
[Parameter(ParameterSetName = 'Manual',
Position = 12)]
[Parameter(ParameterSetName = 'InputObject')]
[bool]$ExcludeFromDirectory = $false,
[Parameter(ParameterSetName = 'Manual',
Position = 13)]
[Parameter(ParameterSetName = 'InputObject')]
[string]$Extension,
[Parameter(ParameterSetName = 'Manual',
Position = 14)]
[Parameter(ParameterSetName = 'InputObject')]
[bool]$FaxCapability = $false,
[Parameter(ParameterSetName = 'Manual',
Position = 15)]
[Parameter(ParameterSetName = 'InputObject')]
[bool]$OutlookIntegrationEnabled = $false,
[Parameter(ParameterSetName = 'Manual',
Position = 16)]
[Parameter(ParameterSetName = 'InputObject')]
[string]$FirstName,
[Parameter(ParameterSetName = 'Manual',
Position = 17)]
[Parameter(ParameterSetName = 'InputObject')]
[string]$LastName,
[Parameter(ParameterSetName = 'Manual',
Position = 18)]
[Parameter(ParameterSetName = 'InputObject')]
[string[]]$WorkgroupList,
[Parameter(ParameterSetName = 'Manual',
Position = 19)]
[Parameter(ParameterSetName = 'InputObject')]
[string]$DepartmentName,
[Parameter(ParameterSetName = 'Manual',
Position = 20)]
[Parameter(ParameterSetName = 'InputObject')]
[string]$City,
[Parameter(ParameterSetName = 'Manual',
Position = 21)]
[Parameter(ParameterSetName = 'InputObject')]
[string]$PostalCode,
[Parameter(ParameterSetName = 'Manual',
Position = 22)]
[Parameter(ParameterSetName = 'InputObject')]
[string]$State,
[Parameter(ParameterSetName = 'Manual',
Position = 23)]
[Parameter(ParameterSetName = 'InputObject')]
[string]$StreetAddress,
[Parameter(ParameterSetName = 'Manual',
Position = 24)]
[Parameter(ParameterSetName = 'InputObject')]
[int]$HomeSite,
[Parameter(ParameterSetName = 'Manual',
Position = 25)]
[Parameter(ParameterSetName = 'InputObject')]
[string[]]$LicenseList,
[Parameter(ParameterSetName = 'Manual',
Position = 26)]
[Parameter(ParameterSetName = 'InputObject')]
[string[]]$RoleList
)
Try {
if ($InputObject) {
$User = $InputObject
$Id = $InputObject.configurationId.id
}
else {
$User = Get-ICUser -ICSession $ICSession -Id $Id -Full
}
'Id','InputObject','ICSession' |Foreach-Object {
$PSBoundParameters.Remove($PSItem) |Out-Null
}
$PSBoundParameters.GetEnumerator() |Foreach-Object {
if ($PSItem.Key -in ('Title','DepartmentName','City','State','StreetAddress','FirstName','LastName','Notes')) {
if ($PSItem.Key -in ('State','FirstName','LastName')) {
$Key = switch ($PSItem.Key) {
'State' {'stateOrProvince'}
'FirstName' {'givenName'}
'LastName' {'surName'}
}
}
else {
$Key = $PSItem.Key
}
$User.personalInformationProperties.$Key = $PSItem.Value
}
elseif ($PSItem.Key -in ('WorkgroupList','LicenseList','RoleList')) {
$Key = $PSItem.Key
if ($Key = 'WorkgroupList' -and $WorkgroupList) {
[array]$Value = Get-ICWorkgroup -ICSession $SessionKey -Id $WorkgroupList
$User.Workgroups = $Value
}
if ($Key = 'LicenseList' -and $LicenseList) {
$Value = @((Get-ICLicenseAllocation -ICSession $SessionKey -Id $LicenseList).configurationId)
if ($User.licenseProperties.PSobject.Properties.name -match 'additionalLicenses') {
$User.licenseProperties.additionalLicenses = $Value
}
else {
$User.licenseProperties | Add-Member -MemberType NoteProperty -Name 'additionalLicenses' -Value $Value -Force
}
}
if ($Key = 'RoleList' -and $RoleList) {
[array]$Value = Get-ICRole -ICSession $SessionKey -Id $RoleList
if ($User.roles.PSobject.Properties.name -match 'actualValue') {
$User.Roles.actualValue = $Value
}
else {
$User.roles | Add-Member -MemberType NoteProperty -Name 'actualValue' -Value $Value -Force
}
}
}
else {
$Key = $PSItem.Key
$Value = $PSItem.Value
$User |Add-Member -MemberType NoteProperty -Name $Key -Value $Value -Force
}
}
$Body = $User |ConvertTo-Json -Depth 5
$Params = @{
Area = $Configuration.Area.Configuration
Resource = $Configuration.Resource.Users
ICSession = $ICSession
Id = $Id
Method = 'Put'
ContentType = 'application/json'
Body = $Body
}
# $Params
_CallApi @Params
}
Catch {
_ExceptionError
}
}
我還將在控制台上提供所有內容。 在此示例中, $AutoAnswerAcd
參數是失敗的參數,但我已經讓它失敗並通過添加/刪除其他參數來工作。 我還沒有檢測到使它失敗的模式,除了它總是在 splat 之外工作。 你可以在下面看到這個模式。
PS C:\> $SessionKey = New-ICSession -ComputerName $server -Credential $Credential
PS C:\> $Params = @{
>> ICSession = $SessionKey
>> Id = 'tautomation'
>> WorkgroupList = "MultiSite-UserSpan"
>> RoleList = "Business User"
>> LicenseList = "I3_ACCESS_RECORDER"
>> DepartmentName = "Infr & Ops"
>> Title = "Process Automation Engineer"
>> OfficeLocation = "Remote"
>> AutoAnswerAcdInteractions = $true
>> }
PS C:\> Update-ICUser @Params
Exception: C:\Repos\ICTools\Code\Private\_ExceptionError.ps1:10
Line |
10 | throw "$($Exception)`n$($Exception.Exception.Message)"
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| {"errorId":"error.request.invalidRepresentation.malformed","errorCode":0,"message":"Invalid parameter value was specified."} Response status code does not indicate
| success: 400 (Bad Request). {"errorId":"error.request.invalidRepresentation.malformed","errorCode":0,"message":"Invalid parameter value was specified."} Response status
| code does not indicate success: 400 (Bad Request).
PS C:\> $Params = @{
>> ICSession = $SessionKey
>> Id = 'tautomation'
>> WorkgroupList = "MultiSite-UserSpan"
>> RoleList = "Business User"
>> LicenseList = "I3_ACCESS_RECORDER"
>> DepartmentName = "Infr & Ops"
>> Title = "Process Automation Engineer"
>> OfficeLocation = "Remote"
>> }
PS C:\> Update-ICUser @Params
id uri
-- ---
tautomation /configuration/users/tautomation
PS C:\> Update-ICUser @Params -AutoAnswerAcdInteractions $true
id uri
-- ---
tautomation /configuration/users/tautomation
PS C:\>
謝謝!
好的,所以我想我已經找到了發生了什么。
首先,這是您的代碼的檢測版本,它在運行時會提供一些日志 output - 這將有助於查看哪里出錯了......
function Update-ICUser {
[CmdletBinding()]
param (
[Parameter(Mandatory,
Position = 0)]
[string]$ICSession,
[Parameter(Mandatory,
ValueFromPipeline,
ParameterSetName = 'InputObject',
Position = 1)]
[object]$InputObject,
[Parameter(Mandatory,
ParameterSetName = 'Manual',
Position = 2)]
[string]$Id,
[Parameter(ParameterSetName = 'Manual',
Position = 3)]
[Parameter(ParameterSetName = 'InputObject')]
[string]$DisplayName,
[Parameter(ParameterSetName = 'Manual',
Position = 4)]
[Parameter(ParameterSetName = 'InputObject')]
[string]$OutboundAni,
[Parameter(ParameterSetName = 'Manual',
Position = 5)]
[Parameter(ParameterSetName = 'InputObject')]
[string]$Title,
[Parameter(ParameterSetName = 'Manual',
Position = 6)]
[Parameter(ParameterSetName = 'InputObject')]
[string]$OfficeLocation,
[Parameter(ParameterSetName = 'Manual',
Position = 7)]
[Parameter(ParameterSetName = 'InputObject')]
[string]$Notes,
[Parameter(ParameterSetName = 'Manual',
Position = 8)]
[Parameter(ParameterSetName = 'InputObject')]
[int]$Cost = 0,
[Parameter(ParameterSetName = 'Manual',
Position = 9)]
[Parameter(ParameterSetName = 'InputObject')]
[bool]$AutoAnswerAcdInteractions = $false,
[Parameter(ParameterSetName = 'Manual',
Position = 10)]
[Parameter(ParameterSetName = 'InputObject')]
[bool]$AutoAnswerNonAcdInteractions = $true,
[Parameter(ParameterSetName = 'Manual',
Position = 11)]
[Parameter(ParameterSetName = 'InputObject')]
[string]$ApplicationId = 'InteractionDesktop',
[Parameter(ParameterSetName = 'Manual',
Position = 12)]
[Parameter(ParameterSetName = 'InputObject')]
[bool]$ExcludeFromDirectory = $false,
[Parameter(ParameterSetName = 'Manual',
Position = 13)]
[Parameter(ParameterSetName = 'InputObject')]
[string]$Extension,
[Parameter(ParameterSetName = 'Manual',
Position = 14)]
[Parameter(ParameterSetName = 'InputObject')]
[bool]$FaxCapability = $false,
[Parameter(ParameterSetName = 'Manual',
Position = 15)]
[Parameter(ParameterSetName = 'InputObject')]
[bool]$OutlookIntegrationEnabled = $false,
[Parameter(ParameterSetName = 'Manual',
Position = 16)]
[Parameter(ParameterSetName = 'InputObject')]
[string]$FirstName,
[Parameter(ParameterSetName = 'Manual',
Position = 17)]
[Parameter(ParameterSetName = 'InputObject')]
[string]$LastName,
[Parameter(ParameterSetName = 'Manual',
Position = 18)]
[Parameter(ParameterSetName = 'InputObject')]
[string[]]$WorkgroupList,
[Parameter(ParameterSetName = 'Manual',
Position = 19)]
[Parameter(ParameterSetName = 'InputObject')]
[string]$DepartmentName,
[Parameter(ParameterSetName = 'Manual',
Position = 20)]
[Parameter(ParameterSetName = 'InputObject')]
[string]$City,
[Parameter(ParameterSetName = 'Manual',
Position = 21)]
[Parameter(ParameterSetName = 'InputObject')]
[string]$PostalCode,
[Parameter(ParameterSetName = 'Manual',
Position = 22)]
[Parameter(ParameterSetName = 'InputObject')]
[string]$State,
[Parameter(ParameterSetName = 'Manual',
Position = 23)]
[Parameter(ParameterSetName = 'InputObject')]
[string]$StreetAddress,
[Parameter(ParameterSetName = 'Manual',
Position = 24)]
[Parameter(ParameterSetName = 'InputObject')]
[int]$HomeSite,
[Parameter(ParameterSetName = 'Manual',
Position = 25)]
[Parameter(ParameterSetName = 'InputObject')]
[string[]]$LicenseList,
[Parameter(ParameterSetName = 'Manual',
Position = 26)]
[Parameter(ParameterSetName = 'InputObject')]
[string[]]$RoleList
)
if ($InputObject) {
$User = $InputObject
$Id = $InputObject.configurationId.id
}
else {
$User = [pscustomobject] @{
personalInformationProperties = [pscustomobject] @{
DepartmentName = $null
Title = $null
}
licenseProperties = [pscustomobject] @{}
roles = [pscustomobject] @{}
Workgroups = $null
}
#Get-ICUser -ICSession $ICSession -Id $Id -Full
}
#write-host "user = '$($User |ConvertTo-Json -Depth 5)'"
'Id','InputObject','ICSession' |Foreach-Object {
$PSBoundParameters.Remove($PSItem) |Out-Null
}
$PSBoundParameters.GetEnumerator() |Foreach-Object {
write-host "processing key '$($PSItem.Key)'"
if ($PSItem.Key -in ('Title','DepartmentName','City','State','StreetAddress','FirstName','LastName','Notes')) {
if ($PSItem.Key -in ('State','FirstName','LastName')) {
$Key = switch ($PSItem.Key) {
'State' {'stateOrProvince'}
'FirstName' {'givenName'}
'LastName' {'surName'}
}
}
else {
$Key = $PSItem.Key
}
$User.personalInformationProperties.$Key = $PSItem.Value
}
elseif ($PSItem.Key -in ('WorkgroupList','LicenseList','RoleList')) {
$Key = $PSItem.Key
if ($Key = 'WorkgroupList' -and $WorkgroupList) {
write-host " WorkgroupList - casting to array"
#$Value = @( Get-ICWorkgroup -ICSession $SessionKey -Id $WorkgroupList )
[array] $Value = @()
#$User.Workgroups = $Value
}
if ($Key = 'LicenseList' -and $LicenseList) {
write-host " LicenseList - casting to array"
#$Value = @((Get-ICLicenseAllocation -ICSession $SessionKey -Id $LicenseList).configurationId)
$Value = @()
if ($User.licenseProperties.PSobject.Properties.name -match 'additionalLicenses') {
$User.licenseProperties.additionalLicenses = $Value
}
else {
$User.licenseProperties | Add-Member -MemberType NoteProperty -Name 'additionalLicenses' -Value $Value -Force
}
}
if ($Key = 'RoleList' -and $RoleList) {
write-host " RoleList - casting to array"
#[array]$Value = Get-ICRole -ICSession $SessionKey -Id $RoleList
[array]$Value = @()
if ($User.roles.PSobject.Properties.name -match 'actualValue') {
$User.Roles.actualValue = $Value
}
else {
$User.roles | Add-Member -MemberType NoteProperty -Name 'actualValue' -Value $Value -Force
}
}
}
else {
write-host "adding key '$($PSItem.Key)' with value '$($PSItem.Value)'"
write-host " value before is '$($Value.GetType().FullName)'"
$Key = $PSItem.Key
write-host " value after is '$($Value.GetType().FullName)'"
$Value = $PSItem.Value
#write-host ($PSItem.Key | convertto-json)
#write-host ($PSItem.Value | convertto-json)
#write-host $PSItem.Key.GetType().FullNane
#write-host $PSItem.Value.GetType().FullNane
#write-host "user before = '$($User |ConvertTo-Json -Depth 5)'"
$User |Add-Member -MemberType NoteProperty -Name $Key -Value $Value -Force
#write-host "user after = '$($User |ConvertTo-Json -Depth 5)'"
}
}
$Body = $User |ConvertTo-Json -Depth 5
write-host $Body
}
當你調用它時,例如:
$Params = @{
ICSession = "aaa"
Id = 'tautomation'
WorkgroupList = "MultiSite-UserSpan"
RoleList = "Business User"
LicenseList = "I3_ACCESS_RECORDER"
DepartmentName = "Infr & Ops"
Title = "Process Automation Engineer"
OfficeLocation = "Remote"
AutoAnswerAcdInteractions = $true
}
Update-ICUser @Params
你得到這個 output:
processing key 'DepartmentName'
processing key 'OfficeLocation'
adding key 'OfficeLocation' with value 'Remote'
processing key 'Title'
processing key 'WorkgroupList'
WorkgroupList - casting to array
LicenseList - casting to array
RoleList - casting to array
processing key 'AutoAnswerAcdInteractions'
adding key 'AutoAnswerAcdInteractions' with value 'True'
value before is 'System.Object[]'
value after is 'System.Object[]'
processing key 'RoleList'
WorkgroupList - casting to array
LicenseList - casting to array
RoleList - casting to array
processing key 'LicenseList'
WorkgroupList - casting to array
LicenseList - casting to array
RoleList - casting to array
{
"personalInformationProperties": {
"DepartmentName": "Infr & Ops",
"Title": "Process Automation Engineer"
},
"licenseProperties": {
"additionalLicenses": []
},
"roles": {
"actualValue": []
},
"Workgroups": null,
"OfficeLocation": "Remote",
"AutoAnswerAcdInteractions": [
true
]
}
所以有幾點需要注意:
投射到數組
在處理每個參數( WorkgroupList
、 RoleList
和LicenseList
)時, casting to array
似乎被記錄下來。
如果您看,您的代碼正在執行此操作: if ($Key = 'WorkgroupList' -and $WorkgroupList)
but =
is an assignment operator ,而不是比較運算符,所以您真正想要的是if ($Key -eq 'WorkgroupList' -and $WorkgroupList)
if ($Key = 'LicenseList' -and $LicenseList)
和if ($Key = 'RoleList' -and $RoleList)
也一樣 - 也將它們更改為-eq
,這是一個被踩踏的錯誤......
添加鍵“AutoAnswerAcdInteractions”,值為“True”
$Value
變量在分配參數值之前和之后都是System.Object[]
類型。 如果您查看日志中的前一個參數,您會看到WorkgroupList - casting to array
- 這是將$Value
的類型更改為數組。 將來任何分配值的嘗試都會自動將該值轉換為數組,因此$true
變為[ $true ]
,這就是您的問題所在。
請注意,在RoleList
中發生了相同的演員陣容,但不是在LicenseList
中。
由於在哈希表或$PSBoundParameters
中無法保證鍵的順序,因此僅在以下情況下才會出現問題:
$WorkgroupList
或$RoleList
在 function 調用中指定$AutoAnswerAcdInteractions
之前被枚舉要解決此問題,請將WorkgroupList
和RoleList
重構為與LicenseList
相同 - 即,而不是:
[array]$Value = <expression>
使用數組子表達式運算符:
$Value = @( <expression> )
這將確保存儲在變量中的值是一個數組,而不會更改未來參數的變量類型。
請注意,額外參數似乎起作用的原因是它改變了$PSBoundParameters
中項目的順序。 例如:
$Params = @{
ICSession = "aaa"
Id = 'tautomation'
WorkgroupList = "MultiSite-UserSpan"
RoleList = "Business User"
LicenseList = "I3_ACCESS_RECORDER"
DepartmentName = "Infr & Ops"
Title = "Process Automation Engineer"
OfficeLocation = "Remote"
}
Update-ICUser @Params -AutoAnswerAcdInteractions $true
給出這個 output
processing key 'AutoAnswerAcdInteractions'
adding key 'AutoAnswerAcdInteractions' with value 'True'
processing key 'DepartmentName'
processing key 'Title'
processing key 'WorkgroupList'
WorkgroupList - casting to array
processing key 'RoleList'
RoleList - casting to array
processing key 'LicenseList'
LicenseList - casting to array
processing key 'OfficeLocation'
adding key 'OfficeLocation' with value 'Remote'
value before is 'System.Object[]'
value after is 'System.Object[]'
{
"personalInformationProperties": {
"DepartmentName": "Infr & Ops",
"Title": "Process Automation Engineer"
},
"licenseProperties": {
"additionalLicenses": []
},
"roles": {
"actualValue": []
},
"Workgroups": null,
"AutoAnswerAcdInteractions": true,
"OfficeLocation": [
"Remote"
]
}
請注意, AutoAnswerAcdInteractions
在任何將$Value
類型更改為數組的路徑之前處理。
順便說一句,如果您省略WorkgroupList
和RoleList
代碼也可以工作,因為$Value
永遠不會更改為數組:
$Params = @{
ICSession = "aaa"
Id = 'tautomation'
#WorkgroupList = "MultiSite-UserSpan"
#RoleList = "Business User"
LicenseList = "I3_ACCESS_RECORDER"
DepartmentName = "Infr & Ops"
Title = "Process Automation Engineer"
OfficeLocation = "Remote"
AutoAnswerAcdInteractions = $true
}
Update-ICUser @Params
使用 output:
processing key 'OfficeLocation'
adding key 'OfficeLocation' with value 'Remote'
processing key 'Title'
processing key 'AutoAnswerAcdInteractions'
adding key 'AutoAnswerAcdInteractions' with value 'True'
value before is 'System.String'
value after is 'System.String'
processing key 'DepartmentName'
processing key 'LicenseList'
LicenseList - casting to array
{
"personalInformationProperties": {
"DepartmentName": "Infr & Ops",
"Title": "Process Automation Engineer"
},
"licenseProperties": {
"additionalLicenses": []
},
"roles": {},
"Workgroups": null,
"OfficeLocation": "Remote",
"AutoAnswerAcdInteractions": true
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.