---
title: "Learn How PowerShell CmdletBinding Enhances Functions"
description: "Learn how to progressively enhance your functions with PowerShell CmdletBinding in this ATA Learning tutorial!"
canonical: "https://adamtheautomator.com/powershell-cmdletbinding/"
---

# Learn How PowerShell CmdletBinding Enhances Functions

> Learn how to progressively enhance your functions with PowerShell CmdletBinding in this ATA Learning tutorial!

Source: https://adamtheautomator.com/powershell-cmdletbinding/

---

ATA Learning

Tap to hide

[

ATA Learning

](/)

*   [Home](/)
*   [Tutorials](/tutorials/)
*   [Instructors](/author/)
*   [Advertising](/advertising/)
*   [Recommended Resources](/resources/)
*   [About Adam](/about-adam/)

Search for:  

*   [](https://twitter.com/adbertram)
*   [](https://github.com/Adam-the-Automator)
*   [](https://www.linkedin.com/company/adam-the-automator-llc)
*   [](/feed/)

![Learn How PowerShell CmdletBinding Enhances Functions](https://adamtheautomator.com/wp-content/uploads/2022/04/Learn-How-PowerShell-CmdletBinding-Enhances-Functions.jpg)

# Learn How PowerShell CmdletBinding Enhances Functions

[![](https://secure.gravatar.com/avatar/537bf71d18a25a770449fdaeae97d1aeefe7438877931afe9e769a5fabfc3908?s=192&d=mm&r=g)Samuel Ogunleke](https://adamtheautomator.com/author/samuel-ogunleke/)5 May 202210 min. read

Categories: [IT Ops](/category/it-ops/)

Tags:[PowerShell](/tag/powershell/)

Table of Contents

*   [Prerequisites](#prerequisites)
*   [Creating a Basic Function to Organize Files with PowerShell](#creating-a-basic-function-to-organize-files-with-powershell)
*   [Gaining Access to Common Parameters with the CmdletBinding Attribute](#gaining-access-to-common-parameters-with-the-cmdletbinding-attribute)
*   [Adding -WhatIf Switch to Double-Check Tasks](#adding--whatif-switch-to-double-check-tasks)
*   [Confirming Actions with the -Confirm Switch](#confirming-actions-with-the--confirm-switch)
*   [Setting Impact Levels on Functions](#setting-impact-levels-on-functions)
*   [Displaying More Information with Write-Verbose Statements](#displaying-more-information-with-write-verbose-statements)
*   [Controlling Parameters with the Parameter Attribute](#controlling-parameters-with-the-parameter-attribute)
*   [Improving Functions with CmdletBinding and Parameter Attributes](#improving-functions-with-cmdletbinding-and-parameter-attributes)
*   [Conclusion](#conclusion)

Have you ever wanted to create a PowerShell cmdlet but didn’t know C# or another Microsoft .NET Framework language? Why keep ‘wanting’ when you have PowerShell `CmdletBinding` at your fingertips?

Not a reader? Watch this related video tutorial!

**_Not seeing the video? Make sure your ad blocker is disabled._**

In this tutorial, you will learn how to use the PowerShell `CmdletBinding` attribute to enhance functions and make them behave like cmdlets.

Ready? Dig in and make your functions behave like never before!

## Prerequisites

This tutorial will be a hands-on demonstration. As long as you have a Windows or Linux PC with PowerShell v5.1 or greater installed, you’re good to go — This tutorial uses a Windows 10 machine with PowerShell v5.1.

## Creating a Basic Function to Organize Files with PowerShell

There are cases where you might have so many files of different types in a directory without a good organization. Keeping your files organized is always a good practice, so you’ll create a basic function to move files by file extensions to a specified folder.

Related:[Your Getting Started Guide to PowerShell Functions](https://adamtheautomator.com/powershell-functions/)

> _A basic PowerShell [function](https://adamtheautomator.com/powershell-functions/) is not defined as having just a few lines of code. “Basic” in this context means that the function lacks the features of a PowerShell cmdlet. The function doesn’t have common parameters, and there’s no full control over the parameters available._

1\. Open Windows PowerShell ISE as administrator.

Related:[How to Run PowerShell as Administrator](https://adamtheautomator.com/powershell-run-as-administrator/)

2\. Copy and paste the code below to the code editor, and run the code. The code below moves all _.pdf_, _.doc_, and _.txt_ files on your Desktop to a single folder called Documents.

> _From this point throughout this tutorial, be sure to replace ADMIN in the Desktop folder path (C:\\Users\\ADMIN\\Desktop\\) with your computer username._

```powershell
Function Group-Files
{    
    Param(
    [string]$Path,
    [string]$Folder
    )
    # Check if the destination folder exists. If not, then create it
    If ((Test-Path -Path ($Path + "\" + $Folder)) -eq $False) {        
        New-Item -Name $Folder -Path $Path -ItemType Directory
    }
    # Move Items
    Get-ChildItem $Path | ForEach-Object {
				# If the last four characters of the filename ends with .pdf, .doc, .txt
        If ($_.FullName.Substring($_.FullName.Length -4) -in ".pdf", ".doc", ".txt") 
				{
            Move-Item -Path $_.FullName -Destination ($Path + $Folder)
        }
    }
}
# Call the Group-Files function
Group-Files -Path C:\Users\ADMIN\Desktop\ -Folder "Documents"
```

![Moving Files from Desktop to Documents Folder](https://adamtheautomator.com/wp-content/uploads/2022/04/image-564.png)

Moving Files from Desktop to Documents Folder

Related:[How to Run a PowerShell Script From the Command Line and More](https://adamtheautomator.com/run-powershell-script/)

> _After running the code above, you may have noticed that all the files just moved without asking you to confirm. Moreover, the function didn’t tell you what would happen if you ran the code. You’ll learn more about enhancing the function with CmdletBinding in the following sections._

3\. Lastly, run the [Get-Command](https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/get-command?view=powershell-7.2) below to list all the parameters available for the Group-Files function you created.

```powershell
(Get-Command Group-Files).Parameters
```

![Getting Parameters for the Group-Files Function](https://adamtheautomator.com/wp-content/uploads/2022/04/image-565.png)

Getting Parameters for the Group-Files Function

## Gaining Access to Common Parameters with the CmdletBinding Attribute

You’ve seen that a basic function works fine. But perhaps you prefer to make parameters mandatory or add a confirm action dialog box? If so, the `CmdletBinding` attribute will do the trick! The `CmdletBinding` attribute allows you to use common parameters available for PowerShell cmdlets.

The following code represents the syntax of the `CmdletBinding`attribute, including all its arguments.

```powershell
{
   [CmdletBinding(
        ConfirmImpact=<string>,
				# Default parameter set name you want PowerShell to use 
				# if there is no parameter set.
        DefaultParameterSetName=<string>, 
				# uri to online help, must begin with http or https
        HelpURI=<uri>, 
				# Used when you’re trying to return data from a large database suchas MySQL.
        SupportsPaging=<boolean>, 
				# Adds three parameters – First, Skip, and IncludeTotalCount to the function.
        SupportsShouldProcess=<boolean>,
				# positional binding binds positions to parameters 
        PositionalBinding=<boolean>) as defined
   ]
	 # It's important to use the Param keyword
   Param ($Parameter1)

   Begin{}
   Process{}
   End{}
}
```

Now, run the `Group-Files` function below, adding the `CmdletBinding` attribute, to give it access to common parameters and display all available parameters.

```powershell
Function Group-Files
{   
    [CmdletBinding()]
    Param(
    [string]$Path,
    [string]$Folder
    )
		#...   
}

# Gets all parameters available for the Group-Files function
(Get-Command Group-Files).Parameters
```

You can now see below that the `Group-Files` function has more parameters than you previously defined. All the common parameters are now available for the function to use.

![Getting All Parameters for the Group-Files Function](https://adamtheautomator.com/wp-content/uploads/2022/04/image-566.png)

Getting All Parameters for the Group-Files Function

## Adding `-WhatIf` Switch to Double-Check Tasks

You’ve seen how a basic function works, but a function is meant for more incredible things. And you can create advanced functions in many ways, like using switch parameters.

Switch parameters in PowerShell allow you to add controls to your functions. If the switch is True, an action will run, and another action will run if the switch is False.

> _Advanced functions work like PowerShell cmdlets. With an advanced function, you can access all the common parameters available for cmdlets. But as you’ve seen, advanced functions are written in the PowerShell language while cmdlets are written in a Microsoft .NET Framework language, such as C#._

There are only two advanced switches for risk mitigation: `WhatIf` and `Confirm` switches. But you’ll start working on the `-WhatIf` switch in this tutorial. This switch lets you check what will happen (a dry run) if you run a function with high impact.

To see how the switch works, run the following command on PowerShell with the `-WhatIf` switch. The command displays the “What if” message explaining the operation of running the `New-Item` command.

```powershell
New-Item -Name AdamBertram -Path C:\\Users\\ADMIN\\Desktop -ItemType Directory -WhatIf
```

![Appending -WhatIf to confirm the New-Item Action](https://adamtheautomator.com/wp-content/uploads/2022/04/image-567.png)

Appending -WhatIf to confirm the New-Item Action

Now, run the code below with the `CmdletBinding` added to make the `-WhatIf` accessible when the function is called.

> _From this point onwards, you’ll learn how to enhance the Group-Files function progressively and confirm the actions with the Write-Host command. And at the end of this tutorial, you’ll see the final structure of the enhanced function._

```powershell
Function Group-Files
{   # Set SupportsShouldProcess to True, to make -WhatIf and -Confirm accessible
    [CmdletBinding(SupportsShouldProcess=$True)]
    Param(
    [string]$Path,
    [string]$Folder
    )
    
    If ($PSCmdlet.ShouldProcess($Path)) {
        Write-Host "WhatIf wasn't used, moving files..."
    }
    Else {
        Write-Host "WhatIf has been used! Doing nothing..."
    } 
}
# Calls the Grou-File function
Group-Files -Path C:\\Users\\ADMIN\\Desktop\\ -Folder "Documents" -WhatIf
```

> _There is a system variable called [$WhatIfPreference](https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_preference_variables?view=powershell-7.2#whatifpreference), which is set to false by default. But when the variable is true, the Group-Files function will be automatically called with -WhatIf_

You can see in the following screenshots that the function prints out two different messages depending on whether you used the `-WhatIf` switch or not.

![Displaying a Message to Confirm -WhatIf was used](https://adamtheautomator.com/wp-content/uploads/2022/04/image-568.png)

Displaying a Message to Confirm -WhatIf was used

![Displaying a Message to Confirm -WhatIf wasn’t used](https://adamtheautomator.com/wp-content/uploads/2022/04/image-569.png)

Displaying a Message to Confirm -WhatIf wasn’t used

## Confirming Actions with the `-Confirm` Switch

Like the `-WhatIf` switch, the `-Confirm` switch tells you what a specific function or command will do. But what’s excellent with adding the `-Confirm` switch in a function is that you’ll get a prompt to confirm the actions to perform.

Adding the `-Confirm` switch comes in handy when your function is supposed to perform high-risk actions, such as moving or deleting files.

Run the following code to prompt for confirmation (`-Confirm`) before performing the specified action. The `-Confirm` parameter only works if `SupportsShouldProcess` is true, similar to `-WhatIf`.

```powershell
Function Group-Files
{
		# Set SupportsShouldProcess to True to make -WhatIf and -Confirm accessibly
    [CmdletBinding(SupportsShouldProcess=$True)]
    Param([string]$Path, [string]$Folders)

    # If the user confirmed Yes, or user didn't use -Confirm
    If ($PSCmdlet.ShouldProcess($Path)) {
        Write-Host "Files Moved"
    }
    # If the user confirmed No
    Else {
        Write-Host "Action Declined"
    }
}

# Calls the Group-Files function
Group-Files -Path C:\\Users\\ADMIN\\Desktop\\ -Folder "Documents" -Confirm
```

Now, choose an option on whether to perform the action or not. The [ShouldProcess](https://docs.microsoft.com/en-us/dotnet/api/system.management.automation.cmdlet.shouldprocess?view=powershellsdk-7.0.0) method from the $PSCmdlet automatic variable will be used to control if the files are moved or not.

![Confirming if Group-Files Function Should Run](https://adamtheautomator.com/wp-content/uploads/2022/04/image-570.png)

Confirming if Group-Files Function Should Run

If you choose to confirm the action, you’ll see the message shown below in the PowerShell terminal. Otherwise, you’ll get the message saying “Action Declined” instead.

![Viewing Confirmed Action Message](https://adamtheautomator.com/wp-content/uploads/2022/04/image-571.png)

Viewing Confirmed Action Message

## Setting Impact Levels on Functions

Perhaps you want to set an impact level to your function and not just rely on the -Confirm switch. If so, setting a confirmation impact to your function by adding the [ConfirmImpact](https://docs.microsoft.com/en-us/dotnet/api/system.management.automation.confirmimpact?view=powershellsdk-7.0.0) argument in CmdletBinding will do the trick.

Below is the syntax of the `CmdletBinding`. The `ConfirmImpact` argument’s level determines the “destructiveness” of the function’s action to perform.

```bash
[CmdletBinding(SupportsShouldProcess=$True, ConfirmImpact='level')]
```

You can set the `ConfirmImpact` argument’s level to one of the following:

*   `None` – PowerShell will not prompt confirmation for any actions unless you use the `-Confirm` switch.
*   `Low` – Actions with low, medium, or high risk will be automatically confirmed.
*   `Medium` – The default level of the `ConfirmImpact` argument, where PowerShell prompts confirmation for actions with medium or high risk, such as deleting files.
*   `High` – PowerShell prompts the user as if the function was called with the `-Confirm` parameter.

Now, run the code below to see how the `ConfirmImpact` argument and the preference `$ConfirmPreference` variable work side-by-side.

The action of `ConfirmImpact` depends on the `$ConfirmPreference` variable’s value. You’ll get a confirmation prompt if you set the `ConfirmImpact` level equal to or greater than the `$ConfirmPreference` variable’s value.

```powershell
$ConfirmPreference='High' # Sets confirmation preference
Function Group-Files
{
		# Sets -WhatIf, -Confirm and ConfirmImpact accessible
    [CmdletBinding(SupportsShouldProcess=$True, ConfirmImpact='High')]
    Param([string]$Path, [string]$Folders)

    # If the user confirmed Yes, or user didn't use -Confirm
    If ($PSCmdlet.ShouldProcess($Path)) {
        Write-Host "Files Moved"
    }
    # If the user confirmed No
    Else {
        Write-Host "Action Declined"
    }
}

# Calls the Group-Files function
Group-Files -Path C:\\Users\\ADMIN\\Desktop\\ -Folder "Documents"
```

Since the `ConfimImpact` level is equal to the `$ConfirmPreference` variable value, PowerShell prompts for confirmation even without using the `-Confirm` switch, as shown below.

![Viewing Action Confirmation Using ConfirmImpact Argument](https://adamtheautomator.com/wp-content/uploads/2022/04/image-572.png)

Viewing Action Confirmation Using ConfirmImpact Argument

## Displaying More Information with `Write-Verbose` Statements

Apart from the parameters you’ve seen in the previous examples, `CmdletBinding` provides many other common parameters, like `-Verbose`.

The `-Verbose` parameter displays more information about what is being done in the code. But how do you utilize it in your function? By adding `Write-Verbose` statements in your function.

Run the code below to see how `Write-Verbose` statements work on functions to display messages.

```powershell
Function Group-Files
{
    [CmdletBinding(SupportsShouldProcess=$True)]
    Param([string]$Path, [string]$Folder)
    
		Write-Verbose "Creating the folder if it doesn't exist..."

    # If the user confirmed Yes, or user didn't use -Confirm switch
    If ($PSCmdlet.ShouldProcess($Path)) {
        Write-Host "Files will be moved"
				Write-Verbose "Moving files..."
    }
    # If the user confirmed No
    Else {
        Write-Host "Files will not be moved"
    }
}

# Calls the Group-Files function
Group-Files -Path C:\\Users\\ADMIN\\Desktop\\ -Folder "Documents"
```

You can see below that PowerShell displays the **VERBOSE** messages in the output when the function is called with the `-Verbose` parameter.

Printing verbose messages while the functions run is helpful for troubleshooting if anything goes wrong since you know precisely what the function is currently doing beforehand.

![Displaying VERBOSE messages with Write-Verbose](https://adamtheautomator.com/wp-content/uploads/2022/04/image-573.png)

Displaying VERBOSE messages with Write-Verbose

> _One key thing to note is that while cmdlets are available everywhere, advanced functions can only be accessed in the current session. And you can only use a few automatic variables in an advanced function. For example, the [$args](https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_automatic_variables?view=powershell-7.2#args) automatic variable is unavailable for an advanced function._

## Controlling Parameters with the `Parameter` Attribute

The `Group-Files` function has just two parameters, and that’s all the function needs. But explicitly defining the behavior of the two parameters is good practice.

For instance, running the `Group-Files` function will not work without parameters, so you’ll set the `$Path` parameter as mandatory. At the same time, you’ll set a default value for the `$Folders` parameter.

Related:[Everything you Ever Wanted to Know about PowerShell Parameters](https://adamtheautomator.com/powershell-parameter/)

Below is the syntax for the `Parameter` attribute and all its arguments.

```powershell
Param
(
    [Parameter(
        Mandatory=<Boolean>,
        Position=<Integer>,
        ParameterSetName=<String>,
        ValueFromPipeline=<Boolean>,
        ValueFromPipelineByPropertyName=<Boolean>,
        ValueFromRemainingArguments=<Boolean>,
        HelpMessage=<String>,
     )]
    [string[]]
    $Parameter1
)
```

Now, run the following code to make the `$Path` parameter mandatory.

```powershell
Function Group-Files
{
		[CmdletBinding(
				SupportsShouldProcess=$True # Since you're using the common parameters
		)]
    Param(
		[Parameter(
        Mandatory=$True,
        Position=0,
				# Since the Path parameter can also get its value from a pipeline input, 
				# provide access to the pipeline input
        ValueFromPipeline=$True,
        ValueFromPipelineByPropertyName=$True
     )]
    [string]$Path,

    [Parameter(
				Mandatory=$False, 
				Position=1
		)]
    [string]$Folder = "Documents" # Default value of $Folder parameter
    )

    # If the user confirmed Yes, or user didn't use -Confirm
    If ($PSCmdlet.ShouldProcess($Path)) {
        Write-Host "Files will be moved"
				Write-Verbose "Moving files..."
    }
    # If the user confirmed No
    Else {Write-Host "Files will not be moved"}
}

# Calls the Group-Files function without the -Path parameter
Group-Files -Folder "Documents"
```

![Below is the syntax for the \`Parameter\` attribute and all its arguments.](https://adamtheautomator.com/wp-content/uploads/2022/04/image-574.png)

Below is the syntax for the `Parameter` attribute and all its arguments.

## Improving Functions with `CmdletBinding` and `Parameter` Attributes

Up to this point, you’ve experimented with the `CmdletBinding` and `Parameter` attributes, so it’s time to add the finishing touches to the `Group-Files` function. You’ll use all necessary arguments and attributes to improve the function.

Moreover, you’ll add the validation attributes below to ensure the user inputs the correct values for the parameters.

*   `ValidateScript` – Used for the `$Path` parameter to make sure the path is a folder and not a file.
*   `ValidateCount` – Ensures the minimum and maximum arguments for `$Folder`.

Run the following code containing all the necessary details for the `Group-Files` function to work more like an advanced function.

The code below checks your Desktop for files ending in `.doc`, `.pdf`, or `.txt` and asks for confirmation before moving them to the `Documents` folder.

```powershell
Function Group-Files
{   
    [CmdletBinding(
        SupportsShouldProcess=$True, # Allows the use of -Confirm and -Whatif
        PositionalBinding=$True, # Binds Path and Folder by their position
        ConfirmImpact="Medium" # Confirms before moving files
    )]  
    Param(
    [Parameter(
        Mandatory=$True,
        ValueFromPipeline=$True,
        ValueFromPipelineByPropertyName=$True,
        HelpMessage="Enter a source folder path"
     )]
  	# Validate the path is a folder and not a file
    [ValidateScript({Test-Path $_ -PathType Container})]
    [String]$Path,

    [Parameter(
        Mandatory=$False,
        HelpMessage="Enter a destination path"
     )]

    [ValidateCount(1,1)] # Must provide 1 argument/folder name
    [String]$Folder = "Documents"
    )
		Begin {
	    # Uncomment the line below to activate -whatif
	    # $WhatIfPreference = $True
	
	    # Uncomment the line below not to ask for confirmation when moving each file
			# $ConfirmPreference = "High"
		}

		# Contains the main part of the function
	  Process { 
        # Check if folders exist. If not, then create them
        If ((Test-Path -Path ($Path + "\\" + $Folder)) -eq $False) {
            #Write-Host ($Path+"\\"+$_) does not exist!
            Write-Verbose "Creating folder $($Path+"\\"+$Folder) since it does not exist."
            New-Item -Name $Folder -Path $Path -ItemType Directory
        }
        # Debug message
        Write-Debug "Make sure files are not opened with any program before moving."
        # If the user confirmed Yes, or user didn't use -Confirm
        If ($PSCmdlet.ShouldProcess($Path)) {
            Write-Host "Files will be moved"
            # Get all the files in the $Path directory
						Write-Verbose "Moving files..."
            Get-ChildItem $Path | ForEach-Object {
		        # Documents
		        If ($_.FullName.Substring($_.FullName.Length -4) -in ".pdf", ".doc", ".txt") {
								Write-Verbose "Moving file $($_.FullName) to $($Path + $Folder)"
		            Move-Item -Path $_.FullName -Destination ($Path + $Folder)
								}
            }
        }
        # If the user confirmed No
        Else {
            Write-Host "Files will not be moved"
        }
    }
}
# Call the Group-Files function
Group-Files -Verbose -Debug
```

![Displaying VERBOSE and DEBUG messages](https://adamtheautomator.com/wp-content/uploads/2022/04/image-575.png)

Displaying VERBOSE and DEBUG messages

## Conclusion

This tutorial aims to teach you how to enhance a basic function. Did it do well? You’ve progressively created advanced functions and gained features of compiled cmdlets. And at this point, you can already create your own cmdlets with PowerShell functions.

Now, why not enhance the functions in your old scripts to make them advanced!

Related:[Related: 5 PowerShell Script Examples To Inspire You to Get Scripting](https://adamtheautomator.com/powershell-script-examples/)

Share this article

[Share on X](https://twitter.com/intent/tweet?url=https%3A%2F%2Fadamtheautomator.com%2Fpowershell-cmdletbinding%2F&text=Learn%20How%20PowerShell%20CmdletBinding%20Enhances%20Functions)[Share on Facebook](https://www.facebook.com/sharer/sharer.php?u=https%3A%2F%2Fadamtheautomator.com%2Fpowershell-cmdletbinding%2F)[Share on LinkedIn](https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fadamtheautomator.com%2Fpowershell-cmdletbinding%2F)

## Related Posts

![](https://adamtheautomator.com/wp-content/uploads/2026/06/26995-troubleshoot-dns-issues-powershell-codex.webp)

### [Troubleshoot DNS Issues with PowerShell](/troubleshoot-dns-issues-powershell/)

Troubleshoot DNS issues with PowerShell by testing name resolution, DNS client settings, cache entries, and network connectivity in a repeatable workflow.

![](https://adamtheautomator.com/wp-content/uploads/2025/10/image_2025-10-24_095322075.png)

### [Migrating from PowerShell 6 to 7.5: Breaking Changes/New Features](/migrating-powershell-6-to-7-5/)

Migrate from PowerShell Core 6 to 7.5: breaking changes, features, and testing tips.

![](https://adamtheautomator.com/wp-content/uploads/2025/06/featured-image-6.png)

### [How to Add Timeouts to Pester Tests with PowerShell Runspaces](/pester-test-timeout-runspaces/)

Prevent Pester tests from hanging indefinitely using PowerShell runspaces. Learn to handle variable scoping, module loading, TestDrive access, and stream capture challenges with timeout protection.

## Categories

*   [IT Ops](/category/it-ops/)
*   [Cloud](/category/cloud/)
*   [DevOps](/category/devops/)
*   [Home Ops](/category/home-ops/)
*   [Information Security](/category/infosec/)
*   [Software Development](/category/software-development/)

## Site

*   [Home](/)
*   [Tutorials](/tutorials/)
*   [Instructors](/author/)
*   [Advertising](/advertising/)
*   [Recommended Resources](/resources/)
*   [About Adam](/about-adam/)

Copyright 2026© ATA Learning | [Privacy Policy](/privacy/)
