Understanding PowerShell Begin, Process, and End blocks

Windows PowerShell advanced functions have built-in control flow that helps both experienced and novice PowerShell developers maintain their code workflows.  If you have worked with PowerShell Advanced Functions then you probably have worked with Begin, Process and End blocks in your code.
Contents of this article

Each Begin, Process, and End block has a specific purpose that helps guide and control your code workflows.  In this blog post, we will dive into each of these controls and show common uses cases for each.

As both Don Jones and Jeffrey Hicks have said in their Learn PowerShell Toolmaking in a Month of Lunches book; PowerShell functions should do one thing, and do it well.  PowerShell’s Begin, Process, and End blocks emphasize this statement of doing one thing and doing it well.

I would like to start with a simple analogy that may help understand the reason’s and uses case’s of the Begin, Process, and End blocks.  I BEGIN my day by getting ready for work.  Once I have begun work, then I start to PROCESS my tasks for the day.  I END my day by clearing my desk and heading home.

It’s a bit cheesy, but I think it gets my point across. Let’s use this fake PowerShell function as an example.  Please note, that this function does NOT work in anyway and it’s just as an example.


In a PowerShell function, you may want to setup your function by specifying variables and arrays to be used throughout your function.  The BEGIN block in a PowerShell function is the appropriate place to set these types of items.

The BEGIN block is optional and is NOT needed if you are just wanting to use either the PROCESS or END blocks

Everything in the BEGIN block will only run once per call of your function.  Just like a typical work day you will only prepare to go to work once.  This may include taking a shower, brushing your teeth, and driving to work.  In code, this is where you are setting up all requirements or dependencies before actually doing the work.  You can also consider this as “pre-processing” or “setup” for your PowerShell function.

In the provided example, this is seen in our BEGIN block:


The process block is where the work is done in a PowerShell advanced function.  There are two different approaches we need to keep in mind and account for.  The first is how you handle parameters and the second is pipeline input into your function.

The PROCESS block can be used without the BEGIN or END blocks

Some questions you should ask yourself:

Does my function take a single value for a parameter or an array of values?

Does my function accept pipeline input (it should)?

If your function takes a single value for a parameter (not an array of values) then the PROCESS block will only process that single value.  If you also accept pipeline input on your single parameter then the PROCESS block will process each of the values in our PROCESS block.  Let’s take a look at an example:

If we call our Example-BeginProcessEnd function with a single value for WorkItem using the parameter value then you will see that it only processes the one passed in WorkItem value.

If we were to pass in an array of values into the pipeline of this function then we will see a different result.  We will see that the PROCESS block is running multiple times based on the array list we passed into our function:

If we want our function to accept an array of values not only via pipeline but also through a parameter then we will need to modify our function to support this logic.  We first need to modify our parameter to accept an array of values by adding [] to our parameter:

Passing an array through a parameter

Passing an array through a parameter

We also need to add a foreach statement in our PROCESS block then we can account for both situations.

By adding this to our PROCESS block then we pass an array of values via both our parameter and pipeline.

We can also pass in multiple values via the pipeline, like we were able to do previously:

We should always aim to provide enough flexibility for users to use our function in a way that supports them but not enough to cause them issues when using our function.

The PROCESS block is powerful and adds clear logic separation when writing PowerShell functions.  Continuing with my analogy, the PROCESS block is the actual work we do when we go to work.  If you work in IT, this can be seen as requests for support or projects (or daily routines) that we process or work on.  We get to work and then begin to process our day or tasks.  This can be seen in our original example:

We receive tickets or WorkItems and either call another function to do some action or process them as they come in.  Whether it is a meeting, a ticket, or a support request, we process them as they are given to us (sometimes using multiple threads - multi-tasking, am I right).


Finally, we get to the END block.  The END block is where we dispose or cleanup if needed.  If we created objects, variables, files, etc in our BEGIN or PROCESS blocks then we will use the END block to either clean these objects up or return any complex data structures.

The END block is optional and is NOT needed if you are just wanting to use either the PROCESS or BEGIN blocks

The main difference between the PROCESS block and the END block is that PowerShell executes code in the latter only once even if you pass an array through the pipeline. Thus, you can use the END block to finalize your function after all members of the array that you passed to your function have been processed. Likewise, the BEGIN block allows you to initialize your function with code that you want to run only once before PowerShell iterates through your input array.

The most common example I have found is that if you created a database connection in your BEGIN block, processed or updated a database in the PROCESS block then you would use the END block to disconnect/destroy our database connection.

Another example is that you may have created an PSObject in the BEGIN block, added data to the object in the PROCESS block and then use the END block to return the final object.


Join the 4sysops PowerShell group!

Your question was not answered? Ask in the forum!

  1. I finally understand the Process block now. I was always confused about how it automatically iterates through multiple inputs.

    Always processes an array passed from the pipeline -- setup a loop for passed parameters.



  2. Jeremy 2 years ago

    Thanks for this.  I have a question about variables that I define in the process block:

    Upon the second and later objects being processed, is it necessary to reset the variables to make sure the previously-processed object's values don't linger?  Or do those variables vanish when an object is finished processing and leaves the process block?


    • @Jeremy

      Variables defined inside the Begin and Process sections are global to the whole function and are available for each processed object, and can even be used inside the End section.

      You can try the following command-line which has the same behaviour like inside a function.

      <pre>1..5|ForEach-Object -Begin{$a=100;"The value has been intialized to:$a";} -Process {$a+=$_;$a} -End{"The final result is:$a"}</pre>


  3. Sandor Szilagyi 2 years ago

    Excellent article which helped me a lot! Thank you for that! Only one note: Within the code example after "We also need to add a foreach statement in our PROCESS block"  you should use $item variable instead of $WorkItem at the Write-Host like this:



  4. Jim 2 years ago

    Another gotcha that you need to keep in mind for advanced functions is the use of the return statement.  If executed within the Begin block, the Process and End blocks will still execute ( if present ), same holds true for a return in the Process block, the End block will still execute.  However thrown exceptions will exit the function at the point of being thrown.


    • Mark Kharitonov 6 months ago

      To Jim's point - the end block would have shined if it executed always. But if process fails with an exception, then the end block would not be called. That means the process block needs to catch exceptions to let the cleanup run. Or you need to call the cleanup logic from two places. Unless one has pipeline items to process, this makes it more cumbersome that having a single try-finally block that spans all of your function. Which you cannot do if you have process and end blocks.


Leave a reply

Your email address will not be published. Required fields are marked *


© 4sysops 2006 - 2020


Please ask IT administration questions in the forums. Any other messages are welcome.


Log in with your credentials


Forgot your details?

Create Account