Загрузить все функции в PowerShell из определенного каталога - PullRequest
15 голосов
/ 18 апреля 2009

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

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

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

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

. .\allFunctions.ps1

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

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

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

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

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

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

Ответы [ 6 ]

15 голосов
/ 18 апреля 2009

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

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

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

11 голосов
/ 24 апреля 2009

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

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

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

6 голосов
/ 18 апреля 2009

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

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

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

Следующая проблема заключается в том, что, по-моему, ваша функция разбиения завершится сбоем, если вы когда-нибудь поместите каталог в путь, содержащий пробел. Это приведет к тому, что путь типа «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
}

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

0 голосов
/ 31 декабря 2015

Я использую PowerShell 4 и следующие две строки в моем Microsoft.PowerShell_profile.ps1:

$modules = $env:USERPROFILE + "\..\*.psm1"
Import-Module $modules

Дополнительно: Учебное пособие по созданию расширенных модулей .

0 голосов
/ 23 февраля 2013

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

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

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

0 голосов
/ 28 января 2013

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

$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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...