When writing large PowerShell scripts or modules, it will eventually become necessary to split up the code into modular pieces. Modularity can be achieved by using basic and advanced PowerShell functions. It also encourages good coding practices. One way to build modular code in PowerShell is to use functions. At their most basic, PowerShell functions allow you to compartmentalize code rather than stringing it all together in one large script.
PowerShell provides two different kinds of functions: basic and advanced. Basic functions are just that: basic. They are the simplest form a function can be. Basic functions do not allow you to do things like accept pipeline input, control streams and so on. For that, we'll have to write advanced functions. But what makes a basic function "advanced"? Let's find out.
Advanced functions give you a few advantages: accepting pipeline input, allowing you to use built-in parameters like -Verbose, -ErrorAction, -ErrorVariable and so on. They also allow you to use advanced parameter attributes and write help content as well.
To demonstrate, let's start with a basic function that tests connectivity of a remote server. Our example of basic function might look something like this:
This is a function that pings a computer and tests to ensure the c$ administrative share is available on a Windows server. If the computer is online and has the c$ share available, it will return True. Otherwise, it will return False.
Passing a computer name to the function works great.
However, what if you have lots of computers perhaps stored in a text file? To run this function for all of those computers, you'll have to use a foreach loop. This is ugly.
It'd be much easier to use the pipeline but doing this won't work with our basic function.
This is because a basic function isn't capable of accepting pipeline input. This is just one feature we're missing with basic functions. Let's convert this basic function to an advanced function. To do this, we'll need to add a [CmdletBinding()] reference as well as building a parameter block. Our function now looks like this:
This "converts" the basic function to advanced but you're still not going to notice much difference. This step just gives you the ability to do all the cool stuff that advanced functions allow. To accept pipeline input, we have to change our parameter to use parameter attributes.
Notice that I've added a ValueFromPipeline parameter attribute as well as adding a process block. The process block is necessary for accepting all kinds of pipeline input. The ValueFromPipeline attribute is one of two ways to accept pipeline input. For more information on pipeline support, visit Boe Prox's blog post.
Parameter validation is another feature you'll get when using PowerShell's advanced functions. This feature allows you to limit input coming into your function. It's important to limit input as strictly as possible when building functions. To demonstrate, let's take our existing function and ensure that only the MEMBERSRV1 and COMPUTER2 computers are allowed in. We can do this by using the ValidateSet validation attribute. This attribute limits the values the ComputerName parameter will accept from an array of strings.
Parameter validation attributes are placed right below the Parameter declaration as shown below.
Notice now when I try to pass a name, not on the list, it will not work.
Stream Control in Advanced Functions
Finally, advanced functions allow you to control the streams that are output to the console. It's possible to use commands like Write-Verbose, Write-Warning and so on inside an advanced function and control when these messages are displayed. For example, let's add a status message to our function.
Running the function as-is does not change. However, notice now we have a -Verbose parameter. Using this parameter displays that verbose message.
You'll find that advanced functions have many parameters by default without having to create them. Just type out the function name, press "-" and start hitting the tab key. This will allow you to see all of the parameters that are now available to you.
Make advanced functions part of your daily scripting habits. They provide lots of extra functionality with minimal code changes to basic functions.