TheCleaner
TheCleaner

Reputation: 255

Powershell - how to combine -whatif with a -confirm?

I referenced this question: how to use 'dry-run' in powershell in my search and I get what it is saying already.

My question though is:

Can I have a Powershell script that invokes a -whatif, then comes back with a confirmation prompt to run the real command(s)?

An example:

#Disable Exchange access
set-casmailbox $1.samaccountname -ewsallowentourage $false -ecpenabled $false -ewsallowoutlook $false -ewsallowmacoutlook $false -activesyncenabled $false -owaenabled $false -OWAforDevicesEnabled $false -mapihttpenabled $false -ewsenabled $false -mapienabled $false

I would like the above to include a -WhatIf and then a prompt to confirm whether to run the real command(s) or not.

I figure I can do it somewhat sloppily by using:

#Check what happens if I disable Exchange Access
set-casmailbox $1.samaccountname -ewsallowentourage $false -ecpenabled $false -ewsallowoutlook $false -ewsallowmacoutlook $false -activesyncenabled $false -owaenabled $false -OWAforDevicesEnabled $false -mapihttpenabled $false -ewsenabled $false -mapienabled $false -whatif
#Prompt for Confirmation to actually disable Exchange Access
set-casmailbox $1.samaccountname -ewsallowentourage $false -ecpenabled $false -ewsallowoutlook $false -ewsallowmacoutlook $false -activesyncenabled $false -owaenabled $false -OWAforDevicesEnabled $false -mapihttpenabled $false -ewsenabled $false -mapienabled $false -confirm

But I was curious if there's a better way, especially since the above is a simple single line command versus a foreach,etc.

Upvotes: 1

Views: 357

Answers (1)

briantist
briantist

Reputation: 47792

This would have to be implemented in the cmdlet you are calling. You could sort of hack this together with your own function:

function Invoke-WhatIfThenConfirm {
[CmdletBinding(SupportsShouldProcess=$true)]
param(
    [Parameter(
        Mandatory=$true
    )]
    [ScriptBlock]
    $ScriptBlock ,

    [Switch]
    $Force
)

    if ($PSCmdlet.ShouldProcess('Calling scriptblock')) {
        $prefSave = $WhatIfPreference
        try {
            $WhatIfPreference = 'Stop'
            & $ScriptBlock
        } finally {
            $WhatIfPreference = $prefSave
        }
        $confSave = $ConfirmPreference
        try {
            $ConfirmPreference = if ($Force) {
                'None'
            } else {
                'High'
            }
            & $ScriptBlock
        } finally {
            $ConfirmPreference = $confSave
        }
    }
}

Then call it like:

Invoke-WhatIfThenConfirm -ScriptBlock {
    set-casmailbox $1.samaccountname -ewsallowentourage $false -ecpenabled $false -ewsallowoutlook $false -ewsallowmacoutlook $false -activesyncenabled $false -owaenabled $false -OWAforDevicesEnabled $false -mapihttpenabled $false -ewsenabled $false -mapienabled $false
}

If you use -Force it should force no confirmation.

This whole thing was just typed here though and I haven't tested it at all, so I'm not certain it will work, but it might be a good starting point.


Alternative

You can use splatting to put your params in a hashtable and modify the switches:

$params = @{
    Identity = $1.samaccountname 
    ewsallowentourage = $false 
    ecpenabled = $false 
    ewsallowoutlook = $false 
    ewsallowmacoutlook = $false 
    activesyncenabled = $false 
    owaenabled = $false 
    OWAforDevicesEnabled = $false 
    mapihttpenabled = $false 
    ewsenabled = $false 
    mapienabled = $false
}

set-casmailbox @params -WhatIf
set-casmailbox @params -Confirm

The second option is a bit easier and probably less error prone, but works best for a call here or there to a single cmdlet where most parameters don't change.

The first option is more versatile for working with many different cmdlets and calling them more naturally.

Upvotes: 2

Related Questions