Свойство, переданное в Invoke-Command, изменяет тип с IDictionary на HashTable.

Я получаю сообщение об ошибке при запуске Invoke-Command, где блок скрипта принимает параметр типа словаря:

Невозможно обработать преобразование аргумента для параметра «словарь». Невозможно преобразовать значение «System.Collections.Hashtable» типа «System.Collections.Hashtable» в тип «System.Collections.Generic.IDictionary`2 [System.String, System.String]». В строке: 7 знаков: 1 + Invoke-Command -ComputerName. -ArgumentList $ dictionary -ScriptBlock ... + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo: InvalidData: (:) [], ParameterBindin ... mationException + FullyQualifiedErrorId: ParameterArgumentTransformationError + PSComputerName: localhost

После долгих поисков я смог сократить сценарий до MVP ниже, чтобы показать корень этой проблемы:

[System.Collections.Generic.IDictionary[string, string]]$dictionary = New-Object -TypeName 'System.Collections.Generic.Dictionary[string, string]' 
$dictionary.Add('one', 'hello')
$dictionary.Add('two', 'world')
Write-Verbose "Main Script $($dictionary.GetType().FullName)" -Verbose #outputs: VERBOSE: Before System.Collections.Generic.Dictionary`2[[System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089],[System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]
Invoke-Command -ComputerName . -ArgumentList $dictionary -ScriptBlock {
    Param (
        #[System.Collections.Generic.IDictionary[string, string]] #if I leave this in I get a conversion error
        $dictionary
    )
    Write-Verbose "Function before $($dictionary.GetType().FullName)" -Verbose #outputs: VERBOSE: After System.Collections.Hashtable
    function Poc {} #this line seems to cause the `$dictionary` to become a HashTable
    Write-Verbose "Function after $($dictionary.GetType().FullName)" -Verbose #outputs: VERBOSE: After System.Collections.Hashtable

}

Кажется, что если блок скрипта для Invoke-Command включает какие-либо встроенные функции, тогда параметр автоматически преобразуется в HashTable; в то время как, если блок скрипта не содержит определений вложенных функций, параметр остается как System.Collections.Generic.IDictionary[string, string].

Использую ли я эту функцию неправильно / есть ли общий обходной путь? Или это просто ошибка в PowerShell?


person JohnLBevan    schedule 20.08.2019    source источник
comment
Ух ты. Я всегда думал, что это основная проблема PS. Но никогда не думал об ошибке. mkelement0 отвечает на это аккуратно, и я рекомендую постоянно хранить этот вопрос. Привлечение внимания модератора к заморозке этого вопроса. Это один из основных недостатков PS, который может помочь всем. Спасибо за ваши усилия   -  person Ranadip Dutta    schedule 20.08.2019


Ответы (1)


Это известная проблема с кодом десериализации, который используется в удаленном взаимодействии PowerShell (на чем основан Invoke-Command -ComputerName), к сожалению, начиная с PowerShell Core 7.0.0-preview.2:

При десериализации любой объект, реализующий интерфейс IDictionary, неправильно считается всегда обычным, неуниверсальным [hashtable] [1] и десериализуется как таковой.

Это особенно проблематично, когда исходный объект был упорядоченным словарем [2], потому что упорядочение ключей теряется, как и возможность индексировать их.

См. этот выпуск GitHub, который помечен как "доступный для всех". , что означает, что сообщество может предложить PR, который устраняет проблему.


[1] System.Collections.Hashtable, можно создать в PowerShell с @{ ... } литералами, где ключи и значения имеют [object] тип.

[2] Например, _7 _, создаваемый в PowerShell с [ordered] @{ ... } литералами, а также с [object]-типизированными ключами и значениями (не универсальный); удивительно, что на момент написания этой статьи не существует универсального упорядоченного типа словаря - см. этот вопрос.

person mklement0    schedule 20.08.2019
comment
Извините, если я говорю как нуб, но я хочу прояснить это. Что вы подразумеваете под неуниверсальной хеш-таблицей? Вы имеете в виду только заказ? - person Ranadip Dutta; 20.08.2019
comment
@RanadipDutta: Пожалуйста, посмотрите мое обновление; аспекты упорядочивания и использования универсального типа не связаны. И неупорядоченный (@{ ... }), и упорядоченный ([ordered] @{ ... }) типы, которые поддерживает PowerShell, не являются универсальными. (И, что удивительно, в настоящее время нет универсального упорядоченного словаря - см. stackoverflow.com/q/2629027/ 45375.) - person mklement0; 20.08.2019