Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
description: Users Requesting Confirmation
ms.date: 09/30/2021
ms.date: 09/24/2024
ms.topic: reference
title: Users Requesting Confirmation
---
Expand All @@ -9,23 +9,22 @@ title: Users Requesting Confirmation
When you specify a value of `true` for the `SupportsShouldProcess` parameter of the Cmdlet attribute
declaration, the **Confirm** parameter is added to the parameters of the cmdlet.

In the default environment, users can specify the **Confirm** parameter or `"-Confirm:$true` so that
confirmation is requested when the `ShouldProcess()` method is called. This forces confirmation
regardless of the impact level setting.
In the default environment, users can specify the **Confirm** parameter so that confirmation is
requested when the `ShouldProcess()` method is called. This forces confirmation regardless of the
impact level setting.

If **Confirm** parameter is not used, the `ShouldProcess()` call requests confirmation if the
`$ConfirmPreference` preference variable is equal to or greater than the `ConfirmImpact` setting of
the cmdlet or provider. The default setting of `$ConfirmPreference` is **High**. Therefore, in the
default environment, only cmdlets and providers that specify a high-impact action request
confirmation.
`ConfirmImpact` setting is equal to or greater than the `$ConfirmPreference` preference variable.
The default setting of `$ConfirmPreference` is **High**. Therefore, in the default environment, only
cmdlets and providers that specify a high-impact action request confirmation.

If **Confirm** is explicitly set to false (`-Confirm:$false`), the cmdlet runs without prompting for
confirmation and the `$ConfirmPreference` shell variable is ignored.

## Remarks

- For cmdlets and providers that specify `SupportsShouldProcess`, but not `ConfirmImpact`, those
actions are handled as "medium impact" actions, and they will not prompt by default. Their impact
actions are handled as `Medium` impact actions, and they will not prompt by default. Their impact
level is less than the default setting of the `$ConfirmPreference` preference variable.

- If the user specifies the `Verbose` parameter, they will be notified of the operation even if they
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
---
description: ShouldProcess is an important feature that is often overlooked is. The WhatIf and Confirm parameters make it easy to add to your functions.
ms.custom: contributor-KevinMarquette
ms.date: 11/16/2022
ms.date: 09/24/2024
title: Everything you wanted to know about ShouldProcess
---
# Everything you wanted to know about ShouldProcess
Expand All @@ -11,18 +11,18 @@ One important feature that is often overlooked is `-WhatIf` and `-Confirm` suppo
add to your functions. In this article, we dive deep into how to implement this feature.

> [!NOTE]
> The [original version][original version] of this article appeared on the blog written by [@KevinMarquette][@KevinMarquette]. The
> PowerShell team thanks Kevin for sharing this content with us. Please check out his blog at
> [PowerShellExplained.com][PowerShellExplained.com].
> The [original version][original version] of this article appeared on the blog written by
> [@KevinMarquette][@KevinMarquette]. The PowerShell team thanks Kevin for sharing this content with
> us. Please check out his blog at [PowerShellExplained.com][PowerShellExplained.com].

This is a simple feature you can enable in your functions to provide a safety net for the users that
need it. There's nothing scarier than running a command that you know can be dangerous for the
first time. The option to run it with `-WhatIf` can make a big difference.

## CommonParameters

Before we look at implementing these [common parameters][common parameters], I want to take a quick look at how
they're used.
Before we look at implementing these [common parameters][common parameters], I want to take a quick
look at how they're used.

## Using -WhatIf

Expand Down Expand Up @@ -141,6 +141,11 @@ Notice that I did not create a parameter called `-WhatIf`. Specifying `SupportsS
automatically creates it for us. When we specify the `-WhatIf` parameter on `Test-ShouldProcess`,
some things we call also perform `-WhatIf` processing.

> [!NOTE]
> When you use `SupportsShouldProcess`, PowerShell doesn't add the `$WhatIf` variable to the
> function. You don't need to check the value of `$WhatIf` because the `ShouldProcess()` method
> takes care of that for you.

### Trust but verify

There's some danger here trusting that everything you call inherits `-WhatIf` values. For the rest
Expand Down Expand Up @@ -513,55 +518,44 @@ function Test-ShouldProcess {
ConfirmImpact = 'High'
)]
param(
[Switch]$Force
[switch]$Force
)

if ($Force -and -not $Confirm){
if ($Force -and -not $PSBoundParameters.ContainsKey('Confirm')) {
$ConfirmPreference = 'None'
}

if ($PSCmdlet.ShouldProcess('TARGET')){
if ($PSCmdlet.ShouldProcess('TARGET')) {
Write-Output "Some Action"
}
}
```

We add our own `-Force` switch as a parameter. The `-Confirm` parameter is automatically added
when using `SupportsShouldProcess` in the `CmdletBinding`.

```powershell
[CmdletBinding(
SupportsShouldProcess,
ConfirmImpact = 'High'
)]
param(
[Switch]$Force
)
```

Focusing in on the `-Force` logic here:
We add our own `-Force` switch as a parameter. The `-Confirm` parameter is automatically added when
using `SupportsShouldProcess` in the `CmdletBinding`. However, when you use `SupportsShouldProcess`,
PowerShell doesn't add the `$Confirm` variable to the function. If you are running in Strict Mode
and try to use the `$Confirm` variable before it has been defined, you get an error. To avoid the
error you can use `$PSBoundParameters` to test if the parameter was passed by the user.

```powershell
if ($Force -and -not $Confirm){
if ($Force -and -not $PSBoundParameters.ContainsKey('Confirm')) {
$ConfirmPreference = 'None'
}
```

If the user specifies `-Force`, we want to suppress the confirm prompt unless they also specify
`-Confirm`. This allows a user to force a change but still confirm the change. Then we set
`$ConfirmPreference` in the local scope. Now, using the `-Force` parameter temporarily sets the
`$ConfirmPreference` to none, disabling prompt for confirmation.
If the user specifies `-Force` we set `$ConfirmPreference` to `None` in the local scope. If the user
also specifies `-Confirm` then `ShoudProcess()` honors the values of the `-Confirm` parameter.

```powershell
if ($PSCmdlet.ShouldProcess('TARGET')){
Write-Output "Some Action"
}
Write-Output "Some Action"
}
```

If someone specifies both `-Force` and `-WhatIf`, then `-WhatIf` needs to take priority. This
approach preserves `-WhatIf` processing because `ShouldProcess` always gets executed.

Do not add a check for the `$Force` value inside the `if` statement with the `ShouldProcess`. That is
Don't add a test for the `$Force` value inside the `if` statement with the `ShouldProcess`. That is
an anti-pattern for this specific scenario even though that's what I show you in the next section
for `ShouldContinue`.

Expand Down
66 changes: 50 additions & 16 deletions reference/docs-conceptual/learn/experimental-features.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
description: Lists the currently available experimental features and how to use them.
ms.date: 08/28/2024
ms.date: 09/24/2024
title: Using Experimental Features in PowerShell
---
# Using Experimental Features in PowerShell
Expand All @@ -15,14 +15,14 @@ breaking changes.
> [!CAUTION]
> Experimental features aren't intended to be used in production since the changes are allowed to be
> breaking. Experimental features aren't officially supported. However, we appreciate any feedback
> and bug reports. You can file issues in the [GitHub source repository][25].
> and bug reports. You can file issues in the [GitHub source repository][26].

For more information about enabling or disabling these features, see
[about_Experimental_Features][06].

## Experimental feature lifecycle

The [Get-ExperimentalFeature][29] cmdlet returns all experimental features available to PowerShell.
The [Get-ExperimentalFeature][30] cmdlet returns all experimental features available to PowerShell.
Experimental features can come from modules or the PowerShell engine. Module-based experimental
features are only available after you import the module. In the following example, the
**PSDesiredStateConfiguration** isn't loaded, so the `PSDesiredStateConfiguration.InvokeDscResource`
Expand All @@ -40,10 +40,11 @@ PSCommandWithArgs False PSEngine Enable `-CommandWithArgs` para
PSFeedbackProvider True PSEngine Replace the hard-coded suggestion framework with …
PSLoadAssemblyFromNativeCode False PSEngine Expose an API to allow assembly loading from nati…
PSModuleAutoLoadSkipOfflineFiles True PSEngine Module discovery will skip over files that are ma…
PSSerializeJSONLongEnumAsNumber True PSEngine Serialize enums based on long or ulong as an nume…
PSSubsystemPluginModel True PSEngine A plugin model for registering and un-registering…
```

Use the [Enable-ExperimentalFeature][28] and [Disable-ExperimentalFeature][27] cmdlets to enable or
Use the [Enable-ExperimentalFeature][29] and [Disable-ExperimentalFeature][28] cmdlets to enable or
disable a feature. You must start a new PowerShell session for this change to be in effect. Run the
following command to enable the `PSCommandNotFoundSuggestion` feature:

Expand Down Expand Up @@ -96,6 +97,7 @@ Legend
| [PSCommandWithArgs][11] | | ![Experimental][02] | ![Experimental][02] |
| [PSNativeWindowsTildeExpansion][22] | | | ![Experimental][02] |
| [PSRedirectToVariable][24] | | | ![Experimental][02] |
| [PSSerializeJSONLongEnumAsNumber][25] | | | ![Experimental][02] |

### PSAnsiRenderingFileInfo

Expand Down Expand Up @@ -213,7 +215,7 @@ a native executable.
> The new behavior is a **breaking change** from current behavior. This may break scripts and
> automation that work around the various issues when invoking native applications. Historically,
> quotes must be escaped and it isn't possible to provide empty arguments to a native application.
> Use the [stop-parsing token][08] (`--%`) or the [`Start-Process`][31] cmdlet to sidestep native
> Use the [stop-parsing token][08] (`--%`) or the [`Start-Process`][32] cmdlet to sidestep native
> argument passing when needed.

This feature adds a new `$PSNativeCommandArgumentPassing` preference variable that controls this
Expand Down Expand Up @@ -245,7 +247,7 @@ and non-Windows platforms is `Standard`.

> [!NOTE]
> The following examples use the `TestExe.exe` tool. You can build `TestExe` from the source code.
> See [TestExe][26] in the PowerShell source repository.
> See [TestExe][27] in the PowerShell source repository.

New behaviors made available by this change:

Expand All @@ -272,7 +274,7 @@ New behaviors made available by this change:
For more examples of the new behavior, see [about_Parsing][07].

PowerShell 7.3 also added the ability to trace parameter binding for native commands. For more
information, see [Trace-Command][32].
information, see [Trace-Command][34].

### PSNativeCommandErrorActionPreference

Expand Down Expand Up @@ -365,7 +367,7 @@ the PSReadLine module to provide custom prediction plugins. In future, **Job**,
**CommandCompleter**, **Remoting** and other components could be separated into subsystem assemblies
outside of `System.Management.Automation.dll`.

The experimental feature includes a new cmdlet, [Get-PSSubsystem][30]. This cmdlet is only available
The experimental feature includes a new cmdlet, [Get-PSSubsystem][31]. This cmdlet is only available
when the feature is enabled. This cmdlet returns information about the subsystems that are available
on the system.

Expand All @@ -392,6 +394,36 @@ This feature only applies to Windows. On non-Windows platforms, tilde expansion

This feature was added in PowerShell 7.5-preview.2.

### PSSerializeJSONLongEnumAsNumber

This feature enables the cmdlet [ConvertTo-Json][33] to serialize any enum values based on
`Int64/long` or `UInt64/ulong` as a numeric value rather than the string representation of that enum
value. This aligns the behavior of enum serialization with other enum base types where the cmdlet
serializes enums as their numeric value. Use the **EnumsAsStrings** parameter to serialize as the
string representation.

For example:

```powershell
# PSSerializeJSONLongEnumAsNumber disabled
@{
Key = [System.Management.Automation.Tracing.PowerShellTraceKeywords]::Cmdlets
} | ConvertTo-Json
# { "Key": "Cmdlets" }

# PSSerializeJSONLongEnumAsNumber enabled
@{
Key = [System.Management.Automation.Tracing.PowerShellTraceKeywords]::Cmdlets
} | ConvertTo-Json
# { "Key": 32 }

# -EnumsAsStrings to revert back to the old behaviour
@{
Key = [System.Management.Automation.Tracing.PowerShellTraceKeywords]::Cmdlets
} | ConvertTo-Json -EnumsAsStrings
# { "Key": "Cmdlets" }
```

<!-- link references -->
[01]: ../../media/shared/check-mark-button-2705.svg
[02]: ../../media/shared/construction-sign-1f6a7.svg
Expand All @@ -414,11 +446,13 @@ This feature was added in PowerShell 7.5-preview.2.
[22]: #psnativewindowstildeexpansion
[23]: #pssubsystempluginmodel
[24]: #psredirecttovariable
[25]: https://github.com/PowerShell/PowerShell/issues/new/choose
[26]: https://github.com/PowerShell/PowerShell/tree/master/test/tools/TestExe
[27]: xref:Microsoft.PowerShell.Core.Disable-ExperimentalFeature
[28]: xref:Microsoft.PowerShell.Core.Enable-ExperimentalFeature
[29]: xref:Microsoft.PowerShell.Core.Get-ExperimentalFeature
[30]: xref:Microsoft.PowerShell.Core.Get-PSSubsystem
[31]: xref:Microsoft.PowerShell.Management.Start-Process
[32]: xref:Microsoft.PowerShell.Utility.Trace-Command
[25]: #psserializejsonlongenumasnumber
[26]: https://github.com/PowerShell/PowerShell/issues/new/choose
[27]: https://github.com/PowerShell/PowerShell/tree/master/test/tools/TestExe
[28]: xref:Microsoft.PowerShell.Core.Disable-ExperimentalFeature
[29]: xref:Microsoft.PowerShell.Core.Enable-ExperimentalFeature
[30]: xref:Microsoft.PowerShell.Core.Get-ExperimentalFeature
[31]: xref:Microsoft.PowerShell.Core.Get-PSSubsystem
[32]: xref:Microsoft.PowerShell.Management.Start-Process
[33]: xref:Microsoft.PowerShell.Utility.ConvertTo-Json
[34]: xref:Microsoft.PowerShell.Utility.Trace-Command
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@ For more information about AppLocker and WDAC, see [Application Controls for Win

## WDAC policy enforcement

When PowerShell runs under a WDAC policy, its behavior changes based on the defined security
policy. Under a WDAC policy, PowerShell runs trusted scripts and modules allowed by the policy in
When PowerShell runs under a WDAC policy, its behavior changes based on the defined security policy.
Under a WDAC policy, PowerShell runs trusted scripts and modules allowed by the policy in
`FullLanguage` mode. All other scripts and script blocks are untrusted and run in
`ConstrainedLanguage` mode. PowerShell throws errors when the untrusted scripts attempt to perform
actions that aren't allowed in `ConstrainedLanguage` mode. It can be difficult to know why a script
Expand All @@ -41,9 +41,9 @@ failed to run correctly in `ConstrainedLanguage` mode.
## WDAC policy auditing

PowerShell 7.4 added a new feature to support WDAC policies in **Audit** mode. In audit mode,
PowerShell runs the untrusted scripts in `ConstrainedLanguage` mode without errors, but logs messages
to the event log instead. The log messages describe what restrictions would apply if the policy were
in **Enforce** mode.
PowerShell runs the untrusted scripts in `ConstrainedLanguage` mode without errors, but logs
messages to the event log instead. The log messages describe what restrictions would apply if the
policy were in **Enforce** mode.

## History of changes

Expand All @@ -54,9 +54,10 @@ described in the later versions include those from earlier versions.

### Changes in PowerShell 7.4

On Windows, when PowerShell runs under a Windows Defender Application Control (WDAC) policy, its behavior changes based on the defined security policy. Under a WDAC policy, PowerShell runs
trusted scripts and modules allowed by the policy in `FullLanguage` mode. All other scripts and
script blocks are untrusted and run in `ConstrainedLanguage` mode. PowerShell throws errors when the
On Windows, when PowerShell runs under a Windows Defender Application Control (WDAC) policy, its
behavior changes based on the defined security policy. Under a WDAC policy, PowerShell runs trusted
scripts and modules allowed by the policy in `FullLanguage` mode. All other scripts and script
blocks are untrusted and run in `ConstrainedLanguage` mode. PowerShell throws errors when the
untrusted scripts attempt to perform disallowed actions. It's difficult to know why a script fails
to run correctly in `ConstrainedLanguage` mode.

Expand All @@ -67,7 +68,8 @@ throwing errors. The log messages describe what restrictions would apply if the

### Changes in PowerShell 7.3

- PowerShell 7.3 now supports the ability to block or allow PowerShell script files via the WDAC API.
- PowerShell 7.3 now supports the ability to block or allow PowerShell script files via the WDAC
API.

### Changes in PowerShell 7.2

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ can configure the policy to enforce or audit the policy's rule. In audit mode, P
doesn't change but it logs Event ID 16387 messages to the `PowerShellCore/Analytic` event log. In
enforcement mode, PowerShell applies the policy's restrictions.

This article assumes you're using a test machine so that you can test PowerShell behavior
under a machine wide WDAC policy before you deploy the policy in your environment.
This article assumes you're using a test machine so that you can test PowerShell behavior under a
machine wide WDAC policy before you deploy the policy in your environment.

## Create a WDAC policy

Expand All @@ -21,8 +21,8 @@ approved files are allowed to load and run. PowerShell either blocks unapproved
running or runs them in `ConstrainedLanguage` mode, depending on policy options.

You create and manipulate WDAC policy using the **ConfigCI** module, which is available on all
supported Windows versions. This Windows PowerShell module can be used in Windows PowerShell 5.1
or in PowerShell 7 through the **Windows Compatibility** layer. It's easier to use this module in
supported Windows versions. This Windows PowerShell module can be used in Windows PowerShell 5.1 or
in PowerShell 7 through the **Windows Compatibility** layer. It's easier to use this module in
Windows PowerShell. The policy you create can be applied to any version of PowerShell.

## Steps to create a WDAC policy
Expand All @@ -44,8 +44,8 @@ For testing, you just need to create a default policy and a self signed code sig
1. Disable Audit Mode in default policy

A new policy is always created in `Audit` mode. To test policy enforcement, you need to disable
Audit mode when you apply the policy. Edit the `SystemCIPolicy.xml` file using a text editor
like `notepad.exe` or Visual Studio Code (VS Code). Comment out the `Audit mode` option.
Audit mode when you apply the policy. Edit the `SystemCIPolicy.xml` file using a text editor like
`notepad.exe` or Visual Studio Code (VS Code). Comment out the `Audit mode` option.

```XML
<!--
Expand Down
Loading