HBoPS #7: Begin, Process, End

Imagine the day where you start writing advanced functions. That’s the day you implement Begin, Process, and End. A beautifully, simple, concept that brings structure to the chaos of our minds!

What is an advanced function?

An advanced function is, simply put, a way to allow you to write functions that behave similar to the Microsoft cmdlets.

It is as simple as adding [CmdletBinding()] right above you Param() declaration in your function.

So what’s up with this Begin, Process, End?

Begin, Process, and End are 3 different blocks to separate your code in to logical blocks. They help you prepare your function, execute the tasks that it needs to do, and end the function in the expected way.

Begin

When you are writing a function, typically you begin by specifying variables, object, or arrays that you will use throughout the function. The BEGIN block is where you would place this code.

The begin block will only run once per call of the function, consider it being pre-processing, setup, or ‘preparing’ your function. It’s important to note that it is NOT required to use the BEGIN block if you want to use PROCESS or END.

Process

The process block is where the meat of your function is. It carves and shapes whatever it is you want to do, and does so very neatly. You can also use it without the BEGIN or END blocks. But ask yourself a few questions

  • Does this function take a single value as a parameter, or can it take an array of values?
  • Is this function going to accept pipeline input? (And if it doesn’t, why not?!)

It is quite important that you ask yourself these questions, because the PROCESS block has a nifty little thing it does. You see, if you pass a single value to your function, the PROCESS block is going to run once. But when you pass multiple values, the PROCESS block is going to run once for every value you pass to the function!

Now that last bit is neat, but it needs some more explanation. Let’s take this function as an example:

function New-BeginProcessEnd {
[CmdletBinding()]
Param (
[Parameter()]
[string]$Item
)
begin{
Write-Output 'Begin block started'
}
process{
Write-Output "Process block is now processing $Item"
}
end{
Write-Output 'End Block started'
}
}

It’s a simple function, that will just go through our different blocks and produces simple output:

If we were going to try and pass items through the pipeline the way the function is now it would cause errors:


If we want to fix this (of course we do!) we need to adapt our code slightly, and add the ValueFromPipeline=$true to our parameter Item:

 
function New-BeginProcessEnd{
[CmdletBinding()]
Param (
[Parameter(ValueFromPipeline=$true)]
[string]$Item
)
begin{
Write-Output 'Begin block started'
}
process{
Write-Output "Process block is now processing $Item"
}
end{
Write-Output 'End Block started'
}
}

This changes the behavior of the function and produces expected output:

But what if we want to process an array as a parameter, and not just from the pipeline? Our current code would cause this:

Currently our parameter does not accept arrays. We can change that by adding [] to our parameter. We’ll also need a way to catch an array in the processing, so our code ends up looking like this:

 
function New-BeginProcessEnd{
[CmdletBinding()]
Param (
[Parameter(ValueFromPipeline=$true)]
[string[]]$Item
)
begin{
Write-Output 'Begin block started'
}
process{
Foreach ($i in $Item){
Write-Output "Process block is now processing $I"
}
}
end{
Write-Output 'End Block started'
}
}

And now we have the expected result no matter how we turn it.

End

Finally the END block. This is where we do the cleanup of our variables, close anything out that needs to be closed out, so general housekeeping.

Returning objects

One last thing… In advanced functions you shouldn’t use the return keyword to return objects, but rather just run a ‘New-Object’ command. Nor should you place the return anywhere but in the PROCESS block. Otherwise it defeats the purpose of using the pipeline…

References:
– About Advanced Functions:
https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_functions_advanced?view=powershell-6

Index:
HBoPS #1: Use a proper editor!
HBoPS #2: Error handling and you!
HBoPS #3: Avoid using Write-Host (and save puppies!)
HBoPS #4: Variables, Parameters, and Battlestar Galactica
HBoPS #5: Reduce, Reuse, Recycle
HBoPS #6: Handling Credentials

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Close Menu
%d bloggers like this: