A function is a reusable, callable code block(s). A function can accept parameters and can produce different results.
A typical anatomy of a PowerShell function looks like this:
function Do-Something { <# comment based help #> param ( #parameters ) #blocks of code }
To illustrate, let's create a very simple function that takes a report server URL and lists all items in that report server.
Note
When naming functions, it is recommended that you adhere to the verb-noun convention. The verb also needs to be approved; otherwise, you may get a warning similar to when you import the SQLPS
module:
WARNING: The names of some imported commands from the 'sqlps'
module include unapproved verbs that might make them less discoverable. To find the commands with unapproved verbs, run the Import-Module
command again with the verbose parameter. For a list of approved verbs, type Get-Verb
.
This function will take in a parameter for the report server URL and another switch called $ReportsOnly
, which can toggle displaying between all items or only report items:
function Get-SSRSItems { <# comment based help #> param ( [Parameter(Position=0,Mandatory=$true)] [alias("reportServer")] [string]$ReportServerUri, [switch]$ReportsOnly ) Write-Verbose "Processing $($ReportServerUri) ..." $proxy = New-WebServiceProxy -Uri $ReportServerUri-UseDefaultCredential if ($ReportsOnly) { $proxy.ListChildren("/", $true) | Where-Object TypeName -eq"Report" } else { $proxy.ListChildren("/", $true) } }
To call this function, we can pass in the value for –ReportServerUri
and also set the –ReportsOnly
switch:
$server = "http://server1/ReportServer/ReportService2010.asmx"
Get-SSRSItems -ReportsOnly -ReportServerUri $server |
Select-Object Path, TypeName |
Format-Table -AutoSize
To allow your function to behave more like a cmdlet and work with the pipeline, we will need to add the [CmdletBinding()]
attribute. We can also change the parameters to enable values to come from the pipeline using ValueFromPipeline=$true
. Inside the function definition, we will need to add three blocks:
BEGIN
: Preprocessing; anything in this block will be executed once when the function is calledPROCESS
: Actual processing that is done for each item that is passed in the pipelineEND
: Post-processing; this block will be executed once before the function terminates executing
We will also need to specify in the parameter block that we want to accept input from the pipeline.
A revised function is as follows:
function Get-SSRSItems { <# comment based help #> [CmdletBinding()] param ( [Parameter(Position=0,Mandatory=$true, ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true)] [alias("reportServer")] [string]$ReportServerUri, [switch]$ReportsOnly ) BEGIN { } PROCESS { Write-Verbose "Processing $($ReportServerUri) ..." $proxy = New-WebServiceProxy ` -Uri $ReportServerUri -UseDefaultCredential if ($ReportsOnly) { $proxy.ListChildren("/", $true) | Where-Object TypeName -eq"Report" } else { $proxy.ListChildren("/", $true) } } END { Write-Verbose "Finished processing" } }
To invoke, we can pipe an array of servers to the Get-SSRSItems
function, and this automatically maps the servers to our –ReportServerUri
parameter as we specified ValueFromPipeline=$true
. Note that Get-SSRSItems
will get invoked for each value in our array:
$servers = @("http://server1/ReportServer/ReportService2010.asmx", "http://server2/ReportServer/ReportService2010.asmx") $servers | Get-SSRSItems -Verbose -ReportsOnly | Select-Object Path, TypeName | Format-Table –AutoSize