В PowerShell, как определить функцию в файле и вызвать ее из командной строки PowerShell?

У меня есть файл .ps1, в котором я хочу определить пользовательские функции.

Представьте, что файл называется MyFunctions.ps1, а содержимое выглядит следующим образом:

Write-Host "Installing functions"
function A1
{
    Write-Host "A1 is running!"
}
Write-Host "Done"

Чтобы запустить этот script и теоретически зарегистрировать функцию A1, я перехожу к папке, в которой находится файл .ps1 и запускает файл:

.\MyFunctions.ps1

Выводится:

Installing functions
Done

Тем не менее, когда я пытаюсь вызвать A1, я просто получаю сообщение об ошибке, указывающее, что с этим именем нет команды/функции:

The term 'A1' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling
 of the name, or if a path was included, verify that the path is correct and try again.
At line:1 char:3
+ A1 <<<<
    + CategoryInfo          : ObjectNotFound: (A1:String) [], CommandNotFoundException
    + FullyQualifiedErrorId : CommandNotFoundException

Я должен неправильно понять некоторые концепции PowerShell. Могу ли я определить функции в файлах script?

Примечание, что я уже установил политику выполнения на "RemoteSigned". И я знаю, чтобы запускать файлы .ps1, используя точку перед именем файла:.\MyFile.ps1

Ответ 1

Попробуйте это в командной строке PowerShell:

. .\MyFunctions.ps1
A1

Оператор dot используется для script include.

Ответ 2

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

Итак, сначала переименуйте файл .ps1, в котором есть все ваши функции, в MyFunctions.psm1 (вы только что создали модуль!). Теперь для правильной загрузки модуля вы должны сделать с файлом определенные вещи. Сначала, чтобы Import-Module увидел модуль (вы используете этот командлет для загрузки модуля в оболочку), он должен находиться в определенном месте. Путь к папке модулей по умолчанию - $ home\Documents\WindowsPowerShell\Modules.

В этой папке создайте папку с именем MyFunctions и поместите в нее файл MyFunctions.psm1 (файл модуля должен находиться в папке с тем же именем, что и файл PSM1).

Как только это будет сделано, откройте PowerShell и выполните следующую команду:

Get-Module -listavailable

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

Чтобы использовать модуль, введите в командной строке следующее (или поместите эту строку в свой профиль $, или поместите ее в качестве первой строки в скрипте):

Import-Module MyFunctions

Теперь вы можете запускать свои функции. Круто то, что когда у вас будет 10-15 функций, вы забудете имя пары. Если они есть в модуле, вы можете запустить следующую команду, чтобы получить список всех функций в вашем модуле:

Get-Command -module MyFunctions

Это довольно мило, и крошечное усилие, которое требуется для установки на лицевой стороне, ОЧЕНЬ того стоит.

Ответ 3

. "$PSScriptRoot\MyFunctions.ps1" MyA1Func

Доступно, начиная с версии 3, до этого см. Как получить расположение файловой системы PowerShell script?. Это ОЧЕНЬ распространено.

P.S. Я не подписываюсь на правило "все является модулем". Мои скрипты используются другими разработчиками из GIT, поэтому мне не нравится помещать материал в определенное место или изменять переменные системной среды до запуска моего script. Это просто script (или два, или три).

Ответ 4

Вы, конечно, можете определять функции в файлах script (тогда я имею тенденцию загружать их через мой профиль Powershell при загрузке).

Сначала вам нужно проверить, чтобы функция загружалась при запуске:

ls function:\ | where { $_.Name -eq "A1"  }

И проверьте, что он отображается в списке (должен быть список 1!), а затем дайте нам знать, какой результат вы получите!

Ответ 5

Вы можете добавить функцию к:

c:\Users\David\Documents\WindowsPowerShell\profile.ps1

Функция будет доступна.

Ответ 6

Если ваш файл имеет только одну основную функцию, которую вы хотите вызвать/выставить, то вы также можете просто запустить файл с помощью

Param($Param1)

Затем вы можете вызвать его, например. следующим образом:

.\MyFunctions.ps1 -Param1 'value1'

Это делает его намного более удобным, если вы хотите легко вызвать только эту функцию без необходимости импортировать функцию.

Ответ 7

Предполагая, что у вас есть файл модуля с именем Dummy-Name.psm1, который имеет метод с именем Function-Dumb()

Import-Module "Dummy-Name.psm1";
Get-Command -Module "Function-Dumb";
#
#
Function-Dumb;