Как передать аргументы командной строки в файл ps1 PowerShell

В течение многих лет я использовал оболочку cmd/DOS/Windows и передал аргументы командной строки пакетным файлам. Например, у меня есть файл zuzu.bat, и в нем я получаю доступ к %1, %2 и т.д. Теперь я хочу сделать то же самое, когда я вызываю PowerShell script when I am in a Cmd.exe shell. У меня есть script, xuxu.ps1 (и я добавил PS1 в свою переменную PATHEXT и связанные с ней файлы PS1 с помощью PowerShell). Но независимо от того, что я делаю, мне кажется, что я ничего не могу получить от переменной $args. Он всегда имеет длину 0.

Если я в оболочке PowerShell вместо cmd.exe, он работает (конечно). Но мне еще не достаточно комфортно жить в среде PowerShell полный рабочий день. Я не хочу набирать powershell.exe -command xuxu.ps1 p1 p2 p3 p4. Я хочу ввести xuxu p1 p2 p3 p4.

Возможно ли это, и если да, то как?

Образец, с которым я не могу работать, тривиален, foo.ps1:

Write-Host "Num Args:" $args.Length;
foreach ($arg in $args) {
    Write-Host "Arg: $arg";
}

Результаты всегда будут такими:

C:\temp> foo
Num Args: 0
C:\temp> foo a b c d
Num Args: 0
c:\temp>

Ответ 1

Эта статья помогает. В частности, этот раздел:

-File

Запускает указанный script в локальной области ( "dot-sourced" ), так что функции и переменные, создаваемые script, доступны в текущем сеансе. Введите путь к файлу script и любые параметры. Файл должен быть последним параметром в команде, потому что все символы, введенные после имени параметра File, интерпретируются как путь к файлу script, за которым следуют параметры script.

то есть.

powershell.exe -File "C:\myfile.ps1" arg1 arg2 arg3

означает запуск файла myfile.ps1 и arg1 arg2 и arg3 - параметры для PowerShell script.

Ответ 2

ОК, поэтому сначала это нарушает базовую функцию безопасности в PowerShell. С этим пониманием, вот как вы можете это сделать:

  • Откройте окно Windows Explorer
  • Инструменты меню → Параметры папки → вкладка Типы файлов
  • Найдите тип файла PS1 и нажмите кнопку "Дополнительно"
  • Нажмите кнопку "Создать"
  • Для Action put: Открыть
  • Для приложения put: "C:\WINNT\system32\WindowsPowerShell\v1.0\powershell.exe" "файл" "% 1" % *

Возможно, вы захотите также добавить аргумент -NoProfile в зависимости от того, что делает ваш профиль.

Ответ 3

После обработки документации PowerShell я обнаружил полезную информацию об этой проблеме. Вы не можете использовать $args, если вы использовали param(...) в начале вашего файла; вместо этого вам нужно будет использовать $PSBoundParameters. Я копировал/вставлял ваш код в PowerShell script, и он работал так, как вы ожидали в PowerShell версии 2 (я не уверен, какая версия была включена, когда вы столкнулись с этой проблемой).

Если вы используете $PSBoundParameters (и это ТОЛЬКО работает, если вы используете param(...) в начале вашего script), то это не массив, это хеш-таблица, поэтому вам нужно будет ссылайтесь на нее с помощью пары ключ/значение.

param($p1, $p2, $p3, $p4)
$Script:args=""
write-host "Num Args: " $PSBoundParameters.Keys.Count
foreach ($key in $PSBoundParameters.keys) {
    $Script:args+= "`$$key=" + $PSBoundParameters["$key"] + "  "
}
write-host $Script:args

И когда вызывается с...

PS> ./foo.ps1 a b c d

Результат...

Num Args:  4
$p1=a  $p2=b  $p3=c  $p4=d

Ответ 4

Вы можете объявить свои параметры в файле, например, param:

[string]$para1
[string]$param2

А затем вызвать файл PowerShell следующим образом .\temp.ps1 para1 para2....para10 и т.д.

Ответ 5

Возможно, вы можете перенести вызов PowerShell в файл .bat следующим образом:

rem ps.bat
@echo off
powershell.exe -command "%*"

Если вы разместили этот файл под папкой в ​​ PATH, вы могли бы вызвать сценарии PowerShell, как это:

ps foo 1 2 3

Цитата может немного запутаться:

ps write-host """hello from cmd!""" -foregroundcolor green

Ответ 6

Вы не можете получить "xuxu p1 p2 p3 p4", как кажется. Но когда вы находитесь в PowerShell, и вы установили

PS > set-executionpolicy Unrestricted -scope currentuser

Вы можете запустить эти скрипты следующим образом:

./xuxu p1 p2 p3 p4

или

.\xuxu p1 p2 p3 p4

или

./xuxu.ps1 p1 p2 p3 p4

Я надеюсь, что это сделает вас более удобным с PowerShell.

Ответ 7

если вы хотите вызывать сценарии ps1 из cmd и передавать аргументы, не вызывая сценарий, как

powershell.exe script.ps1 -c test
script -c test ( wont work )

Вы можете сделать следующее

setx PATHEXT "%PATHEXT%;.PS1" /m
assoc .ps1=Microsoft.PowerShellScript.1
ftype Microsoft.PowerShellScript.1=powershell.exe "%1" %*

Это предполагает, что powershell.exe находится на вашем пути

https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/ftype

Ответ 8

не указывайте $arg в условном блоке