Senior Systems Engineer
Senior Systems Engineer

Reputation: 1141

Powershell Function -WhatIf for cmdlet without the -WhatIf support?

For these cmdlets below, I try to create the function with the [CmdletBinding(SupportsShouldProcess)] line, but not sure that it will work.

Using: https://learn.microsoft.com/en-us/powershell/module/msonline/set-msoluserlicense?view=azureadps-1.0

How can the script be modified to support the -WhatIf parameter?

function Remove-License {
    [CmdletBinding(SupportsShouldProcess)]
    param ([String] $UserPrincipalName )
    
    $AssignedLicense = (Get-MsolUser -UserPrincipalName $UserPrincipalName).licenses.AccountSkuId

    $AssignedLicense |
    ForEach-Object {
        Write-Host "Removing $($UserPrincipalName) License $($AssignedLicense)..." -ForegroundColor Red
        Set-MsolUserLicense -UserPrincipalName $upn -RemoveLicenses $_ -Verbose
    }

}

Remove-License -UserPrincipalName '[email protected]' -WhatIf

Upvotes: 1

Views: 580

Answers (2)

Santiago Squarzon
Santiago Squarzon

Reputation: 60508

To complement guiwhatsthat helpful answer, if you want your function to support Common Parameter including -WhatIf as well as -Confirm, $PSCmdlet.ShouldProcess is how you do it.

If instead you want Set-MsolUserLicense to support it, you would need to create a proxy command / proxy function around this cmdlet to extend it's functionality.

These blogs demonstrate how to do it:


To address some issues on your code, you should note that -RemoveLicenses takes string[] as input, this means you can pass the whole array of licenses to remove as argument.

You could use Write-Verbose instead of Write-Host to display information about what the function is doing (since your function already supports -Verbose, this would be logical). Also, -Verbose is being used always activated on Set-MsolUserLicense which can be confusing if someone else using your function does not want to see verbose messages (this is addressed on the example below).

You can also use ConfirmImpact set to High, this way the function will always ask for confirmation before processing any license removal assuming -WhatIf was not being used. -Confirm:$false becomes the alternative to avoid such confirmation messages.

function Remove-License {
    [CmdletBinding(SupportsShouldProcess, ConfirmImpact = 'High')]
    param(
        [Parameter(ValueFromPipeline, ValueFromPipelineByPropertyName)]
        [string] $UserPrincipalName
    )

    process {
        if($PSCmdlet.ShouldProcess([string] $UserPrincipalName, 'Remove License')) {
            $licenses = (Get-MsolUser -UserPrincipalName $UserPrincipalName).licenses.AccountSkuId
            $param    = @{
                UserPrincipalName = $UserPrincipalName
                RemoveLicenses    = $licenses
                Verbose           = $PSBoundParameters['Verbose'] 
            }
            Set-MsolUserLicense @param
        }
    }
}

Now the function supports pipeline processing, you can process multiple users by piping it into other cmdlets, i.e.:

Get-MsolUser -EnabledFilter DisabledOnly -MaxResults 5 | Remove-License -WhatIf

Upvotes: 2

guiwhatsthat
guiwhatsthat

Reputation: 2434

You can use $PSCmdlet.ShouldProcess

if($PSCmdlet.ShouldProcess("Some text to display")){ 
    Set-MsolUserLicense -UserPrincipalName $upn -RemoveLicenses $_ -Verbose
 }

MS Docs: https://learn.microsoft.com/en-us/powershell/scripting/learn/deep-dives/everything-about-shouldprocess?view=powershell-7.2

Upvotes: 2

Related Questions