PowerShell Invoke-Command с FilePath на локальном компьютере - ошибка неопределенных параметров?

Я хочу запустить сценарий в файле на локальном компьютере с помощью Invoke-Command, чтобы передать параметры с помощью -ArgumentList. Я получаю сообщение об ошибке, которого не понимаю, поэтому я упростил свою команду. Когда я это сделаю:

Invoke-Command -FilePath 'getprocess.ps1'

Содержимое getprocess.ps1:

Get-Process

Я получаю следующее сообщение об ошибке:

Invoke-Command: набор параметров не может быть разрешен с использованием указанных именованных параметров.

В строке: 1 символ: 1

+ Invoke-Command -FilePath 'getprocess.ps1'

+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

+ CategoryInfo: InvalidArgument: (:) [Invoke-Command], ParameterBindingException

+ FullyQualifiedErrorId: AmbiguousParameterSet, Microsoft.PowerShell.Commands.InvokeCommandCommand

Это сообщение об ошибке сбивает меня с толку. Что это значит? Как мне заставить это работать?


person BigScary    schedule 01.04.2020    source источник


Ответы (5)


Хотя сообщение об ошибке не проясняет это, параметр -FilePath делает параметр -ComputerName обязательным. Чтобы явно настроить таргетинг на локальный компьютер, используйте -ComputerName localhost.

Invoke-Command -FilePath 'getprocess.ps1' -ComputerName localhost
person BigScary    schedule 01.04.2020
comment
Ваш ответ технически правильный (вот почему я проголосовал за него), но представление -ComputerName localhost как локальный вызов вводит в заблуждение по причинам, подробно описанным в моем ответе. Короче говоря, никогда не бывает веской причины использовать Invoke-Command для локальных вызовов. (В случае, если это вы проголосовали против моего ответа, я приглашаю вас оспорить его конкретные моменты.) - person mklement0; 02.04.2020
comment
Поразмыслив, я думаю, что создание вводящего в заблуждение впечатления о том, что -ComputerName localhost подходит для локального вызова скриптов, перевешивает техническую правильность информации о требуемой комбинации параметров. - person mklement0; 03.04.2020

tl; dr:

  • Как правило, не используйте Invoke-Command для локальные вызовы - хотя это технически возможно, есть только один конкретный вариант использования, для которого это требуется (см. ниже).

  • Вместо этого вызывайте скрипты напрямую:

.\getprocess.ps1

Примечание. В отличие от cmd.exe, PowerShell по своей конструкции требует .\ для выполнения исполняемого файла, расположенного в текущем каталоге. То есть, чтобы избежать случайного выполнения исполняемых файлов в текущем каталоге, а не из каталога, указанного в $env:Path, PowerShell в качестве функции безопасности требует, чтобы вы явным образом сигнализировали о намерении выполнить что-то в текущем каталоге (.).

Для блоков скриптов ({ ... }), используйте &, вызвать оператора (например, & { Get-Date }).

Исключительно по синтаксическим причинам вам ситуативно также потребуется & для путей к файлам сценария, если они указаны как путь в кавычках (например, & '.\getprocess.ps1' ) и / или если путь включает ссылки на переменные (например,
& $HOME\getprocess.ps1).

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


Обратите внимание, что технически вы можете объединить передачу блока сценария в Invoke-Command (параметр -ScriptBlock) с вызовом локального сценария:

# The script block positionally binds to the -ScriptBlock parameter.
# This is essentially the more expensive equivalent of:
#     & .\getprocess.ps1
Invoke-Command { .\getprocess.ps1 }

Это медленнее и не дает преимуществ перед прямым вызовом. Однако есть один возможный вариант использования:

Если сценарий не является расширенный скрипт, и вы хотели воспользоваться Invoke-Command потоковым сбором вывода общие параметры, такие как -ErrorVariable (если вызываемый скрипт или функция является расширенным, он поддерживает эти общие параметры сам).

# Invoke locally and collect errors in $errs
Invoke-Command { .\getprocess.ps1 } -ErrorVariable errs

Предупреждение: по крайней мере, начиная с PowerShell 7.2, Invoke-Command не применяет общий параметр -ErrorAction для ошибок, возникающих в блоке скрипта, поэтому его нельзя использовать для управления обработка ошибок; например, -ErrorAction Stop не влияет на команды в блоке скрипта.


Что касается того, что вы пробовали:

Действительно, как вы указываете в своем собственном ответе, -FilePath должен сочетаться с параметр
-ComputerName
(прискорбно, что сообщение об ошибке носит столь общий характер).

Назначение параметра -FilePath - скопировать содержимое локального скрипта (*.ps1 файл) на удаленный компьютер для выполнения там. То есть это удобный механизм выполнения кода сценария, доступного (только) локально на удаленной машине.

Хотя технически вы можете настроить таргетинг на локальный компьютер через -ComputerName localhost (или, более кратко, через -ComputerName . / -cn .), это не равнозначно локальному вызову :

Каждый раз, когда указан -ComputerName - даже с -ComputerName localhost - используется инфраструктура удаленного взаимодействия PowerShell, что имеет серьезные последствия:

  • Целевой компьютер - даже если он локальный - должен быть настроен для удаленного взаимодействия PowerShell - см. about_Remote_Requirements.

  • Если вы нацеливаетесь конкретно на локальный компьютер, вы должны работать в сеансе с повышенными правами (под управлением администратора).

  • Выполнение будет намного медленнее, чем прямой (локальный) вызов.

  • Точность типов может быть потеряна как для входных, так и для выходных данных, учитывая, что задействовано межпроцессное маршалинг через инфраструктуру сериализации PowerShell на основе XML - см. это ответ.


Тем не менее, если намерение состоит в том, чтобы локально протестировать удаленное выполнение вашего скрипта и ваш локальный компьютер настроен как цель удаленного взаимодействия, тогда используйте -ComputerName localhost (-ComputerName . / -cn . ) имеет смысл, учитывая, что в этом случае инфраструктура удаленного взаимодействия PowerShell задействуется так же, как и при действительно удаленном вызове.

Обратите внимание, однако, что такие вызовы удаленного взаимодействия с обратной связью требуют повышения прав (выполняются от имени администратора).

person mklement0    schedule 01.04.2020
comment
Это было бы отличным ответом для более общего характера. Какой рекомендуемый подход для вызова сценариев на локальном компьютере, когда эти сценарии находятся в файлах на локальном компьютере? Но мой вопрос касался использования Invoke-Command, который мне нужен в моем конкретном случае. Я не хотел раздувать свой вопрос параграфом с мотивационной справочной информацией, чтобы разговор не зашел о моих мотивах, а не о моем вопросе. Похоже, что так и было. - person BigScary; 10.05.2021
comment
@BigScary, Invoke-Command обычно не тот инструмент, который можно использовать для вызова локальных файлов скриптов. Мой ответ сосредоточен на этом, потому что это информация, которая больше всего важна для будущих читателей. Однако я добавил к ответу один вариант использования, в котором локальное использование Invoke-Command может иметь смысл, но требует использования другого параметра, а именно -ScriptBlock с блоком сценария, из которого вызывается файл сценария. - person mklement0; 10.05.2021

Я не могу использовать invoke-command локально. Вы используете это, когда пытаетесь запустить команду на удаленном ПК.

Например, вы хотите запустить что-то вроде:

invoke-Command -ComputerName REMOTE-PC -Credentials $credential -Scriptblock {Get-Process}

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

попробуйте запустить Get-Help Invoke-Command, чтобы увидеть некоторую информацию о команде и о том, как ее запустить.

person ingenium21    schedule 01.04.2020
comment
Чтобы было ясно: это не я проголосовал против (наоборот). Вы правы, что Invoke-Command в первую очередь полезен для удаленных вызовов, но вы можете использовать его для вызова команды локально, а именно, если блок сценария передается -ScriptBlock, тогда как -FilePath действительно требует использования -ComputerName. Тем не менее, нет веских причин использовать Invoke-Command локально. - person mklement0; 02.04.2020

У вас должно быть имя компьютера.

$parameters = @{
    ComputerName = '255.255.255.255'
    FilePath = 'getprocess.ps1'
    Credential = 'Domain01\User01'
}

invoke-command @parameters

Используйте свой IP :) Чтобы разрешить это, вы также должны включить -credential

Если этого не произойдет ... invoke-expression может быть частично подходящей заменой для тестирования, пока вы не будете готовы вызвать команду на удаленном компьютере.

person shadow2020    schedule 01.04.2020
comment
Похоже, что OP намеревался вызвать локально, и в этом случае Invoke-Command - вообще неправильный инструмент. Предлагать использование Invoke-Expression проблематично не только потому, что в этом сценарии нет необходимости, но и потому, что обычно этого следует избегать. То есть, даже в тех редких случаях, когда его использование оправдано и необходимо, рекомендуется не использовать его в целом. - person mklement0; 02.04.2020
comment
Я согласен с этим для рабочих сценариев, но для тестирования с надежными источниками это нормально. - person shadow2020; 02.04.2020

Вы можете запустить его локально, как это, но вы должны быть в приглашении администратора (с повышенными правами). Приятно иметь возможность запустить это в качестве теста.

invoke-command localhost getprocess.ps1

Вы также можете использовать странную форму параллелизма:

invoke-command localhost,localhost,localhost getprocess.ps1
person js2010    schedule 02.04.2020