Привязка параметров Powershell ByPropertyName и ByValue - PullRequest
1 голос
/ 14 апреля 2020

Я хочу остановить службу с именем "ALG", поэтому я использую: "alg" | stop-service Это работает. Get-help stop-service -parameter name говорит: конвейерный ввод: true (ByPropertyName, ByValue) и "alg" - это "ByPropertyValue", верно? Я хочу остановить процесс с именем notepad, поэтому я использую: "notepad" | stop-process и получаю сообщение об ошибке. Get-help stop-process -parameter name говорит: конвейерный ввод true (ByPropertyName) и "блокнот" это "ByPropertyName"? Почему эта ошибка? Спасибо за вашу помощь

Ответы [ 3 ]

2 голосов
/ 14 апреля 2020

Если вы хотите привязать значение объекта к параметру по имени свойства , либо:

  1. Передайте объект с соответствующим именем:
[pscustomobject]@{Name='notepad'} |Stop-Process
# or, for older versions of powershell:
'notepad' |Select @{Name='Name';Expression={$_}} |Stop-Process
Явное связывание выражения конвейера с именованным параметром:
'notepad' |Stop-Process -Name {$_}
1 голос
/ 15 апреля 2020
  • Ответ Матиаса Р. Джессена дает решение для передачи по трубам строк (имена процессов) в Stop-Process.

  • ответ js2010 имеет правильное объяснение для , почему передача строк в Stop-Process не работает (без дополнительных усилий) , а также предлагает полезную технику для отслеживания привязки параметров, но - на момент написания этой статьи - ответ содержит случайную информацию, которая немного смущает проблему.

Позвольте мне предложить более подробное объяснение :


Stop-Process, в отличие от Stop-Service, равно не , предназначенное для приема строк (имена процессов) в качестве конвейерного ввода.

Хотя строковый ввод в аннотации все еще может работать, а именно, если строки могут автоматически преобразовываться в один из ожидаемых типов данных по ByValue (целому объекту) параметрам привязки к конвейеру команды это не случай с Stop-Process потому что процесс имя (строка) не может (автоматически) быть преобразован в System.Diagnostics.Process экземпляр (-InputObject) [1] .

  • Когда PowerShell рассматривает привязку конвейерного ввода к параметру -Name во время вызова, ищет объект со свойством Name , потому что объявление параметра указывает этот конвейерный ввод принимается только , если входной объект имеет свойство, названное для параметра :

    • В разделах справки, например, для Stop-Process, это выражается как ByPropertyName.

    • В коде это выражается как логическое значение ValueFromPipelineByPropertyName свойство типа System.Management.Automation.ParameterAttribute; то есть, выраженное в коде PowerShell, объявление параметра выглядит примерно так: Обратите внимание, что ValueFromPipelineByPropertyName - это сокращение от ValueFromPipelineByPropertyName = $true
      [Parameter(ValueFromPipelineByPropertyName)] [string[]] $Name

  • A [string] (System.String), такой как "alg", не имеет свойства Name - это само имя .

  • Следовательно, при отсутствии автомата c преобразование [1] в тип System.Diagnostics.Process единственного ByValue параметр -InputObject и при отсутствии свойств Name и Id для параметров ByPropertyValue вызов завершается с ошибкой со следующим сообщением об ошибке, которое, по сути, говорит о том, что конвейерный ввод недопустим (не может быть привязан ни к каким параметрам):

    • The input object cannot be bound to any parameters for the command either because the command does not take pipeline input or the input and its properties do not match any of the parameters that take pipeline input.

Stop-Service, в отличие , - это , предназначенный для приема строкового ввода , потому что его -Name параметр (также) объявлен как принимающий строки непосредственно как объекты ввода, в целом .

  • В разделах справки, например, для Stop-Service, это выражается как ByValue.

  • В коде PowerShell это выражается как ValueFromPipeline:
    [Parameter(ValueFromPipeline)] [string[]] $Name

Примечание:

  • Хотя данный параметр может быть бот h ByValue и ByPropertyValue - что действительно имеет место для -Name параметра Stop-Service - что не типично.

  • Часто параметры привязки к конвейеру объявляются как скаляры , а не как массивы (например, для Sort-Object, -InputObject <PSObject>, а не -InputObject <PSObject[]>), что означает, что передача нескольких аргументов поддерживается только через конвейер, а не по прямому аргументу - см. этот выпуск GitHub для справочной информации.


Изучение параметров привязки к конвейеру:

  • Заданный параметр команды :
PS> Get-Help Stop-Process -Parameter Name

-Name <String[]>
    Specifies the process names of the processes to stop. You can type multiple process names, separated by commas, or use wildcard characters.

    Required?                    true
    Position?                    named
    Default value                None
    Accept pipeline input?       True (ByPropertyName)
    Accept wildcard characters?  true

Обратите внимание на строку Accept pipeline input?; для параметра non -pipeline-привязки вы увидите False во втором столбце.

  • All параметры привязки к конвейеру поддерживается данной командой:
PS> (Get-Help Stop-Process -Parameter *).Where({ $_.pipelineInput -like 'True*' })

-Id <Int32[]>
    Specifies the process IDs of the processes to stop. To specify multiple IDs, use commas to separate the IDs. To find the PID of a process, type 
    `Get-Process`.

    Required?                    true
    Position?                    0
    Default value                None
    Accept pipeline input?       True (ByPropertyName)
    Accept wildcard characters?  false


-InputObject <Process[]>
    Specifies the process objects to stop. Enter a variable that contains the objects, or type a command or expression that gets the objects.

    Required?                    true
    Position?                    0
    Default value                None
    Accept pipeline input?       True (ByValue)
    Accept wildcard characters?  false


-Name <String[]>
    Specifies the process names of the processes to stop. You can type multiple process names, separated by commas, or use wildcard characters.

    Required?                    true
    Position?                    named
    Default value                None
    Accept pipeline input?       True (ByPropertyName)
    Accept wildcard characters?  false

[1] Если не объявлено, что параметр поддерживает преобразование пользовательского типа через атрибут System.Management.Automation.ArgumentTransformationAttribute (редко), здесь применяются обычные правила преобразования PowerShell, в которых используется несколько методы, обсуждаемые в этом ответе . В случае System.Diagnostics.Process преобразование из строки невозможно, поскольку целевой тип не имеет конструктора с одним аргументом, содержащего строку, и не имеет значения c .Parse() метод. Быстрый тест на конвертируемость - попытка сбоя cast : [System.Diagnostics.Process] 'notepad'. Напротив, [System.ServiceProcess.ServiceController] 'alg' работает, потому что этот тип имеет , имеет конструктор с одним параметром, который принимает строку , но обратите внимание, что это преобразование не входит в играть во время привязки параметра при вызове Stop-Service, например, 'alg' | Stop-Service - там строка привязана как есть к параметру ByValue -Name.

1 голос
/ 14 апреля 2020

«stop-service -name» может быть передано по значению (строке), поэтому оно использует это. Stop-process не удается преобразовать строку в тип процесса для -inputobject, который является значением канала. «Stop-process -name» является только bypropertyname.

Здесь происходит немного больше нюансов. Строка может быть приведена к типу servicecontroller, но не к типу process. Таким образом, теоретически строка может быть передана в виде -inputobject для stop-service, но не для stop-process. «stop-service -inputobject alg» также работает, а «stop-process -inputobject notepad» - нет. Несоответствие между этими двумя командами может сбивать с толку.

[System.ServiceProcess.ServiceController]'alg'

Status   Name               DisplayName
------   ----               -----------
Stopped  alg                Application Layer Gateway Service


[system.diagnostics.process]'notepad'
InvalidArgument: Cannot convert the "notepad" value of type "System.String" to type "System.Diagnostics.Process".

Если вы действительно хотите увидеть привязки:

trace-command parameterbinding {'alg' | stop-service} -pshost
trace-command parameterbinding {'notepad' | stop-process} -pshost
...