Загрузите все функции в PowerShell из определенного каталога

Предположим, вы системный администратор, который использует PowerShell для управления множеством вещей в своей системе.

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

Я написал функцию, которая делает это для меня. Я размещаю его здесь, потому что я хочу быть уверенным в его надежности. Сама функция хранится в allFunctions.ps1, поэтому я исключаю ее в код.

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

. .\allFunctions.ps1

Содержимое этого script таково:

[string]$items = Get-ChildItem -Path . -Exclude allFunctions.ps1
$itemlist = $items.split(" ")
foreach($item in $itemlist)
{
    . $item
}

Этот script будет сначала собирать каждый файл в вашем каталоге, то есть все файлы, отличные от ps1, которые у вас могут быть там. allFunctions.ps1 будет исключен.

Затем я разделяю длинную строку на основе пространства, которое здесь является общим разделителем. И затем я просматриваю его с помощью цикла Foreach, каждый раз инициализируя функцию в PowerShell.

Предположим, что у вас более 100 функций, и вы никогда не знаете, какие из них вам понадобятся, а какие нет? Почему бы им не вводить их вместо того, чтобы делать nitpicking?

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

Ответы

Ответ 1

Включите их в свой профиль PowerShell, чтобы они автоматически загружались каждый раз при запуске PS.

Посмотрите Профили Windows PowerShell для получения дополнительной информации о том, где найти свой профиль script.

PS по умолчанию добавляет ваш профиль в папку "Мои документы". Mine находится на сетевом диске, поэтому в любом месте, где бы я ни находился, PowerShell указывает на одну и ту же папку профиля.

Ответ 2

Вы можете сделать это проще. У меня это в моем профиле:

##-------------------------------------------
## Load Script Libraries
##-------------------------------------------
Get-ChildItem ($lib_home + "*.ps1") | ForEach-Object {& (Join-Path $lib_home $_.Name)} | Out-Null

Где $lib_home - это папка, в которой хранятся сценарии, которые я хочу включить. В этом случае он их выполняет. Поэтому у меня есть сценарии, определяющие глобальные функции. Вы также можете рассчитать их источник (замените "&" на "." ).

Ответ 3

Функциональность мудрая Я думаю, что есть несколько способов улучшить ваш script.

Во-первых, ваш script зависит от того, что имя script не меняется. Хотя я не думаю, что вы, вероятно, измените название этого script, вы никогда не знаете, какое настроение вы будете через несколько лет. Вместо этого почему бы просто не вычислить имя script динамически.

$scriptName = split-path -leaf $MyInvocation.MyCommand.Definition

Следующая проблема заключается в том, что я считаю, что функция split будет сбой, если вы когда-нибудь разместите каталог в пути, который содержит пробел. Это приведет к тому, что путь "c:\foo bar\baz.ps1" появится как "c:\foo", "bar\baz.ps1". Гораздо лучше удалить раскол и просто использовать перечисление командой get-childitem.

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

Вот обновленная версия, которую я бы использовал.

$scriptName = split-path -leaf $MyInvocation.MyCommand.Definition
$rootPath = split-path -parent $MyInvocation.MyCommand.Definition
$scripts = gci -re $rootPath -in *.ps1 | ?{ $_.Name -ne $scriptName }
foreach ( $item in $scripts ) {
  . $item.FullName
}

С точки зрения безопасности вы должны учитывать вероятность того, что вредоносный пользователь добавит плохой script в целевой каталог. Если они это сделают, это будет выполнено с вашим файлом allFunctions.ps1 и может нанести ущерб компьютеру. Но в момент, когда злонамеренный пользователь имеет доступ к вашей файловой системе, вероятно, они могут нанести ущерб без помощи вашего script, поэтому это, вероятно, незначительная проблема.

Ответ 4

Простое решение:

$Path - file location
$Name - exluded file

Get-ChildItem -Path $Path | Where {$_.psIsContainer -eq $false}|Where { $_.Name -like "*.ps1" }|Where { $_.Name -ne $Name }|foreach-object -process {.$_.FullName}|out-null

read all object|file only| powershell file only|exclude file $Name| run ...|out-null

Ответ 5

Другим решением является объединение функций в файл модуля (psm1) и импорт с помощью команды Import-Module. Вы можете добавить команду Import-Module в свой профиль, как описано выше, но синтаксис намного проще.

Простой способ начать - создать папку под названием "Модули" в вашем каталоге WindowsPowerShell. В этой папке создайте другую папку с именем вашего модуля. Ваш файл psm1 сохраняется здесь. Затем добавьте Import-Module ModuleName.psm1 в свой профиль, который находится в каталоге WindowsPowerShell. Если вы хотите использовать другой профиль или сохранить свой модуль в другом месте, вам нужно будет управлять этим путем.

Другим советом является использование функции Export-ModuleMember FunctionName для каждой функции в вашем файле модуля. Это затмит вспомогательную функцию для конечных пользователей, которых вы можете распространять.