Разное

Powershell функции: Функции — PowerShell | Microsoft Docs

05.07.1972

Содержание

Функции — PowerShell | Microsoft Docs

  • Чтение занимает 13 мин

В этой статье

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

По возможности я предпочитаю писать функции, потому что они больше ориентированы на работу со средствами. Я могу поместить функции в модуль сценария, отправить этот модуль в $env:PSModulePath и вызвать функции без необходимости физического определения их местонахождения. С помощью модуля PowerShellGet эти модули можно легко запрашивать в репозитории NuGet.

PowerShellGet поставляется с PowerShell версии 5.0 и выше. Он доступен в виде отдельного скачиваемого файла для PowerShell версии 3.0 и более поздних версий.

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

Именование

При именовании функций в PowerShell используйте имя в Регистр Pascal с утвержденным глаголом и существительным в единственном числе. Кроме того, перед существительным рекомендуется добавить префикс. Например:

<ApprovedVerb>-<Prefix><SingularNoun>.

В PowerShell есть конкретный список утвержденных глаголов, которые можно получить, выполнив Get-Verb.

Get-Verb | Sort-Object -Property Verb
Verb        Group
----        -----
Add         Common
Approve     Lifecycle
Assert      Lifecycle
Backup      Data
Block       Security
Checkpoint  Data
Clear       Common
Close       Common
Compare     Data
Complete    Lifecycle
Compress    Data
Confirm     Lifecycle
Connect     Communications
Convert     Data
ConvertFrom Data
ConvertTo   Data
Copy        Common
Debug       Diagnostic
Deny        Lifecycle
Disable     Lifecycle
Disconnect  Communications
Dismount    Data
Edit        Data
Enable      Lifecycle
Enter       Common
Exit        Common
Expand      Data
Export      Data
Find        Common
Format      Common
Get         Common
Grant       Security
Group       Data
Hide        Common
Import      Data
Initialize  Data
Install     Lifecycle
Invoke      Lifecycle
Join        Common
Limit       Data
Lock        Common
Measure     Diagnostic
Merge       Data
Mount       Data
Move        Common
New         Common
Open        Common
Optimize    Common
Out         Data
Ping        Diagnostic
Pop         Common
Protect     Security
Publish     Data
Push        Common
Read        Communications
Receive     Communications
Redo        Common
Register    Lifecycle
Remove      Common
Rename      Common
Repair      Diagnostic
Request     Lifecycle
Reset       Common
Resize      Common
Resolve     Diagnostic
Restart     Lifecycle
Restore     Data
Resume      Lifecycle
Revoke      Security
Save        Data
Search      Common
Select      Common
Send        Communications
Set         Common
Show        Common
Skip        Common
Split       Common
Start       Lifecycle
Step        Common
Stop        Lifecycle
Submit      Lifecycle
Suspend     Lifecycle
Switch      Common
Sync        Data
Test        Diagnostic
Trace       Diagnostic
Unblock     Security
Undo        Common
Uninstall   Lifecycle
Unlock      Common
Unprotect   Security
Unpublish   Data
Unregister  Lifecycle
Update      Data
Use         Other
Wait        Lifecycle
Watch       Common
Write       Communications

В предыдущем примере результаты отсортированы по столбцу Verb. Взглянув на столбец Group, вы получите представление о том, как эти глаголы используются. При добавлении функций в модуль важно выбрать утвержденную команду в PowerShell. Если будет выбран неутвержденный глагол, модуль создаст предупреждение во время загрузки. Из-за этого предупреждения ваши функции выглядят непрофессионально. Кроме того, неутвержденные глаголы ограничивают возможности обнаружения функций.

Простая функция

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

function Get-Version {
    $PSVersionTable.PSVersion
}

Показан простой пример функции, возвращающей версию PowerShell.

Get-Version
Major  Minor  Build  Revision
-----  -----  -----  --------
5      1      14393  693

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

function Get-PSVersion {
    $PSVersionTable.PSVersion
}

Эта функция идентична предыдущей, за исключением имени.

Get-PSVersion
Major  Minor  Build  Revision
-----  -----  -----  --------
5      1      14393  693

Даже при добавлении префикса типа PS все равно есть большая вероятность конфликта имен. Обычно перед существительным в имени функции я указываю свои инициалы. Разработайте свой стандарт и придерживайтесь его.

function Get-MrPSVersion {
    $PSVersionTable.PSVersion
}

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

Get-MrPSVersion
Major  Minor  Build  Revision
-----  -----  -----  --------
5      1      14393  693

Функции, загруженные в память, можно увидеть на PSDrive Function.

Get-ChildItem -Path Function:\Get-*Version
CommandType     Name                                               Version    Source
-----------     ----                                               -------    ------
Function        Get-Version
Function        Get-PSVersion
Function        Get-MrPSVersion

Чтобы удалить эти функции из текущего сеанса, необходимо удалить их из PSDrive

Function или закрыть и повторно открыть PowerShell.

Get-ChildItem -Path Function:\Get-*Version | Remove-Item

Убедитесь, что функции действительно удалены.

Get-ChildItem -Path Function:\Get-*Version

Если функции были загружены в составе модуля, то, чтобы удалить их, можно выгрузить модуль.

Remove-Module -Name <ModuleName>

Командлет Remove-Module удаляет модули из памяти в текущем сеансе PowerShell, но не удаляет их из системы или с диска.

Параметры

Не присваивайте значения статически! Используйте параметры и переменные. Когда дело доходит до именования параметров, по возможности используйте те же имена, что и у командлетов по умолчанию.

function Test-MrParameter {

    param (
        $ComputerName
    )

    Write-Output $ComputerName

}

Почему в качестве имени параметра я использовал ComputerName, а не Computer, ServerName или Host? Потому что я хотел, чтобы мои функции были стандартизированы как стандартные командлеты.

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

function Get-MrParameterCount {
    param (
        [string[]]$ParameterName
    )

    foreach ($Parameter in $ParameterName) {
        $Results = Get-Command -ParameterName $Parameter -ErrorAction SilentlyContinue

        [pscustomobject]@{
            ParameterName = $Parameter
            NumberOfCmdlets = $Results. Count
        }
    }
}

Как видно в приведенных ниже результатах, у 39 команд есть параметр ComputerName. Командлеты с такими параметрами, как Computer, ServerName, Host или Machine

, не найдены.

Get-MrParameterCount -ParameterName ComputerName, Computer, ServerName, Host, Machine
ParameterName NumberOfCmdlets
------------- ---------------
ComputerName               39
Computer                    0
ServerName                  0
Host                        0
Machine                     0

Кроме того, имена параметров рекомендуется указывать в том же регистре, что и имена командлетов по умолчанию. Используйте ComputerName, а не computername. В этом случае функции выглядят и работают как командлеты по умолчанию. Это очень удобно для пользователей, уже знакомых с PowerShell.

paramОператор позволяет определить один или несколько параметров. Определения параметров разделяются запятой ( , ). Дополнительные сведения см. в разделе about_Functions_Advanced_Parameters.

Расширенные функции

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

Я начну с функции Test-MrParameter, которая использовалась в предыдущем разделе.

function Test-MrParameter {

    param (
        $ComputerName
    )

    Write-Output $ComputerName

}

Хочу обратить ваше внимание на то, что функция Test-MrParameter не имеет общих параметров. Существует несколько различных способов просмотра общих параметров. Один из них — просмотр синтаксиса с помощью Get-Command.

Get-Command -Name Test-MrParameter -Syntax
Test-MrParameter [[-ComputerName] <Object>]

Другой — детализация параметров с помощью Get-Command.

(Get-Command -Name Test-MrParameter).Parameters.Keys
ComputerName

Добавьте CmdletBinding, чтобы преобразовать функцию в расширенную.

function Test-MrCmdletBinding {

    [CmdletBinding()] #<<-- This turns a regular function into an advanced function
    param (
        $ComputerName
    )

    Write-Output $ComputerName

}

При добавлении CmdletBinding общие параметры добавляются автоматически. Для CmdletBinding требуется блок param, но блок param может быть пустым.

Get-Command -Name Test-MrCmdletBinding -Syntax
Test-MrCmdletBinding [[-ComputerName] <Object>] [<CommonParameters>]

Если выполнить детализацию параметров с помощью Get-Command, можно увидеть имена параметров, включая общие параметры.

(Get-Command -Name Test-MrCmdletBinding). Parameters.Keys
ComputerName
Verbose
Debug
ErrorAction
WarningAction
InformationAction
ErrorVariable
WarningVariable
InformationVariable
OutVariable
OutBuffer
PipelineVariable

SupportsShouldProcess

SupportsShouldProcess добавляет параметры WhatIf и Confirm. Они необходимы только для команд, которые вносят изменения.

function Test-MrSupportsShouldProcess {

    [CmdletBinding(SupportsShouldProcess)]
    param (
        $ComputerName
    )

    Write-Output $ComputerName

}

Обратите внимание, что теперь появились параметры WhatIf и Confirm.

Get-Command -Name Test-MrSupportsShouldProcess -Syntax
Test-MrSupportsShouldProcess [[-ComputerName] <Object>] [-WhatIf] [-Confirm] [<CommonParameters>]

Опять же: с помощью Get-Command можно получить список фактических имен параметров, включая общие параметры и WhatIf и Confirm.

(Get-Command -Name Test-MrSupportsShouldProcess).Parameters.Keys
ComputerName
Verbose
Debug
ErrorAction
WarningAction
InformationAction
ErrorVariable
WarningVariable
InformationVariable
OutVariable
OutBuffer
PipelineVariable
WhatIf
Confirm

Проверка параметров

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

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

function Test-MrParameterValidation {

    [CmdletBinding()]
    param (
        [string]$ComputerName
    )

    Write-Output $ComputerName

}

В предыдущем примере в качестве типа данных для параметра ComputerName указано String. Это означает, что допускается только одно имя компьютера. Если задается несколько имен компьютеров в виде списка с разделителями-запятыми, возникает ошибка.

Test-MrParameterValidation -ComputerName Server01, Server02
Test-MrParameterValidation : Cannot process argument transformation on parameter
'ComputerName'. Cannot convert value to type System.String.
At line:1 char:42
+ Test-MrParameterValidation -ComputerName Server01, Server02
+
    + CategoryInfo          : InvalidData: (:) [Test-MrParameterValidation], ParameterBindingArg
     umentTransformationException
    + FullyQualifiedErrorId : ParameterArgumentTransformationError,Test-MrParameterValidation

Проблема с текущим определением заключается в том, что значение параметра ComputerName можно опустить, но оно требуется для успешного выполнения функции. Именно в таком случае будет полезен атрибут параметра Mandatory.

function Test-MrParameterValidation {

    [CmdletBinding()]
    param (
        [Parameter(Mandatory)]
        [string]$ComputerName
    )

    Write-Output $ComputerName

}

В предыдущем примере используется синтаксис, совместимый с PowerShell версии 3. 0 и более поздними. Чтобы обеспечить совместимость функции с PowerShell версии 2.0 и более поздними, можно указать [Parameter(Mandatory=$true)]. Теперь, когда потребуется значение параметра ComputerName, которое пока не задано, функция выведет соответствующий запрос.

Test-MrParameterValidation
cmdlet Test-MrParameterValidation at command pipeline position 1
Supply values for the following parameters:
ComputerName:

Чтобы разрешить несколько значений для параметра ComputerName, используйте тип данных String, но добавьте к нему открывающие и закрывающие квадратные скобки, позволяющие использовать массив строк.

function Test-MrParameterValidation {

    [CmdletBinding()]
    param (
        [Parameter(Mandatory)]
        [string[]]$ComputerName
    )

    Write-Output $ComputerName

}

Возможно, вы захотите указать значение по умолчанию для параметра ComputerName, если это еще не сделано. Проблема в том, что значения по умолчанию нельзя использовать с обязательными параметрами. Вместо этого потребуется атрибут проверки параметров ValidateNotNullOrEmpty со значением по умолчанию.

function Test-MrParameterValidation {

    [CmdletBinding()]
    param (
        [ValidateNotNullOrEmpty()]
        [string[]]$ComputerName = $env:COMPUTERNAME
    )

    Write-Output $ComputerName

}

Даже при задании значения по умолчанию старайтесь не прибегать к статическим значениям. В предыдущем примере в качестве значения по умолчанию используется $env:COMPUTERNAME, которое автоматически преобразуется в имя локального компьютера, если значение не указано.

Подробные выходные данные

Несмотря на всю пользу встроенных комментариев, особенно при написании сложного кода, их никогда не увидят пользователи, если только не заглянут в сам код.

Функция, показанная в следующем примере, содержит встроенный комментарий в цикле foreach. Хотя этот конкретный комментарий может быть не так уж сложно обнаружить, представьте, что было бы, если бы функция включала сотни строк кода.

function Test-MrVerboseOutput {

    [CmdletBinding()]
    param (
        [ValidateNotNullOrEmpty()]
        [string[]]$ComputerName = $env:COMPUTERNAME
    )

    foreach ($Computer in $ComputerName) {
        #Attempting to perform some action on $Computer <<-- Don't use
        #inline comments like this, use write verbose instead.
        Write-Output $Computer
    }

}

Лучшим вариантом является использование Write-Verbose вместо встроенных комментариев.

function Test-MrVerboseOutput {

    [CmdletBinding()]
    param (
        [ValidateNotNullOrEmpty()]
        [string[]]$ComputerName = $env:COMPUTERNAME
    )

    foreach ($Computer in $ComputerName) {
        Write-Verbose -Message "Attempting to perform some action on $Computer"
        Write-Output $Computer
    }

}

Если функция вызывается без параметра verbose, подробные выходные данные отображаться не будут.

Test-MrVerboseOutput -ComputerName Server01, Server02

При вызове функции с параметром verbose будут выведены подробные выходные данные.

Test-MrVerboseOutput -ComputerName Server01, Server02 -Verbose

Входные данные конвейера

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

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

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

function Test-MrPipelineInput {

    [CmdletBinding()]
    param (
        [Parameter(Mandatory,
                   ValueFromPipeline)]
        [string[]]$ComputerName
    )

    PROCESS {
        Write-Output $ComputerName
    }

}

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

function Test-MrPipelineInput {

    [CmdletBinding()]
    param (
        [Parameter(Mandatory,
                   ValueFromPipelineByPropertyName)]
        [string[]]$ComputerName
    )

    PROCESS {
            Write-Output $ComputerName
    }

}

Блоки BEGIN и END являются необязательными. BEGIN указывается перед блоком PROCESS и используется для выполнения всех начальных задач до получения элементов из конвейера. Разобраться с этим очень важно. Переданные значения недоступны в блоке BEGIN. Блок END указывается после блока PROCESS и используется для очистки после обработки всех переданных элементов.

Обработка ошибок

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

function Test-MrErrorHandling {

    [CmdletBinding()]
    param (
        [Parameter(Mandatory,
                   ValueFromPipeline,
                   ValueFromPipelineByPropertyName)]
        [string[]]$ComputerName
    )

    PROCESS {
        foreach ($Computer in $ComputerName) {
            Test-WSMan -ComputerName $Computer
        }
    }

}

В PowerShell существует несколько различных способов обработки ошибок. Более современным является Try/Catch.

function Test-MrErrorHandling {

    [CmdletBinding()]
    param (
        [Parameter(Mandatory,
                   ValueFromPipeline,
                   ValueFromPipelineByPropertyName)]
        [string[]]$ComputerName
    )

    PROCESS {
        foreach ($Computer in $ComputerName) {
            try {
                Test-WSMan -ComputerName $Computer
            }
            catch {
                Write-Warning -Message "Unable to connect to Computer: $Computer"
            }
        }
    }

}

Хотя функция, показанная в предыдущем примере, использует обработку ошибок, она также выдает необработанное исключение, так как команда не создает неустранимую ошибку. Разобраться с этим очень важно! Перехватываются только устранимые ошибки. Чтобы преобразовать неустранимую ошибку в устранимую, укажите параметр ErrorAction со значением Stop.

function Test-MrErrorHandling {

    [CmdletBinding()]
    param (
        [Parameter(Mandatory,
                   ValueFromPipeline,
                   ValueFromPipelineByPropertyName)]
        [string[]]$ComputerName
    )

    PROCESS {
        foreach ($Computer in $ComputerName) {
            try {
                Test-WSMan -ComputerName $Computer -ErrorAction Stop
            }
            catch {
                Write-Warning -Message "Unable to connect to Computer: $Computer"
            }
        }
    }

}

Не изменяйте глобальную переменную $ErrorActionPreference, если в этом нет крайней необходимости. Если вы используете нечто вроде .NET непосредственно в функции PowerShell, параметр ErrorAction невозможно указать в самой команде. В этом случае может потребоваться изменить глобальную переменную $ErrorActionPreference, но, если вы измените ее, верните ее к исходному виду сразу же после того, как попробуете запустить команду.

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

function Get-MrAutoStoppedService {

<#
.SYNOPSIS
    Returns a list of services that are set to start automatically, are not
    currently running, excluding the services that are set to delayed start.

.DESCRIPTION
    Get-MrAutoStoppedService is a function that returns a list of services from
    the specified remote computer(s) that are set to start automatically, are not
    currently running, and it excludes the services that are set to start automatically
    with a delayed startup.

.PARAMETER ComputerName
    The remote computer(s) to check the status of the services on.

.PARAMETER Credential
    Specifies a user account that has permission to perform this action.  The default
    is the current user.

.EXAMPLE
     Get-MrAutoStoppedService -ComputerName 'Server1', 'Server2'

.EXAMPLE
     'Server1', 'Server2' | Get-MrAutoStoppedService

.EXAMPLE
     Get-MrAutoStoppedService -ComputerName 'Server1' -Credential (Get-Credential)

.INPUTS
    String

.OUTPUTS
    PSCustomObject

.NOTES
    Author:  Mike F Robbins
    Website: http://mikefrobbins.com
    Twitter: @mikefrobbins
#>

    [CmdletBinding()]
    param (

    )

    #Function Body

}

Добавленную справку на основе комментариев можно получить так же, как встроенные команды по умолчанию.

Весь синтаксис написания функции в PowerShell может показаться слишком объемным и перегруженным, особенно для тех, кто только начинает работу с этой оболочкой. Часто, если я не могу вспомнить какой-то синтаксис, я открываю вторую копию ISE на отдельном мониторе, просматриваю фрагмент «Cmdlet (расширенная функция) — Complete» и одновременно ввожу код для функции. В интегрированной среде сценариев PowerShell доступ к фрагментам кода можно получить с помощью сочетания клавиш CTRL+J.

Сводка

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

Просмотр

  1. Как получить список утвержденных глаголов в PowerShell?
  2. Как преобразовать функцию PowerShell в расширенную функцию?
  3. Когда следует добавлять параметры WhatIf и Confirm в функции PowerShell?
  4. Как преобразовать неустранимую ошибку в устранимую?
  5. Для чего нужно добавлять справку на основе комментариев к функциям?

Рекомендуем прочесть

о функциях — PowerShell | Microsoft Docs

  • Чтение занимает 10 мин

В этой статье

Краткое описание

Описание создания и использования функций в PowerShell.

Подробное описание

Функция — это список операторов PowerShell с назначенным именем. При запуске функции необходимо ввести имя функции. Инструкции в списке выполняются так, как если бы вы вводили их в командной строке.

Функции могут быть простыми:

function Get-PowerShellProcess { Get-Process PowerShell }

Функция также может быть сложной в качестве командлета или программы приложения.

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

Функции могут возвращать значения, которые могут быть отображены, назначены переменным или переданы другим функциям или командлетам. Также можно указать возвращаемое значение с помощью return ключевого слова. returnКлючевое слово не влияет или не подавляет другие выходные данные, возвращаемые функцией. Однако return ключевое слово завершает функцию в этой строке. Дополнительные сведения см. в разделе about_Return.

Список операторов функции может содержать различные типы списков операторов с ключевыми словами Begin , Process и End . Эти списки инструкций обработают входные данные из конвейера по-разному.

Фильтр — это специальный тип функции, который использует Filter ключевое слово.

Функции также могут действовать как командлеты. Можно создать функцию, которая работает так же, как командлет, без использования C# программирования. Дополнительные сведения см. в разделе about_Functions_Advanced.

Синтаксис

Ниже приведен синтаксис функции.

function [<scope:>]<name> [([type]$parameter1[,[type]$parameter2])]
{
  param([type]$parameter1 [,[type]$parameter2])
  dynamicparam {<statement list>}
  begin {<statement list>}
  process {<statement list>}
  end {<statement list>}
}

Функция включает следующие элементы:

  • FunctionКлючевое слово
  • Область (необязательно)
  • Выбранное имя
  • Любое количество именованных параметров (необязательно)
  • Одна или несколько команд PowerShell, заключенных в фигурные скобки {}

Дополнительные сведения о Dynamicparam ключевом слове и динамических параметрах в функциях см. в разделе about_Functions_Advanced_Parameters.

Простые функции

Функции не обязательно должны быть очень сложными. Простейшие функции имеют следующий формат:

function <function-name> {statements}

Например, следующая функция запускает PowerShell с параметром Запуск от имени администратора.

function Start-PSAdmin {Start-Process PowerShell -Verb RunAs}

Чтобы использовать функцию, введите: Start-PSAdmin

Чтобы добавить операторы в функцию, введите каждую инструкцию в отдельной строке или используйте точку с запятой ; для разделения инструкций.

Например, следующая функция находит все .jpg файлы в каталогах текущего пользователя, которые были изменены после начальной даты.

function Get-NewPix
{
  $start = Get-Date -Month 1 -Day 1 -Year 2010
  $allpix = Get-ChildItem -Path $env:UserProfile\*.jpg -Recurse
  $allpix | Where-Object {$_.LastWriteTime -gt $Start}
}

Вы можете создать панель элементов с полезными небольшими функциями. Добавьте эти функции в профиль PowerShell, как описано в about_Profiles и далее в этом разделе.

Имена функций

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

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

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

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

Функции с параметрами

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

именованных параметров

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

Параметры внутри фигурных скобок можно определить с помощью Param ключевого слова, как показано в следующем примере синтаксиса:

function <name> {
  param ([type]$parameter1[,[type]$parameter2])
  <statement list>
}

Можно также определить параметры за пределами фигурных скобок без Param ключевого слова, как показано в следующем примере синтаксиса:

function <name> [([type]$parameter1[,[type]$parameter2])] {
  <statement list>
}

Ниже приведен пример альтернативного синтаксиса.

Function Add-Numbers($one, $two) {
    $one + $two
}

Хотя первый метод является предпочтительным, разница между этими двумя методами отсутствует.

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

В следующем примере показана функция с именем Get-SmallFiles . Эта функция имеет $Size параметр. Функция отображает все файлы, размер которых меньше значения $Size параметра, и исключает каталоги.

function Get-SmallFiles {
  Param($Size)
  Get-ChildItem $HOME | Where-Object {
    $_.Length -lt $Size -and !$_.PSIsContainer
  }
}

В функции можно использовать $Size переменную, которая является именем, определенным для параметра.

Чтобы использовать эту функцию, введите следующую команду:

Get-SmallFiles -Size 50

Можно также ввести значение для именованного параметра без имени параметра. Например, следующая команда дает тот же результат, что и команда, которая присваивает имя параметру size :

Get-SmallFiles 50

Чтобы определить значение по умолчанию для параметра, введите знак равенства и значение после имени параметра, как показано в следующем варианте Get-SmallFiles примера:

function Get-SmallFiles ($Size = 100) {
  Get-ChildItem $HOME | Where-Object {
    $_.Length -lt $Size -and !$_.PSIsContainer
  }
}

Если ввести Get-SmallFiles без значения, функция присваивает 100 значение $size . Если указать значение, то функция использует это значение.

При необходимости можно указать краткую строку справки, описывающую значение параметра по умолчанию, добавив атрибут псдефаултвалуе в описание параметра и указав свойство Help объекта псдефаултвалуе. Чтобы предоставить строку справки, описывающую значение по умолчанию (100) параметра size в Get-SmallFiles функции, добавьте атрибут псдефаултвалуе , как показано в следующем примере.

function Get-SmallFiles {
  param (
      [PSDefaultValue(Help = '100')]
      $Size = 100
  )
}

Дополнительные сведения о классе атрибута псдефаултвалуе см. в разделе псдефаултвалуе Attribute Members.

Параметры позиционирования

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

При использовании позиционированных параметров введите одно или несколько значений после имени функции. Значения позиционированных параметров присваиваются $args переменной массива. Значение, следующее за именем функции, присваивается первой положению в $args массиве, $args[0] .

Следующая Get-Extension функция добавляет .txt расширение имени файла к указанному имени файла:

function Get-Extension {
  $name = $args[0] + ".txt"
  $name
}
Get-Extension myTextFile
myTextFile.txt

Параметры переключателя

Переключатель — это параметр, который не требует значения. Вместо этого введите имя функции, за которым следует имя параметра переключателя.

Чтобы определить параметр переключателя, укажите тип [switch] перед именем параметра, как показано в следующем примере:

function Switch-Item {
  param ([switch]$on)
  if ($on) { "Switch on" }
  else { "Switch off" }
}

При вводе On параметра Switch после имени функции функция отображает параметр on. Без параметра Switch отображается значение «Отключить выключение».

Switch-Item -on
Switch on
Switch-Item
Switch off

При выполнении функции можно также присвоить логическое значение параметру, как показано в следующем примере:

Switch-Item -on:$true
Switch on
Switch-Item -on:$false
Switch off

Использование Сплаттинг для представления параметров команды

Сплаттинг можно использовать для представления параметров команды. Эта функция появилась в Windows PowerShell 3,0.

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

Следующий пример функции вызывает Get-Command командлет. Команда использует @Args для представления параметров Get-Command .

function Get-MyCommand { Get-Command @Args }

Get-CommandПри вызове функции можно использовать все параметры Get-MyCommand . Параметры и значения параметров передаются в команду с помощью команды @Args .

Get-MyCommand -Name Get-ChildItem
CommandType     Name                ModuleName
-----------     ----                ----------
Cmdlet          Get-ChildItem       Microsoft.PowerShell.Management

Эта @Args функция использует $Args Автоматический параметр, представляющий необъявленные параметры и значения командлета из оставшихся аргументов.

Дополнительные сведения о Сплаттинг см. в разделе about_Splatting.

Передача объектов в функции

Любая функция может принимать входные данные из конвейера. Можно контролировать, как функция обрабатывает входные данные из конвейера с помощью Begin Process End ключевых слов, и. В следующем образце синтаксиса показаны три ключевых слова:

function <name> {
  begin {<statement list>}
  process {<statement list>}
  end {<statement list>}
}

BeginСписок инструкций выполняется только один раз в начале функции.

Важно!

Если функция определяет Begin блок, то Process End весь код должен находиться внутри этих блоков. Код не будет располагаться за пределами блоков, если определены какие либо блоки.

ProcessСписок инструкций выполняется один раз для каждого объекта в конвейере. Во время Process выполнения блока каждый объект конвейера назначается $_ автоматической переменной, по одному объекту конвейера за раз.

После того как функция получит все объекты в конвейере, End список инструкций будет выполняться один раз. Если не Begin Process End используются ключевые слова, или, все инструкции рассматриваются как End список инструкций.

Следующая функция использует Process ключевое слово. Функция отображает примеры из конвейера:

function Get-Pipeline
{
  process {"The value is: $_"}
}

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

1,2,4 | Get-Pipeline
The value is: 1
The value is: 2
The value is: 4

При использовании функции в конвейере объекты, переданный функции, назначаются $input автоматической переменной. Функция выполняет инструкции с Begin ключевым словом перед тем, как все объекты поступают из конвейера. Функция выполняет инструкции с End ключевым словом после того, как все объекты были получены из конвейера.

В следующем примере показана $input Автоматическая переменная с Begin End ключевыми словами и.

function Get-PipelineBeginEnd
{
  begin {"Begin: The input is $input"}
  end {"End:   The input is $input" }
}

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

1,2,4 | Get-PipelineBeginEnd
Begin: The input is
End:   The input is 1 2 4

При Begin выполнении инструкции функция не имеет входных данных из конвейера. EndИнструкция выполняется после того, как функция применяет значения.

Если у функции есть Process ключевое слово, каждый объект в удаляется $input из $input и присваивается $_ . В следующем примере содержится Process список операторов:

function Get-PipelineInput
{
  process {"Processing:  $_ " }
  end {"End:   The input is: $input" }
}

В этом примере каждый объект, передаваемый функции, отправляется в Process список инструкций. ProcessИнструкции выполняются для каждого объекта, по одному объекту за раз. $inputАвтоматическая переменная пуста, если функция достигает End ключевого слова.

1,2,4 | Get-PipelineInput
Processing:  1
Processing:  2
Processing:  4
End:   The input is:

Дополнительные сведения см. в разделе Использование перечислителей .

Фильтры

Фильтр — это тип функции, которая выполняется для каждого объекта в конвейере. Фильтр напоминает функцию со всеми ее операторами в Process блоке.

Синтаксис фильтра выглядит следующим образом:

filter [<scope:>]<name> {<statement list>}

Следующий фильтр принимает записи журнала из конвейера, а затем отображает всю запись или только часть сообщения в записи:

filter Get-ErrorLog ([switch]$message)
{
  if ($message) { Out-Host -InputObject $_.Message }
  else { $_ }
}

Область действия функции

Функция существует в области, в которой она была создана.

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

Можно указать область функции. Например, функция добавляется в глобальную область в следующем примере:

function global:Get-DependentSvs {
  Get-Service | Where-Object {$_.DependentServices}
}

Если функция находится в глобальной области, ее можно использовать в скриптах, функциях и в командной строке.

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

Дополнительные сведения об области действия в PowerShell см. в разделе about_Scopes.

Поиск функций и управление ими с помощью диска Function:

Все функции и фильтры в PowerShell автоматически сохраняются на Function: диске. Этот диск предоставляется поставщиком функций PowerShell.

При обращении к Function: диску введите двоеточие после функции, как при обращении к C диску или на D диске компьютера.

Следующая команда отображает все функции в текущем сеансе PowerShell:

Get-ChildItem function:

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

(Get-ChildItem function:help).Definition

Можно также использовать следующий синтаксис.

$function:help

Дополнительные сведения о Function: диске см. в разделе справки по поставщику функций . Введите Get-Help Function.

Повторное использование функций в новых сеансах

При вводе функции в командной строке PowerShell функция станет частью текущего сеанса. Он доступен до завершения сеанса.

Чтобы использовать функцию во всех сеансах PowerShell, добавьте функцию в профиль PowerShell. Дополнительные сведения о профилях см. в разделе about_Profiles.

Можно также сохранить функцию в файле сценария PowerShell. Введите функцию в текстовом файле, а затем сохраните файл с .ps1 расширением имени файла.

Написание справки для функций

Get-HelpКомандлет возвращает справку по функциям, а также к командлетам, поставщикам и скриптам. Чтобы получить справку по функции, введите, Get-Help за которым следует имя функции.

Например, чтобы получить справку по Get-MyDisks функции, введите:

Get-Help Get-MyDisks

Вы можете написать справку для функции с помощью любого из двух следующих методов:

  • Comment-Based справки по функциям

    Создайте раздел справки, используя специальные ключевые слова в комментариях. Чтобы создать справку на основе комментариев для функции, комментарии должны располагаться в начале или в конце тела функции или в строках, предшествующих ключевому слову Function. Дополнительные сведения о справке на основе комментариев см. в разделе about_Comment_Based_Help.

  • XML-Based справки по функциям

    Создайте раздел справки на основе XML, например тип, который обычно создается для командлетов. При локализации разделов справки на несколько языков требуется справка на основе XML.

    Чтобы связать функцию с разделом справки на основе XML, используйте .ExternalHelp ключевое слово справки на основе комментариев. Без этого ключевого слова Get-Help не удается найти раздел справки по функциям и вызовы для Get-Help функции, возвращающие только автоматически созданную справку.

    Дополнительные сведения о ExternalHelp ключевом слове см. в разделе about_Comment_Based_Help. Дополнительные сведения о справке на основе XML см. в разделе как написать справку по командлетам.

См. также

about_Automatic_Variables

about_Comment_Based_Help

about_Functions_Advanced

about_Functions_Advanced_Methods

about_Functions_Advanced_Parameters

about_Functions_CmdletBindingAttribute

about_Functions_OutputTypeAttribute

about_Parameters

about_Profiles

about_Scopes

about_Script_Blocks

about_Function_provider

PowerShell. Пользовательские функции для пользователей / Хабр

Привет! Довольно часто в своей работе приходиться пользоваться самостоятельно написанными функциями и таскать куски кода между разными скриптами. На Хабре уже есть довольно хорошая статья про

Повторное использование кода

от

Mroff

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


Давайте для начала разберем стандартную структуру функции в PowerShell. Выглядит она следующим образом

Function TestPath ([String]$Path)
        {
                Return(Test-Path $Path)
        }

В общем то ничего сложного, как и в других языках задали имя TestPath, в круглых скобках через запятую скормили переменные $Path, выполнили в теле функции необходимые действия и при необходимости вернули Return() значение. А как быть, когда нужно работать с несколькими переменными? Выходов всегда больше одного – постоянно давать мнемонические коды или делать описание переменной, давайте рассмотрим, как это делается:

Function TestPath
        {
                PARAM (
                [PARAMETER(Mandatory=$True,Position=0,HelpMessage = "Путь до проверяемого ресурса",ParameterSetName='Path')]$Path
                )
                Return(Test-Path $Path)
        }

Сложности никакой нет, но появились дополнительные параметры, которые нам упрощают жизнь:

Mandatory – Принимает два значения True обязательный для заполнения и False необязательный;
HelpMessage – Справка по переменной;
ParameterSetName – Имя переменной к которой относятся данные параметры;
Position – Позиция переменной при вызове функции;

Вроде бы все хорошо теперь у нас есть переменная, у которой есть описание, но для того что бы его узнать необходимо выполнить следующий код:

((Get-Command TestPath).ParameterSets.Parameters | Where-Object Name -eq Path).HelpMessage

PowerShell ответит нам одной строкой в которой будет написано: Путь до проверяемого ресурса.

В какой-то степени удобно, но если мы привыкли работать с PowerShell, то знаем команду Get-Help которая выводит подробную информацию о функции с примерами ее использования и переменными, которые необходимо передавать.

Немного усложним задачу и подготовим функцию информация о которой по запросу Get-Help будет выводиться в полном объеме:

Function WriteToLog {
    <#
    .SYNOPSIS
        Вывод сообщения в консоль и в файл лога.
    .DESCRIPTION
        Данная функция выводит переданную строку в лог файл и в консоль PowerShell
    .EXAMPLE
        #WriteToLog -Str "Данное сообщение будет выведено в консоль красным цветом и в файл C:\Log\log.txt" -FileName 'C:\Log\log.txt' -Color Red
    .EXAMPLE
        #WriteToLog -Str "Данное сообщение будет выведено в консоль цветом по умолчанию (White) и в файл C:\Log\log.txt" -FileName 'C:\Log\log.txt'
    .PARAMETER Str
        Строка, которую необходимо вывести (обязательный параметр)
    .PARAMETER FileName
        Имя файла лога (обязательный параметр)
    .PARAMETER Color
        Цвет текста сообщения в консоли PowerShell (По умолчанию цвет текста белый (White))
    #>
    param (
        [PARAMETER(Mandatory=$True,Position=0)][String]$Str,
        [PARAMETER(Mandatory=$True,Position=1)][String]$FileName,
        [PARAMETER(Mandatory=$False,Position=2)][String]$Color='White'
        )
        Write-Host $Str -ForegroundColor $Color
        If ((Test-Path $FileName) -eq $True)
            {
                Add-Content -Path $FileName -Value $Str
            }
        Else
            {
                Set-Content -Path $FileName -Value $Str
            }
    }

После выполнения данного кода команда Get-Help ‘WriteToLog’ -ShowWindow выведет нам следующее окно.

Давайте разберем что же мы такого написали:

<##> – В данном блоке написаны параметры для справки PowerShell.
.SYNOPSIS – блок для краткого описание функции
.DESCRIPTION – блок для полного описание функции
.EXAMPLE – блок для примера использования функции, может быть несколько
.PARAMETR Имя параметра – блок для описания переменной, для каждой переменной свой блок.

Как вы могли заметить текстовый комментарий начинается со следующей строки после ключевого названия раздела и может быть многострочным. Окончанием комментария считается закрывающий тег #> или следующий блок.

param () – блок для описания переменных, в котором мы указали их порядок и необходимость передачи параметров при вызове функции. Для переменной $Color мы присвоили значение по умолчанию’White’.

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

Спасибо что дочитали до конца.

Использование функций

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

Функции — это тип команд в Windows PowerShell. Для запуска функции введите ее имя, точно так же, как и для командлета. Как и командлеты, функции могут иметь параметры. Как и командлеты, функции могут использовать объекты .NET в качестве источника ввода и выводить объекты .NET. Фактически функции обладают теми же возможностями, что и командлеты.

Лучше всего в функциях то, что их очень легко создавать. В отличие от командлетов, которые пишутся на языке C#, функции представляют собой просто именованные наборы команд и выражений Windows PowerShell. Создавать функции так же просто, как и вводить команды в Windows PowerShell.

Функции являются командами, и поэтому для поиска функций используйте командлет Get-Command.

Например, чтобы найти все функции текущего сеанса, введите команду:


get-command -CommandType function

Кроме того, в Windows PowerShell имеется диск Function:, содержащий все функции текущего сеанса. Для просмотра диска Function: используйте те же методы, что и для просмотра дисков файловой системы.

Чтобы открыть диск функций, введите:

Чтобы вывести функции с диска функций, введите:

Для запуска функции нужно просто ввести ее имя. Например, для запуска функции Clear-Host введите следующую команду:

В консоли Windows PowerShell функция Clear-Host служит для удаления всего текста из окна консоли. В других приложениях эта функция может иметь другое действие или не иметь никакого действия.

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

Например, функция Help, выводящая разделы справки постранично, имеет те же параметры, что и командлет Get-Help. Чтобы использовать функцию Help для вывода только примеров из раздела справки для командлета Get-Service, введите следующую команду:


help -name get-service -examples

Для функций могут существовать разделы справки. Чтобы найти раздел справки для функции, используйте командлет Get-Help. Это тот же командлет, что используется для получения справки по командлетам.

Например, для получения справки по функции Disable-PSRemoting, введите следующую команду:


get-help Disable-PSRemoting

Для получения справки по функциям можно использовать любые параметры командлета Get-Help. Например, чтобы получить примеры из раздела справки для функции Disable-PSRemoting, введите следующую команду:


get-help Disable-PSRemoting -example

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


function <name> { <commands> }

Введите ключевое слово function и имя функции и заключите команды в фигурные скобки ({ }).

Например, если какая-то команда, например, get-help get-member -examples, используется часто, для экономии времени можно написать функцию, исполняющую эту команду. Следующая функция с именем GMEX исполняет эту команду.


function GMEX {get-help get-member -examples}

После ввода в командной строке Windows PowerShell (или после копирования и вставки из этого раздела) и нажатия клавиши ENTER эту функцию можно будет использовать в текущем сеансе. Для исполнения функции введите команду GMEX.

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

Дополнительные сведения о написании функций см. в разделах about_Functions, about_Comment_Based_Help и about_Functions_Advanced.

При запуске Windows PowerShell открывается ее сеанс. Сеанс длится, пока не закрывается окно Windows PowerShell (или пока сеанс не завершается с помощью команды Exit). Элементы, созданные во время сеанса, удаляются при его закрытии, если они не сохранены в файле на диске или в реестре.

Для использования функций в будущих сеансах Windows PowerShell нужно создать профиль Windows PowerShell и сохранить эти функции в нем.

Дополнительную информацию см. в разделе about_Profiles.

Функции в Windows PowerShell | вебисторий

В предыдущей статье мы говорили о командлетах в Windows PowerShell. Теперь поговорим о следующем типе команд — функциях.

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

Создадим простейшую функцию Primer, которая просто выводит сообщение. Для этого введем в PowerShell

Function Primer{"Это пример функции."}

Таким образом мы задали имя функции и выполняемое действие. Теперь, для того, чтобы исполнить функцию, нам достаточно написать её имя.

Функции способны работать с аргументами, которые передаются им при запуске. Сделать это можно с помощью переменной $Args, которая представляет собою массив с аргументами, или при помощи формальных параметров.

Изменим нашу функцию Primer, добавив в неё переменную $Args.

Function Primer{"Это пример $Args."}

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

Пример функции с аргументами в PowerShell

В данном случае «функции», «с» и «аргументами» — три элемента массива $Args. Как видим, они выводятся через пробел. Для того, чтобы убедиться, что это именно три отдельных элемента, введем разделитель в виде точки с помощью специальной переменной $OFS.

Function Primer{
>> $OFS="."
>> "Это пример $Args."}
>>

 Смотрим результат.

Использование переменной $OFS

Второй способ обработки аргументов функций в Windows PowerShell это использование формальных параметров. Формальные параметры указываются в круглых скобках после имени функции.

Продолжим наш пример с выводом сообщения. Снова изменим функцию Primer, приведя её к следующему виду

Function Primer ($a, $b, $c) {"Это пример $a $b $c."}

Результат будет тем же самым.

Использование формальных параметров

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

Создадим функцию Summa, которая складывала бы значения двух аргументов.

Function Summa ($a, $b) {$a+$b}

Мы можем задать значения параметров сразу. Если все значения уже заданы, функции не нужны дополнительные аргументы. Мы также вольны называть параметры по собственному усмотрению.

Видоизменим функцию Summa.

Function Summa ($chislo1=15,$chislo2=20) {$chislo1+$chislo2}

Мы обозначили параметры как $chislo1 и $chislo2, задав им значения соответственно 15 и 20. Поскольку значения всех параметров здесь указаны, аргументы нам не нужны. Но, если мы всё-таки запустим эту функцию с дополнительным аргументом, то он заменит собой значение $chislo1, а $chislo2 останется без изменений.

PowerShell также позволяет указывать тип параметра функции. Например, тип [int] это целые числа, [string] — текст, а [boolean] — логический тип данных.

Вот следующий пример.

Использование типов данных в Windows PowerShell

Как видим, в результате деления $a на $b должно было получиться 1,15. Но, поскольку мы указали интерпретатору воспринимать все параметры функции как целые числа, дробные значения были округлены до целых. Обратите внимание на округления, которые представлены ниже.

Они не совсем соответствуют тем законам математики, к которым мы привыкли.

Среди типов параметров есть так называемые «параметры-переключатели» обозначающиеся типом [Switch]. Их смысл состоит в логическом выборе, а сами параметры могут принимать только значения $True или $False.

Создадим функцию с таким переключателем.

Function Vybor ([Switch] $a) {
>> if ($a) {
>> "Это первый вариант."
>> }
>> else { "Это второй вариант."
>> }
>> }
>>

В данном случае, если мы запустим функцию Vybor с параметром -a (аналогично, как мы запускали dir с параметрами -recurse и -filter в прошлой статье), то нам выйдет одно сообщение, а если без параметра, то другое.

Использование переключателя Switch в Windows PowerShell

На этом с функциями пока всё. Далее мы продолжим изучать типы команд в Windows PowerShell.

Переменные и функции

Security Controls поддерживает использование ряда переменных и функций PowerShell для выполнения каждого сценария. Все имена переменных начинаются с «ST_». Все имена функций начинаются с «ST-«. Вы можете использовать эти переменные и функции в своих сценариях.

Переменные PowerShell могут иметь другие области действия:

•Global: Доступна в текущем сеансе PowerShell.

•Script: Используется в сценарии (вне функций) и локально для этого сценария.

•Закрытая: Используется в функции и локально для этой функции.

•Local: Текущая область действия, которая может быть глобальной, сценарием или закрытой.

Переменные, используемые с Security Controls, имеют общую область действия. Так как каждый целевой компьютер выполняет собственный сеанс PowerShell, это равносильно использованию области действия сценария.

Переменные выполнения

В следующей таблице перечислены переменные для каждого выполнения. Для всех компьютеров будет отображаться одно и то же значение этих переменных. Не изменяйте значения переменных, отмеченных как [Только чтение].

ST_OutputDirectoryПолный путь к базовому каталогу вывода. Для выполнения будет создан подкаталог. [Только чтение]
ST_RunDirectoryПолный путь к каталогу выполнения вывода. [Только чтение]
ST_RunErrorFileПолный путь к файлу ошибок выполнения вывода. В этом файле должны быть представлены ошибки, не относящиеся к конкретному компьютеру. Этот файл также будет содержать сообщения о компьютерах, для которых не удалось определить IP-адрес, и о компьютерах, на которых не будут созданы соответствующие им вложенные папки. [Только чтение]
ST_RunNameИмя выполнения, указанное в пользовательском интерфейсе во время запуска вручную или по расписанию с добавленным временем выполнения. По умолчанию используется имя сценария или шаблона. [Только чтение]
ST_RunOnConsoleУстановите значение $false, если в сценарии используется удаленное подключение PowerShell, а в противном случае — $true. [Только чтение]
ST_RunOutputFileПолный путь к стандартному файлу вывода выполнения вывода. В этом файле будут присутствовать все данные вывода, отображаемые на консоли во время запуска из командной строки. [Только чтение]
ST_RunResultЭто краткий результат выполнения, отображаемый в Мониторе операций. Он ограничен 100 символами. Если вы не введете эту переменную явно в своем сценарии, она будет установлена для указания количества компьютеров, на которых были обнаружены ошибки, и количество ошибок обнаружения компьютеров.

Переменные компьютера

В следующей таблице перечислены переменные для каждого компьютера. Значения этих переменных могут отличаться для каждого целевого компьютера. Не изменяйте значения переменных, отмеченных как [Только чтение].

ST_ComputerNameИмя целевого компьютера. [Только чтение]
ST_CredentialОбъект PSCredential, содержащий имя пользователя и пароль SecureString, используемые для подключения к целевому компьютеру. Эту переменную можно передать в любую команду, которая поддерживает параметр Credential. [Только чтение]
ST_DomainNameИмя домена или рабочей группы целевого компьютера. [Только чтение]
ST_MachineDirectoryПолный путь к каталогу компьютера. Обычно это имя компьютера, однако, если имя компьютера содержит символы, недопустимые в именах папок, эти символы будут заменены символами подчеркивания. [Только чтение]
ST_MachineErrorЛогическое значение, указывающее, что во время выполнения этого сценария на конкретном компьютере, обнаружена одна или несколько ошибок.
ST_MachineErrorFileПолный путь к файлу ошибок компьютера. Если во время выполнения сценария будут обнаружены ошибки, они будут записаны в этот файл. [Только чтение]
ST_MachineOutputFileПолный путь к файлу вывода компьютера. В этом файле будут представлены данные вывода, созданные сценарием для стандартного вывода.
ST_MachineResultЭто краткий результат для компьютера, отображаемый в Мониторе операций. Он ограничен 100 символами. Если вы не укажете эту переменную явно в своем сценарии, для нее будет установлено значение «Успешно» в случае отсутствия ошибок на компьютере, или сообщение первой ошибки, обнаруженной для этого компьютера. Используйте функцию ST-SetMachineResult для явной установки значения этой переменной.
ST_MachineResultSetЛогическое значение, указывающее, что сценарий установил переменную ST_MachineResult. Используйте функцию ST-SetMachineResult для явной установки значения ST_MachineResult и этой переменной.

Функции

Security Controls содержит набор функций, доступных для каждого создаваемого вами сценария. Они перечислены в следующей таблице.

ST-GetTargetOSЭта функция выполняет попытку подключения к целевой системе, опрашивая WMI и получая объект Win32_OperatingSystem.
ST-SetMachineResultЭта функция использует строковый параметр. Она устанавливает переменную ST_MachineResult для передачи строки и устанавливает для переменной ST_MachineResultSet значение $true.
ST-SetMachineErrorЭта функция использует строковый аргумент в качестве параметра. Она устанавливает переменную ST_MachineResult для передачи строки. Она также устанавливает для переменных ST_MachineResultSet и ST_MachineError значение $true.
ST-SendMessageЭта функция использует строковый параметр. Эта строка будет отображаться в Мониторе операций. Используйте эту функцию для отслеживания выполнения долговременных сценариев. После выполнения сценария строка в ST_MachineResult будет отображена в Мониторе операций. За исключением процесса отладки вы должны избегать вызова этого метода в быстро выполняемых сценариях. Строка будет усечена до 100 символов, если будет передана строка длиннее этого значения.
ST-CreateMachineDirectoryОбычно каталог компьютера не создается до записи выводных данных. Если ваш сценарий создает файлы в каталоге компьютера, перед записью в каталоге вы должны вызвать эту функцию для создания каталога. Вызов этой функции более одного раза не имеет отрицательного эффекта.
ST-CreateRunDirectoryОбычно каталог выполнения не создается до тех пор, пока во время выполнения не будут записаны любые выходные данные. Если ваш сценарий создает файлы в каталоге выполнения, перед записью в каталоге вы должны вызвать эту функцию для создания каталога. Вызов этой функции более одного раза не имеет отрицательного эффекта.
ST-ComputerAndCredentialЭта функция возвращает для целевого компьютера соответствующие значения для использования в параметрах ComputerName и Credential. Для получения информации см. раздел Использование параметров ComputerName и Credential.
ST-SubCCЭта функция принимает строковый параметр, который является допустимым для команд PowerShell. Эта функция заменяет параметр «$ST_CC» в этой командной строке соответствующими значениями для использования параметров ComputerName и Credential. Затем она выполняет полученную команду и возвращает результаты выполнения. Для получения информации см. раздел Использование параметров ComputerName и Credential.

powershell — Как передать несколько параметров в функцию в PowerShell?

Здесь есть несколько хороших ответов, но я хотел бы отметить пару других вещей. Параметры функций — это место, где светит PowerShell. Например, вы можете иметь именованные или позиционные параметры в расширенных функциях, например:

function Get-Something
{
    Param
    (
         [Parameter(Mandatory=$true, Position=0)]
         [string] $Name,
         [Parameter(Mandatory=$true, Position=1)]
         [int] $Id
    )
}

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

Get-Something -Id 34 -Name "Blah" 
Get-Something "Blah" 34

Первый пример работает, хотя имя предоставляется вторым, потому что мы явно использовали имя параметра. Второй пример работает на основе позиции, поэтому имя должно быть первым. Когда это возможно, я всегда стараюсь определить позиции, чтобы оба варианта были доступны.

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

function Get-Something
{
    [CmdletBinding(DefaultParameterSetName='Name')]
    Param
    (
         [Parameter(Mandatory=$true, Position=0, ParameterSetName='Name')]
         [string] $Name,
         [Parameter(Mandatory=$true, Position=0, ParameterSetName='Id')]
         [int] $Id
    )
}

Теперь функция будет либо принимать имя, либо идентификатор, но не оба. Вы можете использовать их по месту или по имени. Так как они другого типа, PowerShell поймет это.Some.*’)] [string] $Name, [Parameter(Mandatory=$true, Position=1)] [ValidateRange(10,100)] [int] $Id ) }

В первом примере ValidatePattern принимает регулярное выражение, которое гарантирует, что предоставленный параметр соответствует ожидаемому. Если это не так, выдается интуитивно понятное исключение, которое говорит вам, что именно не так. Таким образом, в этом примере «Something» будет работать нормально, но «Summer» не пройдет проверку.

ValidateRange гарантирует, что значение параметра находится в диапазоне, который вы ожидаете для целого числа. Таким образом, 10 или 99 сработают, но 101 сгенерирует исключение.

Еще одним полезным является ValidateSet, который позволяет явно определять массив допустимых значений. Если будет введено что-то еще, будет сгенерировано исключение. Есть и другие, но, вероятно, самый полезный один из них — ValidateScript. Это берет блок скрипта, который должен иметь значение $ true, поэтому пределом является небо. Например:

function Get-Something
{
    Param
    (
         [Parameter(Mandatory=$true, Position=0)]
         [ValidateScript({ Test-Path $_ -PathType 'Leaf' })]
         [ValidateScript({ (Get-Item $_ | select -Expand Extension) -eq ".csv" })]
         [string] $Path
    )
}

В этом примере мы уверены, что не только $ Path существует, но и что это файл (в отличие от каталога) и имеет расширение .csv. ($ _ относится к параметру, находящемуся внутри вашего скриптового блока.) Вы также можете передать гораздо большие многострочные скриптовые блоки, если требуется этот уровень, или использовать несколько скриптовых блоков, как я сделал здесь. Это чрезвычайно полезно, и делает для Nice чистые функции и интуитивно понятные исключения.

функций — PowerShell | Документы Microsoft

  • 14 минут на чтение

В этой статье

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

По возможности, я предпочитаю писать функции, потому что они больше ориентированы на инструменты. Я могу поставить функции в модуле сценария, поместите этот модуль в $ env: PSModulePath и вызовите функции без необходимости физически определять, где они сохранены. Используя модуль PowerShellGet, это просто для совместного использования этих модулей в репозитории NuGet. PowerShellGet поставляется с PowerShell версии 5.0 и выше. Он доступен для отдельной загрузки для PowerShell версии 3.0 и выше.

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

Именование

При именовании ваших функций в PowerShell используйте регистр Pascal с утвержденным глаголом и существительное в единственном числе.Я также рекомендую ставить перед существительным префикс. Например: - .

В PowerShell есть специальный список утвержденных глаголов, который можно получить, запустив Get-Verb .

  Get-Verb | Sort-Object -Property Глагол
  
  Verb Group
---- -----
Добавить общий
Утвердить жизненный цикл
Жизненный цикл утверждения
Резервные данные
Блокировать безопасность
Данные контрольной точки
Очистить общий
Закрыть общий
Сравнить данные
Полный жизненный цикл
Сжать данные
Подтвердить жизненный цикл
Подключить коммуникации
Конвертировать данные
Конвертировать из данных
Преобразовать в данные
Копировать Common
Диагностика отладки
Запретить жизненный цикл
Отключить жизненный цикл
Отключить связь
Снять данные
Редактировать данные
Включить жизненный цикл
Введите общий
Выход из общего
Развернуть данные
Экспорт данных
Найти общий
Формат Общий
Общайся
Обеспечение безопасности
Групповые данные
Скрыть общее
Импортировать данные
Инициализировать данные
Установить жизненный цикл
Вызов жизненного цикла
Присоединяйтесь к Common
Ограничить данные
Замок Общий
Измерение диагностики
Объединить данные
Смонтировать данные
Переместить общий
Новый Common
Открытый общий
Оптимизировать Общие
Выходные данные
Ping Diagnostic
Поп-Коммон
Защитить безопасность
Опубликовать данные
Нажмите Common
Читать сообщения
Получать сообщения
Повторить Common
Жизненный цикл регистрации
Удалить общие
Переименовать общий
Диагностика ремонта
Жизненный цикл запроса
Сбросить общий
Изменить размер общего
Разрешить диагностику
Перезапустить жизненный цикл
Восстановить данные
Продолжить жизненный цикл
Отменить безопасность
Сохранять данные
Общий поиск
Выберите Common
Отправить сообщения
Установить общий
Показать общие
Пропустить Common
Разделить общий
Начать жизненный цикл
Шаг Общий
Остановить жизненный цикл
Отправить жизненный цикл
Приостановить жизненный цикл
Коммутатор Общий
Синхронизировать данные
Диагностический тест
Диагностика трассировки
Разблокировать безопасность
Отменить общее
Жизненный цикл удаления
Разблокировать Common
Снять защиту безопасности
Отменить публикацию данных
Отменить регистрацию жизненного цикла
Обновить данные
Использовать другое
Ждать жизненный цикл
Смотреть общие
Написать сообщение
  

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

Простая функция

Функция в PowerShell объявляется с ключевым словом function, за которым следует имя функции и затем открывающая и закрывающая фигурная скобка.Код, который будет выполнять функция, содержится в эти фигурные скобки.

  function Get-Version {
    $ PSVersionTable.PSVersion
}
  

Показанная функция представляет собой простой пример, возвращающий версию PowerShell.

  Get-версия
  
  Major Minor Build Revision
----- ----- ----- --------
5 1 14393 693
  

Существует большая вероятность конфликта имен с функциями, названными чем-то вроде Get-Version и default. команды в PowerShell или команды, которые могут писать другие.Вот почему я рекомендую ставить перед существительным префикс часть ваших функций, чтобы помочь предотвратить конфликты имен. В следующем примере я буду использовать приставка «PS».

  function Get-PSVersion {
    $ PSVersionTable.PSVersion
}
  

За исключением названия, эта функция идентична предыдущей.

  Get-PSVersion
  
  Major Minor Build Revision
----- ----- ----- --------
5 1 14393 693
  

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

  function Get-MrPSVersion {
    $ PSVersionTable.PSVersion
}
  

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

  Get-MrPSVersion
  
  Major Minor Build Revision
----- ----- ----- --------
5 1 14393 693
  

После загрузки в память вы можете видеть функции на Function PSDrive.

  Get-ChildItem -Path Функция: \ Get- * Версия
  
  CommandType Имя Версия Источник
----------- ---- ------- ------
Функция Get-Version
Функция Get-PSVersion
Функция Get-MrPSVersion
  

Если вы хотите удалить эти функции из текущего сеанса, вам придется удалить их из Функция PSDrive или закрыть и снова открыть PowerShell.

  Get-ChildItem -Path Функция: \ Get- * Version | Убрать предмет
  

Убедитесь, что функции действительно были удалены.

  Get-ChildItem -Path Функция: \ Get- * Версия
  

Если функции были загружены как часть модуля, модуль можно выгрузить, чтобы удалить их.

  Remove-Module -Name 
  

Командлет Remove-Module удаляет модули из памяти в текущем сеансе PowerShell. не удаляет их из вашей системы или с диска.

Параметры

Не присваивать значения статически! Используйте параметры и переменные. Когда дело доходит до наименования вашего параметры, по возможности используйте то же имя, что и командлеты по умолчанию для имен параметров.

  function Test-MrParameter {

    парам (
        $ ComputerName
    )

    Запись-вывод $ ComputerName

}
  

Почему я использовал ComputerName , а не Computer , ServerName или Host для моего параметра название? Это потому, что я хотел, чтобы моя функция была стандартизирована, как командлеты по умолчанию.

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

  function Get-MrParameterCount {
    парам (
        [строка []] $ ParameterName
    )

    foreach ($ Parameter в $ ParameterName) {
        $ Results = Get-Command -ParameterName $ Parameter -ErrorAction SilentlyContinue

        [pscustomobject] @ {
            ParameterName = $ Parameter
            NumberOfCmdlets = $ Results.Count
        }
    }
}
  

Как видно из результатов, показанных ниже, 39 команд имеют параметр ComputerName .Там нет командлетов с такими параметрами, как Computer , ServerName , Host или Станок .

  Get-MrParameterCount -ParameterName ComputerName, Computer, ServerName, Host, Machine
  
  ParameterName NumberOfCmdlets
------------- ---------------
ComputerName 39
Компьютер 0
ServerName 0
Хост 0
Машина 0
  

Я также рекомендую использовать тот же регистр для имен параметров, что и для командлетов по умолчанию.Использовать Имя компьютера , а не имя компьютера . Это заставляет ваши функции выглядеть и чувствовать себя как по умолчанию командлеты. Люди, которые уже знакомы с PowerShell, будут чувствовать себя как дома.

Оператор param позволяет определить один или несколько параметров. Определения параметров: через запятую (, ). Для получения дополнительной информации см. About_Functions_Advanced_Parameters.

Расширенные функции

Превратить функцию в PowerShell в расширенную функцию действительно просто.Одно из отличий между функцией и расширенной функцией заключается в том, что расширенные функции имеют ряд общих параметры, которые добавляются к функции автоматически. Эти общие параметры включают параметры например Verbose и Debug .

Я начну с функции Test-MrParameter , которая использовалась в предыдущем разделе.

  function Test-MrParameter {

    парам (
        $ ComputerName
    )

    Запись-вывод $ ComputerName

}
  

Я хочу, чтобы вы заметили, что функция Test-MrParameter не имеет общего параметры.Есть несколько разных способов увидеть общие параметры. Один из них — просмотр синтаксис с использованием Get-Command .

  Get-Command -Name Test-MrParameter -Syntax
  
  Test-MrParameter [[-ComputerName] ]
  

Другой способ — развернуть параметры с помощью команды Get-Command .

  (Get-Command -Name Test-MrParameter) .Parameters.Keys
  
  Имя компьютера
  

Добавьте CmdletBinding , чтобы превратить функцию в расширенную функцию.

  function Test-MrCmdletBinding {

    [CmdletBinding ()] # << - превращает обычную функцию в расширенную.
    парам (
        $ ComputerName
    )

    Запись-вывод $ ComputerName

}
  

Добавление CmdletBinding автоматически добавляет общие параметры. CmdletBinding требует параметра блок, но блок param может быть пустым.

  Get-Command -Name Test-MrCmdletBinding -Syntax
  
  Test-MrCmdletBinding [[-ComputerName] ] []
  

Детализация параметров с помощью команды Get-Command показывает фактические имена параметров, включая общие.

  (Get-Command -Name Test-MrCmdletBinding) .Parameters.Keys
  
  Имя компьютера
Подробный
Отлаживать
ErrorAction
ПредупреждениеДействие
ИнформацияДействие
ErrorVariable
ПредупреждениеПеременная
ИнформацияПеременная
OutVariable
OutBuffer
PipelineVariable
  

Поддерживает процесс

SupportsShouldProcess добавляет WhatIf и Подтвердите параметры . Они нужны только для команды, которые вносят изменения.

  function Test-MrSupportsShouldProcess {

    [CmdletBinding (SupportsShouldProcess)]
    парам (
        $ ComputerName
    )

    Запись-вывод $ ComputerName

}
  

Обратите внимание, что теперь есть параметры WhatIf и Confirm .

  Get-Command -Name Test-MrSupportsShouldProcess -Syntax
  
  Test-MrSupportsShouldProcess [[-ComputerName] ] [-WhatIf] [-Confirm] []
  

Еще раз, вы также можете использовать Get-Command для возврата списка фактических имен параметров, включая общие вместе с WhatIf и Confirm.

  (Get-Command -Name Test-MrSupportsShouldProcess) .Parameters.Keys
  
  Имя компьютера
Подробный
Отлаживать
ErrorAction
ПредупреждениеДействие
ИнформацияДействие
ErrorVariable
ПредупреждениеПеременная
ИнформацияПеременная
OutVariable
OutBuffer
PipelineVariable
Что если
Подтверждать
  

Проверка параметров

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

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

  function Test-MrParameterValidation {

    [CmdletBinding ()]
    парам (
        [строка] $ ComputerName
    )

    Запись-вывод $ ComputerName

}
  

В предыдущем примере я указал String в качестве типа данных для ComputerName параметр.Это приводит к тому, что он позволяет указать только одно имя компьютера. Если более одного имя компьютера указывается через список, разделенный запятыми, генерируется ошибка.

  Test-MrParameterValidation -ComputerName Server01, Server02
  
  Test-MrParameterValidation: невозможно обработать преобразование аргумента для параметра
'Имя компьютера'. Невозможно преобразовать значение в тип System.String.
В строке: 1 символ: 42
+ Test-MrParameterValidation -ComputerName Server01, Server02
+
    + CategoryInfo: InvalidData: (:) [Test-MrParameterValidation], ParameterBindingArg
     umentTransformationException
    + FullyQualifiedErrorId: ParameterArgumentTransformationError, Test-MrParameterValidation
  

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

  function Test-MrParameterValidation {

    [CmdletBinding ()]
    парам (
        [Параметр (обязательный)]
        [строка] $ ComputerName
    )

    Запись-вывод $ ComputerName

}
  

Синтаксис, использованный в предыдущем примере, совместим с PowerShell версии 3.0 и выше. [Параметр (Обязательный = $ true)] Вместо этого можно указать , чтобы функция была совместима с PowerShell версии 2.0 и выше. Теперь, когда требуется ComputerName , если он не указано, функция запросит один.

  Test-MrParameterValidation
  
  командлет Test-MrParameterValidation в позиции 1 командного конвейера
Задайте значения для следующих параметров:
Имя компьютера:
  

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

  function Test-MrParameterValidation {

    [CmdletBinding ()]
    парам (
        [Параметр (обязательный)]
        [строка []] $ ComputerName
    )

    Запись-вывод $ ComputerName

}
  

Может быть, вы хотите указать значение по умолчанию для параметра ComputerName , если оно не указано. Проблема в том, что значения по умолчанию нельзя использовать с обязательными параметрами. Вместо этого вам нужно используйте атрибут проверки параметра ValidateNotNullOrEmpty со значением по умолчанию.

  function Test-MrParameterValidation {

    [CmdletBinding ()]
    парам (
        [ValidateNotNullOrEmpty ()]
        [строка []] $ ComputerName = $ env: COMPUTERNAME
    )

    Запись-вывод $ ComputerName

}
  

Даже при установке значения по умолчанию старайтесь не использовать статические значения. В предыдущем примере $ env: COMPUTERNAME используется как значение по умолчанию, которое автоматически переводится в локальный имя компьютера, если значение не указано.

Подробный вывод

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

Функция, показанная в следующем примере, имеет встроенный комментарий в цикле foreach . Пока это конкретный комментарий может быть не так уж сложно найти, представьте, если бы функция включала сотни строки кода.

  function Test-MrVerboseOutput {

    [CmdletBinding ()]
    парам (
        [ValidateNotNullOrEmpty ()]
        [строка []] $ ComputerName = $ env: COMPUTERNAME
    )

    foreach ($ Computer в $ ComputerName) {
        # Попытка выполнить какое-либо действие на $ Computer << - Не используйте
        # встраивайте такие комментарии, используйте вместо этого подробный текст.Запись-Вывод $ Компьютер
    }

}
  

Лучше использовать Write-Verbose вместо встроенных комментариев.

  function Test-MrVerboseOutput {

    [CmdletBinding ()]
    парам (
        [ValidateNotNullOrEmpty ()]
        [строка []] $ ComputerName = $ env: COMPUTERNAME
    )

    foreach ($ Computer в $ ComputerName) {
        Write-Verbose -Message «Попытка выполнить какое-либо действие на $ Computer»
        Запись-Вывод $ Компьютер
    }

}
  

Когда функция вызывается без параметра Verbose , подробный вывод не будет отображается.

  Test-MrVerboseOutput -ComputerName Server01, Server02
  

Когда он вызывается с параметром Verbose , выводится подробный вывод.

  Test-MrVerboseOutput -ComputerName Server01, Server02 -Verbose
  

Вход трубопровода

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

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

Ввод в конвейер поступает по одному элементу за раз, аналогично тому, как элементы обрабатываются в цикле foreach . Как минимум, для обработки каждого из этих элементов требуется блок процесса , если вы принимаете массив в качестве входных данных. Если вы принимаете в качестве входных данных только одно значение, блок процесса не нужен, но я все же рекомендую указать его для единообразия.

  function Test-MrPipelineInput {

    [CmdletBinding ()]
    парам (
        [Параметр (обязательный,
                   ValueFromPipeline)]
        [строка []] $ ComputerName
    )

    ПРОЦЕСС {
        Запись-вывод $ ComputerName
    }

}
  

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

  function Test-MrPipelineInput {

    [CmdletBinding ()]
    парам (
        [Параметр (обязательный,
                   ValueFromPipelineByPropertyName)]
        [строка []] $ ComputerName
    )

    ПРОЦЕСС {
            Запись-вывод $ ComputerName
    }

}
  
Блоки

BEGIN и END являются необязательными. BEGIN должен быть указан перед блоком PROCESS и используется для выполнения любой начальной работы до получения элементов из конвейера. Это важно понять. Введенные значения недоступны в блоке BEGIN . КОНЕЦ блок будет указан после блока PROCESS и используется для очистки после того, как все элементы , которые подаются по трубопроводу, были обработаны.

Обработка ошибок

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

  function Test-MrErrorHandling {

    [CmdletBinding ()]
    парам (
        [Параметр (обязательный,
                   ValueFromPipeline,
                   ValueFromPipelineByPropertyName)]
        [строка []] $ ComputerName
    )

    ПРОЦЕСС {
        foreach ($ Computer в $ ComputerName) {
            Test-WSMan -ComputerName $ Компьютер
        }
    }

}
  

Есть несколько различных способов обработки ошибок в PowerShell. Try / Catch более современный способ обработки ошибок.

  function Test-MrErrorHandling {

    [CmdletBinding ()]
    парам (
        [Параметр (обязательный,
                   ValueFromPipeline,
                   ValueFromPipelineByPropertyName)]
        [строка []] $ ComputerName
    )

    ПРОЦЕСС {
        foreach ($ Computer в $ ComputerName) {
            пытаться {
                Test-WSMan -ComputerName $ Компьютер
            }
            поймать {
                Предупреждение о записи - сообщение «Невозможно подключиться к компьютеру: $ Computer»
            }
        }
    }

}
  

Хотя функция, показанная в предыдущем примере, использует обработку ошибок, она также генерирует необработанное исключение, потому что команда не генерирует завершающую ошибку.Это тоже важно понять. Выявляются только завершающие ошибки. Задайте параметр ErrorAction с помощью Остановить как значение для превращения непрекращающейся ошибки в прерывающуюся.

  function Test-MrErrorHandling {

    [CmdletBinding ()]
    парам (
        [Параметр (обязательный,
                   ValueFromPipeline,
                   ValueFromPipelineByPropertyName)]
        [строка []] $ ComputerName
    )

    ПРОЦЕСС {
        foreach ($ Computer в $ ComputerName) {
            пытаться {
                Test-WSMan -ComputerName $ Computer -ErrorAction Stop
            }
            поймать {
                Предупреждение о записи - сообщение «Невозможно подключиться к компьютеру: $ Computer»
            }
        }
    }

}
  

Не изменяйте глобальную переменную $ ErrorActionPreference без крайней необходимости.Если ты используя что-то вроде .NET непосредственно из вашей функции PowerShell, вы не можете указать ErrorAction на самой команде. В этом случае вам может потребоваться изменить глобальный $ ErrorActionPreference , но если вы измените ее, верните ее сразу после попытки команда.

Лучшей практикой считается добавление справки на основе комментариев к вашим функциям, чтобы люди вы делитесь ими, и будете знать, как их использовать.

  function Get-MrAutoStoppedService {

<#
.ОБЗОР
    Возвращает список служб, которые настроены на автоматический запуск, но не
    в настоящее время работает, за исключением служб, для которых настроен отложенный запуск.

.ОПИСАНИЕ
    Get-MrAutoStoppedService - это функция, которая возвращает список служб из
    указанные удаленные компьютеры, которые настроены на автоматический запуск, не
    в настоящее время работает, и исключает службы, которые настроены на автоматический запуск
    с отложенным запуском.

.PARAMETER имя_компьютера
    Удаленный компьютер (ы), на которых нужно проверить статус служб..PARAMETER Учетные данные
    Задает учетную запись пользователя, у которой есть разрешение на выполнение этого действия. По умолчанию
    текущий пользователь.

.ПРИМЕР
     Get-MrAutoStoppedService -ComputerName 'Server1', 'Server2'

.ПРИМЕР
     «Сервер1», «Сервер2» | Get-MrAutoStoppedService

.ПРИМЕР
     Get-MrAutoStoppedService -ComputerName 'Server1' -Credential (Get-Credential)

.ВХОДЫ
    Нить

ВЫХОДЫ
    PSCustomObject

.ПРИМЕЧАНИЯ
    Автор: Майк Ф. Роббинс
    Сайт: http://mikefrobbins.com
    Twitter: @mikefrobbins
#>

    [CmdletBinding ()]
    парам (

    )

    #Function Body

}
  

Когда вы добавляете справку на основе комментариев к своим функциям, справку для них можно получить так же, как встроенные команды по умолчанию.

Весь синтаксис для написания функции в PowerShell может показаться ошеломляющим, особенно для кого-то. кто только начинает. Часто, если я не могу вспомнить синтаксис для чего-либо, я открываю второй экземпляр ISE на отдельном мониторе и просмотр «Командлет (расширенная функция) - Завершено» фрагмент кода при вводе кода для моей функции. Доступ к фрагментам можно получить в среде PowerShell ISE. используя комбинацию клавиш Ctrl + J .

Сводка

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

Обзор

  1. Как получить список утвержденных глаголов в PowerShell?
  2. Как превратить функцию PowerShell в расширенную функцию?
  3. Когда нужно добавить WhatIf и Confirm в ваши функции PowerShell параметры ?
  4. Как превратить непрекращающуюся ошибку в прерывающуюся?
  5. Почему вы должны добавлять справку на основе комментариев к своим функциям?

Рекомендуемая литература

функций - PowerShell - SS64.com

Функции - PowerShell - SS64.com

Блок кода может содержаться в функции для удобного повторного использования.
Чтобы создать функцию, вызовите ключевое слово function , за которым следует имя функции, а затем включите свой код в пару фигурных скобок.

функция Сложение чисел {
$ args [0] + $ args [1]
}

PS C: \> Добавить номера 5 10
15

Аналогичная функция с именованными параметрами:

функция Выходной налог с продаж {
param ( [int] $ Цена, [int] $ Tax )
$ Цена + $ НДС
}

PS C: \> Output-SalesTax -price 1000 -tax 38
1038

Для отображения определения функции можно использовать несколько методов:

функция cat: добавочные номера
или
$ {function: Add-Numbers}
или
(Get-команда Добавить номера).определение

Чтобы вывести список всех функций в текущем сеансе: get-command -CommandType function

Обратите внимание: в блоке кода вам нужно определить функцию до того, как вы ее вызовете.

Не добавляйте скобки к параметрам функции:

$ result = Сложить числа (5, 10) - Неверно!
$ результат = Сложение 5 10 - Право

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

Как запустить функцию

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

Добавочные номера функции

{
$ args [0] + $ args [1]
}
Добавочные номера 5 10

Для небольших функций и / или при тестировании также можно ввести (или скопировать и вставить) всю функцию в командной строке PowerShell.Это не совсем практично для более длинных скриптов, потому что это заполняет большую часть вашей истории команд.

PowerShell по умолчанию не сохраняет функции или фильтры постоянно. Поэтому, если вы закроете и снова откроете PowerShell, функция / фильтр больше не будут доступны. Чтобы сделать функцию постоянно доступной, добавьте ее в свой PowerShell $ Profile, после чего она будет загружаться для каждого нового сеанса PowerShell и может вызываться из нескольких разных сценариев без необходимости явного включения.

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

. C: \ Scripts \ Tools.ps1
Добавочные номера 5 10

Другой способ сделать функцию доступной для нескольких сценариев / сеансов - включить ее как часть модуля PowerShell . При сохранении в папке системного модуля или в папке пользовательского модуля автоматическое обнаружение командлетов (в PowerShell v3 и выше) гарантирует доступность этих функций.

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

Выберите хорошее имя функции

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

Лучше всего использовать имя в формате Глагол-Существительное , поскольку оно содержит символ «-», это не будет конфликтовать с любыми встроенными псевдонимами. Вы можете создать список утвержденных команд PowerShell, запустив командлет Get-Verb

.

Определение функции или фильтра:

  функция  [ scope_type :]  имя 
 {
  [param ( param_list )]
     script_block
  } 
  фильтр  [ scope_type :]  имя 
 {
  [param ( param_list )]
    script_block 
 } 

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

В случае обычной функции объекты конвейера привязываются к автоматической переменной $ input, и выполнение блокируется до тех пор, пока не будет получен весь ввод.Затем функция начинает обработку данных.

С функцией фильтрации данные обрабатываются во время их получения, не дожидаясь ввода всех данных. Фильтр получает каждый объект из конвейера через автоматическую переменную $ _, и блок скрипта обрабатывается для каждого объекта.

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

Расширенная функция

Функция Advanced PowerShell содержит атрибут [cmdletbinding ()] (или атрибут Parameter). Это добавляет несколько возможностей, таких как дополнительная проверка параметров и возможность простого использования Write-Verbose.
Функция с cmdletbinding выдаст ошибку, если в командной строке появятся необработанные значения параметров.

Расширенные функции PowerShell обычно включают блоки Begin..Process..End для обработки входных данных, документации и автопомощи, включая параметры.

Диапазон изменения

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

Чтобы сохранить переменную, чтобы функция могла вызываться многократно, а переменная сохраняла свое последнее значение, добавьте $ script: к имени переменной, например $ script: myvar

Чтобы сделать переменную global, добавьте $ global: к имени переменной, e.г. $ global: myvar

Примеры функций

Функция для поиска всех файлов на диске C:, принадлежащих определенному пользователю:

  функция  Get-ByOwner
  {
   Get-ChildItem -recurse C: \ | get-acl | где {$ _. Owner -match $ args [0]}
 } 

PS C: \> Get-ByOwner JackFrost

Функция для отображения справки PowerShell на SS64.com, при этом будет запущен веб-браузер по умолчанию:

  функция  Get-Help2
  { 
параметр ([строка] $ команда) Start-process -filepath "https: // ss64.com / ps / $ command.html " }

Затем вы можете сделать:
PS C: \> Get-Help2 -command set-acl

или потому что есть только один параметр:
PS C: \> Get-Help2 set-acl

Фильтр для отображения только файлов меньше заданного размера:

  фильтр  FileSizeBelow ($ size)  { if ($ _. Length -le ​​$ size) {$ _} }  

PS C: \> gci \\ server64 \ workgroups -filter | FileSizeBelow 200kb
PS C: \> gci -recurse \\ server64 \ workgroups | ? {! $ _.PSIsContainer} | Размер файла ниже 100 МБ

Функция со значениями по умолчанию:

  функция  цена записи 
 {
  параметр  ( [строка] $ description = "unknown",
        [int] $ price = 100 ) 
  Запись-вывод "$ описание ..... $ цена"
 } 

PS C: \> написать-цена -цена 250 -описание Hammer 
Hammer ..... 250

Фильтр для поиска файлов, принадлежащих определенному пользователю:

  фильтр  ownbyme
  {
  если ($ _.Владелец -матч "JackFrost") {$ _}
 } 

PS C: \> gci -recurse C: \ | Get-Acl | где {$ _ |  ownbyme } 

«Функция воображения состоит не в том, чтобы уладить странные вещи, а в том, чтобы сделать их странными» ~ Г. К. Честертон

Связанные командлеты PowerShell:

Расширенные функции - включают функции командлетов, общие параметры -verbose, -whatif, -confirm и т. Д.
Утверждения - Использование фильтра для утверждения определенных предварительных условий.
New-Alias ​​- Создайте новый (короткий) псевдоним для вашей функции.
Begin..Process..End - Обработка ввода функции.
Scriptblock - набор операторов.
Ref vars - Передача ссылочной переменной функции.


Авторские права © 1999-2021 SS64.com
Некоторые права защищены.

Функции PowerShell - Технические мысли

В этом выпуске серии «Изучение PowerShell» мы рассмотрим функции PowerShell. В последнем выпуске мы рассмотрели сценарии PowerShell, в которых мы начали создавать решения и решать проблемы с помощью PowerShell.Сценарии PowerShell великолепны, и многие люди тратят на этом этапе довольно много времени при изучении PowerShell. Сценарии позволяют упростить работу и помогают быстро автоматизировать задачи. По мере того, как вы поправитесь и начнете писать больше PowerShell, вам нужно будет заняться созданием функций PowerShell!

Видео

Если вы предпочитаете формат видео, а не письменную документацию, я обсуждаю эту тему в следующем видео TechThoughts:

Когда следует писать функцию PowerShell

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

  • Одноцелевое - функция обычно используется для выполнения узкой задачи и «делать одно, и делать это хорошо». Это делает функции очень удобными для повторного использования . Например, если вы пишете функцию ведения журнала, вы можете использовать эту функцию ведения журнала PowerShell с другими функциями или сценариями.
  • Справка - функции поддерживают комментарии на основе справки. Это позволяет вашим пользователям делать такие вещи, как вводить Get-Help и выяснять, как использовать вашу функцию.
  • Параметры - поддержка простых и расширенных объявлений параметров и управления позволяет вашей функции быть динамической и принимать различные формы пользовательского ввода.
  • Testable - функции можно тестировать и имитировать, что значительно улучшает качество кода.

Анатомия функции PowerShell

Вот базовая структура и порядок функции PowerShell. Мы подробно рассмотрим каждый из этих разделов ниже.

 # function help - (необязательно, но настоятельно рекомендуется)
# имя функции
# CmdletBinding - (необязательно)
# параметры - (необязательно)
# функциональная логика (необязательно Begin / Process / End)
# return - (необязательно)

function Verb-Noun {
    [CmdletBinding ()]
    парам (

    )

    начинать {

    }

    процесс {

    }

    конец {

    }
}
 

Справка по функциям

Когда вы включаете справку в верхней части вашей функции, она будет отображаться, когда Get-Help запускается для вашей функции. Это мощная возможность, когда другие изучают ваш код.Потратьте время на то, чтобы конкретизировать хороший Синопсис и Описание в сочетании с убедительными примерами, чтобы помочь другим понять, для чего предназначена ваша функция и как ее использовать.

Все поля справки необязательны, и вы можете добавлять или удалять их по своему усмотрению. Я рекомендую вам включить как минимум поля ниже.

 <#
.СИНОПСИС
    Краткое описание
.ОПИСАНИЕ
    Длинное описание
.ПРИМЕР
    C: \ PS>
    Пример использования этого командлета
.ПРИМЕР
    C: \ PS>
    Еще один пример использования этого командлета
.ПАРАМЕТР InputObject
    Задает обрабатываемый объект. Вы также можете передать объекты по конвейеру этой команде.
ВЫХОДЫ
    Выходные данные этого командлета (если есть)
.ПРИМЕЧАНИЯ
    Главные примечания
.КОМПОНЕНТ
    Компонент, которому принадлежит этот командлет
#>
 

CmdletBinding

Когда вы пишете отличную функцию и даете ей имя, например, Get-AllFileInformation , она выглядит и будет действовать как командлет . Но важным отличием является то, что функция PowerShell не является командлетом .Командлеты написаны и скомпилированы на C #, а ваша функция PowerShell написана на PowerShell.

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

  • Write-Verbose - разрешите пользователям использовать переключатель -Verbose, чтобы узнать, что делает ваша функция, пока она ее выполняет.
  • ShouldProcess - если ваша функция внесет изменения в систему с высоким риском, вы можете захотеть, чтобы пользователь подтвердил действие.
  • PositionalBinding - позволяет запускать вашу функцию без явного указания имени каждого параметра. Значения могут быть выведены по порядку, в котором они предоставляются вашей функции

параметры

 параметр (
    [Параметр (
        Позиция = 0,
        Обязательно = $ false
    )]
    [нить]
    $ Город,

    [Параметр (позиция = 1)]
    [ValidateSet ('Метрика', 'USCS')]
    [нить]
    $ Units = 'USCS',

    [Параметр (Позиция = 2)]
    [ValidateSet ('ar', 'af', 'be', 'ca', 'da', 'de', 'el', 'en', 'et', 'fr', 'fa', 'hu' , 'ia', 'id', 'it', 'nb', 'nl', 'pl', 'pt-br', 'ro', 'ru', 'tr', 'th', 'uk' , 'vi', 'zh-cn', 'zh-tw')]
    [нить]
    $ Language = 'ru',

    [Параметр (Позиция = 3)]
    [выключатель]
    $ Короткие
)
 

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

Вы можете оставаться очень простым и объявлять только имена своих параметров. В качестве альтернативы вы можете уточнить, что требуется для ваших параметров:

  • Обязательный ли параметр
  • Положение параметра (порядок)
  • Тип параметра (строка / int / bool / и т. Д.)
  • Установка значений по умолчанию
  • Проверка ввода
  • Наборы параметров
  • Намного больше

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

Начало процесса Конец

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

  • Начало инициализирует некоторые шаги в начале
  • Процесс будет обрабатывать каждый полученный объект
  • Конец может выполнить очистку.

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

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

 function Get-PipelineBeginEnd {
    парам (
        [строка] $ SomeInput
    )
    начинать {
        "Начало: вход $ SomeInput"
    }
    процесс {
        "Значение: $ _"
    }
    конец {
        "Конец: вход $ SomeInput"
    }
} # Get-PipelineBeginEnd
1, 2, 3 | Get-PipelineBeginEnd -SomeInput 'Test'
 

Когда вы запускаете приведенный выше код, обратите внимание, что Begin запускается один раз, как и End . Процесс запускается для каждого переданного в него элемента, и Процесс имеет доступ к текущему объекту в конвейере.

Функциональная логика

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

Возврат функции

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

 function Get-Total {
    парам (
        [int] $ Number1,
        [int] $ Number2
    )
    $ total = $ Number1 + $ Number2

    вернуть $ total
}
Get-Total -Number1 2 -Number2 2
 

В приведенном выше примере эта простая функция содержит два параметра целочисленного типа. Логика функции складывает два числа вместе и возвращает целое число пользователю.

Ваша первая функция PowerShell

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

 <#
.СИНОПСИС
    Возвращает ваш публичный IP-адрес.
.ОПИСАНИЕ
    Запрашивает API общедоступного IP-адреса ipify и возвращает ваш общедоступный IP-адрес.
.ПРИМЕР
    Get-PublicIP

    Возвращает публичный IP.
ВЫХОДЫ
    System.String
.ПРИМЕЧАНИЯ
    https://github.com/rdegges/ipify-api
#>
function Get-PublicIP {
    $ uri = 'https://api.ipify.org'
    пытаться {
        $ invokeRestMethodSplat = @ {
            Uri = $ uri
            ErrorAction = 'Стоп'
        }
        $ publicIP = Invoke-RestMethod @invokeRestMethodSplat
    }
    поймать {
        Ошибка записи $ _
    }

    вернуть $ publicIP
} # Get-PublicIP
 

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

Объем функций

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

 function Get-NumberTimesTwo {
    парам (
        [int] $ Number
    )
    $ total = $ Number * 2
    вернуть $ total
} # Get-NumberTimesTwo
Get-NumberTimesTwo -Number 2
 

Функция работает должным образом и правильно умножает число на два.Однако в консоли попробуйте посмотреть, что такое $ всего . Вы не сможете. Это связано с тем, что $ total - это с областью действия для функции, а не для активного сеанса консоли.

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

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

В качестве альтернативы вы можете использовать Write-Host , Write-Output или еще лучше Write-Debug , чтобы увидеть, что происходит с вашими переменными внутри вашей функции!

 function Get-NumberTimesTwo {
    [CmdletBinding ()]
    парам (
        [int] $ Number
    )
    $ total = $ Number * 2
    Всего $ Write-Debug
    вернуть $ total
} # Get-NumberTimesTwo
Get-NumberTimesTwo -Number 2 -Debug
 

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

Пример закрытия

Вот более крупный закрывающий пример двух функций PowerShell, которые позволят вам просматривать популярный веб-сайт reddit с помощью PowerShell!

Перейдите по ссылке GitHub gist ниже, чтобы получить доступ к коду и загрузить его в консоль.

https://gist.github.com/techoughtts2/cd2b720c9b291510cbd643e6ca73e05f

По мере изучения этих функций попытайтесь ответить на следующие вопросы:

  • Какая из двух функций является основной функцией ?
  • Это стандартные или расширенные функции?
  • Какая функция будет поддерживать ввод конвейера?

Дополнительная литература

Навигация по сериям << Сценарии PowerShellУправление облаком с помощью PowerShell >>

Просмотр содержимого функций PowerShell | PDQ.com

Вы когда-нибудь задумывались: «Я… как работает эта функция PowerShell?» Если да, то вам повезло! С PowerShell очень просто просматривать содержимое функции.

Фактически, мы собираемся показать вам несколько различных способов отображения этой информации.

Итак, держитесь за свои стулья и свои монокли! Давайте погрузимся и узнаем больше!

Определение функций PowerShell

Во-первых, нам нужно определить функцию, на которую нужно взглянуть.

Для этого упражнения я выбрал команду Пауза из-за ее простоты.Прежде чем продолжить, давайте убедимся, что эта команда действительно является функцией.

Get-Command Pause

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

Просмотр содержимого функции

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

Метод 1 - Использование команды Get

Команда Get <Имя функции> | Выберите -ExpandProperty ScriptBlock

OR

(Get-Command <Имя функции>).ScriptBlock

Да да! Вот и все!

Get-Command Pause | Выберите -ExpandProperty ScriptBlock

Итак, похоже, что функция Pause запускает следующую команду:

$ null = Read-Host 'Нажмите Enter, чтобы продолжить ...'

Как красиво!

Метод 2 - Использование $ function

Еще один интересный способ увидеть содержимое функции паузы - использовать следующее:

$ Function: Pause

Так просто, так прекрасно.

Метод 3 - Использование функции: Drive

Функции автоматически сохраняются в функции: Drive. Вы можете убедиться в этом сами, набрав: Get-PSDrive

Поскольку это диск, мы можем просматривать его с помощью Get-ChildItem. Get-ChildItem, функция: пауза | Выберите *

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

Отображение всех доступных функций

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

Get-Command -CommandType Function

Заключение

Следует отметить, что это будет работать только для функций. Если вы хотите знать, что делают командлеты, вы можете взглянуть на проект с открытым исходным кодом PowerShell на GitHub (ссылка здесь).

Удачи и счастливого PowerShelling!

Чтобы увидеть это в действии, посмотрите это короткое видео:


Это сообщение в блоге является частью серии о PowerShell:

Как использовать функции в PowerShell - блог Джонатана Медда

За последние несколько недель у меня было несколько комментариев к сообщениям, в которых, по сути, задавался один и тот же вопрос: «Как мне использовать функции, которые вы публикуете в своем блоге?».Поэтому я подумал, что стоит делать пост, чтобы рекомендовать людям, а не пытаться отвечать тем же на каждый комментарий. Есть несколько способов сделать это в зависимости от ваших требований, и они перечислены ниже.

Прежде всего, давайте создадим простую функцию для тестирования:

function Get-TimesResult {

Param ([int] $ a, [int] $ b)

$ c = $ a * $ b

Запись-вывод $ c
}

 

1) Вставить в существующий сеанс PowerShell

Если вы работаете в интерактивном режиме в консоли, то функцию можно скопировать / вставить в этот сеанс, и тогда она будет доступна в течение этого сеанса.Я считаю, что это проще сделать через PowerShell ISE, чем через стандартную консоль.

Скопируйте функцию в панель сценария:

Нажмите Зеленую кнопку запуска сценария или нажмите F5 , и на панели консоли появится код:

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

2) Профиль PowerShell

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

Если вы не знаете, что такое профиль PowerShell и как его использовать, здесь есть полезная информация. Быстрый способ его создания:

New-Item -Path $ profile -ItemType File -Force

 

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

3) Непосредственно в скрипте

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

4) Вызывается из другого скрипта

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

Файл скрипта функций Tools.ps1:

Файл сценария Get-Results, вызывающий Tools.ps1:

Обратите внимание на точку и пробел перед ссылкой на файл Tools.ps1

. C: \ Users \ jmedd \ Documents \ WindowsPowerShell \ Scratch \ Tools.ps1

Get-TimesResult -a 6 -b 8

 

5) Хранится в модуле

Использование модуля PowerShell - более продвинутый, значительно более структурированный и мощный метод достижения того, что было сделано в п. 4).Если вы не использовали модули PowerShell до этого, я недавно написал введение в модули PowerShell, которое вы можете найти здесь.

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

Для этого примера я создал модуль Tools для использования, который по сути является тем же содержимым, что и файл Tools.ps1, но хранится в *.psm1 (Tools.psm1) в папке Modules \ Tools на моей рабочей станции.

Примечание: имя файла * .psm1 должно совпадать с именем папки. Можно создать более усовершенствованный модуль, чем этот подход, используя манифест модуля, но нам это не нужно для целей этой публикации. Это описано далее в ранее упомянутой статье.

Теперь мы можем использовать командлеты * -Module PowerShell для работы с нашим контентом.

Для наблюдения за модулем мы можем использовать Get-Module:

Get-Module Tools -ListAvailable

 

Для использования функций, содержащихся в модуле, мы можем использовать Import-Module

Инструменты импорта-модуля

Get-TimesResult -a 6 -b 8

 

Примечание: Начиная с PowerShell v3 поддерживается автоматическое обнаружение командлетов и загрузка модулей.(Вы можете узнать больше об этом здесь) Следовательно, вам фактически не нужно использовать Import-Module для получения доступа к функциям, если вы разместите модуль в правильном месте. Однако было бы неплохо добавить в сценарий строку Import-Module, чтобы другой пользователь знал, откуда вы получаете эту функциональность.

Поиск функций PowerShell - Power Tips - Power Tips

PowerShell 3.0 и выше

Чтобы быстро просканировать репозиторий сценариев PowerShell и найти все файлы, в которых есть заданная функция, попробуйте этот фильтр:

 фильтр Find-Function
{
   $ path = $ _.Полное имя
   $ lastwrite = $ _. LastWriteTime
   $ text = Get-Content -Path $ path
   
   если ($ text.Length -gt 0)
   {
      
      $ токен = $ ноль
      $ errors = $ null
      $ ast = [System.Management.Automation.Language.Parser] :: ParseInput ($ text, [ref] $ token, [ref] $ errors)
      $ ast.FindAll ({$ args [0] -is [System.Management.Automation.Language.FunctionDefinitionAst]}, $ true) |
      Select-Object -Property Name, Path, LastWriteTime |
      ForEach-Object {
         $ _. Путь = $ путь
         $ _. LastWriteTime = $ lastwrite
         $ _
      }
   }
}
 

Вот как вы сканируете свой профиль пользователя на наличие всех скриптов PowerShell, определяющих функции:

 

PS> dir $ home -Filter *.ps1 -Recurse -Exclude * .ps1xml | Функция поиска

Имя Путь LastWriteTime ---- ---- ------------- Inject-LogonCredentials C: \ Users \ Tobias \ Desktop ... 06.01.2014 02:43:00 Тестовая команда C: \ Users \ Tobias \ Desktop ... 06.03.2014 10:17:02 Тест C: \ Users \ Tobias \ Desktop ... 30.01.2014 09:32:20 Get-WebPictureOriginal C: \ Users \ Tobias \ Desktop... 11.12.2013 11:37:53 Get-ConnectionString C: \ Users \ Tobias \ Documen ... 23.05.2014 10:49:09 Convert-SID2User C: \ Users \ Tobias \ Documen ... 23.05.2014 15:33:06 Блокировка экрана C: \ Users \ Tobias \ Documen ... 19.03.2014 12:51:54 Показать-OpenFileDialog C: \ Users \ Tobias \ Documen ... 16.05.2014 13:42:16 Show-UniversalData C: \ Users \ Tobias \ Documen ... 16.05.2014 13:23:20 Start-TimebombMemory C: \ Users \ Tobias \ Documen ... 23.05.2014 09:12:28 Stop-TimebombMemory C: \ Users \ Tobias \ Documen... 23.05.2014 09:12:28 (...)

Просто передайте результат в Out-GridView, чтобы получить полную и неразрезанную информацию.

Повторите этот совет повторно!

Управление функциями PowerShell • Одинокий администратор

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

Во-первых, о скольких функциях я говорю? PowerShell хранит определенные и активные функции в PSDrive, что означает, что довольно легко получить список и подсчитать «каталог».

Однако некоторые из этих функций определены Microsoft и другими модулями.

У меня нет проблем с функциями, определенными из данного источника. Моя проблема в тех 100, у которых нет источника. Опять же, некоторые из них определены Microsoft, и это нормально. Поэтому я рассмотрел один из них более подробно.

Я заметил, что эти функции включают HelpFile. Я знал, что ни одна из моих функций не работает. С помощью этой информации я могу получить список каталогов и отфильтровать с помощью Where-Object.

 функция dir: | где {(-Не $ _. Источник) -И ($ _.HelpFile -notmatch "System \ .Management")} 

Это функции, которые загружаются из точечного источника файла ps1. Кстати, в списке было 62 пункта.

В качестве альтернативы я мог бы использовать Get-Command, чтобы избавиться от любых фильтров.

 get-command -CommandType function | где {(-Not $ _. Source) -AND ($ _. HelpFile -notmatch "System \ .Management")} 

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

Но теперь, по крайней мере, я могу просмотреть список и определить функции, которые я не использовал годами или которые сейчас устарели. К сожалению, с помощью функции PSDrive или Get-Command невозможно определить, откуда эта функция. К счастью, я храню все свои файлы на одном диске, и, скорее всего, функция будет определена в сценарии .ps1. Я могу использовать Select-String, чтобы найти его.

В моем списке есть функция под названием Show-Balloon, которую я, вероятно, не использовал годами.В каком это файле?

 каталог c: \ scripts \ *. Ps1 | строка выбора "\ bshow-balloon \ b" –List 

Я заключаю имя функции в границу слова регулярного выражения, чтобы не было совпадений с чем-то вроде show-balloontip. Параметр –List дает мне первое совпадение, которое мне действительно нужно.

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

 каталог c: \ scripts \ *. Ps1 | select-string "\ bFunction show-balloon \ b" –List 

Результатом Select-String является объект, который включает свойство для имени файла или пути.

Теперь я могу собрать все воедино.

 $ scripts = каталог c: \ scripts \ *. Ps1
функция dir: |
где {(-Not $ _. Source) -AND ($ _. HelpFile -notmatch "System \ .Management")} |
Выберите имя, @ {Name = "Source"; Expression = {($ scripts | select-string "\ b $ ($ _. Name) \ b" -list) .Path}} 

Мне не нужно заново перечислять все файлы скриптов для каждой функции, поэтому я получу их один раз, а затем использую эту переменную в выражении Select-Object.

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

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *