Skip to content

Fix individual commands that do not respect an explicit $false value passed to a switch parameter #25242

Open
2 of 2 issues completed

Description

@surfingoldelephant

Prerequisites

Steps to reproduce

# The *presence* of the switch selects UseWindowsPowerShellParameterSet.
# Irrespective of the switch *value*, CreateRunspacesForUseWindowsPowerShellParameterSet() is called.
# This subverts reasonable user expectation. UseWindowsPowerShell was NOT requested, yet the command
# ignores that request.
New-PSSession -UseWindowsPowerShell:$false

# Likewise, this results in [datetime] output, despite it not being requested.
$params = @{ Since = $false }
Get-Uptime @params

Context:

This is a continuation of the following issues:

Summary:

  • The first issue discusses how Get-Uptime -Since:$false is not respected. That is, despite the explicit $false value, Get-Uptime behaves as if -Since or -Since:$true was specified.
    • This behavior was deemed erroneous and the issue was labelled Up-for-grabs.
  • The second issue is a proposal by Michael Klement (@mklement0) for a systematic change that would implicitly fix the Get-Uptime issue and other commands that exhibit the same problem.
    • This proposal was rejected due to backwards compatibility concerns.
  • I encountered at least 10 commands shipped with PowerShell that exhibit the same problem when looking into the issue further. See here.
  • Per Ilya (@iSazonov) in #25015:

Up-for-Grabs - we should fix all cmdlets in the repo if they implement a switch in wrong way.

List of commands to fix:

Request

Fix each command listed above individually, so that explicitly passing a $false value to the specified switch parameter is respected.

Expected behavior

-Switch:$false results in the same behavior as not passing -Switch.

Actual behavior

For the commands listed above, -Switch:$false results in the same behavior as -Switch or -Switch:$true.

Environment data

Name                           Value
----                           -----
PSVersion                      7.6.0-preview.3
PSEdition                      Core
GitCommitId                    7.6.0-preview.3
OS                             Microsoft Windows 10.0.19045
Platform                       Win32NT
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0, 5.0, 5.1…}
PSRemotingProtocolVersion      2.3
SerializationVersion           1.1.0.1
WSManStackVersion              3.0

Activity

  1. surfingoldelephant commented on Mar 26, 2025

    @surfingoldelephant
    Author

    Ilya (@iSazonov) Are individual issues for each of the affected commands also required? Or will this singular, meta-issue suffice?

  2. changed the title [-]Fix PS-shipped commands that do not respect an explicit `$false` value passed to a switch parameter[/-] [+]Fix individual commands that do not respect an explicit `$false` value passed to a switch parameter[/+] on Mar 26, 2025
  3. kilasuit commented on Mar 26, 2025

    @kilasuit
    Collaborator

    Single issues & are linked to this one please. This allows smaller easier to review commits/PR's whilst enabling more than 1 person to work on fixing these issues at a time. It also helps the WG's when reviewing issues/PR's to be able to quickly review them if it's a smaller change.

  4. surfingoldelephant commented on Mar 26, 2025

    @surfingoldelephant
    Author

    Thanks, sounds good. I will link the new issues in the OP as and when they're submitted.

  5. added
    Issue-BugIssue has been identified as a bug in the product
    Up-for-GrabsUp-for-grabs issues are not high priorities, and may be opportunities for external contributors
    WG-ReviewedA Working Group has reviewed this and made a recommendation
    and removed
    Needs-TriageThe issue is new and needs to be triaged by a work group.
    on Oct 1, 2025
  6. SteveL-MSFT commented on Oct 1, 2025

    @SteveL-MSFT
    Member

    @PowerShell/wg-powershell-cmdlets agree these are bugs

  7. surfingoldelephant commented on Nov 17, 2025

    @surfingoldelephant
    Author

    I've removed Register-PSResourceRepository -PSGallery from the OP as it pertains to a command in a different repo.

    Here's the PSResourceGet issue: PowerShell/PSResourceGet#1805

  8. iSazonov commented on Nov 21, 2025

    @iSazonov
    Collaborator

    Are there other cases in our code base for fixing?

  9. surfingoldelephant commented on Nov 21, 2025

    @surfingoldelephant
    Author

    Are there other cases in our code base for fixing?

    The original list in the OP is based on the testing here. I focused on all mandatory switch parameters belonging to commands shipped with PowerShell.

    For non-mandatory, at the very least, we'd need to check parameters that meet the following criteria:

    • Belongs to a command from this repo (not already fixed in this issue).
    • Is a switch parameter (not common).
    • Belongs to a parameter set that isn't __AllParameterSets.

    There's 137 parameters that meet that. Checking those would cover the most common cause of the issue (i.e., branching on the parameter set name instead of the switch value).

    Parameter list to check:
    Command                    Parameter                        Source                           InParameterSet
    -------                    ---------                        ------                           --------------
    Add-Member                 Force                            Microsoft.PowerShell.Utility     MemberSet, NotePropertySingleMemberSet, NotePropertyMultiMemberSet
    Add-Member                 PassThru                         Microsoft.PowerShell.Utility     MemberSet, TypeNameSet, NotePropertySingleMemberSet, NotePropertyMultiMemberSet
    Add-Type                   IgnoreWarnings                   Microsoft.PowerShell.Utility     FromSource, FromMember, FromPath, FromLiteralPath
    Connect-PSSession          AllowRedirection                 Microsoft.PowerShell.Core        ConnectionUri, ConnectionUriGuid
    Connect-PSSession          UseSSL                           Microsoft.PowerShell.Core        ComputerName, ComputerNameGuid
    Connect-WSMan              UseSSL                           Microsoft.WSMan.Management       ComputerName
    ConvertFrom-Csv            UseCulture                       Microsoft.PowerShell.Utility     UseCulture
    ConvertFrom-SecureString   AsPlainText                      Microsoft.PowerShell.Security    AsPlainText
    ConvertTo-Csv              UseCulture                       Microsoft.PowerShell.Utility     UseCulture
    ConvertTo-Html             Fragment                         Microsoft.PowerShell.Utility     Fragment
    ConvertTo-Html             Transitional                     Microsoft.PowerShell.Utility     Page
    ConvertTo-SecureString     AsPlainText                      Microsoft.PowerShell.Security    PlainText
    ConvertTo-SecureString     Force                            Microsoft.PowerShell.Security    PlainText
    Enable-RunspaceDebug       BreakAll                         Microsoft.PowerShell.Utility     RunspaceParameterSet, RunspaceNameParameterSet, RunspaceIdParameterSet
    Enter-PSSession            EnableNetworkAccess              Microsoft.PowerShell.Core        ComputerName, Uri
    Enter-PSSession            RunAsAdministrator               Microsoft.PowerShell.Core        ContainerId
    Enter-PSSession            UseSSL                           Microsoft.PowerShell.Core        ComputerName
    Enter-PSSession            AllowRedirection                 Microsoft.PowerShell.Core        Uri
    Enter-PSSession            SSHTransport                     Microsoft.PowerShell.Core        SSHHost
    Export-Csv                 UseCulture                       Microsoft.PowerShell.Utility     UseCulture
    ForEach-Object             AsJob                            Microsoft.PowerShell.Core        ParallelParameterSet
    ForEach-Object             UseNewRunspace                   Microsoft.PowerShell.Core        ParallelParameterSet
    Format-Hex                 Raw                              Microsoft.PowerShell.Utility     ByInputObject
    Get-CimInstance            KeyOnly                          CimCmdlets                       ClassNameComputerSet, ClassNameSessionSet, ResourceUriComputerSet, ResourceUriSessionSet
    Get-CimInstance            Shallow                          CimCmdlets                       ClassNameComputerSet, ClassNameSessionSet, ResourceUriSessionSet, ResourceUriComputerSet, QueryComputerSet, QuerySessionSet
    Get-Command                UseFuzzyMatching                 Microsoft.PowerShell.Core        AllCommandSet
    Get-Command                UseAbbreviationExpansion         Microsoft.PowerShell.Core        AllCommandSet
    Get-Counter                Continuous                       Microsoft.PowerShell.Diagnostics GetCounterSet
    Get-Culture                NoUserOverrides                  Microsoft.PowerShell.Utility     CurrentCulture, Name
    Get-Culture                ListAvailable                    Microsoft.PowerShell.Utility     ListAvailable
    Get-Help                   Detailed                         Microsoft.PowerShell.Core        DetailedView
    Get-Help                   Full                             Microsoft.PowerShell.Core        AllUsersView
    Get-Help                   Examples                         Microsoft.PowerShell.Core        Examples
    Get-Help                   Online                           Microsoft.PowerShell.Core        Online
    Get-Help                   ShowWindow                       Microsoft.PowerShell.Core        ShowWindow
    Get-Job                    IncludeChildJob                  Microsoft.PowerShell.Core        SessionIdParameterSet, InstanceIdParameterSet, NameParameterSet, StateParameterSet, CommandParameterSet
    Get-Location               Stack                            Microsoft.PowerShell.Management  Stack
    Get-Module                 All                              Microsoft.PowerShell.Core        Loaded, Available
    Get-Module                 ListAvailable                    Microsoft.PowerShell.Core        Available, PsSession, CimSession
    Get-Module                 SkipEditionCheck                 Microsoft.PowerShell.Core        Available, PsSession, CimSession
    Get-Module                 Refresh                          Microsoft.PowerShell.Core        Available, PsSession, CimSession
    Get-Process                IncludeUserName                  Microsoft.PowerShell.Management  NameWithUserName, IdWithUserName, InputObjectWithUserName
    Get-Process                Module                           Microsoft.PowerShell.Management  Name, Id, InputObject
    Get-Process                FileVersionInfo                  Microsoft.PowerShell.Management  Name, Id, InputObject
    Get-PSSession              AllowRedirection                 Microsoft.PowerShell.Core        ConnectionUri, ConnectionUriInstanceId
    Get-PSSession              UseSSL                           Microsoft.PowerShell.Core        ComputerName, ComputerInstanceId
    Get-Unique                 AsString                         Microsoft.PowerShell.Utility     AsString
    Get-Unique                 OnType                           Microsoft.PowerShell.Utility     UniqueByType
    Get-WinEvent               Force                            Microsoft.PowerShell.Diagnostics ListLogSet, GetProviderSet, GetLogSet, HashQuerySet
    Get-WinEvent               Oldest                           Microsoft.PowerShell.Diagnostics FileSet, GetProviderSet, GetLogSet, HashQuerySet, XmlQuerySet
    Get-WSManInstance          BasePropertiesOnly               Microsoft.WSMan.Management       Enumerate
    Get-WSManInstance          Enumerate                        Microsoft.WSMan.Management       Enumerate
    Get-WSManInstance          Associations                     Microsoft.WSMan.Management       Enumerate
    Get-WSManInstance          Shallow                          Microsoft.WSMan.Management       Enumerate
    Get-WSManInstance          UseSSL                           Microsoft.WSMan.Management       GetInstance, Enumerate
    Group-Object               AsHashTable                      Microsoft.PowerShell.Utility     HashTable
    Group-Object               AsString                         Microsoft.PowerShell.Utility     HashTable
    Import-Csv                 UseCulture                       Microsoft.PowerShell.Utility     CulturePath, CultureLiteralPath
    Import-Module              SkipEditionCheck                 Microsoft.PowerShell.Core        Name, FullyQualifiedName, ModuleInfo, Assembly, PSSession, CimSession, FullyQualifiedNameAndPSSession
    Import-Module              UseWindowsPowerShell             Microsoft.PowerShell.Core        WinCompat, FullyQualifiedNameAndWinCompat
    Invoke-Command             UseSSL                           Microsoft.PowerShell.Core        ComputerName, FilePathComputerName
    Invoke-Command             AsJob                            Microsoft.PowerShell.Core        ComputerName, Session, Uri, FilePathComputerName, FilePathRunspace, FilePathUri, VMId, VMName, ContainerId, FilePathVMId, FilePathVMName, FilePathContainerId, SSHHost, SSHHostHashParam, FilePathSSHHost, FilePathSSHHostHash
    Invoke-Command             InDisconnectedSession            Microsoft.PowerShell.Core        ComputerName, FilePathComputerName, Uri, FilePathUri
    Invoke-Command             HideComputerName                 Microsoft.PowerShell.Core        ComputerName, Session, Uri, FilePathComputerName, FilePathRunspace, FilePathUri, VMId, VMName, ContainerId, FilePathVMId, FilePathVMName, FilePathContainerId, SSHHost, SSHHostHashParam, FilePathSSHHost, FilePathSSHHostHash
    Invoke-Command             NoNewScope                       Microsoft.PowerShell.Core        InProcess
    Invoke-Command             AllowRedirection                 Microsoft.PowerShell.Core        Uri, FilePathUri
    Invoke-Command             EnableNetworkAccess              Microsoft.PowerShell.Core        ComputerName, FilePathComputerName, Uri, FilePathUri
    Invoke-Command             RunAsAdministrator               Microsoft.PowerShell.Core        ContainerId, FilePathContainerId
    Invoke-Command             SSHTransport                     Microsoft.PowerShell.Core        SSHHost, FilePathSSHHost
    Invoke-Command             RemoteDebug                      Microsoft.PowerShell.Core        ComputerName, Session, Uri, FilePathComputerName, FilePathRunspace, FilePathUri, VMId, VMName, ContainerId, FilePathVMId, FilePathVMName, FilePathContainerId, SSHHost, SSHHostHashParam, FilePathSSHHost, FilePathSSHHostHash
    Invoke-RestMethod          NoProxy                          Microsoft.PowerShell.Utility     CustomMethodNoProxy, StandardMethodNoProxy
    Invoke-RestMethod          ProxyUseDefaultCredentials       Microsoft.PowerShell.Utility     StandardMethod, CustomMethod
    Invoke-WebRequest          NoProxy                          Microsoft.PowerShell.Utility     CustomMethodNoProxy, StandardMethodNoProxy
    Invoke-WebRequest          ProxyUseDefaultCredentials       Microsoft.PowerShell.Utility     StandardMethod, CustomMethod
    Invoke-WSManAction         UseSSL                           Microsoft.WSMan.Management       ComputerName
    Join-String                SingleQuote                      Microsoft.PowerShell.Utility     SingleQuote
    Join-String                DoubleQuote                      Microsoft.PowerShell.Utility     DoubleQuote
    Measure-Object             StandardDeviation                Microsoft.PowerShell.Utility     GenericMeasure
    Measure-Object             Sum                              Microsoft.PowerShell.Utility     GenericMeasure
    Measure-Object             AllStats                         Microsoft.PowerShell.Utility     GenericMeasure
    Measure-Object             Average                          Microsoft.PowerShell.Utility     GenericMeasure
    Measure-Object             Maximum                          Microsoft.PowerShell.Utility     GenericMeasure
    Measure-Object             Minimum                          Microsoft.PowerShell.Utility     GenericMeasure
    Measure-Object             Line                             Microsoft.PowerShell.Utility     TextMeasure
    Measure-Object             Word                             Microsoft.PowerShell.Utility     TextMeasure
    Measure-Object             Character                        Microsoft.PowerShell.Utility     TextMeasure
    Measure-Object             IgnoreWhiteSpace                 Microsoft.PowerShell.Utility     TextMeasure
    New-CimInstance            ClientOnly                       CimCmdlets                       ClassNameSessionSet, ClassNameComputerSet, CimClassComputerSet, CimClassSessionSet
    New-CimSessionOption       NoEncryption                     CimCmdlets                       WSManParameterSet
    New-CimSessionOption       SkipCACheck                      CimCmdlets                       WSManParameterSet
    New-CimSessionOption       SkipCNCheck                      CimCmdlets                       WSManParameterSet
    New-CimSessionOption       SkipRevocationCheck              CimCmdlets                       WSManParameterSet
    New-CimSessionOption       EncodePortInServicePrincipalName CimCmdlets                       WSManParameterSet
    New-CimSessionOption       UseSsl                           CimCmdlets                       WSManParameterSet
    New-CimSessionOption       PacketIntegrity                  CimCmdlets                       DcomParameterSet
    New-CimSessionOption       PacketPrivacy                    CimCmdlets                       DcomParameterSet
    New-Object                 Strict                           Microsoft.PowerShell.Utility     Com
    New-WSManInstance          UseSSL                           Microsoft.WSMan.Management       ComputerName
    Out-GridView               Wait                             Microsoft.PowerShell.Utility     Wait
    Out-GridView               PassThru                         Microsoft.PowerShell.Utility     PassThru
    Out-String                 Stream                           Microsoft.PowerShell.Utility     StreamFormatting
    Out-String                 NoNewline                        Microsoft.PowerShell.Utility     NoNewLineFormatting
    Read-Host                  AsSecureString                   Microsoft.PowerShell.Utility     AsSecureString
    Read-Host                  MaskInput                        Microsoft.PowerShell.Utility     AsString
    Receive-PSSession          AllowRedirection                 Microsoft.PowerShell.Core        ConnectionUriSessionName, ConnectionUriInstanceId
    Receive-PSSession          UseSSL                           Microsoft.PowerShell.Core        ComputerInstanceId, ComputerSessionName
    Register-ArgumentCompleter Native                           Microsoft.PowerShell.Core        NativeSet
    Remove-Job                 Force                            Microsoft.PowerShell.Core        InstanceIdParameterSet, JobParameterSet, NameParameterSet, SessionIdParameterSet, FilterParameterSet
    Remove-WSManInstance       UseSSL                           Microsoft.WSMan.Management       ComputerName
    Resolve-Path               Relative                         Microsoft.PowerShell.Management  Path, LiteralPath
    Restart-Computer           Wait                             Microsoft.PowerShell.Management  DefaultSet
    Select-Object              Wait                             Microsoft.PowerShell.Utility     DefaultParameter, IndexParameter
    Select-String              Raw                              Microsoft.PowerShell.Utility     ObjectRaw, FileRaw, LiteralFileRaw
    Select-String              Quiet                            Microsoft.PowerShell.Utility     Object, File, LiteralFile
    Set-Acl                    ClearCentralAccessPolicy         Microsoft.PowerShell.Security    ByPath, ByLiteralPath
    Set-PSDebug                Step                             Microsoft.PowerShell.Core        on
    Set-PSDebug                Strict                           Microsoft.PowerShell.Core        on
    Set-PSDebug                Off                              Microsoft.PowerShell.Core        off
    Set-StrictMode             Off                              Microsoft.PowerShell.Core        Off
    Set-TraceSource            Force                            Microsoft.PowerShell.Utility     optionsSet
    Set-TraceSource            Debugger                         Microsoft.PowerShell.Utility     optionsSet
    Set-TraceSource            PSHost                           Microsoft.PowerShell.Utility     optionsSet
    Set-TraceSource            PassThru                         Microsoft.PowerShell.Utility     optionsSet
    Set-WSManInstance          UseSSL                           Microsoft.WSMan.Management       ComputerName
    Sort-Object                Stable                           Microsoft.PowerShell.Utility     Default
    Start-Job                  RunAs32                          Microsoft.PowerShell.Core        FilePathComputerName, ComputerName, LiteralFilePathComputerName
    Start-Process              LoadUserProfile                  Microsoft.PowerShell.Management  Default
    Start-Process              NoNewWindow                      Microsoft.PowerShell.Management  Default
    Start-Process              UseNewEnvironment                Microsoft.PowerShell.Management  Default
    Tee-Object                 Append                           Microsoft.PowerShell.Utility     File
    Test-WSMan                 UseSSL                           Microsoft.WSMan.Management       ComputerName
    Update-TypeData            Force                            Microsoft.PowerShell.Utility     DynamicTypeSet, TypeDataSet
    help                       Detailed                                                          DetailedView
    help                       Full                                                              AllUsersView
    help                       Examples                                                          Examples
    help                       Online                                                            Online
    help                       ShowWindow                                                        ShowWindow
    
    Code to generate list:
    # In a fresh session (-NoProfile, -NonInteractive):
    # Ensure modules owned by PowerShell/PowerShell are loaded, otherwise
    # the CommandInfo's ParameterSets is empty when getting the command.
    $pwshModules = @(
        'CimCmdlets'
        'Microsoft.PowerShell.Core'
        'Microsoft.PowerShell.Diagnostics'
        'Microsoft.PowerShell.Host'
        'Microsoft.PowerShell.Management'
        'Microsoft.PowerShell.Security'
        'Microsoft.PowerShell.Utility'
        'Microsoft.WSMan.Management'
        'PSDiagnostics'
    )
    Import-Module -Name ($pwshModules -ne 'Microsoft.PowerShell.Core')
    
    # Get commands belonging to PowerShell/PowerShell, including built-in functions (help, oss, etc).
    $pwshCmds = @(
        Get-Command -CommandType Cmdlet, Function, Filter -Module $pwshModules
        Get-Command -CommandType Function, Filter | Where-Object -Not Source
    ) 
    
    # Commands already fixed in #25242.
    $alreadyFixed = @(
        'Get-Uptime'
        'New-Guid'
        'Get-Random'
        'Get-SecureRandom'
        'Get-TimeZone'
        'New-PSSession'
        'Split-Path'
        'Test-Connection'
        'Where-Object'
    )
    
    foreach ($cmd in $pwshCmds | Where-Object Name -NotIn $alreadyFixed) {
        foreach ($param in $cmd.Parameters.Values) {
            # Only output switch parameters that are in an explicit parameter set.
            if (!$param.SwitchParameter -or $param.ParameterSets.ContainsKey('__AllParameterSets')) { 
                continue 
            }
    
            [pscustomobject] @{
                Command        = $cmd
                Parameter      = $param.Name
                Source         = $cmd.Source
                InParameterSet = $param.ParameterSets.Keys
            }
        }
    }

    However, it doesn't cover causes of the issue that don't involve parameter sets at all (e.g., MyInvocation.BoundParameters.ContainsKey('SwitchParam')). So for completeness, there's a total of 450+ parameters that require checking.

    Fully automating that will be difficult, I think. Some degree of manual checking (either by searching the code base or testing commands manually) will probably be needed, but naturally it would require substantial effort.

  10. iSazonov commented on Nov 22, 2025

    @iSazonov
    Collaborator

    here's a total of 450+ parameters that require checking.

    Too much to fix in a reasonable time. Rather, we should ask - are there any cmdlets where there are very annoying problems with switches?

    If we don't know any of them now, then I suggest closing this issue. Users can always open a new one if the need arises.

  11. surfingoldelephant commented on Nov 22, 2025

    @surfingoldelephant
    Author

    I don't necessarily know about annoying, but I did take a cursory look through the list and the following are broken in a similar way to the ones we've already fixed:

    • ConvertTo-Csv -UseCulture:$false (results in no delimiter at all)
    • Export-Csv -UseCulture:$false (results in space as the delimiter)
    • ConvertFrom-Csv -UseCulture:$false (doesn't parse using default delimiter)
    • Import-Csv -UseCulture:$false (doesn't parse using default delimiter)
    • Get-Culture -ListAvailable:$false (behaves like -ListAvailable)
    • Get-Location -Stack:$false (behaves like -Stack)
    • Format-Hex -Raw:$false (behaves like -Raw and still emits warning)

    It really depends how far we want to take this.

    If -Switch:$false should behave as if -Switch wasn't specified, all commands with switches tied to a distinct parameter set are technically broken. E.g.,

    • Measure-Object, Measure-Object -Line and Measure-Object -Line:$false all behave differently (that is, -Line:$false doesn't behave like omitting the switch or including -Line). Measure-Object has many switches like this split across different sets.
    • New-Object -TypeName int -Strict:$false should behave like New-Object -TypeName int, but fails because -TypeName/-Strict are in different sets.
    • All of help's switches.

    It's probably not feasible/worth it to fix all of the commands like that.


    I suggest ConvertTo-Csv, Export-Csv, ConvertFrom-Csv, Import-Csv, Get-Culture and Get-Location at the very least should be fixed before closing this issue. I've updated the OP accordingly and filed #26513 as a start.

  12. SufficientDaikon commented on Mar 15, 2026

    @SufficientDaikon
    Contributor

    Submitted #27034 — fixes Get-Culture -ListAvailable:$false and Get-Location -Stack:$false. Same if-guard pattern as the 9 previously merged sibling PRs.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Issue-BugIssue has been identified as a bug in the productUp-for-GrabsUp-for-grabs issues are not high priorities, and may be opportunities for external contributorsWG-Cmdletsgeneral cmdlet issuesWG-ReviewedA Working Group has reviewed this and made a recommendation

    Type

    No type

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions