PowerShell / PowerShell

Contribution Review Guide

Three pull requests addressing 3 open issues — 12 files changed across the PowerShell engine, cmdlets, and CIM infrastructure.

3 PRs 12 files 3 issues All builds pass
01

Overview

Each card links to its detailed section below. All changes are built and tested against the latest master.

PR A — #27033

UUID v7 for New-Guid

Fixes #24895
1 source + 1 test • 9/9 tests
PR B — #27034

-Switch:$false Fixes

Part of #25242
2 source + 2 test • 14/14 tests
PR C — #27035

Static Analyzer Fixes

Addresses #25289
6 source files • build clean

02

PR A — UUID v7 for New-Guid #27033

One-line change. Switches New-Guid from UUID v4 to v7 per #24895. WG approved — no switches needed.

UUID v7 (RFC 9562) embeds a millisecond-precision timestamp, making GUIDs monotonically sortable — ideal for database keys and distributed systems. Guid.CreateVersion7() is available since .NET 9; PowerShell targets .NET 11.

What changed

FileChange
NewGuidCommand.cs Guid.NewGuid()Guid.CreateVersion7()
New-Guid.Tests.ps1 Added version-nibble test: position 14 == 7

Before / After

// Before (line 52)
guid = Empty.ToBool() ? Guid.Empty : Guid.NewGuid();

// After
guid = Empty.ToBool() ? Guid.Empty : Guid.CreateVersion7();
New Pester test
It "Should generate a UUID v7" {
    $guid = New-Guid
    $guid.ToString()[14] | Should -BeExactly '7'
}
Why UUID string position 14?

UUID format: xxxxxxxx-xxxx-Vxxx-xxxx-xxxxxxxxxxxx

The V at 0-indexed position 14 is the version nibble. For v7, it's 7.

Related


03

PR B — Fix -Switch:$false Handling #27034

Two cmdlets fixed. Part of the ongoing cleanup in #25242. Same pattern as #26463, #26457, #26437 and 6 more merged PRs.

The bug

When -ListAvailable:$false or -Stack:$false is passed, PowerShell’s parameter binder selects the switch’s ParameterSetName but the cmdlet code branches on the set name without checking the actual switch value.

CmdletBug behaviorExpected
Get-Culture -ListAvailable:$false Dumps all ~800 cultures Returns current culture
Get-Location -Stack:$false Shows location stack Returns current directory

Fix pattern

Wrap the switch-path code in if (SwitchParam) with an else fallback to default behavior.

// Before
case ListAvailableParameterSet:
    foreach (var ci in CultureInfo.GetCultures(...))
        WriteObject(ci);
    break;

// After
case ListAvailableParameterSet:
    if (ListAvailable)
    {
        foreach (var ci in CultureInfo.GetCultures(...))
            WriteObject(ci);
    }
    else
    {
        WriteObject(Host.CurrentCulture);
    }
    break;

What changed

FileChange
GetCultureCommand.csGuard ListAvailableParameterSet with if (ListAvailable)
Navigation.csGuard StackParameterSet with if (Stack)
Get-Culture.Tests.ps1Add -ListAvailable:$false test
Get-Location.Tests.ps1Add -Stack:$false test
Sibling PRs already merged (same pattern)

04

PR C — PVS-Studio Static Analyzer Fixes #27035

6 of 10 findings fixed. Addresses items from #25289. Remaining 4 require design decisions or touch auto-generated code.
ItemFileBugSeverityFix
9 StringUtil.cs ?? operator precedence — appendStr length silently ignored Medium Added parentheses
2 CimCmdlets/Utils.cs Unsafe double-checked locking Low Added volatile
6 ConsoleHost.cs RunspaceRef used before null check High Moved null check first
1 CimGetInstance.cs GetCimInstanceParameter can return null, dereferenced High Added null guard
5 ShowCommandCommandInfo.cs Members["Module"] accessed without null-conditional Medium Added ?.
7 typeDataQuery.cs vd.mainControl accessed when vd == null High Split into separate checks

Before / After for each item

Item 9 — Operator precedence in StringUtil.cs
// Before (line 246) — ?? has lower priority than +
int capacity = length + prependStr?.Length ?? 0 + appendStr?.Length ?? 0;

// After — explicit grouping
int capacity = length + (prependStr?.Length ?? 0) + (appendStr?.Length ?? 0);
Item 2 — Missing volatile in Utils.cs
// Before
private static bool logInitialized = false;

// After
private static volatile bool logInitialized = false;
Item 6 — Null check order in ConsoleHost.cs
// Before — RunspaceRef used before null check
if (_isRunspacePushed)
    return RunspaceRef.OldRunspace as LocalRunspace;
if (RunspaceRef == null) return null;

// After — null check first
if (RunspaceRef == null) return null;
if (_isRunspacePushed)
    return RunspaceRef.OldRunspace as LocalRunspace;
Item 1 — Null dereference in CimGetInstance.cs
// Before — instance used without null check
CimInstance instance = GetCimInstanceParameter(cmdlet);
nameSpace = instance.CimSystemProperties.Namespace;

// After — null guard added
CimInstance instance = GetCimInstanceParameter(cmdlet);
if (instance != null)
{
    nameSpace = instance.CimSystemProperties.Namespace;
    ...
}
Item 5 — Null access in ShowCommandCommandInfo.cs
// Before
this.Module = other.Members["Module"].Value as ShowCommandModuleInfo;

// After
this.Module = other.Members["Module"]?.Value as ShowCommandModuleInfo;
Item 7 — Null dereference in typeDataQuery.cs
// Before — vd.mainControl accessed in both branches
if (vd == null || mainControlType != vd.mainControl.GetType())
{
    ActiveTracer.WriteLine("NOT MATCH ...",
        ControlBase.GetControlShapeName(vd.mainControl), ...);
}

// After — separate checks
if (vd == null)
{
    ActiveTracer.WriteLine("NOT MATCH null view definition");
    continue;
}
if (mainControlType != vd.mainControl.GetType())
{
    ActiveTracer.WriteLine("NOT MATCH ...", ...);
    continue;
}

05

Skipped Items (with rationale)

Four items from #25289 were intentionally left for maintainer guidance.

ItemFileStatusWhy
3 GetEventCommand.cs Skipped suppressOpener has no format placeholders — may be intentional. Needs maintainer input.
4 New-Object.cs Skipped Switch doesn’t cover FullLanguage — may be a deliberate fall-through. Needs WG guidance.
8 xmlSerializer.autogen.cs Skipped Auto-generated file. Fix would be overwritten on next generation.
10 Command.cs Skipped PipelineResultTypes Flags enum values — changing is a public API breaking change.

06

Test Results

PRSuiteResultDetails
A Pester — New-Guid 9/9 pass 8 existing + 1 new v7 nibble test
A Smoke test pass (New-Guid).ToString()[14] returns 7
B Pester — Get-Culture 12/12 pass 11 existing + 1 new -ListAvailable:$false
B Pester — Get-Location 2/2 pass 1 existing + 1 new -Stack:$false
B Smoke test pass Both cmdlets return correct default with :$false
C Full build 0 errors Clean compile, all 6 changes verified