PowerShell / PowerShell — Contribution Portfolio

5 Pull Requests Review Guide

Four pull requests reviewed in detail below, plus a fifth (#27027) with its own dedicated docs site.

5 PRs total 4 detailed here 5 issues referenced
See also: Hosting API Bounded-Wait Timeouts — The fifth contribution (#27027) has its own dedicated documentation site with interactive scenario runner, execution flow diagrams, and formal specification: ps-bounded-wait-docs.pages.dev
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 • 6 fixes
PR D — #27078

Fix Markdown Links CI

Fixes #27091
3 files • CI workflow

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, #26140 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
9 sibling PRs already merged (same pattern)
  • #26140 — New-Guid (-Empty:$false)
  • #26141 — Get-Uptime (-Since:$false)
  • #26457 — Get-Random (-Shuffle:$false)
  • #26460 — Get-SecureRandom (-Shuffle:$false)
  • #26463 — Get-TimeZone (-ListAvailable:$false)
  • #26469 — New-PSSession (-UseWindowsPowerShell:$false)
  • #26474 — Split-Path (-Qualifier/-NoQualifier/-Leaf/-IsAbsolute:$false)
  • #26479 — Test-Connection (-Repeat/-MtuSize/-Traceroute:$false)
  • #26485 — Where-Object (-[Operator]:$false)

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.

What Changed

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

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

PR D — Fix Verify Markdown Links CI #27078

CI infrastructure fix. The weekly markdown link checker has been failing every Sunday since October 2025 — fixes #27091.

The Bug

The Verify Markdown Links workflow declares schedule (weekly Sunday cron) and workflow_dispatch triggers, but the underlying get-changed-files action only handles pull_request and push. Every cron run fails with:

Unsupported event type: schedule. Supported types: pull_request, push

What changed

FileChange
get-changed-files/action.yml Add schedule + workflow_dispatch handlers using GitHub Trees API
markdownlinks/action.yml Update event-types to include new triggers
get-changed-files/README.md Document new event type support

Design

For schedule/workflow_dispatch events there is no diff to compare, so the new code path uses github.rest.git.getTree with recursive: 'true' to enumerate all blobs, then feeds them through the existing filter logic. The pull_request and push code paths are completely untouched.


06

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.

07

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 Static analysis 6/6 items Null checks, operator precedence, volatile — no automated test suite (code review only)