Funções em Scripts PowerShell
Feb 12, 2025
As funções do PowerShell agrupam código reutilizável em unidades modulares e de fácil manutenção que simplificam a escrita de scripts e reduzem erros. Definidas com a palavra-chave function , podem incluir parâmetros, aceitar entrada de pipeline e comportar-se como cmdlets usando [CmdletBinding()]. As funções suportam recursos avançados como tratamento de erros com Try/Catch, saída detalhada e de depuração, e organização em módulos. As melhores práticas incluem nomes significativos, design modular, retorno de objetos e documentação com ajuda baseada em comentários.
Uma função do PowerShell é um bloco de código projetado para realizar uma tarefa específica. Uma vez que uma função é criada e testada, ela pode ser usada em vários scripts, reduzindo o esforço de codificação e o risco de erros. Usar funções bem nomeadas também torna os scripts mais fáceis de ler e manter. E como as funções podem retornar valores que podem ser usados como entrada para outras funções ou blocos de código, elas facilitam a construção de operações complexas.
Este artigo explica tudo o que você precisa saber para começar a usar funções do PowerShell, incluindo as melhores práticas importantes, e até oferece orientações para se aprofundar em opções mais avançadas.
Introdução às Funções do PowerShell
Como Criar uma Função no PowerShell
Para definir uma função, você usa a palavra-chave function. A sintaxe básica é a seguinte:
function <Function-Name> {
<Code-Block>
}
O código dentro das chaves {} será executado quando a função for chamada.
Se desejar, você pode usar a palavra-chave param para especificar parâmetros de função, juntamente com tipos de dados, valores padrão e assim por diante. Aqui está a sintaxe com parâmetros adicionados:
function <Function-Name> {
[param(
[<ParameterType>]$<ParameterName>,
[<ParameterType>]$<ParameterName2> = <DefaultValue>
)]
<Code-Block>
}
Este exemplo de função PowerShell irá multiplicar dois números e exibir o resultado:
function Multiply-Numbers {
param (
[int]$Number1,
[int]$Number2
)
$Result = $Number1 * $Number2
Write-Output "The multiplication value of $Number1 and $Number2 is $Result."
}
Salvando uma Função
Para salvar uma função, basta armazená-la em um arquivo de script com uma?.ps1?extensão.
Chamando uma Função
Para invocar uma função no PowerShell, digite o nome da função seguido pelos parâmetros nomeados necessários. Por exemplo, aqui está como chamar a função que definimos acima:
Multiply-Numbers -number1 6 -Number2 8
Executando uma Função como Parte da Sessão Atual (Dot-Sourcing)
O dot-sourcing permite que você execute um script do PowerShell como se estivesse definido diretamente na sua sessão atual do console. Para usar o dot-sourcing, preceda o nome da função com um ponto e espaço (. ) ao chamá-la.
Por exemplo, suponha que tenhamos definido a seguinte função chamada Add-Numbers:
function Add-Numbers {
param (
[int]$Number1,
[int]$Number2
)
$Sum = $Number1 + $Number2
Write-Output "The sum of $Number1 and $Number2 is $Sum."
}
Podemos usar dot-sourcing nesta função na nossa sessão conforme mostrado aqui:
Nomeando suas funções PowerShell
Para obter o máximo valor das funções do PowerShell, certifique-se de seguir estas diretrizes ao nomear suas funções.
Use o formato verbo-substantivo.
O PowerShell fornece um conjunto de cmdlets pré-construídos cujos nomes seguem um formato específico: um verbo que especifica a ação a ser realizada, seguido por um substantivo que nomeia o objeto sobre o qual se vai atuar. Por exemplo, o cmdlet get-user recupera informações sobre um usuário e remove-item deleta um item especificado.
É uma boa prática seguir a mesma convenção de nomenclatura para as funções que você cria. Fazer isso ajudará você a projetar suas funções de forma mais eficaz e torná-las mais fáceis de reutilizar.
Use verbos aprovados.
O PowerShell fornece uma lista de verbos recomendados para uso em funções. Para visualizar a lista, basta executar o seguinte cmdlet:
Get-Verb
Escolha substantivos descritivos.
É essencial não dar a uma função o mesmo nome de um cmdlet integrado. Uma boa maneira de evitar esse problema é não usar substantivos genéricos como user e data. Em vez disso, escolha substantivos que indiquem claramente o tipo de dados sobre os quais a função está atuando. Por exemplo, é fácil entender como essas funções diferem: Get-EmployeeData, Get-UserInfo e Get-ServiceInfo.
Evite usar nomes de funções para fins de versionamento.
Adicionar números de versão aos nomes de funções, como Get-UserInfoV2, não é recomendado. Isso torna os scripts mais difíceis de entender e aumenta as chances de usar versões antigas de uma função. Em vez disso, gerencie a versão através do seu sistema de versionamento de arquivos.
Capacidades Avançadas de Função
Aceitando entrada de Pipeline
Você pode projetar uma função para aceitar entrada de outra função ou comando por meio de um pipeline usando o atributo ValueFromPipeline.
Para ilustrar, vamos criar uma função que processe uma lista de strings uma a uma, converta cada string para maiúsculas e exiba os resultados. Para clareza, vamos dividir o processamento de strings em três blocos distintos:
- BEGIN — Este código é executado uma vez, antes de processar qualquer entrada do pipeline.
- PROCESSO — Esta seção é executada para cada item que é passado para o pipeline, processando os objetos de entrada um por um.
- FIM — Este código é executado após todos os dados de entrada serem processados para finalizar a saída.
function Convert-ToUppercase {
[CmdletBinding()]
param (
[Parameter(ValueFromPipeline = $true, Mandatory = $true)]
[string]$InputString
)
BEGIN {
Write-Verbose "Starting the uppercase conversion process."
}
PROCESS {
if (-not [string]::IsNullOrWhiteSpace($InputString)) {
Write-Verbose "Processing string: $InputString"
$InputString.ToUpper()
} else {
Write-Verbose "Skipped empty or null string."
}
}
END {
Write-Verbose "Finished processing all strings."
}
}
Eis como poderíamos chamar nossa função para converter uma lista de strings fornecida através de um pipeline:
"hello", "world", "this", "is", "powershell" | Convert-ToUppercase -Verbose
Observe que funções leves chamadas filters podem fornecer uma maneira altamente eficiente de processar objetos que passam por um pipeline.
Permitindo que uma Função se Comporte como um Cmdlet
Você pode transformar uma função básica em uma função avançada usando o atributo CmdletBinding. Ao fazer isso, a função passará a se comportar como um cmdlet, incluindo suporte a parâmetros definidos do PowerShell.
Aqui está a função básica que definimos anteriormente para adicionar dois números:
function Add-Numbers {
param (
[int]$Number1,
[int]$Number2
)
$Sum = $Number1 + $Number2
Write-Output "The sum of $Number1 and $Number2 is $Sum."
}
Podemos transformá-lo em uma função avançada da seguinte forma:
function Add-Numbers {
[CmdletBinding()]
param (
[Parameter(Mandatory)]
[int]$Number1,
[Parameter(Mandatory)]
[int]$Number2
)
process {
# Verbose Output
Write-Verbose "Starting addition of $Number1 and $Number2"
# Debugging Output
Write-Debug "Debugging: Ensuring numbers are valid integers"
# Perform the Addition
try {
$Result = $Number1 + $Number2
Write-Output $Result
} catch {
# Handle errors with error stream
Write-Error "An error occurred while performing the addition."
}
# Verbose Completion Message
Write-Verbose "Addition completed successfully"
}
}
Solicite uma avaliação gratuita do Netwrix Auditor
Construindo Módulos de Função
Um módulo de função é um arquivo com uma extensão .psm1 que contém uma coleção de funções relacionadas. Organizar funções em módulos facilita a reutilização e manutenção.
Para criar um módulo de função, basta criar um arquivo de texto, colar suas funções e salvar o arquivo com a extensão .psm1 no diretório C:\Program Files\WindowsPowerShell\Modules. Por exemplo, poderíamos criar um módulo com função aritmética como a função Add-Numbers definida anteriormente.
Para importar o módulo para a sua sessão do PowerShell, use o comando Import-Module, conforme mostrado aqui:
Tratamento de Erros
PowerShell offers several error handling techniques to help you smoothly handle issues that could otherwise cause function execution to stop with an error, such as an attempt to divide by zero.
Try/Catch/Finally Blocks
When you know that a certain condition could cause a problem, you can use Try, Catch and Finally blocks in your function to handle that condition gracefully:
- Try — This block contains code that may produce an error (such as a division operation). If no error occurs, the Catch block will not be executed.
- Catch — If an error occurs in the Try block, the Catch block will handle it by capturing and processing the error details.
- Finally — This block is optional. If is present, it is executed after the Try and Catch blocks, regardless of whether an error occurred.
-ErrorAction Parameter
The -ErrorAction parameter allows you to specify how errors should be handled for a particular function. The possible values are:
- Continue — Display an error message and continue.
- Stop — Halts execution of the script when an error occurs.
- SilentlyContinue — Suppress the error message and continue execution.
- Inquire — Prompt the user for how to handle the error with options like Yes, No and Retry.
- Ignore — Ignore the error completely without even displaying a message.
Below are some examples of the -ErrorAction parameter:
Remove-Item "C:\path\to\nonexistentfile.txt" -ErrorAction SilentlyContinue
Get-Process -Name "Notepad" -ErrorAction Stop
$ErrorActionPreference Variable
The $ErrorActionPreference variable controls how errors are handled globally for all cmdlets in a session. This variable can be set to influence the behavior of error handling across all commands unless overridden by the -ErrorAction parameter.
Detailed Example
Below is an example that uses multiple methods of error handling:
- The $ErrorActionPreference variable sets the global error handling preference to stop, so when an error occurs that is not otherwise handled, execution will stop.
- The Try/Catch blocks gracefully handle the potential error of dividing by zero without halting execution. The Try block performs the mathematical operations. If it encounters division by zero, processing moves to the Catch block, which prints an error message.
- The Finally block will execute regardless of whether an error occurred, printing a message that operations are complete.
# Set global error action preference to 'Stop' to immediately halt on errors
$ErrorActionPreference = 'Stop'
function Perform-MathOperations {
param (
[int]$Num1,
[int]$Num2
)
try {
# Performing addition
Write-Host "Performing addition: $Num1 + $Num2"
$additionResult = $Num1 + $Num2
Write-Host "Addition Result: $additionResult"
# Checking for division by zero before performing division
if ($Num2 -eq 0) {
throw "Division by zero is not allowed."
}
# Performing division
Write-Host "Performing division: $Num1 / $Num2"
$divisionResult = $Num1 / $Num2
Write-Host "Division Result: $divisionResult"
}
catch {
# Catching any error that occurs in the try block
Write-Host "An error occurred: $_"
Write-Host "Error Type: $($_.Exception.GetType().Name)"
}
finally {
# This block always runs regardless of error occurrence
Write-Host "Finished performing math operations."
}
}
The screenshot below shows the result of calling this function in two ways. First, we call it with valid input:
Perform-MathOperations -Num1 10 -Num2 2
Then we call it with input that will result in an attempt to divide by zero:
Perform-MathOperations -Num1 10 -Num2 0
Troubleshooting Your Functions
You can display messages that provide various levels of detail during function execution using Write-output (or Write-host), Write-Verbose and Write-Debug. This information can help you trace the execution path step by step to pinpoint unexpected behavior.
For example, the following screenshot shows how we could revise our basic Add-Numbers function to provide troubleshooting details. Note that by default, the verbose message stream is not displayed, so we need to use -Verbose when invoking the function.
Add-Numbers -Number1 5 -Number2 10 -Verbose
Similarly, Write-Debug messages are not displayed in the console by default, but you can display them by including -Debug when you execute the function:
Add-Numbers -Number1 5 -Number2 10 -Debug
Best Practices
- Design each function to perform one task. This make them easier to test, use and maintain.
- Design functions in a modular way so that they can be reused in different scripts.
- When using parameters, specify their default values.
- Include detailed comments in your functions. This comment based help will facilitate debugging and function reuse.
- Have your functions return objects rather than formatted output to enhance reusability.
Additional Example
The following function illustrates many of the capabilities discussed earlier, including error handling:
# Function: Backup-Files
# Description: Backs up files from a source directory to a backup directory.
function Backup-Files {
param (
[Parameter(Mandatory = $true)]
[string]$SourcePath, # The directory containing the files to back up
[Parameter(Mandatory = $true)]
[string]$BackupPath, # The directory where files will be backed up
[string[]]$Extensions = @("*") # File extensions to back up (default: all files)
)
# Check if the source path exists
if (-not (Test-Path -Path $SourcePath)) {
Write-Error "Source path '$SourcePath' does not exist."
return
}
# Create the backup directory if it does not exist
if (-not (Test-Path -Path $BackupPath)) {
Write-Output "Creating backup directory at '$BackupPath'..."
New-Item -ItemType Directory -Path $BackupPath | Out-Null
}
# Get files matching the specified extensions
foreach ($extension in $Extensions) {
$files = Get-ChildItem -Path $SourcePath -Filter "*.$extension" -File -ErrorAction SilentlyContinue
foreach ($file in $files) {
$destination = Join-Path -Path $BackupPath -ChildPath $file.Name
Write-Output "Backing up file: $($file.FullName) -> $destination"
Copy-Item -Path $file.FullName -Destination $destination -Force
}
}
Write-Output "Backup completed successfully."
}
We can call this function to back up all files, or only select file extensions as shown here:
Backup-Files -SourcePath "D:\Office\project" -BackupPath "D:\Backup" -Extensions @("csv", "txt")
Conclusion
Functions in PowerShell provide a structured approach to scripting that improves modularity, reusability and maintainability. Feel free to experiment with all the sample code provided in this article. As you start creating your own functions, be sure to adopt the best practices for naming and using them.
Compartilhar em
Saiba Mais
Sobre o autor
Tyler Reese
VP de Gestão de Produto, CISSP
Com mais de duas décadas na indústria de segurança de software, Tyler Reese tem um conhecimento íntimo dos desafios de identidade e segurança que evoluem rapidamente e com os quais as empresas se deparam hoje. Atualmente, ele atua como diretor de produto para o portfólio de Netwrix Identity and Access Management, onde suas responsabilidades incluem avaliar tendências de mercado, definir a direção para a linha de produtos IAM e, em última análise, atender às necessidades dos usuários finais. Sua experiência profissional varia desde consultoria em IAM para empresas Fortune 500 até atuar como arquiteto empresarial de uma grande empresa de venda direta ao consumidor. Atualmente, ele possui a certificação CISSP.