Ошибка PowerShell? не может передать свойство computername в get-service
Похоже, ошибка, нет? В этом случае powershell преобразует хеш-таблицу в строку '@{computername=comp001}' и пытается использовать ее с -Name (ByValue) вместо -ComputerName (ByPropertyName). Даже PS 6 делает это. Трубопровод "get-service -name *" работает нормально.
PS C:\> [pscustomobject]@{computername='comp001'} | get-service
get-service : Cannot find any service with service name '@{computername=comp001}'.
At line:1 char:45
+ [pscustomobject]@{computername='comp001'} | get-service
+ ~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (@{computername=comp001}:String)
[Get-Service], ServiceCommandException
+ FullyQualifiedErrorId :
NoServiceFoundForGivenName,Microsoft.PowerShell.Commands.GetServiceCommand
2 ответа
Похоже, ошибка, нет?
Не ошибка как таковая, но неожиданное следствие разработки параметров Get-Service
командлет:
Пометить типизированный параметр [string]
/ [string[]]
или же [object]
/ [object[]]
(или же [psobject]
/ [psobject[]]
) с ValueFromPipeline
Атрибут делает этот параметр привязанным к любому входу конвейера, возможно, в дополнение к привязке к другим параметрам - если только этот параметр не связан аргументом командной строки, который является вашим -Name *
обходной путь делает.
- Причина в том, что экземпляры любого типа данных могут быть преобразованы в
[string]
/ получены из[object]
([psobject]
), вызывая привязку всех входных объектов, независимо от типа, к этому параметру.
Короче говоря, проблема здесь не в том [pscustomobject]@{computername='comp001'}
не связан с
-ComputerName
- это на самом деле - это то, что это также связано с -Name
неизменно.
Механизм связывания параметров PowerShell фундаментально связывает входные данные конвейера со всеми подходящими параметрами, а не только с одним.
Как уже говорилось, единственный способ предотвратить -Name
привязка из конвейера заключается в передаче значения по аргументу - даже если это значение просто *
сигнализировать о включении услуг любого имени.
Поведение теперь также обсуждается на GitHub.
Примечание:
Как указывает js2010 (OP), возможно осмысленно объединить ValueFromPipeline
а также ValueFromPipelineByPropertyName
атрибуты в одном параметре так, что Get-Service
"s -Name
параметр делает, но обратите внимание на ограничения:
Работает только для не типизированного параметра
[object]
или же[psobject]
/[object[]]
или же[psobject[]]
(такой параметр неизменно связывал бы все по значению, даже не учитывая свойства).Тип свойства входного объекта, соответствующего имени параметра, должен либо соответствовать типу параметра, либо, по крайней мере, быть преобразованным в него, чтобы быть связанным.
Пример команды, которая привязывает тот же сервис к
-Name
сначала как строка, а затем как объект с.Name
имущество:'rpcss', [pscustomobject] @{ Name = 'rpcss' } | Get-Service
Как вы отправляете полный объект Get-Service
У него есть только два варианта привязки: Name
а также InputObject
, которые являются параметрами, которые принимают ByValue
трубопроводный ввод. К сожалению, ваш объект не в той форме, которая либо понимает.
Вы можете увидеть, что делает PowerShell, запустив этот Trace-Command
:
Trace-Command -Name ParameterBinding -PSHost -Expression {[pscustomobject]@{ComputerName='comp001'} | Get-Service}
Как вы говорите, способ обойти это заключается в предоставлении значения для -Name
поэтому он не пытается связать это:
[pscustomobject]@{ComputerName='comp001'} | Get-Service -Name *
Еще раз, вы можете использовать Trace-Command
как указано выше, чтобы увидеть, что теперь он счастлив связать '*' с -Name
затем он связывает дополнительные параметры, такие как -ComputerName
,
Документация PowerShell ( about_Parameters) гласит:
Если для параметра установлено значение "True (по значению)", Windows PowerShell пытается связать любые переданные по конвейеру значения с этим параметром, прежде чем он попытается интерпретировать команду другими методами.