From 67ac3e9d59a5d10be15d3a412b3c3795d5a401d4 Mon Sep 17 00:00:00 2001 From: Xelu86 <103963494+Xelu86@users.noreply.github.com> Date: Mon, 8 Jun 2026 14:09:56 -0400 Subject: [PATCH 1/7] [Freshness] PSScriptAnalyzer Article Updates - Batch 7 (#408) * Freshness * Minor edit * Applied feedback * Applied feedback --- .../Rules/DSCDscExamplesPresent.md | 24 ++++++------- .../Rules/DSCDscTestsPresent.md | 27 +++++++-------- .../DSCReturnCorrectTypesForDSCFunctions.md | 34 +++++++------------ .../DSCStandardDSCFunctionsInResource.md | 31 ++++++++--------- ...SCUseIdenticalMandatoryParametersForDSC.md | 27 +++++++-------- .../Rules/DSCUseIdenticalParametersForDSC.md | 18 +++++----- .../DSCUseVerboseMessageInDSCResource.md | 22 ++++++------ 7 files changed, 83 insertions(+), 100 deletions(-) diff --git a/reference/docs-conceptual/PSScriptAnalyzer/Rules/DSCDscExamplesPresent.md b/reference/docs-conceptual/PSScriptAnalyzer/Rules/DSCDscExamplesPresent.md index b2b1cf6..cd15788 100644 --- a/reference/docs-conceptual/PSScriptAnalyzer/Rules/DSCDscExamplesPresent.md +++ b/reference/docs-conceptual/PSScriptAnalyzer/Rules/DSCDscExamplesPresent.md @@ -1,6 +1,6 @@ --- description: DSC examples are present -ms.date: 06/28/2023 +ms.date: 06/03/2026 ms.topic: reference title: DSCDscExamplesPresent --- @@ -10,23 +10,21 @@ title: DSCDscExamplesPresent ## Description -Checks that DSC examples for given resource are present. +This rule detects if Desired State Configuration (DSC) examples for a given resource are present. -## How +To fix a violation of this rule, you must ensure that the `Examples` directory exists for: -To fix a violation of this rule, please make sure `Examples` directory is present: +- Non-class based resources, it should be at the same folder level as the `DSCResources` folder. +- Class based resources, it should be at the same folder level as the resource's `.psm1` file. -- For non-class based resources it should exist at the same folder level as `DSCResources` folder. -- For class based resources it should be present at the same folder level as resource `.psm1` file. - -The `Examples` folder should contain a sample configuration for given resource. The filename should -contain the resource's name. +The `Examples` folder must contain a sample configuration for the resource. The filename should +include the resource's name. ## Example ### Non-class based resource -Let's assume we have non-class based resource with a following file structure: +Let's assume we have non-class based resource with the following file structure: - xAzure - DSCResources @@ -34,7 +32,7 @@ Let's assume we have non-class based resource with a following file structure: - MSFT_xAzureSubscription.psm1 - MSFT_xAzureSubscription.schema.mof -In this case, to fix this warning, we should add examples in a following way: +In this case, to fix this warning, add examples in the following way: - xAzure - DSCResources @@ -47,13 +45,13 @@ In this case, to fix this warning, we should add examples in a following way: ### Class based resource -Let's assume we have class based resource with a following file structure: +Let's assume we have class based resource with the following file structure: - MyDscResource - MyDscResource.psm1 - MyDscResource.psd1 -In this case, to fix this warning, we should add examples in a following way: +In this case, to fix this warning, add examples in the following way: - MyDscResource - MyDscResource.psm1 diff --git a/reference/docs-conceptual/PSScriptAnalyzer/Rules/DSCDscTestsPresent.md b/reference/docs-conceptual/PSScriptAnalyzer/Rules/DSCDscTestsPresent.md index f8fe319..663a6aa 100644 --- a/reference/docs-conceptual/PSScriptAnalyzer/Rules/DSCDscTestsPresent.md +++ b/reference/docs-conceptual/PSScriptAnalyzer/Rules/DSCDscTestsPresent.md @@ -1,6 +1,6 @@ --- -description: Dsc tests are present -ms.date: 06/28/2023 +description: DSC tests are present +ms.date: 06/03/2026 ms.topic: reference title: DSCDscTestsPresent --- @@ -10,23 +10,22 @@ title: DSCDscTestsPresent ## Description -Checks that DSC tests for given resource are present. +This rule detects if Desired State Configuration (DSC) tests for a given resource are present. -## How +To fix a violation of this rule, you must ensure that the `Tests` directory is present for: -To fix a violation of this rule, please make sure `Tests` directory is present: +- Non-class based resources, it should exist at the same folder level as the `DSCResources` + folder. +- Class based resources, it should be at the same folder level as the resource's `.psm1` file. -- For non-class based resources it should exist at the same folder level as `DSCResources` folder. -- For class based resources it should be present at the same folder level as resource `.psm1` file. - -The `Tests` folder should contain test script for given resource. The filename should contain the -resource's name. +The `Tests` folder must contain a test script for the given resource. The filename should include +the resource's name. ## Example ### Non-class based resource -Let's assume we have non-class based resource with a following file structure: +Let's assume we have non-class based resource with the following file structure: - xAzure - DSCResources @@ -34,7 +33,7 @@ Let's assume we have non-class based resource with a following file structure: - MSFT_xAzureSubscription.psm1 - MSFT_xAzureSubscription.schema.mof -In this case, to fix this warning, we should add tests in a following way: +In this case, to fix this warning, add tests in the following way: - xAzure - DSCResources @@ -46,13 +45,13 @@ In this case, to fix this warning, we should add tests in a following way: ### Class based resource -Let's assume we have class based resource with a following file structure: +Let's assume we have class based resource with the following file structure: - MyDscResource - MyDscResource.psm1 - MyDscResource.psd1 -In this case, to fix this warning, we should add tests in a following way: +In this case, to fix this warning, add tests in the following way: - MyDscResource - MyDscResource.psm1 diff --git a/reference/docs-conceptual/PSScriptAnalyzer/Rules/DSCReturnCorrectTypesForDSCFunctions.md b/reference/docs-conceptual/PSScriptAnalyzer/Rules/DSCReturnCorrectTypesForDSCFunctions.md index 1681852..99dc1a4 100644 --- a/reference/docs-conceptual/PSScriptAnalyzer/Rules/DSCReturnCorrectTypesForDSCFunctions.md +++ b/reference/docs-conceptual/PSScriptAnalyzer/Rules/DSCReturnCorrectTypesForDSCFunctions.md @@ -1,6 +1,6 @@ --- -description: Return Correct Types For DSC Functions -ms.date: 06/28/2023 +description: Return correct types for DSC functions +ms.date: 06/03/2026 ms.topic: reference title: DSCReturnCorrectTypesForDSCFunctions --- @@ -10,27 +10,24 @@ title: DSCReturnCorrectTypesForDSCFunctions ## Description -The functions in DSC resources have specific return objects. +This rule detects if functions in Desired State Configuration (DSC) resources have specific return +objects. You'll need to ensure that each function returns the correct type. For non-class based resources: +- `Get-TargetResource` must return a hash table. - `Set-TargetResource` must not return any value. - `Test-TargetResource` must return a boolean. -- `Get-TargetResource` must return a hash table. For class based resources: +- `Get` must return an instance of the DSC class. - `Set` must not return any value. - `Test` must return a boolean. -- `Get` must return an instance of the DSC class. - -## How - -Ensure that each function returns the correct type. -## Example 1 +## Example -### Wrong +### Noncompliant MOF-based resource ```powershell function Get-TargetResource @@ -67,7 +64,7 @@ function Test-TargetResource } ``` -### Correct +### Compliant MOF-based resource ```powershell function Get-TargetResource @@ -106,9 +103,7 @@ function Test-TargetResource } ``` -## Example 2 - -### Wrong +### Noncompliant class-based resource ```powershell [DscResource()] @@ -117,12 +112,7 @@ class MyDSCResource [DscProperty(Key)] [string] $Name - [String] Get() - { - ... - } - - [String] Set() + [void] Set() { ... } @@ -134,7 +124,7 @@ class MyDSCResource } ``` -### Correct +### Compliant class-based resource ```powershell [DscResource()] diff --git a/reference/docs-conceptual/PSScriptAnalyzer/Rules/DSCStandardDSCFunctionsInResource.md b/reference/docs-conceptual/PSScriptAnalyzer/Rules/DSCStandardDSCFunctionsInResource.md index f455d74..96a8125 100644 --- a/reference/docs-conceptual/PSScriptAnalyzer/Rules/DSCStandardDSCFunctionsInResource.md +++ b/reference/docs-conceptual/PSScriptAnalyzer/Rules/DSCStandardDSCFunctionsInResource.md @@ -1,6 +1,6 @@ --- -description: Use Standard Get/Set/Test TargetResource functions in DSC Resource -ms.date: 06/28/2023 +description: Use standard DSC Get, Set, and Test TargetResource functions in a resource +ms.date: 06/03/2026 ms.topic: reference title: DSCStandardDSCFunctionsInResource --- @@ -10,27 +10,24 @@ title: DSCStandardDSCFunctionsInResource ## Description -All DSC resources are required to implement the correct functions. +This rule detects if all Desired State Configuration (DSC) resources implement the correct +functions. Add the missing functions to the resource. For non-class based resources: +- `Get-TargetResource` - `Set-TargetResource` - `Test-TargetResource` -- `Get-TargetResource` For class based resources: +- `Get` - `Set` - `Test` -- `Get` - -## How - -Add the missing functions to the resource. -## Example 1 +## Example -### Wrong +### Noncompliant MOF-based resource ```powershell function Get-TargetResource @@ -45,8 +42,9 @@ function Get-TargetResource ... } -function Set-TargetResource +function Test-TargetResource { + [OutputType([System.Boolean])] param ( [parameter(Mandatory = $true)] @@ -57,7 +55,7 @@ function Set-TargetResource } ``` -### Correct +### Compliant MOF-based resource ```powershell function Get-TargetResource @@ -96,9 +94,7 @@ function Test-TargetResource } ``` -## Example 2 - -### Wrong +### Noncompliant class-based resource ```powershell [DscResource()] @@ -117,8 +113,9 @@ class MyDSCResource ... } } +``` -### Correct +### Compliant class-based resource ```powershell [DscResource()] diff --git a/reference/docs-conceptual/PSScriptAnalyzer/Rules/DSCUseIdenticalMandatoryParametersForDSC.md b/reference/docs-conceptual/PSScriptAnalyzer/Rules/DSCUseIdenticalMandatoryParametersForDSC.md index dc8e9e9..00d45f2 100644 --- a/reference/docs-conceptual/PSScriptAnalyzer/Rules/DSCUseIdenticalMandatoryParametersForDSC.md +++ b/reference/docs-conceptual/PSScriptAnalyzer/Rules/DSCUseIdenticalMandatoryParametersForDSC.md @@ -1,6 +1,6 @@ --- -description: Use identical mandatory parameters for DSC Get/Test/Set TargetResource functions -ms.date: 06/28/2023 +description: Use identical mandatory parameters for DSC Get, Set, and Test TargetResource functions in a resource +ms.date: 06/03/2026 ms.topic: reference title: DSCUseIdenticalMandatoryParametersForDSC --- @@ -10,20 +10,19 @@ title: DSCUseIdenticalMandatoryParametersForDSC ## Description -For script based DSC resources, if a property is declared with attributes `Key` of `Required` in a -mof file, then is should be present as a mandatory parameter in the corresponding -`Get-TargetResource`, `Set-TargetResource` and `Test-TargetResource` functions. +This rule detects if MOF-based Desired State Configuration (DSC) resources have properties +declared with `Key` or `Required` attributes in a `.mof` file that aren't present as mandatory +parameters in the corresponding functions. These properties must be declared as mandatory +parameters in the `Get-TargetResource`, `Set-TargetResource`, and `Test-TargetResource` functions. -## How - -Make sure all the properties with `Key` and `Required` attributes have equivalent mandatory -parameters in the `Get/Set/Test` functions. +All properties with `Key` and `Required` attributes should have matching mandatory +parameters in the **Get**, **Set**, and **Test** functions. ## Example -Consider the following `mof` file. +Consider the following MOF schema file. -```powershell +```mof class WaitForAny : OMI_BaseResource { [key, Description("Name of Resource on remote machine")] @@ -34,7 +33,7 @@ class WaitForAny : OMI_BaseResource }; ``` -### Wrong +### Noncompliant ```powershell function Get-TargetResource @@ -74,7 +73,7 @@ function Test-TargetResource [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [String] - $Message, + $Message [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] @@ -84,7 +83,7 @@ function Test-TargetResource } ``` -### Correct +### Compliant ```powershell function Get-TargetResource diff --git a/reference/docs-conceptual/PSScriptAnalyzer/Rules/DSCUseIdenticalParametersForDSC.md b/reference/docs-conceptual/PSScriptAnalyzer/Rules/DSCUseIdenticalParametersForDSC.md index 8f8e98e..98e3e33 100644 --- a/reference/docs-conceptual/PSScriptAnalyzer/Rules/DSCUseIdenticalParametersForDSC.md +++ b/reference/docs-conceptual/PSScriptAnalyzer/Rules/DSCUseIdenticalParametersForDSC.md @@ -1,6 +1,6 @@ --- -description: Use Identical Parameters For DSC Test and Set Functions -ms.date: 06/28/2023 +description: Use identical parameters for DSC Get, Set, and Test TargetResource functions in a resource +ms.date: 06/03/2026 ms.topic: reference title: DSCUseIdenticalParametersForDSC --- @@ -10,16 +10,14 @@ title: DSCUseIdenticalParametersForDSC ## Description -The `Get-TargetResource`, `Test-TargetResource` and `Set-TargetResource` functions of DSC Resource -must have the same parameters. - -## How - -Correct the parameters for the functions in DSC resource. +This rule detects if the `Get-TargetResource`, `Set-TargetResource`, and `Test-TargetResource` +functions in a Desired State Configuration (DSC) resource all have identical parameters. If they +don't match, you'll need to update the function parameters to be consistent across all three +functions. ## Example -### Wrong +### Noncompliant ```powershell function Get-TargetResource @@ -61,7 +59,7 @@ function Test-TargetResource } ``` -### Correct +### Compliant ```powershell function Get-TargetResource diff --git a/reference/docs-conceptual/PSScriptAnalyzer/Rules/DSCUseVerboseMessageInDSCResource.md b/reference/docs-conceptual/PSScriptAnalyzer/Rules/DSCUseVerboseMessageInDSCResource.md index bb5abac..3fa9754 100644 --- a/reference/docs-conceptual/PSScriptAnalyzer/Rules/DSCUseVerboseMessageInDSCResource.md +++ b/reference/docs-conceptual/PSScriptAnalyzer/Rules/DSCUseVerboseMessageInDSCResource.md @@ -1,6 +1,6 @@ --- -description: Use verbose message in DSC resource -ms.date: 06/28/2023 +description: Use verbose message in DSC resources +ms.date: 06/03/2026 ms.topic: reference title: DSCUseVerboseMessageInDSCResource --- @@ -10,16 +10,14 @@ title: DSCUseVerboseMessageInDSCResource ## Description -Best practice recommends that additional user information is provided within commands, functions and -scripts using `Write-Verbose`. - -## How - -Make use of the `Write-Verbose` command. +This rule detects DSC resources that don't include `Write-Verbose` messages in their functions or +scripts. It's a best practice to provide additional user information within commands, functions, and +scripts using [Write-Verbose][01]. This helps users understand what's happening during execution. +You should include `Write-Verbose` messages to make your code more informative and easier to debug. ## Example -### Wrong +### Noncompliant ```powershell Function Test-Function @@ -30,7 +28,7 @@ Function Test-Function } ``` -### Correct +### Compliant ```powershell Function Test-Function @@ -41,3 +39,7 @@ Function Test-Function ... } ``` + + + +[01]: /powershell/module/microsoft.powershell.utility/write-verbose From b471075ef349b3efd2f724cb816eb4805258dd7f Mon Sep 17 00:00:00 2001 From: Xelu86 <103963494+Xelu86@users.noreply.github.com> Date: Mon, 8 Jun 2026 14:11:39 -0400 Subject: [PATCH 2/7] [Freshness] PSScriptAnalyzer Article Updates - Batch 8 (#409) * Freshness * Applied feedback * Applied feedback --- .../Rules/MisleadingBacktick.md | 26 +++++++++++++++--- .../Rules/MissingModuleManifestField.md | 27 ++++++++++--------- 2 files changed, 37 insertions(+), 16 deletions(-) diff --git a/reference/docs-conceptual/PSScriptAnalyzer/Rules/MisleadingBacktick.md b/reference/docs-conceptual/PSScriptAnalyzer/Rules/MisleadingBacktick.md index e140b8e..3ea4ebc 100644 --- a/reference/docs-conceptual/PSScriptAnalyzer/Rules/MisleadingBacktick.md +++ b/reference/docs-conceptual/PSScriptAnalyzer/Rules/MisleadingBacktick.md @@ -1,6 +1,6 @@ --- -description: Misleading Backtick -ms.date: 06/28/2023 +description: Misleading backtick +ms.date: 06/04/2026 ms.topic: reference title: MisleadingBacktick --- @@ -10,4 +10,24 @@ title: MisleadingBacktick ## Description -Checks that lines don't end with a backtick followed by whitespace. +This rule detects lines where a trailing backtick is followed by one or more whitespace characters. +A trailing backtick is used for line continuation only when it's the last character on the line. If +whitespace follows the backtick on the same line the continuation doesn't work as intended, which +can make the code look valid but behave unexpectedly. + +## Example + +### Noncompliant + +```powershell +# The line in this example ends with a backtick and trailing whitespace +Get-Process ` +| Where-Object CPU -gt 100 +``` + +### Compliant + +```powershell +Get-Process ` +| Where-Object CPU -gt 100 +``` diff --git a/reference/docs-conceptual/PSScriptAnalyzer/Rules/MissingModuleManifestField.md b/reference/docs-conceptual/PSScriptAnalyzer/Rules/MissingModuleManifestField.md index c19d534..436c783 100644 --- a/reference/docs-conceptual/PSScriptAnalyzer/Rules/MissingModuleManifestField.md +++ b/reference/docs-conceptual/PSScriptAnalyzer/Rules/MissingModuleManifestField.md @@ -1,6 +1,6 @@ --- -description: Module Manifest Fields -ms.date: 06/28/2023 +description: Module manifest fields +ms.date: 06/04/2026 ms.topic: reference title: MissingModuleManifestField --- @@ -10,23 +10,20 @@ title: MissingModuleManifestField ## Description -A module manifest is a `.psd1` file that contains a hash table. The keys and values in the hash -table describe the contents and attributes of the module, define the prerequisites, and determine -how the components are processed. +This rule detects when a module manifest is missing required fields. A module manifest is a `.psd1` +file that contains a hash table. The keys and values in the hash table describe the contents and +attributes of the module, define the prerequisites, and determine how the components are processed. -Module manifests must contain the following keys (and a corresponding value) to be considered valid: +A module manifest must contain the following key (and a corresponding value) to be considered valid: - `ModuleVersion` -All other keys are optional. The order of the entries is not important. - -## How - -Please consider adding the missing fields to the manifest. +All other keys are optional and the order you place them doesn't matter. To learn more, see +[about_Module_Manifests][01]. ## Example -### Wrong +### Noncompliant ```powershell @{ @@ -38,7 +35,7 @@ Please consider adding the missing fields to the manifest. } ``` -### Correct +### Compliant ```powershell @{ @@ -50,3 +47,7 @@ Please consider adding the missing fields to the manifest. VariablesToExport = '*' } ``` + + + +[01]: /powershell/module/microsoft.powershell.core/about/about_module_manifests From 79305774e2bc60fbb8a9bb831bf4fdaefaeafeea Mon Sep 17 00:00:00 2001 From: Xelu86 <103963494+Xelu86@users.noreply.github.com> Date: Mon, 8 Jun 2026 14:16:00 -0400 Subject: [PATCH 3/7] [Freshness] PSScriptAnalyzer Article Updates - Batch 9 (#411) * Freshness * Applied feedback + acrolinx * Applied feedback --- .../PSScriptAnalyzer/Rules/PlaceCloseBrace.md | 56 +++++--- .../PSScriptAnalyzer/Rules/PlaceOpenBrace.md | 53 +++++--- .../PossibleIncorrectComparisonWithNull.md | 71 +++++------ ...sibleIncorrectUsageOfAssignmentOperator.md | 56 ++++---- ...ibleIncorrectUsageOfRedirectionOperator.md | 20 +-- .../Rules/ProvideCommentHelp.md | 120 ++++++++++-------- 6 files changed, 220 insertions(+), 156 deletions(-) diff --git a/reference/docs-conceptual/PSScriptAnalyzer/Rules/PlaceCloseBrace.md b/reference/docs-conceptual/PSScriptAnalyzer/Rules/PlaceCloseBrace.md index 6e14acc..aa249b0 100644 --- a/reference/docs-conceptual/PSScriptAnalyzer/Rules/PlaceCloseBrace.md +++ b/reference/docs-conceptual/PSScriptAnalyzer/Rules/PlaceCloseBrace.md @@ -1,6 +1,6 @@ --- -description: Place close braces -ms.date: 06/28/2023 +description: Place close braces consistently +ms.date: 06/05/2026 ms.topic: reference title: PlaceCloseBrace --- @@ -10,10 +10,28 @@ title: PlaceCloseBrace ## Description -Close brace placement should follow a consistent style. It should be on a new line by itself and -should not be followed by an empty line. +This rule detects closing braces (`}`) that aren't placed on a new line by themselves or that are +followed by empty lines. Close brace placement should follow a consistent style. It should be on a +new line by itself and shouldn't be followed by an empty line. This rule is **disabled** by default. -**Note**: This rule is not enabled by default. The user needs to enable it through settings. +## Example + +### Noncompliant + +```powershell +if ($true) { + 'example' } +Get-Process +``` + +### Compliant + +```powershell +if ($true) { + 'example' +} +Get-Process +``` ## Configuration @@ -28,23 +46,27 @@ Rules = @{ } ``` -### Parameters +## Parameters -#### Enable: bool (Default value is `$false`) +### Enable -Enable or disable the rule during ScriptAnalyzer invocation. +This parameter controls whether ScriptAnalyzer checks the code against this rule. It accepts a +boolean value. To enable this rule, set this parameter to `$true`. The default value is `$false`. -#### NoEmptyLineBefore: bool (Default value is `$false`) +### NoEmptyLineBefore -Create violation if there is an empty line before a close brace. +This parameter controls whether ScriptAnalyzer checks the code for an empty line before a close +brace. It accepts a boolean value. To enable this check, set this parameter to `$true`. The default +value is `$false`. -#### IgnoreOneLineBlock: bool (Default value is `$true`) +### IgnoreOneLineBlock -Indicates if closed brace pairs in a one line block should be ignored or not. For example, -`$x = if ($true) { 'blah' } else { 'blah blah' }`, if the property is set to true then the rule -doesn't fire a violation. +This parameter controls whether ScriptAnalyzer skips one-line blocks when checking the code against +this rule. It accepts a boolean value. To disable skipping one-line blocks, set this parameter to +`$false`. The default value is `$true`. -#### NewLineAfter: bool (Default value is `$true`) +### NewLineAfter -Indicates if a new line should follow a close brace. If set to true a close brace should be followed -by a new line. +This parameter controls whether ScriptAnalyzer checks that a new line follows a closing brace. It +accepts a boolean value. To disable this check, set this parameter to `$false`. The default value is +`$true`. diff --git a/reference/docs-conceptual/PSScriptAnalyzer/Rules/PlaceOpenBrace.md b/reference/docs-conceptual/PSScriptAnalyzer/Rules/PlaceOpenBrace.md index a523ec4..9b74c57 100644 --- a/reference/docs-conceptual/PSScriptAnalyzer/Rules/PlaceOpenBrace.md +++ b/reference/docs-conceptual/PSScriptAnalyzer/Rules/PlaceOpenBrace.md @@ -1,6 +1,6 @@ --- description: Place open braces consistently -ms.date: 06/28/2023 +ms.date: 06/05/2026 ms.topic: reference title: PlaceOpenBrace --- @@ -10,10 +10,28 @@ title: PlaceOpenBrace ## Description -Open brace placement should follow a consistent style. It can either follow K&R style (on same line) -or the Allman style (not on same line). +This rule detects opening braces (`{`) that don't follow a consistent style. Opening braces can be +required on the same line as the preceding keyword or on the next line, based on configuration. You +can also require a new line after the opening brace. This rule is **disabled** by default. -**Note**: This rule is not enabled by default. The user needs to enable it through settings. +## Example + +### Noncompliant + +```powershell +if ($true) +{ + 'example' +} +``` + +### Compliant + +```powershell +if ($true) { + 'example' +} +``` ## Configuration @@ -28,22 +46,27 @@ Rules = @{ } ``` -### Parameters +## Parameters -#### Enable: bool (Default value is `$false`) +### Enable -Enable or disable the rule during ScriptAnalyzer invocation. +This parameter controls whether ScriptAnalyzer checks the code against this rule. It accepts a +boolean value. To enable this rule, set this parameter to `$true`. The default value is `$false`. -#### OnSameLine: bool (Default value is `$true`) +### OnSameLine -Enforce open brace to be on the same line as that of its preceding keyword. +This parameter controls whether ScriptAnalyzer checks that an open brace is on the same line as the +preceding keyword. It accepts a boolean value. To disable this check, set this parameter to +`$false`. The default value is `$true`. -#### NewLineAfter: bool (Default value is `$true`) +### NewLineAfter -Enforce a new line character after an open brace. The default value is true. +This parameter controls whether ScriptAnalyzer checks that a new line follows an opening brace. It +accepts a boolean value. To disable this check, set this parameter to `$false`. The default value is +`$true`. -#### IgnoreOneLineBlock: bool (Default value is `$true`) +### IgnoreOneLineBlock -Indicates if open braces in a one line block should be ignored or not. For example, -`$x = if ($true) { 'blah' } else { 'blah blah' }`, if the property is set to true then the rule -doesn't fire a violation. +This parameter controls whether ScriptAnalyzer skips one-line blocks when checking the code against +this rule. It accepts a boolean value. To disable skipping one-line blocks, set this parameter to +`$false`. The default value is `$true`. diff --git a/reference/docs-conceptual/PSScriptAnalyzer/Rules/PossibleIncorrectComparisonWithNull.md b/reference/docs-conceptual/PSScriptAnalyzer/Rules/PossibleIncorrectComparisonWithNull.md index 9a28646..8b0f375 100644 --- a/reference/docs-conceptual/PSScriptAnalyzer/Rules/PossibleIncorrectComparisonWithNull.md +++ b/reference/docs-conceptual/PSScriptAnalyzer/Rules/PossibleIncorrectComparisonWithNull.md @@ -1,6 +1,6 @@ --- -description: Null Comparison -ms.date: 12/03/2024 +description: Comparison with null +ms.date: 06/05/2026 ms.topic: reference title: PossibleIncorrectComparisonWithNull --- @@ -10,27 +10,53 @@ title: PossibleIncorrectComparisonWithNull ## Description -To ensure that PowerShell performs comparisons correctly, the `$null` element should be on the left +This rule detects comparisons where `$null` isn't on the left side of the comparison operator. To +ensure that PowerShell performs comparisons correctly, the `$null` element should be on the left side of the operator. -There are multiple reasons why this occurs: +There are multiple reasons why this placement matters: - `$null` is a scalar value. When the value on the left side of an operator is a scalar, comparison operators return a **Boolean** value. When the value is a collection, the comparison operators - return any matching values or an empty array if there are no matches in the collection. + return any matching values or an empty array if there aren't any matches in the collection. - PowerShell performs type casting on the right-hand operand, resulting in incorrect comparisons when `$null` is cast to other scalar types. The only way to reliably check if a value is `$null` is to place `$null` on the left side of the operator so that a scalar comparison is performed. -## How +### Comparison operator behavior -Move `$null` to the left side of the comparison. +The comparison operator works by design in the following way. + +```powershell +# This example returns 'false' because the comparison doesn't return any objects from the array +if (@() -eq $null) { 'true' } else { 'false' } + +# This example returns 'true' because the array is empty +if ($null -ne @()) { 'true' } else { 'false' } +``` + +This behavior can produce unexpected results, especially when you intend to perform a null check. + +The following example demonstrates how comparison operators behave when the left-hand side is a +collection. The operator compares each element in the collection to the right-hand side value and +returns only the matching elements from the collection. + +```powershell +PS> 1,2,3,1,2 -eq $null +PS> 1,2,3,1,2 -eq 1 +1 +1 +PS> (1,2,3,1,2 -eq $null).count +0 +PS> (1,2,$null,3,$null,1,2 -eq $null).count +2 +``` ## Example -### Wrong +### Noncompliant ```powershell function Test-CompareWithNull @@ -41,7 +67,7 @@ function Test-CompareWithNull } ``` -### Correct +### Compliant ```powershell function Test-CompareWithNull @@ -51,30 +77,3 @@ function Test-CompareWithNull } } ``` - -## Try it Yourself - -```powershell -# This example returns 'false' because the comparison does not return any objects from the array -if (@() -eq $null) { 'true' } else { 'false' } -# This example returns 'true' because the array is empty -if ($null -ne @()) { 'true' } else { 'false' } -``` - -This is how the comparison operator works by-design. But, as demonstrated, this can lead -to non-intuitive behavior, especially when the intent is simple test for null. - -The following example demonstrates the designed behavior of the comparison operator when the -left-hand side is a collection. Each element in the collection is compared to the right-hand side -value. When true, that element of the collection is returned. - -```powershell -PS> 1,2,3,1,2 -eq $null -PS> 1,2,3,1,2 -eq 1 -1 -1 -PS> (1,2,3,1,2 -eq $null).count -0 -PS> (1,2,$null,3,$null,1,2 -eq $null).count -2 -``` diff --git a/reference/docs-conceptual/PSScriptAnalyzer/Rules/PossibleIncorrectUsageOfAssignmentOperator.md b/reference/docs-conceptual/PSScriptAnalyzer/Rules/PossibleIncorrectUsageOfAssignmentOperator.md index 11c5d23..8408ac0 100644 --- a/reference/docs-conceptual/PSScriptAnalyzer/Rules/PossibleIncorrectUsageOfAssignmentOperator.md +++ b/reference/docs-conceptual/PSScriptAnalyzer/Rules/PossibleIncorrectUsageOfAssignmentOperator.md @@ -1,6 +1,6 @@ --- -description: Equal sign is not an assignment operator. Did you mean the equality operator \'-eq\'? -ms.date: 06/28/2023 +description: Use equality operator (==) instead of an equal sign (=) as an assignment operator +ms.date: 06/05/2026 ms.topic: reference title: PossibleIncorrectUsageOfAssignmentOperator --- @@ -10,17 +10,38 @@ title: PossibleIncorrectUsageOfAssignmentOperator ## Description -In many programming languages, the equality operator is denoted as `==` or `=`, but `PowerShell` -uses `-eq`. Therefore, it can easily happen that the wrong operator is used unintentionally. This -rule catches a few special cases where the likelihood of that is quite high. +This rule detects when conditional statements use `=` or `==` instead of the PowerShell equality +operator (`-eq`). The rule looks for usages of `==` and `=` operators inside `if`, `elseif`, +`while`, and `do-while` statements. In PowerShell, `=` represents the [assignment operator][01] and +`-eq` represents the [equality comparison operator][02]. -The rule looks for usages of `==` and `=` operators inside `if`, `else if`, `while` and `do-while` -statements but it does not warn if any kind of command or expression is used at the right hand side -as this is probably by design. +In many programming languages, `==` represents the equality comparison operator. When you define +`==` in a PowerShell expression, including conditional statements, PowerShell raises an error +because `==` isn't valid PowerShell syntax. This rule _always_ flags uses of `==` in conditional +statements. However, it doesn't flag uses of `=` when the right hand side of the conditional uses +any commands or expressions. + +In these cases, it's likely that the use of the assignment operator is intentional. This +construction is often used to concisely assign a value to the variable or property on the left hand +side _and_ check whether the assigned value evaluates as true. + +### Implicit suppression using Clang style + +There are some rare cases where assigning a variable inside an `if` statement is intentional. +Instead of suppressing the rule, you can signal that the assignment's intentional by wrapping the +expression in extra parentheses. An exception applies when `$null` is used on the left-hand side +because there's no use case for it. For example: + +```powershell +if (($shortVariableName = $SuperLongVariableName['SpecialItem']['AnotherItem'])) +{ + ... +} +``` ## Example -### Wrong +### Noncompliant ```powershell if ($a = $b) @@ -36,7 +57,7 @@ if ($a == $b) } ``` -### Correct +### Compliant ```powershell if ($a -eq $b) # Compare $a with $b @@ -52,16 +73,7 @@ if ($a = Get-Something) # Only execute action if command returns something and a } ``` -## Implicit suppression using Clang style - -There are some rare cases where assignment of variable inside an `if` statement is by design. -Instead of suppressing the rule, one can also signal that assignment was intentional by wrapping the -expression in extra parenthesis. An exception for this is when `$null` is used on the LHS because -there is no use case for this. + -```powershell -if (($shortVariableName = $SuperLongVariableName['SpecialItem']['AnotherItem'])) -{ - ... -} -``` +[01]: /powershell/module/microsoft.powershell.core/about/about_assignment_operators +[02]: /powershell/module/microsoft.powershell.core/about/about_comparison_operators#-eq-and--ne \ No newline at end of file diff --git a/reference/docs-conceptual/PSScriptAnalyzer/Rules/PossibleIncorrectUsageOfRedirectionOperator.md b/reference/docs-conceptual/PSScriptAnalyzer/Rules/PossibleIncorrectUsageOfRedirectionOperator.md index 871d134..7ceb152 100644 --- a/reference/docs-conceptual/PSScriptAnalyzer/Rules/PossibleIncorrectUsageOfRedirectionOperator.md +++ b/reference/docs-conceptual/PSScriptAnalyzer/Rules/PossibleIncorrectUsageOfRedirectionOperator.md @@ -1,6 +1,6 @@ --- -description: \'>\' is not a comparison operator. Use \'-gt\' (greater than) or \'-ge\' (greater or equal). -ms.date: 06/28/2023 +description: Use -gt or -ge comparison operators instead of redirection operators +ms.date: 06/05/2026 ms.topic: reference title: PossibleIncorrectUsageOfRedirectionOperator --- @@ -10,17 +10,17 @@ title: PossibleIncorrectUsageOfRedirectionOperator ## Description -In many programming languages, the comparison operator for 'greater than' is `>` but `PowerShell` -uses `-gt` for it and `-ge` (greater or equal) for `>=`. Therefore, it can easily happen that the -wrong operator is used unintentionally. This rule catches a few special cases where the likelihood -of that is quite high. +This rule detects the use of the sequences `>` and `>=` in conditional statements where comparison +operators are intended. This rule catches instances where `>` or `>=` appears inside `if`, `elseif`, +`while`, and `do-while` statements, which are almost always unintentional. -The rule looks for usages of `>` or `>=` operators inside `if`, `elseif`, `while` and `do-while` -statements because this is likely going to be unintentional usage. +In many programming languages, `>` is the comparison operator for _greater than_, but PowerShell +uses `-gt` (greater than) and `-ge` (greater or equal) instead. It's easy to accidentally use the +wrong operator, especially if you're familiar with other languages. ## Example -### Wrong +### Noncompliant ```powershell if ($a > $b) @@ -29,7 +29,7 @@ if ($a > $b) } ``` -### Correct +### Compliant ```powershell if ($a -gt $b) diff --git a/reference/docs-conceptual/PSScriptAnalyzer/Rules/ProvideCommentHelp.md b/reference/docs-conceptual/PSScriptAnalyzer/Rules/ProvideCommentHelp.md index b010295..f53c0e9 100644 --- a/reference/docs-conceptual/PSScriptAnalyzer/Rules/ProvideCommentHelp.md +++ b/reference/docs-conceptual/PSScriptAnalyzer/Rules/ProvideCommentHelp.md @@ -1,6 +1,6 @@ --- -description: Basic Comment Help -ms.date: 06/28/2023 +description: Basic comment help +ms.date: 06/05/2026 ms.topic: reference title: ProvideCommentHelp --- @@ -10,65 +10,20 @@ title: ProvideCommentHelp ## Description -Comment based help should be provided for all PowerShell commands. This test only checks for the -presence of comment based help and not on the validity or format. +This rule detects functions and cmdlets that don't have comment-based help. Every PowerShell command +should include comment-based help to document its purpose, parameters, and usage. PSScriptAnalyzer +checks for the presence of comment-based help but doesn't validate its content or format. -For assistance on comment based help, use the command `Get-Help about_comment_based_help` or the -following articles: +For assistance on comment-based help, use the command `Get-Help about_comment_based_help` or refer +to these resources: -- [Writing Comment-based Help][01] -- [Writing Help for PowerShell Cmdlets][02] +- [Writing comment-based help][01] +- [Writing help for PowerShell cmdlets][02] - [Create XML-based help using PlatyPS][03] -## Configuration - -```powershell -Rules = @{ - PSProvideCommentHelp = @{ - Enable = $true - ExportedOnly = $false - BlockComment = $true - VSCodeSnippetCorrection = $false - Placement = 'before' - } -} -``` - -### Parameters - -- `Enable`: **bool** (Default value is `$true`) - - Enable or disable the rule during ScriptAnalyzer invocation. - -- `ExportedOnly`: **bool** (Default value is `$true`) - - If enabled, throw violation only on functions/cmdlets that are exported using the - `Export-ModuleMember` cmdlet. - -- `BlockComment`: **bool** (Default value is `$true`) - - If enabled, returns comment help in block comment style (`<#...#>`). Otherwise returns - comment help in line comment style where each comment line starts with `#`. - -- `VSCodeSnippetCorrection`: **bool** (Default value is `$false`) - - If enabled, returns comment help in vscode snippet format. - -- `Placement`: **string** (Default value is `before`) - - Represents the position of comment help with respect to the function definition. - - Possible values are: - - - `before`: means the help is placed before the function definition - - `begin` means the help is placed at the beginning of the function definition body - - `end` means the help is places the end of the function definition body - - If any invalid value is given, the property defaults to `before`. - ## Example -### Wrong +### Noncompliant ```powershell function Get-File @@ -82,7 +37,7 @@ function Get-File } ``` -### Correct +### Compliant ```powershell <# @@ -118,7 +73,60 @@ function Get-File } ``` + +## Configuration + +```powershell +Rules = @{ + PSProvideCommentHelp = @{ + Enable = $true + ExportedOnly = $false + BlockComment = $true + VSCodeSnippetCorrection = $false + Placement = 'before' + } +} +``` + +## Parameters + +### Enable + +This parameter controls whether ScriptAnalyzer checks the code against this rule. It accepts a +boolean value. The default value is `$true`. + +### ExportedOnly + +This parameter controls whether violations are reported only for functions and cmdlets that are +exported using the `Export-ModuleMember` cmdlet. It accepts a boolean value. The default value +is `$true`. + +### BlockComment + +This parameter controls the style of comment help returned by the rule. It accepts a boolean +value. When set to `$true`, comment help is returned in block comment style (`<#...#>`). +When set to `$false`, comment help is returned in line comment style where each comment line +starts with `#`. The default value is `$true`. + +### VSCodeSnippetCorrection + +This parameter controls whether comment help is returned in Visual Studio Code snippet format. It +accepts a boolean value. The default value is `$false`. + +### Placement + +This parameter controls the position of comment help with respect to the function definition. It +accepts a string value. If any invalid value is given, the property defaults to `before`. The +default value is `before`. + +The possible values are: + +- `before`: The comment is placed before the function definition +- `begin`: The comment is placed at the beginning of the function definition body +- `end`: The comment is placed at the end of the function definition body + + [01]: /powershell/scripting/developer/help/writing-comment-based-help-topics [02]: /powershell/scripting/developer/help/writing-help-for-windows-powershell-cmdlets [03]: /powershell/utility-modules/platyps/create-help-using-platyps From ebdec36fc81aaf8327554f787306ebd569a396f7 Mon Sep 17 00:00:00 2001 From: Xelu86 <103963494+Xelu86@users.noreply.github.com> Date: Tue, 9 Jun 2026 11:40:13 -0400 Subject: [PATCH 4/7] [Freshness] PSScriptAnalyzer Article Updates - Batch 10 (#413) * Freshness * Minor edits * Applied feedback * Apply suggestions from review Co-authored-by: Mikey Lombardi (He/Him) --------- Co-authored-by: Mikey Lombardi (He/Him) --- .../Rules/ReservedCmdletChar.md | 44 +++++++++++---- .../PSScriptAnalyzer/Rules/ReservedParams.md | 20 +++---- .../Rules/ReviewUnusedParameter.md | 55 +++++++++---------- 3 files changed, 67 insertions(+), 52 deletions(-) diff --git a/reference/docs-conceptual/PSScriptAnalyzer/Rules/ReservedCmdletChar.md b/reference/docs-conceptual/PSScriptAnalyzer/Rules/ReservedCmdletChar.md index 55acfc7..9e781eb 100644 --- a/reference/docs-conceptual/PSScriptAnalyzer/Rules/ReservedCmdletChar.md +++ b/reference/docs-conceptual/PSScriptAnalyzer/Rules/ReservedCmdletChar.md @@ -1,6 +1,6 @@ --- -description: Reserved Cmdlet Chars -ms.date: 06/28/2023 +description: Reserved cmdlet characters +ms.date: 06/08/2026 ms.topic: reference title: ReservedCmdletChar --- @@ -10,25 +10,45 @@ title: ReservedCmdletChar ## Description -You cannot use following reserved characters in a function or cmdlet name as these can cause parsing -or runtime errors. - -Reserved Characters include: ``#,(){}[]&/\\$^;:\"'<>|?@`*%+=~`` - -## How - -Remove reserved characters from names. +This rule detects when reserved characters are used in function or cmdlet names. You can't use +reserved characters in a function or cmdlet name as they cause parsing or runtime errors. Remove +reserved characters from your names. + +Reserved characters include: + +| Character | Meaning | +|:---------:|:---------------------------------------------| +| `` ` `` | Escape character (backtick) | +| `$` | Variable expansion | +| `"` | String delimiter (allows variable expansion) | +| `'` | String delimiter (literal string) | +| `( )` | Grouping expressions / method calls | +| `{ }` | Script blocks / hash tables | +| `[ ]` | Type literals / array indexing | +| `,` | Array element separator | +| `;` | Statement separator | +| `&` | Call operator | +| `?` | Alias for Where-Object in some contexts | +| `*` | Wildcard | +| `< >` | Redirection operators | +| `@` | Array or hash table literal | +| `:` | Scope modifier / drive separator | +| `#` | Comment | +| `=` | Assignment operator | +| `+` | String concatenation operator | +| `~` | Expands to the value of the $HOME variable | +| `\|` | Pipe operator | ## Example -### Wrong +### Noncompliant ```powershell function MyFunction[1] {...} ``` -### Correct +### Compliant ```powershell function MyFunction diff --git a/reference/docs-conceptual/PSScriptAnalyzer/Rules/ReservedParams.md b/reference/docs-conceptual/PSScriptAnalyzer/Rules/ReservedParams.md index f0b6e5f..a892e6b 100644 --- a/reference/docs-conceptual/PSScriptAnalyzer/Rules/ReservedParams.md +++ b/reference/docs-conceptual/PSScriptAnalyzer/Rules/ReservedParams.md @@ -1,6 +1,6 @@ --- -description: Reserved Parameters -ms.date: 03/06/2024 +description: Reserved parameters +ms.date: 06/08/2026 ms.topic: reference title: ReservedParams --- @@ -10,17 +10,15 @@ title: ReservedParams ## Description -You can't redefine [common parameters][01] in an advanced function. Using the `CmdletBinding` or -`Parameter` attributes creates an advanced function. The common parameters are are automatically -available in advanced functions, so you can't redefine them. - -## How - -Change the name of the parameter. +This rule detects when you attempt to redefine [common parameters][01] in an advanced function. When +you use the `CmdletBinding` or `Parameter` attributes, you're creating an advanced function. Common +parameters are automatically available in advanced functions, so you can't redefine them. If you're +trying to use a parameter name that conflicts with a common parameter, you need to change the name +of your parameter to something else. ## Example -### Wrong +### Noncompliant ```powershell function Test @@ -34,7 +32,7 @@ function Test } ``` -### Correct +### Compliant ```powershell function Test diff --git a/reference/docs-conceptual/PSScriptAnalyzer/Rules/ReviewUnusedParameter.md b/reference/docs-conceptual/PSScriptAnalyzer/Rules/ReviewUnusedParameter.md index 4732b8a..abc5357 100644 --- a/reference/docs-conceptual/PSScriptAnalyzer/Rules/ReviewUnusedParameter.md +++ b/reference/docs-conceptual/PSScriptAnalyzer/Rules/ReviewUnusedParameter.md @@ -1,6 +1,6 @@ --- description: ReviewUnusedParameter -ms.date: 03/26/2024 +ms.date: 06/08/2026 ms.topic: reference title: ReviewUnusedParameter --- @@ -10,34 +10,13 @@ title: ReviewUnusedParameter ## Description -This rule identifies parameters declared in a script, scriptblock, or function scope that have not -been used in that scope. - -## Configuration settings - -By default, this rule doesn't consider child scopes other than scriptblocks provided to -`Where-Object` or `ForEach-Object`. The `CommandsToTraverse` setting is an string array allows you -to add additional commands that accept scriptblocks that this rule should examine. - -```powershell -@{ - Rules = @{ - PSReviewUnusedParameter = @{ - CommandsToTraverse = @( - 'Invoke-PSFProtectedCommand' - ) - } - } -} -``` - -## How - -Consider removing the unused parameter. +This rule detects parameters that are declared but not used a script, scriptblock, or function +scope. You should consider removing unused parameters to improve code clarity and reduce confusion +about your function's dependencies. ## Example -### Wrong +### Noncompliant ```powershell function Test-Parameter @@ -45,7 +24,7 @@ function Test-Parameter Param ( $Parameter1, - # this parameter is never called in the function + # This parameter is never called in the function $Parameter2 ) @@ -53,7 +32,7 @@ function Test-Parameter } ``` -### Correct +### Compliant ```powershell function Test-Parameter @@ -61,10 +40,28 @@ function Test-Parameter Param ( $Parameter1, - # now this parameter is being called in the same scope + # Now this parameter is being called in the same scope $Parameter2 ) Get-Something $Parameter1 $Parameter2 } ``` + +## Configure rule + +By default, this rule doesn't consider child scopes other than scriptblocks provided to either +`Where-Object` or `ForEach-Object`. The `CommandsToTraverse` setting is a string array that allows +you to add extra commands that accept scriptblocks that this rule should examine. + +```powershell +@{ + Rules = @{ + PSReviewUnusedParameter = @{ + CommandsToTraverse = @( + 'Invoke-PSFProtectedCommand' + ) + } + } +} +``` From c66c996ebab0856f90f91a0d58c0c2e13a2477a0 Mon Sep 17 00:00:00 2001 From: Xelu86 <103963494+Xelu86@users.noreply.github.com> Date: Tue, 9 Jun 2026 11:40:26 -0400 Subject: [PATCH 5/7] [Freshness] PSScriptAnalyzer Article Updates - Batch 11 (#414) * Freshness * Minor edit * Applied feedback * Acrolinx --- .../PSScriptAnalyzer/Rules/ShouldProcess.md | 33 ++++++------ .../Rules/UseApprovedVerbs.md | 26 +++++----- .../Rules/UseBOMForUnicodeEncodedFile.md | 46 ++++++++++------ .../Rules/UseCmdletCorrectly.md | 17 +++--- .../Rules/UseCompatibleCmdlets.md | 52 ++++++++++++------- 5 files changed, 101 insertions(+), 73 deletions(-) diff --git a/reference/docs-conceptual/PSScriptAnalyzer/Rules/ShouldProcess.md b/reference/docs-conceptual/PSScriptAnalyzer/Rules/ShouldProcess.md index 0bdb73d..cb79562 100644 --- a/reference/docs-conceptual/PSScriptAnalyzer/Rules/ShouldProcess.md +++ b/reference/docs-conceptual/PSScriptAnalyzer/Rules/ShouldProcess.md @@ -1,6 +1,6 @@ --- -description: Should Process -ms.date: 06/28/2023 +description: Pair ShouldProcess with SupportsShouldProcess +ms.date: 06/08/2026 ms.topic: reference title: ShouldProcess --- @@ -10,26 +10,27 @@ title: ShouldProcess ## Description -If a cmdlet declares the `SupportsShouldProcess` attribute, then it should also call -`ShouldProcess`. A violation is any function which either declares `SupportsShouldProcess` attribute -but makes no calls to `ShouldProcess` or it calls `ShouldProcess` but does not declare -`SupportsShouldProcess`. +This rule detects mismatches between `SupportsShouldProcess` declarations and `ShouldProcess` calls. +When a cmdlet declares the `SupportsShouldProcess` attribute, it should also call the +`ShouldProcess` method. -For more information, see the following articles: +Violations occur when: + +- A function declares `SupportsShouldProcess` but doesn't call `ShouldProcess` +- A function calls `ShouldProcess` but doesn't declare `SupportsShouldProcess` + +To fix this violation, ensure that `ShouldProcess` calls are paired with the `SupportsShouldProcess` +attribute declaration. + +To learn more, see the following articles: - [about_Functions_Advanced_Methods][01] - [about_Functions_CmdletBindingAttribute][02] - [Everything you wanted to know about ShouldProcess][03] -## How - -To fix a violation of this rule, please call `ShouldProcess` method when a cmdlet declares -`SupportsShouldProcess` attribute. Or please add `SupportsShouldProcess` attribute argument when -calling `ShouldProcess`. - ## Example -### Wrong +### Noncompliant ```powershell function Set-File @@ -45,7 +46,7 @@ function Set-File } ``` -### Correct +### Compliant ```powershell function Set-File @@ -72,7 +73,9 @@ function Set-File } } ``` + + [01]: /powershell/module/microsoft.powershell.core/about/about_functions_advanced_methods [02]: /powershell/module/microsoft.powershell.core/about/about_Functions_CmdletBindingAttribute [03]: /powershell/scripting/learn/deep-dives/everything-about-shouldprocess diff --git a/reference/docs-conceptual/PSScriptAnalyzer/Rules/UseApprovedVerbs.md b/reference/docs-conceptual/PSScriptAnalyzer/Rules/UseApprovedVerbs.md index c1bcaa0..436db23 100644 --- a/reference/docs-conceptual/PSScriptAnalyzer/Rules/UseApprovedVerbs.md +++ b/reference/docs-conceptual/PSScriptAnalyzer/Rules/UseApprovedVerbs.md @@ -1,6 +1,6 @@ --- -description: Cmdlet Verbs -ms.date: 03/26/2024 +description: Approved cmdlet verbs +ms.date: 06/08/2026 ms.topic: reference title: UseApprovedVerbs --- @@ -10,22 +10,19 @@ title: UseApprovedVerbs ## Description -All cmdlets must used approved verbs. +This rule detects cmdlets that use unapproved verbs in their names. All cmdlets must use approved +verbs. You can find approved verbs by running the `Get-Verb` command. If your cmdlet uses an +unapproved verb, change it to an approved alternative. -Approved verbs can be found by running the command `Get-Verb`. +Some unapproved verbs are documented on the approved verbs page with suggested alternatives. Try +searching for the verb you're using to find its approved form. For example, `Read`, `Open`, or +`Search` should be replaced with `Get`. -For a more information about approved verbs, see [Approved Verbs for PowerShell Commands][01]. Some -unapproved verbs are documented on the approved verbs page and point to approved alternatives. Try -searching for the verb you used to find its approved form. For example, searching for `Read`, -`Open`, or `Search` leads you to `Get`. - -## How - -Change the verb in the cmdlet's name to an approved verb. +To learn more, see [Approved Verbs for PowerShell Commands][01]. ## Example -### Wrong +### Noncompliant ```powershell function Change-Item @@ -34,7 +31,7 @@ function Change-Item } ``` -### Correct +### Compliant ```powershell function Update-Item @@ -44,4 +41,5 @@ function Update-Item ``` + [01]: /powershell/scripting/developer/cmdlet/approved-verbs-for-windows-powershell-commands diff --git a/reference/docs-conceptual/PSScriptAnalyzer/Rules/UseBOMForUnicodeEncodedFile.md b/reference/docs-conceptual/PSScriptAnalyzer/Rules/UseBOMForUnicodeEncodedFile.md index 9e03959..01e6c15 100644 --- a/reference/docs-conceptual/PSScriptAnalyzer/Rules/UseBOMForUnicodeEncodedFile.md +++ b/reference/docs-conceptual/PSScriptAnalyzer/Rules/UseBOMForUnicodeEncodedFile.md @@ -1,6 +1,6 @@ --- description: Use BOM encoding for non-ASCII files -ms.date: 01/07/2025 +ms.date: 06/08/2026 ms.topic: reference title: UseBOMForUnicodeEncodedFile --- @@ -10,17 +10,18 @@ title: UseBOMForUnicodeEncodedFile ## Description -For a file encoded with a format other than ASCII, ensure Byte Order Mark (BOM) is present to ensure -that any application consuming this file can interpret it correctly. +This rule detects files that are encoded with Unicode or other non-ASCII formats but don't include a +Byte Order Mark (BOM). -You can use this rule to test any arbitrary text file, but the intent is to ensure that PowerShell -scripts are saved with a BOM when using a Unicode encoding. +When you save files with Unicode encoding, it's important to include a BOM so that applications can +properly interpret the file's encoding. This rule helps ensure that your PowerShell scripts and +other text files are saved with the appropriate BOM when using Unicode or similar non-ASCII +encodings. -## How +### Using the Encoding parameter -For PowerShell commands that write to files, ensure that you set the encoding parameter to a value -that produces a BOM. In PowerShell 7 and higher, the following values of the **Encoding** parameter -produce a BOM: +When you use PowerShell commands that write to files, set the **Encoding** parameter to a value that +produces a BOM. In PowerShell 7 and later, these encoding values produce a BOM: - `bigendianunicode` - `bigendianutf32` @@ -29,14 +30,27 @@ produce a BOM: - `utf32` - `utf8BOM` -When you create a script file using a text editor, ensure that the editor is configured to save the -file with a BOM. Consult the documentation for your text editor for instructions on how to save -files with a BOM. +When you create a script file using a text editor, configure the editor to save the file with a BOM. +Consult your editor's documentation for instructions on how to save files with a BOM. -## Further reading +## Example -For more information, see the following articles: +### Noncompliant + +```powershell +# Writes non-ASCII text without a BOM. +Set-Content -Path .\script.ps1 -Value "Write-Output 'café'" -Encoding utf8NoBOM +``` + +### Compliant + +```powershell +# Writes non-ASCII text with a BOM. +Set-Content -Path .\script.ps1 -Value "Write-Output 'café'" -Encoding utf8BOM +``` + +## See also - [about_Character_Encoding](/powershell/module/microsoft.powershell.core/about/about_character_encoding) -- [Set-Content](xref:Microsoft.PowerShell.Management.Set-Content) -- [Understanding file encoding in VS Code and PowerShell](/powershell/scripting/dev-cross-plat/vscode/understanding-file-encoding) +- [Set-Content](/powershell/module/microsoft.powershell.management/set-content) +- [Understanding file encoding in Visual Studio Code and PowerShell](/powershell/scripting/dev-cross-plat/vscode/understanding-file-encoding) diff --git a/reference/docs-conceptual/PSScriptAnalyzer/Rules/UseCmdletCorrectly.md b/reference/docs-conceptual/PSScriptAnalyzer/Rules/UseCmdletCorrectly.md index 81ec42e..ddc24f5 100644 --- a/reference/docs-conceptual/PSScriptAnalyzer/Rules/UseCmdletCorrectly.md +++ b/reference/docs-conceptual/PSScriptAnalyzer/Rules/UseCmdletCorrectly.md @@ -1,6 +1,6 @@ --- -description: Use Cmdlet Correctly -ms.date: 06/28/2023 +description: Use cmdlets correctly +ms.date: 06/08/2026 ms.topic: reference title: UseCmdletCorrectly --- @@ -10,16 +10,13 @@ title: UseCmdletCorrectly ## Description -Whenever we call a command, care should be taken that it is invoked with the correct syntax and -parameters. - -## How - -Specify all mandatory parameters when calling commands. +This rule detects commands that are invoked without their required mandatory parameters. When you +call a command, it must be invoked with the correct syntax and all mandatory parameters specified. +Missing required parameters can cause commands to fail or behave unexpectedly. ## Example -### Wrong +### Noncompliant ```powershell Function Set-TodaysDate () @@ -29,7 +26,7 @@ Function Set-TodaysDate () } ``` -### Correct +### Compliant ```powershell Function Set-TodaysDate () diff --git a/reference/docs-conceptual/PSScriptAnalyzer/Rules/UseCompatibleCmdlets.md b/reference/docs-conceptual/PSScriptAnalyzer/Rules/UseCompatibleCmdlets.md index 4cd5234..7675bcd 100644 --- a/reference/docs-conceptual/PSScriptAnalyzer/Rules/UseCompatibleCmdlets.md +++ b/reference/docs-conceptual/PSScriptAnalyzer/Rules/UseCompatibleCmdlets.md @@ -1,6 +1,6 @@ --- description: Use compatible cmdlets -ms.date: 12/12/2024 +ms.date: 06/08/2026 ms.topic: reference title: UseCompatibleCmdlets --- @@ -10,41 +10,57 @@ title: UseCompatibleCmdlets ## Description -This rule flags cmdlets that aren't available in a given Edition and Version of PowerShell on a -given Operating System. It works by comparing a cmdlet against a set of allowlists which ship with -PSScriptAnalyzer. They can be found at `/path/to/PSScriptAnalyzerModule/Settings`. These files are -of the form, `--.json` where `` can be either `Core` or -`Desktop`, `` can be either `Windows`, `Linux` or `MacOS`, and `` is the PowerShell -version. To enable the rule to check if your script is compatible on PowerShell Core on windows, put -the following your settings file: +This rule detects cmdlets that aren't available for the PowerShell edition, version, and operating +system you target. The rule compares each cmdlet in your script against a compatibility allow list +that ships with PSScriptAnalyzer. These files are in the following location: +`/path/to/PSScriptAnalyzerModule/Settings`. + +Each file uses this naming format: + +`--.json` + +Where: + +- `` is `Core` or `Desktop` +- `` is the PowerShell version +- `` is `Windows`, `Linux`, `Linux-Arm`, or `MacOS` + +## Example + +To check whether your script is compatible with PowerShell Core 6.1 on Windows, add this +configuration: ```powershell @{ 'Rules' = @{ 'PSUseCompatibleCmdlets' = @{ - 'compatibility' = @('core-6.1.0-windows') + 'Compatibility' = @('core-6.1.0-windows') } } } ``` -The parameter `compatibility` is a list that contain any of the following +The **Compatibility** parameter accepts a list of one or more target identifiers, such as: - desktop-2.0-windows - desktop-3.0-windows -- desktop-4.0-windows (taken from Windows Server 2012R2) +- desktop-4.0-windows (taken from Windows Server 2012 R2) - desktop-5.1.14393.206-windows -- core-6.1.0-windows (taken from Windows 10 - 1803) +- core-6.1.0-windows (taken from Windows 10, version 1803) - core-6.1.0-linux (taken from Ubuntu 18.04) - core-6.1.0-linux-arm (taken from Raspbian) - core-6.1.0-macos -Usually, patched versions of PowerShell have the same cmdlet data, therefore only settings of major -and minor versions of PowerShell are supplied. You can also create a custom settings file with the -[New-CommandDataFile.ps1][01] script. Place the created `.json` file in the `Settings` folder of the -`PSScriptAnalyzer` module folder. Then the `compatibility` parameter values is just the filename. -Note that the `core-6.0.2-*` files were removed in PSScriptAnalyzer 1.18 since PowerShell 6.0 -reached it's end of life. +Patched PowerShell versions usually have the same cmdlet data, so this rule mainly ships major and +minor version profiles. + +You can also create a custom profile with [New-CommandDataFile.ps1][01]. Place the generated JSON +file in the `Settings` folder of the `PSScriptAnalyzer` module. Then you can reference that file by +name under `Compatibility`. + +The `core-6.0.2-*` files were removed in PSScriptAnalyzer 1.18 because PowerShell 6.0 reached its +end of life. + [01]: https://github.com/PowerShell/PSScriptAnalyzer/blob/main/Utils/New-CommandDataFile.ps1 From 0a2d7596ed8bdd56da3856433ccf0c088a9d5147 Mon Sep 17 00:00:00 2001 From: Xelu86 <103963494+Xelu86@users.noreply.github.com> Date: Thu, 11 Jun 2026 11:59:36 -0400 Subject: [PATCH 6/7] [Freshness] PSScriptAnalyzer Article Updates - Batch 12 (#415) * Freshness * Applied feedback * Applied feedback --- .../Rules/UseCompatibleCommands.md | 112 +++++++++++------ .../Rules/UseCompatibleSyntax.md | 50 +++++++- .../Rules/UseCompatibleTypes.md | 114 ++++++++++++------ .../Rules/UseConsistentIndentation.md | 78 +++++++++--- .../Rules/UseConsistentParameterSetName.md | 56 ++++----- 5 files changed, 284 insertions(+), 126 deletions(-) diff --git a/reference/docs-conceptual/PSScriptAnalyzer/Rules/UseCompatibleCommands.md b/reference/docs-conceptual/PSScriptAnalyzer/Rules/UseCompatibleCommands.md index ae74862..229187d 100644 --- a/reference/docs-conceptual/PSScriptAnalyzer/Rules/UseCompatibleCommands.md +++ b/reference/docs-conceptual/PSScriptAnalyzer/Rules/UseCompatibleCommands.md @@ -1,6 +1,6 @@ --- description: Use compatible commands -ms.date: 12/12/2024 +ms.date: 06/09/2026 ms.topic: reference title: UseCompatibleCommands --- @@ -10,9 +10,9 @@ title: UseCompatibleCommands ## Description -This rule identifies commands that are not available on a targeted PowerShell platform. +This rule detects commands that aren't available on your targeted PowerShell platform. -A PowerShell platform is identified by a name in the following format: +A name in the PowerShell platform is identified in the following format: ``` ______ @@ -20,12 +20,11 @@ A PowerShell platform is identified by a name in the following format: Where: -- ``: The name of the operating system PowerShell is running on. - On Windows, this includes the SKU number. - On Linux, this is the name of the distribution. -- ``: The machine architecture the operating system is running on (this is usually `x64`). -- ``: The self-reported version of the operating system (on Linux, this is the - distribution version). +- ``: The name of the operating system PowerShell is running on. On Windows, the SKU number + is included. On Linux, the value is the name of the distribution. +- ``: The machine architecture the operating system is running on (usually `x64`). +- ``: The self-reported version of the operating system (the distribution version on + Linux). - ``: The PowerShell version (from `$PSVersionTable.PSVersion`). - ``: The machine architecture of the PowerShell process. - ``: The reported version of the .NET runtime PowerShell is running on (from @@ -41,8 +40,8 @@ For example: operating system. - `ubuntu_x64_18.04_6.2.0_x64_4.0.30319.42000_core` is PowerShell 6.2.0 running on Ubuntu 18.04. -Some platforms come bundled with PSScriptAnalyzer as JSON files, named in this way for targeting in -your configuration. +PSScriptAnalyzer includes some platform profiles as JSON files. You can target these built-in +profiles directly in your configuration. Platforms bundled by default are: @@ -64,37 +63,53 @@ Platforms bundled by default are: Other profiles can be found in the [GitHub repo][02]. -You can also generate your own platform profile using the [PSCompatibilityCollector module][01]. +You can also generate your own platform profile with the [PSCompatibilityCollector module][01]. -The compatibility profile settings takes a list of platforms to target under `TargetProfiles`. A -platform can be specified as: +Compatibility settings take a list of platforms under `TargetProfiles`. You can specify each target +platform as: -- A platform name (like `ubuntu_x64_18.04_6.1.1_x64_4.0.30319.42000_core`), which will have `.json` - added to the end and is searched for in the default profile directory. -- A filename (like `my_custom_platform.json`), which will be searched for the in the default profile - directory. +- A platform name (for example, `ubuntu_x64_18.04_6.1.1_x64_4.0.30319.42000_core`). + PSScriptAnalyzer appends `.json` and searches for it in the default profile directory. +- A filename (for example, `my_custom_platform.json`), which PSScriptAnalyzer searches for in the + default profile directory. - An absolute path to a file (like `D:\PowerShellProfiles\TargetMachine.json`). -The default profile directory is under the PSScriptAnalzyer module at +The default profile directory is under the PSScriptAnalyzer module at `$PSScriptRoot/compatibility_profiles` (where `$PSScriptRoot` here refers to the directory containing `PSScriptAnalyzer.psd1`). -The compatibility analysis compares a command used to both a target profile and a 'union' profile -(containing all commands available in _any_ profile in the profile dir). If a command is not present -in the union profile, it is assumed to be locally created and ignored. Otherwise, if a command is -present in the union profile but not present in a target, it is deemed to be incompatible with that -target. +The compatibility analysis compares each command you use against both a target profile and a union +profile. The union profile contains every command available in any profile in the profile +directory. -## Configuration settings +If a command isn't in the union profile, the rule assumes it's local to your environment and ignores +it. If a command is in the union profile but missing from a target profile, the rule flags it as +incompatible with that target. -| Configuration key | Meaning | Accepted values | Mandatory | Example | -| ----------------- | -------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------- | -| `Enable` | Activates the rule | bool (`$true`/`$false`) | No (default: `$false`) | `$true` | -| `TargetProfiles` | The list of PowerShell profiles to target | string[]: absolute paths to profile files or names of profiles in the profile directory | No (default: `@()`) | `@('ubuntu_x64_18.04_6.1.3_x64_4.0.30319.42000_core', 'win-48_x64_10.0.17763.0_5.1.17763.316_x64_4.0.30319.42000_framework')` | -| `ProfileDirPath` | The location to search for profiles by name and use for union profile generation | string: absolute path to new profile dir | No (defaults to `compatibility_profiles` directory in PSScriptAnalyzer module | `C:\Users\me\Documents\pssaCompatProfiles` | -| `IgnoreCommands` | Commands to ignore compatibility of in scripts | string[]: names of commands to ignore | No (default: `@()`) | `@('Get-ChildItem','Import-Module')` | +## Example -An example configuration might look like: +The following examples assume `TargetProfiles` includes +`ubuntu_x64_18.04_6.2.4_x64_4.0.30319.42000_core` (Ubuntu 18.04, PowerShell 6.2). + +### Noncompliant + +```powershell +function Get-OsInfo { + $os = Get-WmiObject -Class Win32_OperatingSystem + return $os.Caption +} +``` + +### Compliant + +```powershell +function Get-OsInfo { + $os = Get-CimInstance -ClassName Win32_OperatingSystem + return $os.Caption +} +``` + +## Configure rule ```powershell @{ @@ -119,27 +134,52 @@ An example configuration might look like: ## Suppression -Command compatibility diagnostics can be suppressed with an attribute on the `param` block of a -scriptblock as with other rules. +As with other rules, you can suppress command compatibility diagnostics by adding a suppression +attribute to the `param` block of a scriptblock. ```powershell [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseCompatibleCommands', '')] ``` -The rule can also be suppressed only for particular commands: +You can also suppress the rule for specific commands: ```powershell [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseCompatibleCommands', 'Start-Service')] ``` -And also suppressed only for parameters: +You can also suppress it for specific parameters: ```powershell [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseCompatibleCommands', 'Import-Module/FullyQualifiedName')] ``` +## Parameters + +### Enable + +This parameter controls whether ScriptAnalyzer checks the code against this rule. It accepts a +boolean value. To enable this rule, set this parameter to `$true`. The default value is `$false`. + +### TargetProfiles + +This parameter specifies the list of platform profiles to check compatibility against. It accepts +an array of strings. Each value can be a platform name, a filename, or an absolute path to a +profile file. The default value is `@()`. + +### ProfileDirPath + +This parameter controls the directory that ScriptAnalyzer searches for profiles by name and uses +to generate the union profile. It accepts a string containing an absolute path. The default +location is the `compatibility_profiles` directory in the PSScriptAnalyzer module. + +### IgnoreCommands + +This parameter specifies commands to exclude from compatibility checks. It accepts an array of +command-name strings. The default value is `@()`. + + [01]: https://github.com/PowerShell/PSScriptAnalyzer/tree/main/PSCompatibilityCollector [02]: https://github.com/PowerShell/PSScriptAnalyzer/tree/main/PSCompatibilityCollector/optional_profiles diff --git a/reference/docs-conceptual/PSScriptAnalyzer/Rules/UseCompatibleSyntax.md b/reference/docs-conceptual/PSScriptAnalyzer/Rules/UseCompatibleSyntax.md index a2adbbb..aa1f245 100644 --- a/reference/docs-conceptual/PSScriptAnalyzer/Rules/UseCompatibleSyntax.md +++ b/reference/docs-conceptual/PSScriptAnalyzer/Rules/UseCompatibleSyntax.md @@ -1,6 +1,6 @@ --- description: Use compatible syntax -ms.date: 06/28/2023 +ms.date: 06/09/2026 ms.topic: reference title: UseCompatibleSyntax --- @@ -10,10 +10,39 @@ title: UseCompatibleSyntax ## Description -This rule identifies syntax elements that are incompatible with targeted PowerShell versions. +This rule detects syntax elements that aren't compatible with your specified PowerShell target +versions. When you run this rule from PowerShell 3 or 4, it can't detect syntax that's incompatible +with those versions because those versions can't parse newer syntax constructs. -It cannot identify syntax elements incompatible with PowerShell 3 or 4 when run from those -PowerShell versions because they aren't able to parse the incompatible syntaxes. +## Example + +### Noncompliant + +The following example uses PowerShell 7 syntax. If `TargetVersions` includes `5.1` or earlier, this +rule flags these statements. + +```powershell +$message = $IsReady ? 'Ready' : 'Not ready' +$displayName = $name ?? 'Unknown' +``` + +### Compliant + +```powershell +if ($IsReady) { + $message = 'Ready' +} else { + $message = 'Not ready' +} + +if ($name -ne $null) { + $displayName = $name +} else { + $displayName = 'Unknown' +} +``` + +## Configure rule ```powershell @{ @@ -29,3 +58,16 @@ PowerShell versions because they aren't able to parse the incompatible syntaxes. } } ``` + +## Parameters + +### Enable + +This parameter controls whether ScriptAnalyzer checks the code against this rule. It accepts a +boolean value. To enable this rule, set this parameter to `$true`. The default value is `$false`. + +### TargetVersions + +This parameter specifies the PowerShell versions your code must be compatible with. It accepts an +array of version strings, such as `'7.0'`, `'5.1'`, or `'4.0'`. ScriptAnalyzer flags syntax that's +not supported in any version you target. diff --git a/reference/docs-conceptual/PSScriptAnalyzer/Rules/UseCompatibleTypes.md b/reference/docs-conceptual/PSScriptAnalyzer/Rules/UseCompatibleTypes.md index 9bff5fa..8b9a633 100644 --- a/reference/docs-conceptual/PSScriptAnalyzer/Rules/UseCompatibleTypes.md +++ b/reference/docs-conceptual/PSScriptAnalyzer/Rules/UseCompatibleTypes.md @@ -1,6 +1,6 @@ --- description: Use compatible types -ms.date: 12/12/2024 +ms.date: 06/09/2026 ms.topic: reference title: UseCompatibleTypes --- @@ -10,10 +10,9 @@ title: UseCompatibleTypes ## Description -This rule identifies types that are not available (loaded by default) in targeted PowerShell -platforms. +This rule detects types that aren't available by default on your targeted PowerShell platforms. -A PowerShell platform is identified by a name in the following format: +A name in the PowerShell platform is identified in the following format: ``` ______ @@ -21,12 +20,11 @@ A PowerShell platform is identified by a name in the following format: Where: -- ``: The name of the operating system PowerShell is running on. - On Windows, this includes the SKU number. - On Linux, this is the name of the distribution. -- ``: The machine architecture the operating system is running on (this is usually `x64`). -- ``: The self-reported version of the operating system (on Linux, this is the - distribution version). +- ``: The name of the operating system PowerShell is running on. On Windows, the SKU number + is included. On Linux, the value is the name of the distribution. +- ``: The machine architecture the operating system is running on (usually `x64`). +- ``: The self-reported version of the operating system (the distribution version on + Linux). - ``: The PowerShell version (from `$PSVersionTable.PSVersion`). - ``: The machine architecture of the PowerShell process. - ``: The reported version of the .NET runtime PowerShell is running on (from @@ -42,8 +40,8 @@ For example: operating system. - `ubuntu_x64_18.04_6.2.0_x64_4.0.30319.42000_core` is PowerShell 6.2.0 running on Ubuntu 18.04. -Some platforms come bundled with PSScriptAnalyzer as JSON files, named in this way for targeting in -your configuration. +PSScriptAnalyzer includes some platform profiles as JSON files. You can target these built-in +profiles directly in your configuration. Platforms bundled by default are: @@ -65,34 +63,53 @@ Platforms bundled by default are: Other profiles can be found in the [GitHub repo][02]. -You can also generate your own platform profile using the [PSCompatibilityCollector module][01]. +You can also generate your own platform profile with the [PSCompatibilityCollector module][01]. -The compatibility profile settings takes a list of platforms to target under `TargetProfiles`. A -platform can be specified as: +Compatibility settings take a list of platforms under `TargetProfiles`. You can specify each target +platform as: -- A platform name (like `ubuntu_x64_18.04_6.1.1_x64_4.0.30319.42000_core`), which will have `.json` - added to the end and is searched for in the default profile directory. -- A filename (like `my_custom_platform.json`), which will be searched for the in the default profile - directory. +- A platform name (for example, `ubuntu_x64_18.04_6.1.1_x64_4.0.30319.42000_core`). + PSScriptAnalyzer appends `.json` and searches for it in the default profile directory. +- A filename (for example, `my_custom_platform.json`), which PSScriptAnalyzer searches for in the + default profile directory. - An absolute path to a file (like `D:\PowerShellProfiles\TargetMachine.json`). -The default profile directory is under the PSScriptAnalzyer module at +The default profile directory is under the PSScriptAnalyzer module at `$PSScriptRoot/PSCompatibilityCollector/profiles` (where `$PSScriptRoot` here refers to the directory containing `PSScriptAnalyzer.psd1`). -The compatibility analysis compares a type used to both a target profile and a 'union' profile -(containing all types available in _any_ profile in the profile dir). If a type is not present in -the union profile, it is assumed to be locally created and ignored. Otherwise, if a type is present -in the union profile but not present in a target, it is deemed to be incompatible with that target. +The compatibility analysis compares each type you use against both a target profile and a union +profile. The union profile contains every type available in any profile in the profile directory. -## Configuration settings +If a type isn't in the union profile, the rule assumes it's local to your environment and ignores +it. If a type is in the union profile but missing from a target profile, the rule flags it as +incompatible with that target. -| Configuration key | Meaning | Accepted values | Mandatory | Example | -| ----------------- | -------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------- | -| `Enable` | Activates the rule | bool (`$true`/`$false`) | No (default: `$false`) | `$true` | -| `TargetProfiles` | The list of PowerShell profiles to target | string[]: absolute paths to profile files or names of profiles in the profile directory | No (default: `@()`) | `@('ubuntu_x64_18.04_6.1.3_x64_4.0.30319.42000_core', 'win-48_x64_10.0.17763.0_5.1.17763.316_x64_4.0.30319.42000_framework')` | -| `ProfileDirPath` | The location to search for profiles by name and use for union profile generation | string: absolute path to new profile dir | No (defaults to `compatibility_profiles` directory in PSScriptAnalyzer module | `C:\Users\me\Documents\pssaCompatProfiles` | -| `IgnoreTypes` | Full names of types or type accelerators to ignore compatibility of in scripts | string[]: names of types to ignore | No (default: `@()`) | `@('System.Collections.ArrayList','string')` | +## Example + +The following examples assume `TargetProfiles` includes +`win-48_x64_10.0.17763.0_5.1.17763.316_x64_4.0.30319.42000_framework` (Windows 10 Pro, +PowerShell 5.1). + +### Noncompliant + +`System.Management.Automation.SemanticVersion` isn't available by default in Windows PowerShell +5.1, so the rule flags this type usage for that target profile. + +```powershell +$version = [System.Management.Automation.SemanticVersion]'1.2.3' +``` + +### Compliant + +`System.Version` is available in Windows PowerShell 5.1 and PowerShell 7, so it passes +compatibility checks across those targets. + +```powershell +$version = [System.Version]'1.2.3.0' +``` + +## Configure rule An example configuration might look like: @@ -139,27 +156,52 @@ PSUseCompatibleTypes Warning 1 The type 'System.Managemen ## Suppression -Command compatibility diagnostics can be suppressed with an attribute on the `param` block of a -scriptblock as with other rules. +As with other rules, you can suppress type compatibility diagnostics by adding a suppression +attribute to the `param` block of a scriptblock. ```powershell [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseCompatibleTypes', '')] ``` -The rule can also be suppressed only for particular types: +You can also suppress the rule for specific types: ```powershell [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseCompatibleTypes', 'System.Management.Automation.Security.SystemPolicy')] ``` -And also suppressed only for type members: +You can also suppress it for specific type members: ```powershell -[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseCompatibleCommands', +[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseCompatibleTypes', 'System.Management.Automation.LanguagePrimitives/ConvertTypeNameToPSTypeName')] ``` +## Parameters + +### Enable + +This parameter controls whether ScriptAnalyzer checks the code against this rule. It accepts a +boolean value. To enable this rule, set this parameter to `$true`. The default value is `$false`. + +### TargetProfiles + +This parameter specifies the list of platform profiles to check compatibility against. It accepts an +array of strings. Each value can be a platform name, a filename, or an absolute path to a profile +file. The default value is `@()`. + +### ProfileDirPath + +This parameter controls the directory that ScriptAnalyzer searches for profiles by name and uses to +generate the union profile. It accepts a string containing an absolute path. The default location is +the `compatibility_profiles` directory in the PSScriptAnalyzer module. + +### IgnoreTypes + +This parameter specifies the full names of types or type accelerators to exclude from compatibility +checks. It accepts an array of type-name strings. The default value is `@()`. + + [01]: https://github.com/PowerShell/PSScriptAnalyzer/tree/main/PSCompatibilityCollector [02]: https://github.com/PowerShell/PSScriptAnalyzer/tree/main/PSCompatibilityCollector/optional_profiles diff --git a/reference/docs-conceptual/PSScriptAnalyzer/Rules/UseConsistentIndentation.md b/reference/docs-conceptual/PSScriptAnalyzer/Rules/UseConsistentIndentation.md index f084d5a..1bf186e 100644 --- a/reference/docs-conceptual/PSScriptAnalyzer/Rules/UseConsistentIndentation.md +++ b/reference/docs-conceptual/PSScriptAnalyzer/Rules/UseConsistentIndentation.md @@ -1,6 +1,6 @@ --- description: Use consistent indentation -ms.date: 06/28/2023 +ms.date: 06/09/2026 ms.topic: reference title: UseConsistentIndentation --- @@ -10,11 +10,42 @@ title: UseConsistentIndentation ## Description -Indentation should be consistent throughout the source file. +This rule detects inconsistent indentation patterns within a source file. Indentation should be +consistent throughout your script. This rule is **disabled** by default. -**Note**: This rule is not enabled by default. The user needs to enable it through settings. +## Example -## Configuration +### Noncompliant + +```powershell +function Get-ItemName { + param( + [string]$Path + ) + + if ($Path) { + Get-Item $Path | + Select-Object -ExpandProperty Name + } +} +``` + +### Compliant + +```powershell +function Get-ItemName { + param( + [string]$Path + ) + + if ($Path) { + Get-Item $Path | + Select-Object -ExpandProperty Name + } +} +``` + +## Configure rule ```powershell Rules = @{ @@ -27,21 +58,27 @@ Indentation should be consistent throughout the source file. } ``` -### Parameters +## Parameters + +### Enable -#### Enable: bool (Default value is `$false`) +This parameter controls whether ScriptAnalyzer checks the code against this rule. It accepts a +boolean value. To enable this rule, set this parameter to `$true`. The default value is `$false`. -Enable or disable the rule during ScriptAnalyzer invocation. +### IndentationSize -#### IndentationSize: int (Default value is `4`) +This parameter controls the indentation size when `Kind` is set to `space`. It accepts an integer +value. To use four spaces per indentation level, set this parameter to `4`. The default value is +`4`. -Indentation size in the number of space characters. +### PipelineIndentation -#### PipelineIndentation: string (Default value is `IncreaseIndentationForFirstPipeline`) +This parameter controls pipeline indentation for multi-line statements. It accepts a string value. +The default value is `IncreaseIndentationForFirstPipeline`. -Whether to increase indentation after a pipeline for multi-line statements. The settings are: +Acceptable values are: -- IncreaseIndentationForFirstPipeline (default): Indent once after the first pipeline and keep this +- `IncreaseIndentationForFirstPipeline`: Indent once after the first pipeline and keep this indentation. Example: ```powershell @@ -50,7 +87,7 @@ Whether to increase indentation after a pipeline for multi-line statements. The baz ``` -- IncreaseIndentationAfterEveryPipeline: Indent more after the first pipeline and keep this +- `IncreaseIndentationAfterEveryPipeline`: Indent more after the first pipeline and keep this indentation. Example: ```powershell @@ -59,7 +96,7 @@ Whether to increase indentation after a pipeline for multi-line statements. The baz ``` -- NoIndentation: Do not increase indentation. Example: +- `NoIndentation`: Don't increase indentation. Example: ```powershell foo | @@ -67,12 +104,13 @@ Whether to increase indentation after a pipeline for multi-line statements. The baz ``` -- None: Do not change any existing pipeline indentation. +- `None`: Don't change any existing pipeline indentation. -#### Kind: string (Default value is `space`) +### Kind -Represents the kind of indentation to be used. Possible values are: `space`, `tab`. If any invalid -value is given, the property defaults to `space`. +This parameter controls which indentation character ScriptAnalyzer expects. It accepts a string +value. To use spaces for indentation, set this parameter to `space`. The default value is `space`. -`space` means `IndentationSize` number of `space` characters are used to provide one level of -indentation. `tab` means a tab character, `\t`. +When `Kind` is set to `space`, ScriptAnalyzer uses the value of `IndentationSize` for each +indentation level. When `Kind` is set to `tab`, ScriptAnalyzer uses a tab character (`\t`) per +indentation level. If you provide an invalid value, ScriptAnalyzer uses `space`. diff --git a/reference/docs-conceptual/PSScriptAnalyzer/Rules/UseConsistentParameterSetName.md b/reference/docs-conceptual/PSScriptAnalyzer/Rules/UseConsistentParameterSetName.md index c9b4b12..4eaaef7 100644 --- a/reference/docs-conceptual/PSScriptAnalyzer/Rules/UseConsistentParameterSetName.md +++ b/reference/docs-conceptual/PSScriptAnalyzer/Rules/UseConsistentParameterSetName.md @@ -1,6 +1,6 @@ --- -description: Use consistent parameter set names and proper parameter set configuration. -ms.date: 03/20/2026 +description: Use consistent parameter set names and proper parameter set configuration +ms.date: 06/09/2026 ms.topic: reference title: UseConsistentParameterSetName --- @@ -11,37 +11,41 @@ title: UseConsistentParameterSetName ## Description -Parameter set names in PowerShell are case-sensitive, unlike most other PowerShell elements. This -rule ensures consistent casing and proper configuration of parameter sets to avoid runtime errors -and improve code clarity. +This rule detects inconsistent parameter set naming and configuration issues that can cause runtime +errors. Parameter set names in PowerShell are case-sensitive, unlike most other PowerShell elements. +With this rule enabled, it's easier to debug your functions. This rule is **disabled** by default. -The rule performs five different checks: +This rule performs five different checks: 1. **Missing DefaultParameterSetName** - Warns when parameter sets are used but no default is - specified + specified. 1. **Multiple parameter declarations** - Detects when a parameter is declared multiple times in the - same parameter set. This is ultimately a runtime exception - this check helps catch it sooner. + same parameter set. This issue becomes a runtime exception, so this check catches it earlier. 1. **Case mismatch between DefaultParameterSetName and ParameterSetName** - Ensures consistent - casing + casing. 1. **Case mismatch between different ParameterSetName values** - Ensures all references to the same - parameter set use identical casing + parameter set use identical casing. 1. **Parameter set names containing newlines** - Warns against using newline characters in parameter - set names + set names. -> [!NOTE] -> This rule isn't enabled by default. The user needs to enable it through settings. - -## How +## Guidance - Use a `DefaultParameterSetName` when defining multiple parameter sets - Ensure consistent casing between `DefaultParameterSetName` and `ParameterSetName` values - Use identical casing for all references to the same parameter set name - Avoid declaring the same parameter multiple times in a single parameter set -- Do not use newline characters in parameter set names +- Don't use newline characters in parameter set names + +### Notes + +- The first occurrence of a parameter set name in your code is treated as the canonical casing +- Parameters without `[Parameter()]` attributes are automatically part of all parameter sets +- It's a PowerShell best practice to always specify a `DefaultParameterSetName` when you're using + parameter sets ## Example -### Wrong +### Noncompliant ```powershell # Missing DefaultParameterSetName @@ -98,7 +102,7 @@ function Get-Data { } ``` -### Correct +### Compliant ```powershell # Proper parameter set configuration @@ -128,17 +132,9 @@ Rules = @{ } ``` -### Parameters +## Parameters -- `Enable`: **bool** (Default value is `$false`) +### Enable - Enable or disable the rule during ScriptAnalyzer invocation. - -## Notes - -- Parameter set names are case-sensitive in PowerShell, making this different from most other - PowerShell elements -- The first occurrence of a parameter set name in your code is treated as the canonical casing -- Parameters without `[Parameter()]` attributes are automatically part of all parameter sets -- It's a PowerShell best practice to always specify a `DefaultParameterSetName` when using parameter - sets \ No newline at end of file +This parameter controls whether ScriptAnalyzer checks the code against this rule. It accepts a +boolean value. To enable this rule, set this parameter to `$true`. The default value is `$false`. From 11f37776f62032be6704f28298b94b230391a999 Mon Sep 17 00:00:00 2001 From: Xelu86 <103963494+Xelu86@users.noreply.github.com> Date: Thu, 11 Jun 2026 14:04:01 -0400 Subject: [PATCH 7/7] [Freshness] PSScriptAnalyzer Article Updates - Batch 13 (#416) * Freshness * Applied feedback * Applied feedback --- .../Rules/UseConsistentParametersKind.md | 51 +-- .../Rules/UseConsistentWhitespace.md | 100 ++++-- .../Rules/UseConstrainedLanguageMode.md | 330 ++++++------------ .../Rules/UseCorrectCasing.md | 83 +++-- .../UseDeclaredVarsMoreThanAssignments.md | 28 +- 5 files changed, 229 insertions(+), 363 deletions(-) diff --git a/reference/docs-conceptual/PSScriptAnalyzer/Rules/UseConsistentParametersKind.md b/reference/docs-conceptual/PSScriptAnalyzer/Rules/UseConsistentParametersKind.md index ce0c365..60d36ea 100644 --- a/reference/docs-conceptual/PSScriptAnalyzer/Rules/UseConsistentParametersKind.md +++ b/reference/docs-conceptual/PSScriptAnalyzer/Rules/UseConsistentParametersKind.md @@ -1,6 +1,6 @@ --- -description: Use the same pattern when defining parameters. -ms.date: 03/20/2026 +description: Use the same pattern when defining parameters +ms.date: 06/10/2026 ms.topic: reference title: UseConsistentParametersKind --- @@ -10,58 +10,25 @@ title: UseConsistentParametersKind ## Description -All functions should use the same pattern when defining parameters. Possible pattern types are: - -1. `Inline` - - ```powershell - function f([Parameter()]$FirstParam) { - return - } - ``` - -1. `ParamBlock` - - ```powershell - function f { - param([Parameter()]$FirstParam) - return - } - ``` - -In simple scenarios, both function definitions shown are considered to be equal. The purpose of this -rule is to enforce consistent code style across the codebase. - -## How to Fix - -Rewrite function so it defines parameters as specified in the rule +This rule detects when functions don't consistently use the same pattern for defining parameters. +All functions should use the same parameter definition pattern to enforce consistent code style +across the codebase. Rewrite any function that doesn't match the configured parameter definition +kind. In simple scenarios, both the `Inline` and `ParamBlock` function definition patterns are +functionally equivalent. ## Example -When the rule sets parameters definition kind to `Inline`: +### Noncompliant ```powershell -# Correct function f([Parameter()]$FirstParam) { return } - -# Incorrect -function g { - param([Parameter()]$FirstParam) - return -} ``` -When the rule sets parameters definition kind to `ParamBlock`: +### Compliant ```powershell -# Incorrect -function f([Parameter()]$FirstParam) { - return -} - -# Correct function g { param([Parameter()]$FirstParam) return diff --git a/reference/docs-conceptual/PSScriptAnalyzer/Rules/UseConsistentWhitespace.md b/reference/docs-conceptual/PSScriptAnalyzer/Rules/UseConsistentWhitespace.md index e36c427..5531d2e 100644 --- a/reference/docs-conceptual/PSScriptAnalyzer/Rules/UseConsistentWhitespace.md +++ b/reference/docs-conceptual/PSScriptAnalyzer/Rules/UseConsistentWhitespace.md @@ -1,6 +1,6 @@ --- -description: Use whitespaces -ms.date: 06/28/2023 +description: Use consistent whitespace in PowerShell code +ms.date: 06/10/2026 ms.topic: reference title: UseConsistentWhitespace --- @@ -10,9 +10,27 @@ title: UseConsistentWhitespace ## Description -This rule is not enabled by default. The user needs to enable it through settings. +This rule detects inconsistent or redundant whitespace around braces, parentheses, operators, +separators, pipes, and parameter values. Use this rule to keep PowerShell code readable and +consistently formatted. This rule is **disabled** by default. -## Configuration +## Example + +### Noncompliant + +```powershell +if($true) {foo| ForEach-Object{ $_ -eq 1}} +@{a = 1;b = 2} +``` + +### Compliant + +```powershell +if ($true) { foo | ForEach-Object { $_ -eq 1 } } +@{a = 1; b = 2} +``` + +## Configure rule ```powershell Rules = @{ @@ -31,55 +49,63 @@ Rules = @{ } ``` -### Enable: bool (Default value is `$false`) +## Parameters + +### Enable -Enable or disable the rule during ScriptAnalyzer invocation. +This parameter controls whether ScriptAnalyzer checks code against this rule. It accepts a boolean +value. To enable this rule, set this parameter to `$true`. The default value is `$false`. -### CheckInnerBrace: bool (Default value is `$true`) +### CheckInnerBrace -Checks if there is a space after the opening brace and a space before the closing brace. E.g. -`if ($true) { foo }` instead of `if ($true) {bar}`. +This parameter checks whether there's a space after an opening brace and a space before a closing +brace. For example, it prefers `if ($true) { foo }` over `if ($true) {bar}`. The default value is +`$true`. -### CheckOpenBrace: bool (Default value is `$true`) +### CheckOpenBrace -Checks if there is a space between a keyword and its corresponding open brace. E.g. `foo { }` -instead of `foo{ }`. If an open brace is preceded by an open parenthesis, then no space is required. +This parameter checks whether there's a space between a keyword and its corresponding opening brace. +For example, it prefers `foo { }` over `foo{ }`. No space is required if an open brace precedes an +open parenthesis. The default value is `$true`. -### CheckOpenParen: bool (Default value is `$true`) +### CheckOpenParen -Checks if there is space between a keyword and its corresponding open parenthesis. E.g. `if (true)` -instead of `if(true)`. +This parameter checks whether there's a space between a keyword and its corresponding opening +parenthesis. For example, it prefers `if (true)` over `if(true)`. The default value is `$true`. -### CheckOperator: bool (Default value is `$true`) +### CheckOperator -Checks if a binary or unary operator is surrounded on both sides by a space. E.g. `$x = 1` instead -of `$x=1`. +This parameter checks whether binary or unary operators are surrounded by spaces. For example, it +prefers `$x = 1` over `$x=1`. The default value is `$true`. -### CheckSeparator: bool (Default value is `$true`) +### CheckSeparator -Checks if a comma or a semicolon is followed by a space. E.g. `@(1, 2, 3)` or `@{a = 1; b = 2}` -instead of `@(1,2,3)` or `@{a = 1;b = 2}`. +This parameter checks whether commas and semicolons are followed by a space. For example, it prefers +`@(1, 2, 3)` over `@(1,2,3)` and `@{a = 1; b = 2}` over `@{a = 1;b = 2}`. The default value is +`$true`. -### CheckPipe: bool (Default value is `$true`) +### CheckPipe -Checks if a pipe is surrounded on both sides by a space but ignores redundant whitespace. E.g. -`foo | bar` instead of `foo|bar`. +This parameter checks whether a pipe is surrounded by a single space on each side, while ignoring +redundant whitespace. For example, it prefers `foo | bar` over `foo|bar`. The default value is +`$true`. -### CheckPipeForRedundantWhitespace : bool (Default value is `$false`) +### CheckPipeForRedundantWhitespace -Checks if a pipe is surrounded by redundant whitespace (i.e. more than 1 whitespace). E.g. -`foo | bar` instead of `foo | bar`. +This parameter checks whether a pipe is surrounded by redundant whitespace, meaning more than one +space. For example, it prefers `foo | bar` over `foo | bar`. The default value is `$false`. -### CheckParameter: bool (Default value is `$false` at the moment due to the setting being new) +### CheckParameter -Checks if there is more than one space between parameters and values. E.g. `foo -bar $baz -bat` -instead of `foo -bar $baz -bat`. This eliminates redundant whitespace that was probably added -unintentionally. The rule does not check for whitespace between parameter and value when the colon -syntax `-ParameterName:$ParameterValue` is used as some users prefer either 0 or 1 whitespace in -this case. +This parameter checks whether there's more than one space between parameters and values. For +example, it prefers `foo -bar $baz -bat` over `foo -bar $baz -bat`, which helps remove +redundant whitespace that was likely added unintentionally. The rule doesn't check whitespace +between a parameter and value when the colon syntax `-ParameterName:$ParameterValue` is used, +because some users prefer either zero or one space in that case. The default value is `$false`. -### IgnoreAssignmentOperatorInsideHashTable: bool (Default value is `$false`) +### IgnoreAssignmentOperatorInsideHashTable -When `CheckOperator` is set, ignore whitespace around assignment operators within multi-line hash -tables. Set this option to use the `AlignAssignmentStatement` rule and still check whitespace around -operators everywhere else. +When `CheckOperator` is enabled, this parameter ignores whitespace around assignment operators +within multi-line hash tables. Use it with the `AlignAssignmentStatement` rule when you want to +align assignments in hash tables but still check operator whitespace everywhere else. The default +value is `$false`. diff --git a/reference/docs-conceptual/PSScriptAnalyzer/Rules/UseConstrainedLanguageMode.md b/reference/docs-conceptual/PSScriptAnalyzer/Rules/UseConstrainedLanguageMode.md index 19e1566..7661e11 100644 --- a/reference/docs-conceptual/PSScriptAnalyzer/Rules/UseConstrainedLanguageMode.md +++ b/reference/docs-conceptual/PSScriptAnalyzer/Rules/UseConstrainedLanguageMode.md @@ -1,6 +1,6 @@ --- -description: Use patterns compatible with Constrained Language Mode -ms.date: 03/20/2026 +description: Use patterns compatible with Constrained Language Mode (CLM) +ms.date: 06/10/2026 ms.topic: reference title: UseConstrainedLanguageMode --- @@ -10,13 +10,15 @@ title: UseConstrainedLanguageMode ## Description -This rule identifies PowerShell patterns that are restricted or not permitted in Constrained -Language Mode (CLM). +This rule detects PowerShell patterns that are restricted or not permitted in Constrained Language +Mode (CLM). Use it when scripts must remain compatible with restricted PowerShell environments such +as App Control for Business, AppLocker, or Just Enough Administration (JEA) endpoints. This rule is +**disabled** by default. -Constrained Language Mode is a PowerShell security feature that restricts: +CLM is a PowerShell security feature that restricts: - .NET types that can be used -- COM objects that can be instantiated +- Component Object Model (COM) objects that can be instantiated - Commands that can be executed - Language features that can be used @@ -24,144 +26,43 @@ CLM is commonly used in: - Application Control environments (Application Control for Business, AppLocker) - Just Enough Administration (JEA) endpoints -- Secure environments requiring additional PowerShell restrictions +- Secure environments requiring other PowerShell restrictions -Digitally signed scripts from trusted publishers execute in Full Language Mode (FLM) even in CLM -environments. The rule detects signature blocks (`# SIG # Begin signature block`) and adjusts checks -accordingly. Most restrictions don't apply to signed scripts, but certain checks (dot-sourcing, -parameter types, manifest best practices) are always enforced. +Digitally signed scripts from trusted publishers run in Full Language Mode (FLM), even in CLM +environments. The rule detects signature blocks (`# SIG # Begin signature block`) and adjusts its +checks accordingly. Most restrictions don't apply to signed scripts, but some checks are still +enforced. > [!IMPORTANT] -> The rule performs a simple text check for signature blocks and does NOT validate signature -> authenticity or certificate trust. Actual signature validation is performed by PowerShell at -> runtime. - -## Constrained Language Mode Restrictions - -### Unsigned Scripts (Full CLM Checking) - -The following are flagged for unsigned scripts: - -1. **Add-Type** - Code compilation not permitted -1. **Disallowed COM Objects** - Only Scripting.Dictionary, Scripting.FileSystemObject, - VBScript.RegExp allowed -1. **Disallowed .NET Types** - Only ~70 allowed types (string, int, hashtable, pscredential, etc.) -1. **Type Constraints** - On parameters and variables -1. **Type Expressions** - Static type references like `[Type]::Method()` -1. **Type Casts** - Converting to disallowed types -1. **Member Invocations** - Methods/properties on disallowed types -1. **PowerShell Classes** - `class` keyword not permitted -1. **XAML/WPF** - Not permitted -1. **Invoke-Expression** - Restricted -1. **Dot-Sourcing** - May be restricted depending on the file being sourced -1. **Module Manifest Wildcards** - Wildcard exports not recommended -1. **Module Manifest .ps1 Files** - Script modules ending with .ps1 not allowed - -Always enforced, even for signed scripts - -### Signed Scripts (Selective Checking) - -For scripts with signature blocks, only these are checked: - -- Dot-sourcing -- Parameter type constraints -- Module manifest wildcards (.psd1 files) -- Module manifest script modules (.psd1 files) - -## Configuration - -### Basic Configuration - -```powershell -@{ - Rules = @{ - PSUseConstrainedLanguageMode = @{ - Enable = $true - } - } -} -``` - -### Parameters - -#### Enable: bool (Default value is `$false`) - -Enable or disable the rule during ScriptAnalyzer invocation. This rule is disabled by default -because not all scripts need CLM compatibility. - -#### IgnoreSignatures: bool (Default value is `$false`) - -Control signature detection behavior: - -- `$false` (default): Automatically detect signatures. Signed scripts get selective checking, - unsigned get full checking. -- `$true`: Bypass signature detection. ALL scripts get full CLM checking regardless of signature - status. - -```powershell -@{ - Rules = @{ - PSUseConstrainedLanguageMode = @{ - Enable = $true - IgnoreSignatures = $true # Enforce full CLM compliance for all scripts - } - } -} -``` - -Use `IgnoreSignatures = $true` when: - -- Auditing signed scripts for complete CLM compatibility -- Preparing scripts for untrusted environments -- Enforcing strict CLM compliance organization-wide -- Development/testing to see all potential issues - -## How to Fix - -### Replace Add-Type - -Use allowed cmdlets or pre-compile assemblies. - -### Replace Disallowed COM Objects - -Use only allowed COM objects (Scripting.Dictionary, Scripting.FileSystemObject, VBScript.RegExp) or -PowerShell cmdlets. - -### Replace Disallowed Types - -Use allowed type accelerators (`[string]`, `[int]`, `[hashtable]`, etc.) or allowed cmdlets instead -of disallowed .NET types. - -### Replace PowerShell Classes - -Use `New-Object PSObject` with `Add-Member` or hashtables instead of classes. - -> [!IMPORTANT] -> `[PSCustomObject]@{}` syntax is NOT allowed in CLM because it uses type casting. - -### Avoid XAML - -Don't use WPF/XAML in CLM-compatible scripts. - -### Replace Invoke-Expression - -Use direct execution (`&`) or safer alternatives. - -### Replace Dot-Sourcing - -Use modules with Import-Module instead of dot-sourcing when possible. - -### Fix Module Manifests - -- Replace wildcard exports (`*`) with explicit lists. -- Use `.psm1` or `.dll` instead of `.ps1` for RootModule/NestedModules. -- Don't use `ScriptsToProcess`. These scripts are loaded in the caller's scope and are blocked. +> The rule performs a simple text check for signature blocks and doesn't validate signature +> authenticity or certificate trust. PowerShell performs actual signature validation at runtime. + +## CLM restriction and remediation reference + +Use the following table for a consolidated view of each CLM restriction, what it means, the +recommended remediation, and whether checks apply to signed scripts, unsigned scripts, or both. + +| Restriction | What it means | Recommended remediation | Enforced for | +| ---------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | +| Add-Type | `Add-Type` compiles arbitrary C# code, which isn't permitted in CLM. | Use allowed cmdlets, or precompile, sign, and load assemblies. | Unsigned scripts only | +| Disallowed COM objects | Only `Scripting.Dictionary`, `Scripting.FileSystemObject`, and `VBScript.RegExp` are allowed. Other COM objects (for example, `Excel.Application`) are flagged. | Use one of the allowed COM objects, or replace COM usage with PowerShell cmdlets. | Unsigned scripts only | +| Disallowed .NET types | Only about 70 .NET and type-accelerator types are allowed. These types include common primitives, selected collections, PowerShell-specific types, utilities, and arrays of allowed types. | Replace disallowed types with allowed accelerators such as `[string]`, `[int]`, and `[hashtable]`, or use cmdlets that avoid direct disallowed type usage. | Parameter type constraints are always enforced; other .NET type checks apply to unsigned scripts only | +| Type constraints | Type constraints on parameters and variables are checked for CLM compatibility. | Use allowed types in constraints, especially in parameter declarations. | Parameter constraints are always enforced; variable constraints are unsigned scripts only | +| Type expressions | Static references such as `[Type]::Method()` are flagged when they use disallowed types. | Replace with CLM-compatible cmdlet-based patterns or allowed type usage. | Unsigned scripts only | +| Type casts | Casts to disallowed types are flagged. | Remove the cast or cast to an allowed type. | Unsigned scripts only | +| Member invocations | Method or property calls on disallowed typed objects are flagged. | Use allowed types and CLM-compatible cmdlets instead of disallowed typed objects. | Unsigned scripts only | +| PowerShell classes | The `class` keyword isn't permitted in CLM. | Use `New-Object PSObject` with `Add-Member` or use hashtables. Avoid `[PSCustomObject]@{}` because it uses type casting. | Unsigned scripts only | +| XAML or WPF | XAML or WPF usage isn't permitted in CLM. | Avoid XAML and WPF in CLM-compatible scripts. | Unsigned scripts only | +| Invoke-Expression | `Invoke-Expression` is restricted in CLM. | Use direct invocation (`&`) or safer alternatives. | Unsigned scripts only | +| Dot-sourcing | Dot-sourcing can be restricted depending on the source location. | Prefer modules and `Import-Module` over dot-sourcing where possible. | All scripts (signed and unsigned) | +| Module manifest wildcards | Wildcards in `FunctionsToExport`, `CmdletsToExport`, `AliasesToExport`, or `VariablesToExport` aren't recommended and can be blocked in CLM contexts. | Replace `*` with explicit export lists. | All `.psd1` files (signed and unsigned) | +| Module manifest `.ps1` files | Attempts to use `.ps1` for `RootModule`, `ModuleToProcess`, or `NestedModules` isn't CLM-friendly. | Use `.psm1` (script module) or `.dll` (binary module). Avoid `ScriptsToProcess`. | All `.psd1` files (signed and unsigned) | ## Examples -### Example 1: Add-Type +### Add-Type -#### Wrong +#### Noncompliant ```powershell Add-Type -TypeDefinition @" @@ -171,24 +72,24 @@ Add-Type -TypeDefinition @" "@ ``` -#### Correct +#### Compliant ```powershell - # Code sign your scripts/modules using proper signing tools - # (for example, Set-AuthenticodeSignature or external signing processes) - # Use allowed cmdlets instead of Add-Type-defined types where possible - # Or pre-compile, sign, and load the assembly (for example, via Add-Type -Path) +# Sign your scripts or modules by using appropriate signing tools +# (for example, Set-AuthenticodeSignature or an external signing process). +# Use allowed cmdlets instead of Add-Type-defined types where possible. +# Or precompile, sign, and load the assembly (for example, by using Add-Type -Path). ``` -### Example 2: COM Objects +### COM objects -#### Wrong +#### Noncompliant ```powershell $excel = New-Object -ComObject Excel.Application ``` -#### Correct +#### Compliant ```powershell # Use allowed COM object @@ -198,9 +99,9 @@ $dict = New-Object -ComObject Scripting.Dictionary Import-Excel -Path $file # From ImportExcel module ``` -### Example 3: Disallowed Types +### Disallowed types -#### Wrong +#### Noncompliant ```powershell # Type constraint and member invocation flagged @@ -214,7 +115,7 @@ function Download-File { $data = $client.DownloadData($url) ``` -#### Correct +#### Compliant ```powershell # Use allowed cmdlets @@ -230,9 +131,9 @@ function Process-Text { } ``` -### Example 4: PowerShell Classes +### PowerShell classes -#### Wrong +#### Noncompliant ```powershell class MyClass { @@ -249,7 +150,7 @@ $obj = [PSCustomObject]@{ } ``` -#### Correct +#### Compliant ```powershell # Option 1: New-Object PSObject with Add-Member @@ -270,9 +171,9 @@ $obj = @{ } ``` -### Example 5: Module Manifests +### Module manifests -#### Wrong +#### Noncompliant ```powershell @{ @@ -283,7 +184,7 @@ $obj = @{ } ``` -#### Correct +#### Compliant ```powershell @{ @@ -297,16 +198,16 @@ $obj = @{ } ``` -### Example 6: Array Types +### Array types -#### Wrong +#### Noncompliant ```powershell # Disallowed type in array param([System.Net.WebClient[]]$Clients) ``` -#### Correct +#### Compliant ```powershell # Allowed types in arrays are fine @@ -315,92 +216,62 @@ param([int[]]$Numbers) param([hashtable[]]$Configuration) ``` -## Detailed Restrictions - -### 1. Add-Type - -`Add-Type` allows compiling arbitrary C# code and isn't permitted in CLM. - -**Enforced For**: Unsigned scripts only - -### 2. COM Objects - -Only three COM objects are allowed: - -- `Scripting.Dictionary` -- `Scripting.FileSystemObject` -- `VBScript.RegExp` - -All others (Excel.Application, WScript.Shell, etc.) are flagged. - -**Enforced For**: Unsigned scripts only - -### 3. .NET Types - -Only ~70 allowed types including: - -- Primitives: `string`, `int`, `bool`, `byte`, `char`, `datetime`, `decimal`, `double`, etc. -- Collections: `hashtable`, `array`, `arraylist` -- PowerShell: `pscredential`, `psobject`, `securestring` -- Utilities: `regex`, `guid`, `version`, `uri`, `xml` -- Arrays: `string[]`, `int[][]`, etc. (array of any allowed type) - -The rule checks type usage in: - -- Parameter type constraints (**always enforced, even for signed scripts**) -- Variable type constraints -- New-Object -TypeName -- Type expressions (`[Type]::Method()`) -- Type casts (`[Type]$variable`) -- Member invocations on typed variables - -**Enforced For**: Parameter constraints always; others unsigned only - -### 4. PowerShell Classes - -The `class` keyword is not permitted. Use `New-Object PSObject` with `Add-Member` or hashtables. - -**Note**: `[PSCustomObject]@{}` is also not allowed because it uses type casting. - -**Enforced For**: Unsigned scripts only - -### 5. XAML/WPF - -XAML and WPF are not permitted in CLM. - -**Enforced For**: Unsigned scripts only +## Configure rule -### 6. Invoke-Expression - -`Invoke-Expression` is restricted in CLM. - -**Enforced For**: Unsigned scripts only +```powershell +@{ + Rules = @{ + PSUseConstrainedLanguageMode = @{ + Enable = $true + } + } +} +``` -### 7. Dot-Sourcing +## Parameters -Dot-sourcing (`. $PSScriptRoot\script.ps1`) may be restricted depending on source location. +### Enable -**Enforced For**: ALL scripts (unsigned and signed) +This parameter controls whether ScriptAnalyzer checks code against this rule. It accepts a boolean +value. To enable this rule, set this parameter to `$true`. The default value is `$false`. -### 8. Module Manifest Best Practices +### IgnoreSignatures -#### Wildcard Exports +This parameter controls how the rule handles signature detection. It accepts a boolean value. The +default value is `$false`. -Don't use `*` in: `FunctionsToExport`, `CmdletsToExport`, `AliasesToExport`, `VariablesToExport` +When this parameter is set to `$false`, ScriptAnalyzer automatically detects whether a script is +signed. Signed scripts get selective CLM checking, and unsigned scripts get full CLM checking. -Use explicit lists for security and clarity. +When this parameter is set to `$true`, ScriptAnalyzer skips signature detection and applies full CLM +checking to all scripts, regardless of signature status. -**Enforced For**: ALL .psd1 files (unsigned and signed) +The behavior is: -#### Script Module Files +- `$false` (default): Automatically detect signatures. Signed scripts receive selective checking. + Unsigned scripts receive full checks. +- `$true`: Bypass signature detection. All scripts get full CLM checking regardless of signature + status. -Don't use `.ps1` files in: `RootModule`, `ModuleToProcess`, `NestedModules` +```powershell +@{ + Rules = @{ + PSUseConstrainedLanguageMode = @{ + Enable = $true + IgnoreSignatures = $true # Enforce full CLM compliance for all scripts + } + } +} +``` -Use `.psm1` (script modules) or `.dll` (binary modules) for better performance and compatibility. +Use `IgnoreSignatures = $true` when: -**Enforced For**: ALL .psd1 files (unsigned and signed) +- Auditing signed scripts for complete CLM compatibility +- Preparing scripts for untrusted environments +- Enforcing strict CLM compliance organization-wide +- During development and testing, to see all potential issues -## More Information +## See also - [About Language Modes][01] - [PowerShell Constrained Language Mode][03] @@ -408,6 +279,7 @@ Use `.psm1` (script modules) or `.dll` (binary modules) for better performance a - [PowerShell Constrained Language Mode and the Dot-Source Operator][02] + [01]: /powershell/module/microsoft.powershell.core/about/about_language_modes [02]: https://devblogs.microsoft.com/powershell/powershell-constrained-language-mode-and-the-dot-source-operator/ [03]: https://devblogs.microsoft.com/powershell/powershell-constrained-language-mode/ diff --git a/reference/docs-conceptual/PSScriptAnalyzer/Rules/UseCorrectCasing.md b/reference/docs-conceptual/PSScriptAnalyzer/Rules/UseCorrectCasing.md index b73df64..f82f51c 100644 --- a/reference/docs-conceptual/PSScriptAnalyzer/Rules/UseCorrectCasing.md +++ b/reference/docs-conceptual/PSScriptAnalyzer/Rules/UseCorrectCasing.md @@ -1,6 +1,6 @@ --- -description: Use exact casing of cmdlet/function/parameter name. -ms.date: 03/19/2025 +description: Use exact casing for cmdlet names, functions, and parameters +ms.date: 06/10/2026 ms.topic: reference title: UseCorrectCasing --- @@ -10,17 +10,42 @@ title: UseCorrectCasing ## Description -This is a style/formatting rule. PowerShell is case insensitive wherever possible, so the casing of -cmdlet names, parameters, keywords and operators doesn't matter. This rule nonetheless ensures -consistent casing for clarity and readability. Using lowercase keywords helps distinguish them from -commands. Using lowercase operators helps distinguish them from parameters. +This rule detects inconsistent casing in cmdlet names, parameters, type names, keywords, and +operators. PowerShell is case-insensitive wherever possible, so the casing of cmdlet names, +parameters, keywords, and operators don't affect functionality. -## How +However, this rule ensures consistent casing for clarity and readability. Using lowercase keywords +helps distinguish them from commands, while using lowercase operators helps distinguish them from +parameters. + +To follow this rule: - Use exact casing for type names. -- Use exact casing of the cmdlet and its parameters. +- Use exact casing for cmdlet and parameter names. - Use lowercase for language keywords and operators. +## Example + +### Noncompliant + +```powershell +ForEach ($file in Get-childitem -Recurse) { + $file.Extension -EQ '.txt' +} + +invoke-command { 'foo' } -runasadministrator +``` + +### Compliant + +```powershell +foreach ($file in Get-ChildItem -Recurse) { + $file.Extension -eq '.txt' +} + +Invoke-Command { 'foo' } -RunAsAdministrator +``` + ## Configuration ```powershell @@ -36,40 +61,22 @@ Rules = @{ ## Parameters -### Enable: bool (Default value is `$false`) +### Enable -Enable or disable the rule during ScriptAnalyzer invocation. +This parameter controls whether ScriptAnalyzer checks code against this rule. It accepts a boolean +value. To enable this rule, set this parameter to `$true`. The default value is `$false`. -### CheckCommands: bool (Default value is `$true`) +### CheckCommands -If true, require the case of all command and parameter names to match their canonical casing. +This parameter controls whether ScriptAnalyzer checks that the casing of all command and parameter +names matches their canonical casing. It accepts a boolean value. The default value is `$true`. -### CheckKeyword: bool (Default value is `$true`) +### CheckKeyword -If true, require the case of all keywords to be lowercase. +This parameter controls whether ScriptAnalyzer checks that all language keywords are lowercase. It +accepts a boolean value. The default value is `$true`. -### CheckOperator: bool (Default value is `$true`) +### CheckOperator -If true, require the case of all operators to be lowercase. For example: `-eq`, `-ne`, `-gt` - -## Examples - -### Wrong way - -```powershell -ForEach ($file in Get-childitem -Recurse) { - $file.Extension -EQ '.txt' -} - -invoke-command { 'foo' } -runasadministrator -``` - -### Correct way - -```powershell -foreach ($file in Get-ChildItem -Recurse) { - $file.Extension -eq '.txt' -} - -Invoke-Command { 'foo' } -RunAsAdministrator -``` +This parameter controls whether ScriptAnalyzer checks that all operators are lowercase. For example, +`-eq`, `-ne`, and `-gt`. It accepts a boolean value. The default value is `$true`. diff --git a/reference/docs-conceptual/PSScriptAnalyzer/Rules/UseDeclaredVarsMoreThanAssignments.md b/reference/docs-conceptual/PSScriptAnalyzer/Rules/UseDeclaredVarsMoreThanAssignments.md index e316dbf..8a86d1d 100644 --- a/reference/docs-conceptual/PSScriptAnalyzer/Rules/UseDeclaredVarsMoreThanAssignments.md +++ b/reference/docs-conceptual/PSScriptAnalyzer/Rules/UseDeclaredVarsMoreThanAssignments.md @@ -1,6 +1,6 @@ --- -description: Extra Variables -ms.date: 03/06/2024 +description: Detect variables that are assigned but never used +ms.date: 06/10/2026 ms.topic: reference title: UseDeclaredVarsMoreThanAssignments --- @@ -10,19 +10,13 @@ title: UseDeclaredVarsMoreThanAssignments ## Description -Variables that are assigned but not used are not needed. - -> [!NOTE] -> For this rule, the variable must be used within the same scriptblock that it was declared or it -> won't be considered to be 'used'. - -## How - -Remove the variables that are declared but not used. +This rule detects variables that are assigned a value but never used. A variable counts as "used" +only when code references it in the same script block as its assignment. Variables that exist only +as assignments add noise to the code and should be removed. ## Example -### Wrong +### Noncompliant ```powershell function Test @@ -33,7 +27,7 @@ function Test } ``` -### Correct +### Compliant ```powershell function Test @@ -43,13 +37,13 @@ function Test } ``` -### Special cases +## Special cases The following examples trigger the **PSUseDeclaredVarsMoreThanAssignments** warning. This behavior -is a limitation of the rule. There is no way to avoid these false positive warnings. +is a limitation of the rule. There's no way to avoid these false positive warnings. -In this case, the warning is triggered because `$bar` is not used within the scriptblock where it -was defined. +In this case, the warning is triggered because `$bar` isn't used within the scriptblock where it was +defined. ```powershell $foo | ForEach-Object {