GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — Fix -WindowStyle Hidden console window flash by SufficientDaikon · Pull Request #27111 · PowerShell/PowerShell

Conversation

@SufficientDaikon

@SufficientDaikon Ahmed Taha (SufficientDaikon) commented Mar 28, 2026 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown
Contributor

PR Summary

Eliminate the console window flash when launching pwsh -WindowStyle Hidden on Windows 11 24H2+ by using the consoleAllocationPolicy=detached manifest element and AllocConsoleWithOptions kernel32 API.

Fixes #3028

Important

Progressive enhancement: On older Windows the manifest is ignored and behavior is identical to the current release. On newer Windows (build 26100+) the console window is never created in the first place.

On Windows 11 build 26100+, the OS no longer auto-creates a console window for pwsh.exe — PowerShell allocates it programmatically at the top of Main():

  • -WindowStyle Hidden — AllocConsoleWithOptions(NoWindow): console I/O works, no window appears
  • Normal launch — AllocConsoleWithOptions(Default): respects DETACHED_PROCESS from the parent (per DHowett's review)
  • Older Windows — API not available → TryAlloc* returns false via catch (EntryPointNotFoundException) → no-op (OS already auto-allocated the console)

No AllocConsole() fallback in EarlyConsoleInit — plain AllocConsole() would override DETACHED_PROCESS from the parent. On older Windows the manifest is ignored, so the OS auto-allocates the console before Main() runs and GetConsoleWindow() returns non-zero — EarlyConsoleInit is a no-op.

pwsh.exe stays a CUI subsystem binary. No new executables, no breaking changes, no new public API.

Changes

File Change
assets/pwsh.manifest Add consoleAllocationPolicy=detached in a new <application> block (asm.v3 xmlns required)
engine/Interop/Windows/AllocConsoleWithOptions.cs New — P/Invoke for AllocConsoleWithOptions, shared TryAllocConsoleWithMode() helper, checks AllocConsoleResult != NoConsole
host/msh/ManagedEntrance.cs New EarlyConsoleInit(args) + EarlyCheckForHiddenWindowStyle(args)
host/msh/ConsoleControl.cs SetConsoleMode() guards against null handle — graceful return instead of Dbg.Assert
engine/NativeCommandProcessor.cs AllocateHiddenConsole() prefers AllocConsoleWithOptions(NoWindow) with AllocConsole() fallback (native commands always need a console)
test/powershell/Host/WindowStyleHidden.Tests.ps1 New — 13 Pester tests (Pester 4 compatible)

Behavior by launch context

Context Old Windows Windows 26100+
Terminal / cmd / pwsh Console inherited — unchanged Console inherited — unchanged
Explorer double-click OS creates console — unchanged AllocConsoleWithOptions(Default)
CreateProcess(DETACHED_PROCESS) No console — unchanged Default mode respects detached intent
CreateProcess(CREATE_NO_WINDOW) Console session, no window — unchanged AllocConsoleWithOptions returns ExistingConsole (no-op)
DETACHED_PROCESS + -WindowStyle Hidden No console (crash) NoWindow creates invisible console — user explicitly requested working I/O
Task Scheduler + -WindowStyle Hidden Flash then hide No flash
Shortcut + -WindowStyle Hidden Flash then hide No flash
  public static int Start(string[] args, int argc)
  {
      ArgumentNullException.ThrowIfNull(args);
+
+ #if !UNIX
+     // Allocate console before anything touches CONOUT$/CONIN$ handles.
+     EarlyConsoleInit(args);
+ #endif
+
  #if DEBUG

Warning

Ordering constraint: EarlyConsoleInit() must run before EarlyStartup.Init(). The Lazy<ConsoleHandle> in ConsoleControl.cs opens CONOUT$ via CreateFile — it's a once-only Lazy initializer, so if accessed before a console exists, the HostException is cached permanently. The console must exist before any background warmup (AMSI, Compiler init) touches it.

Root cause and how the fix works
flowchart TD
    A["pwsh.exe launched with\n-WindowStyle Hidden"] --> B{"Windows checks\nPE subsystem"}

    B -->|"CUI (current behavior)"| C["OS creates visible\nconsole window"]
    C --> D["Main() starts"]
    D --> E["PowerShell parses\n-WindowStyle Hidden"]
    E --> F["ShowWindow(SW_HIDE)"]
    F --> G["Window already\nflashed on screen"]

    B -->|"CUI + detached manifest\n(this PR)"| H["OS skips\nconsole allocation"]
    H --> I["Main() starts"]
    I --> J["EarlyConsoleInit()\nscans args immediately"]
    J --> K["AllocConsoleWithOptions\n(NoWindow)"]
    K --> L["Console I/O works\nNo window ever appeared"]
Loading

The key insight: previous fixes tried to hide the window faster. This fix prevents the window from being created at all by shifting console allocation from the OS to PowerShell.

How EarlyConsoleInit decides what to do

flowchart LR
    A["EarlyConsoleInit(args)"] --> B{"GetConsoleWindow()\n!= 0?"}
    B -->|"Yes (inherited /\nolder Windows)"| C["return\n(leave to SetConsoleMode)"]

    B -->|"No (detached policy /\nDETACHED_PROCESS /\nCREATE_NO_WINDOW)"| F{"-WindowStyle\nHidden?"}
    F -->|Yes| G["TryAllocConsoleNoWindow()"]
    F -->|No| H["TryAllocConsoleDefault()"]

    G -->|"API missing\n(older Windows)"| I["no-op\n(preserve existing behavior)"]
    H -->|"API missing\n(older Windows)"| J["no-op\n(preserve existing behavior)"]
Loading
Early arg scan design

EarlyCheckForHiddenWindowStyle(args) runs before CommandLineParameterParser. Uses ReadOnlySpan<char> for zero heap allocations.

Matches:

  • Single dash: -w, -wi, -win, ..., -windowstyle
  • Double dash: --w, --windowstyle (strips second dash, matching GetSwitchKey)
  • Forward slash: /w, /windowstyle
  • Case-insensitive via StringComparison.OrdinalIgnoreCase

Design tradeoffs:

  • False positives acceptable — worst case is allocating a hidden console that the full parser later makes visible
  • False negatives fall through to the existing SetConsoleMode path which handles -WindowStyle via ShowWindow
  • Colon syntax (-windowstyle:hidden) intentionally unhandled — the full parser's MatchSwitch also does not split on colons for this parameter
Why no AllocConsole() fallback in EarlyConsoleInit

Per DHowett's review: plain AllocConsole() overrides DETACHED_PROCESS from the parent's CreateProcess call and force-creates a console. AllocConsoleWithOptions with Default mode respects the parent's intent.

The manifest (consoleAllocationPolicy=detached) and the API (AllocConsoleWithOptions) were designed and shipped together in Windows 11 build 26100. Therefore:

  • API available → manifest is effective → TryAlloc* handles everything
  • API not available → manifest is ignored → OS auto-allocated the console → GetConsoleWindow() != 0 → EarlyConsoleInit returns early (no-op)
  • DETACHED_PROCESS on older Windows → only path where TryAlloc* returns false and no console exists → existing behavior is no console I/O; a plain AllocConsole() fallback would defeat DETACHED_PROCESS

NativeCommandProcessor.AllocateHiddenConsole() retains its AllocConsole() fallback because native commands unconditionally need a console for I/O — that's a different contract than startup allocation.

Both TryAllocConsoleNoWindow() and TryAllocConsoleDefault() funnel through a shared TryAllocConsoleWithMode() helper that checks result != AllocConsoleResult.NoConsole.

DETACHED_PROCESS + -WindowStyle Hidden

daxian-dbw raised an inconsistency: with -WindowStyle Hidden, NoWindow mode creates a console even under DETACHED_PROCESS, while without -WindowStyle Hidden, Default mode respects DETACHED_PROCESS and creates none.

This is intentional. Per the API docs, ALLOC_CONSOLE_MODE_NO_WINDOW "allocates a console session without a window, even if this process was created with DETACHED_PROCESS." When the user explicitly passes -WindowStyle Hidden, they are requesting invisible PowerShell with working I/O (Write-Host, native commands, pipeline). The alternative — honoring DETACHED_PROCESS and providing no console, causing stdin/stdout crashes — is strictly worse.

Launch flags Without -WindowStyle Hidden With -WindowStyle Hidden
Normal Default → new visible console NoWindow → new invisible console
DETACHED_PROCESS Default → NoConsole (respected) NoWindow → new invisible console (user asked for I/O)
CREATE_NO_WINDOW Default → ExistingConsole (no-op) NoWindow → ExistingConsole (no-op)
API reference
API Docs Notes
AllocConsoleWithOptions learn.microsoft.com Returns HRESULT, takes ALLOC_CONSOLE_OPTIONS* and ALLOC_CONSOLE_RESULT*
ALLOC_CONSOLE_OPTIONS learn.microsoft.com { ALLOC_CONSOLE_MODE mode; BOOL useShowWindow; WORD showWindow; }

Minimum: Windows 11 24H2 (build 26100) / Windows Server 2025

Test coverage

13 Pester tests in WindowStyleHidden.Tests.ps1 (Pester 4 compatible — -Skip on It blocks, not Context):

Context Tests
Manifest verification PE embedded manifest extraction
Output capture -WindowStyle Hidden -Command, pipeline, Write-Host, exit codes
Arg prefix variants -w, -win, --windowstyle, /windowstyle, -WINDOWSTYLE
API probe AllocConsoleWithOptions availability detection
Regression Normal startup, -WindowStyle Normal
Known limitations
  • Unix: All changes are #if !UNIX guarded — no effect, no risk.
  • Windows Server Core / RDP sessions: Not explicitly tested. Progressive enhancement design means no regression risk, but behavior under headless or remote display contexts has not been verified.
  • -NonInteractive interaction: The early arg scan only looks for -WindowStyle Hidden. It does not check -NonInteractive. This matches existing behavior (the full parser handles -NonInteractive separately).
  • pwsh-preview.exe: No separate pwsh-preview.manifest exists in the repo. If the preview binary shares the same manifest, the fix applies automatically.
  • Colon syntax (-windowstyle:hidden): Intentionally unhandled — the full parser's MatchSwitch also does not split on colons for this parameter. Open to guidance if reviewers feel the early scan should handle it.

PR Context

Issue #3028 has been open since January 2017 with 160+ upvotes. Two previous PRs attempted to fix it:

PR Approach Result
#10962 Separate pwshw.exe (WinExe subsystem) Closed — 127 test failures; Write-Host, Read-Host, native commands broke
#10965 Parser-level changes Closed — 66 test failures

Both failed because pwsh.exe is a CUI binary and Windows creates a visible console window before Main() runs. The flash cannot be eliminated by optimizing managed code startup — the window is created by the Windows loader. The fix required an OS-level mechanism: consoleAllocationPolicy and AllocConsoleWithOptions, shipped in Windows 11 build 26100. The Windows Console team (DHowett — designer/implementer of consoleAllocationPolicy) recommended this approach in issue #3028.

📚 Interactive walkthrough of this fix — visual before/after comparisons, annotated source changes, and quizzes

PR Checklist

  • PR has a meaningful title
    • Use the present tense and imperative mood when describing your changes
  • Summarized changes
  • Make sure all .h, .cpp, .cs, .ps1 and .psm1 files have the correct copyright header
  • This PR is ready to merge. If this PR is a work in progress, please open this as a Draft Pull Request and mark it as Ready to Review when it is ready to merge.
  • Breaking changes
    • None
    • OR
    • Experimental feature(s) needed
      • Experimental feature name(s):
  • User-facing changes
    • Not Applicable
    • OR
    • Documentation needed
      • Issue filed: Document -WindowStyle Hidden behavior change on Windows 11 24H2+ MicrosoftDocs/PowerShell-Docs#12897
  • Testing - New and feature
    • N/A or can only be tested interactively
    • OR
    • Make sure you've added a new test if existing tests do not effectively test the code changed

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
@SufficientDaikon
Fix -WindowStyle Hidden console window flash
5dfe5ae
Use consoleAllocationPolicy=detached manifest and AllocConsoleWithOptions
to prevent the OS from auto-allocating a visible console window on newer
Windows. On older Windows the manifest is ignored and behavior is unchanged.

On Windows 11 build 26100+, the detached policy stops the OS from
creating a console window before any code runs. PowerShell now allocates
the console itself at the earliest point in startup — visibly for
interactive use, or invisibly via AllocConsoleWithOptions(NoWindow) when
-WindowStyle Hidden is specified.

This approach was recommended by @DHowett (Windows Console team) in
PowerShell#3028 (comment)

Fix PowerShell#3028
@SufficientDaikon
Ahmed Taha (SufficientDaikon) requested a review from a team as a code owner March 28, 2026 12:42
@SufficientDaikon
Address review: zero-alloc arg scan, shared helper, test cleanup
4b4a8ef
- Replace Substring(1) with AsSpan(1) for zero-alloc early arg parsing
- Extract TryAllocConsoleNoWindow() into Interop.Windows (DRY)
- Add XML doc comments to AllocConsoleWithOptions enums and struct
- Document colon-syntax and false-positive behavior in arg scanner
- Change test tag from CI to Feature (matches existing WindowStyle tests)
- Remove hardcoded build number from API probe test
- Add -ErrorAction Stop to Add-Type in tests
- Use double quotes consistently in test file
@DHowett

Dustin L. Howett (DHowett) commented Mar 28, 2026

Copy link
Copy Markdown

This sounds awesome! I haven't been able to give it an in-depth review, but I do have a note from reading the PR description.

If you are on a version of Windows which has AllocConsoleWithOptions, you should always use it (when coupled with the "detached" policy). Using AllocConsole will override a CreateProcess(... DETACHED_PROCESS), whereas AllocConsoleWithOptions with ALLOC_CONSOLE_MODE_DEFAULT will respect DETACHED_PROCESS.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@SufficientDaikon @claude
Use AllocConsoleWithOptions(Default) for normal launches
1a86fe6
Per DHowett's feedback: plain AllocConsole() overrides DETACHED_PROCESS
from the parent's CreateProcess call. AllocConsoleWithOptions with
Default mode respects it. Extract shared TryAllocConsoleWithMode() and
add TryAllocConsoleDefault() alongside TryAllocConsoleNoWindow().

Co-Authored-By: Claude Opus 4.6 <[email protected]>
@SufficientDaikon

Ahmed Taha (SufficientDaikon) commented Mar 28, 2026 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown
Contributor Author

Thanks Dustin L. Howett (@DHowett)! Great catch — you're absolutely right.

I've pushed a fix in 1a86fe6: normal (non-hidden) launches now use AllocConsoleWithOptions(Default) instead of plain AllocConsole(), so DETACHED_PROCESS from the parent's CreateProcess call is properly respected.

The logic is now:

  • -WindowStyle Hidden → AllocConsoleWithOptions(NoWindow) — invisible console session
  • Normal launch → AllocConsoleWithOptions(Default) — respects parent's detach intent
  • Older Windows (API missing) → falls back to AllocConsole() via catch (EntryPointNotFoundException)

Both helpers go through a shared TryAllocConsoleWithMode() to keep it DRY.

generated by opus.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@DHowett

Dustin L. Howett (DHowett) commented Mar 28, 2026

Copy link
Copy Markdown

Great catch — you're absolutely right.

It is rude to respond to people with AI-generated text.

mjr4077au reacted with heart emoji
All reactions
  • ❤️ 1 reaction

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@SufficientDaikon
Merge branch 'master' into fix/windowstyle-hidden-console-flash
b2a7b30
@SufficientDaikon

Ahmed Taha (SufficientDaikon) commented Mar 28, 2026 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown
Contributor Author

Dustin L. Howett (@DHowett) i'm sorry, won't happen again.

i automated the process too much, i'm working on dialing it down and adding rules to prevent comments all together because that's not at all the kind of automation i'm looking for.

but yes, thank you so much for your reply, and i really do appreciate it because the powershell repo is waaay to big for me to understand quickly enough for my PRs to not have mistakes, so i need feedback so i can keep working on iterating on the PRs i'm making quickly so they get merged as cleanly as easily as possible.

again, i apologize, that is incrediblly rude, i didn't mean for that to happen at all, i also acknowledge that i should've been more attentive of what my powershell agent was doing.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@DHowett

Dustin L. Howett (DHowett) commented Mar 28, 2026

Copy link
Copy Markdown

Ahmed Taha (@SufficientDaikon) hey thanks for saying all that :) it's really cool that the tools of the modern day allow you to take on a daunting task like this! I know everyone's still figuring out their whole workflow, so don't feel too bad!

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@SufficientDaikon

Ahmed Taha (SufficientDaikon) commented Mar 28, 2026 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown
Contributor Author

Dustin L. Howett (@DHowett)
omg i was like panicking thinking i made a huge error, i appreciate that you're so understanding, that's actually so nice, i'm not worried now of actaully making the PRs i want because this whole time i'm just trying to fix my problems but they're way too big to be reviewed in a timely manner 😅

but yea, i'll keep working on this and tag you when i need input.

thank you again, i appreciate your understanding ❤️

DHowett reacted with heart emoji
All reactions
  • ❤️ 1 reaction

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@SufficientDaikon @claude
Handle --windowstyle double-dash in early scan, expand tests
86735ad
The early arg scan only stripped one leading dash, so --windowstyle
hidden was not detected (the key became "-windowstyle" with length 12,
failing the <= "windowstyle".Length check). Add double-dash stripping
to match the full parser's GetSwitchKey behavior.

Remove misleading comment claiming colon syntax is handled by the full
parser (GetSwitchKey does not split on colons for windowstyle).

Rewrite manifest test to extract embedded manifest from PE binary
instead of checking a source file that doesn't exist in $PSHOME.

Add 5 early arg scan variant tests: -w, -win, --windowstyle,
/windowstyle, UPPERCASE. Total: 12 Pester tests.

Co-Authored-By: Claude Opus 4.6 <[email protected]>
@kilasuit Ryan Yates (kilasuit) added WG-Engine core PowerShell engine, interpreter, and runtime CL-Engine Indicates that a PR should be marked as an engine change in the Change Log WG-NeedsReview Needs a review by the labeled Working Group labels Mar 28, 2026
@SufficientDaikon Ahmed Taha (SufficientDaikon) mentioned this pull request Mar 29, 2026
Document -WindowStyle Hidden behavior change on Windows 11 24H2+ MicrosoftDocs/PowerShell-Docs#12897
Open
@daxian-dbw
Dongbo Wang (daxian-dbw) requested a review from Copilot March 30, 2026 17:36
Copilot started reviewing on behalf of Dongbo Wang (daxian-dbw) March 30, 2026 17:54
View session
Copilot AI reviewed Mar 30, 2026
View reviewed changes

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

There was a problem hiding this comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR aims to eliminate the visible console window “flash” when launching pwsh -WindowStyle Hidden on newer Windows builds by opting into detached console allocation via the app manifest and proactively allocating the console in Main() using AllocConsoleWithOptions.

Changes:

  • Add consoleAllocationPolicy=detached to pwsh’s embedded manifest to prevent OS auto-allocating a visible console on Win11 24H2+.
  • Add AllocConsoleWithOptions interop helpers and use them during early console initialization and hidden-console allocation.
  • Add a new Pester test file intended to validate manifest and -WindowStyle Hidden behavior.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 7 comments.

Show a summary per file
File Description
assets/pwsh.manifest Opts into detached console allocation policy on newer Windows builds.
src/System.Management.Automation/engine/Interop/Windows/AllocConsoleWithOptions.cs Introduces P/Invoke + helpers for AllocConsoleWithOptions.
src/Microsoft.PowerShell.ConsoleHost/host/msh/ManagedEntrance.cs Adds early console allocation logic prior to EarlyStartup.Init().
src/Microsoft.PowerShell.ConsoleHost/host/msh/ConsoleControl.cs Makes SetConsoleMode resilient when no console window handle exists.
src/System.Management.Automation/engine/NativeCommandProcessor.cs Prefers allocating a hidden console via AllocConsoleWithOptions(NoWindow) when needed.
test/powershell/Host/WindowStyleHidden.Tests.ps1 Adds tests for manifest presence and -WindowStyle Hidden behavior.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
Comment thread test/powershell/Host/WindowStyleHidden.Tests.ps1 Resolved

Uh oh!

There was an error while loading. Please reload this page.

Comment thread test/powershell/Host/WindowStyleHidden.Tests.ps1 Resolved

Uh oh!

There was an error while loading. Please reload this page.

Comment thread test/powershell/Host/WindowStyleHidden.Tests.ps1 Resolved

Uh oh!

There was an error while loading. Please reload this page.

Comment thread src/System.Management.Automation/engine/NativeCommandProcessor.cs
Comment on lines +2492 to +2516
// Try AllocConsoleWithOptions with NoWindow mode first to avoid the flash
// that the AllocConsole() + ShowWindow(SW_HIDE) pattern causes.
bool allocated = Interop.Windows.TryAllocConsoleNoWindow();

bool returnValue;
if (hwnd == nint.Zero)
if (!allocated)
{
returnValue = false;
}
else
{
returnValue = true;
// Fallback for older Windows: allocate and then hide.
Interop.Windows.AllocConsole();
hwnd = Interop.Windows.GetConsoleWindow();
if (hwnd == nint.Zero)
{
return false;
}

Interop.Windows.ShowWindow(hwnd, Interop.Windows.SW_HIDE);
AlwaysCaptureApplicationIO = true;
}

AlwaysCaptureApplicationIO = true;

if (savedForeground != nint.Zero && Interop.Windows.GetForegroundWindow() != savedForeground)
{
Interop.Windows.SetForegroundWindow(savedForeground);
}

return returnValue;
return true;

Copilot AI Mar 30, 2026

Copy link

There was a problem hiding this comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AllocateHiddenConsole() now returns true whenever TryAllocConsoleNoWindow() returns true, without verifying that a console was actually allocated/attached. Previously the code validated by checking GetConsoleWindow() after allocation and returned false if it was still zero. To preserve the method’s contract, consider validating console allocation after the NoWindow call and falling back (or returning false) if no console is present.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
Copilot uses AI. Check for mistakes.
Comment thread src/System.Management.Automation/engine/Interop/Windows/AllocConsoleWithOptions.cs Resolved

Uh oh!

There was an error while loading. Please reload this page.

Comment thread src/Microsoft.PowerShell.ConsoleHost/host/msh/ManagedEntrance.cs Resolved

Uh oh!

There was an error while loading. Please reload this page.

Comment thread test/powershell/Host/WindowStyleHidden.Tests.ps1 Resolved

Uh oh!

There was an error while loading. Please reload this page.

@SufficientDaikon
Fix Pester 4 compat: move -Skip from Context to It blocks
87933d3
CI uses Pester 4.x which does not support -Skip on Context blocks,
causing 'A parameter cannot be found that matches parameter name Skip'
on all three platforms.

Move -Skip:(!$IsWindows) to individual It blocks (standard pattern).

Also addresses Copilot review feedback:
- Add CI tag so tests run in standard CI (not just Others)
- Remove Assembly::LoadFile path (pwsh.exe is native, not managed)
- Use repo-relative path via $PSScriptRoot for manifest fallback
- Add return after Set-ItResult -Skipped per Pester guidance

Co-authored-by: Copilot <[email protected]>
daxian-dbw
Dongbo Wang (daxian-dbw) reviewed Mar 30, 2026
View reviewed changes
Comment thread src/System.Management.Automation/engine/NativeCommandProcessor.cs Resolved

Uh oh!

There was an error while loading. Please reload this page.

Comment thread assets/pwsh.manifest Resolved

Uh oh!

There was an error while loading. Please reload this page.

Comment thread src/Microsoft.PowerShell.ConsoleHost/host/msh/ManagedEntrance.cs Resolved

Uh oh!

There was an error while loading. Please reload this page.

Comment thread src/Microsoft.PowerShell.ConsoleHost/host/msh/ManagedEntrance.cs Resolved

Uh oh!

There was an error while loading. Please reload this page.

Comment thread src/Microsoft.PowerShell.ConsoleHost/host/msh/ManagedEntrance.cs Resolved

Uh oh!

There was an error while loading. Please reload this page.

@DHowett

Dustin L. Howett (DHowett) commented Mar 30, 2026

Copy link
Copy Markdown

(FWIW, as a note for the author -- I'm not just the person who recommended consoleAllocationPolicy, but the person who designed and implemented it. 🙂 )

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

daxian-dbw
Dongbo Wang (daxian-dbw) reviewed Mar 31, 2026
View reviewed changes
Comment thread src/Microsoft.PowerShell.ConsoleHost/host/msh/ManagedEntrance.cs
Comment on lines +141 to +142
nint existingConsole = Interop.Windows.GetConsoleWindow();
if (existingConsole != nint.Zero)

@daxian-dbw Dongbo Wang (daxian-dbw) Mar 31, 2026

Copy link
Copy Markdown
Member

There was a problem hiding this comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Dustin L. Howett (@DHowett) If the process is started by CreateProcess with the CREATE_NO_WINDOW flag, it may inherit the existing console session but have no console window created for it, right?

If so, existingConsole would be nint.Zero in that case, and we will call AllocConsoleWithOptions in the new code path. I guess AllocConsoleWithOptions(Default) will return that existing console session, but what will AllocConsoleWithOptions(No_Window) do in that case?

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
@SufficientDaikon

Ahmed Taha (SufficientDaikon) commented Mar 31, 2026

Copy link
Copy Markdown
Contributor Author

(FWIW, as a note for the author -- I'm not just the person who recommended consoleAllocationPolicy, but the person who designed and implemented it. 🙂 )

Wow, how does one go about designing and architecting something that'll be used by millions? where do you even start so you make sure people's computers don't like... explode? xD

Dongbo Wang (@daxian-dbw) thank you so much for feedback, very very helpful, you're mentioning things i haven't even thought of.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@SufficientDaikon
Ahmed Taha (SufficientDaikon) force-pushed the fix/windowstyle-hidden-console-flash branch 2 times, most recently from 4a930c9 to 4050f51 Compare March 31, 2026 07:14
@SufficientDaikon
Address reviewer feedback from daxian-dbw and DHowett
6214139
EarlyConsoleInit: remove early ShowWindow(SW_HIDE) for existing consoles
per daxian-dbw — leave -WindowStyle handling to the existing SetConsoleMode
code path. EarlyConsoleInit now only handles the no-console case.

TryAllocConsoleWithMode: check AllocConsoleResult instead of discarding it.
Return false when result is NoConsole (DETACHED_PROCESS respected) so
callers know a console was not actually allocated.

NativeCommandProcessor: add comment clarifying foreground window restore
runs for both NoWindow and fallback paths.

Manifest: add XML comment explaining why asm.v3 xmlns is required on
the application element (distinct from root asm.v1 namespace).

Co-authored-by: Copilot <[email protected]>
@SufficientDaikon
Ahmed Taha (SufficientDaikon) force-pushed the fix/windowstyle-hidden-console-flash branch from 4050f51 to 6214139 Compare March 31, 2026 07:43
@SufficientDaikon
Merge branch 'master' into fix/windowstyle-hidden-console-flash
add7938
@DHowett

Dustin L. Howett (DHowett) commented Mar 31, 2026

Copy link
Copy Markdown

where do you even start so you make sure people's computers don't like... explode? xD

Hah, well, the jury is still out on whether I've made any computers explode. :)

Honestly though... this has been a problem that bugged me for years and years. I wrote a spec (here), forgot about it, sent it to people to get their opinions, promoted it on Twitter, got a few responses, let it sit for multiple years (it was written in 2020 and completed in 2023!)... and then when it seemed like everything was agreed, started writing the code.

Then we had a Microsoft-internal "API review" and the AllocConsoleWithOptions API changed a good amount between what I originally wrote and what we finally shipped.

If you want to see all the gory discussion details, they're over here: microsoft/terminal#7337

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@SufficientDaikon

Ahmed Taha (SufficientDaikon) commented Mar 31, 2026

Copy link
Copy Markdown
Contributor Author

If you want to see all the gory discussion details, they're over here: microsoft/terminal#7337

You really didn't have to ask, i love this stuff, looks like I have reading material for tonight, thanks for sharing!

I'm always interested in learning how engineers solve the problems they find often times there's a fun story that comes a along with it, and it always fun to see how people even come up with soultions in the first place it been helping me in thinking how to solve my own problems, even none software people have problems to solve and they come up with soultions that I wouldn't even think to consider, so yeah I'm really excited to read that pr.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@htcfreek

Heiko (htcfreek) commented Apr 2, 2026

Copy link
Copy Markdown

Nice. ♥️ Will this get backported to PowerShell 5.1?

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@SufficientDaikon

Ahmed Taha (SufficientDaikon) commented Apr 2, 2026 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown
Contributor Author

Nice. ♥️ Will this get backported to PowerShell 5.1?

Idk, I made this for me, but if there's a lot of people still on older versions I don't mind doing the work to backport. Lemme lookup how many powershell users are still on older versions

Edit: ooof okay, yea I'll see what I can do xD

htcfreek reacted with heart emoji
All reactions
  • ❤️ 1 reaction

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@microsoft-github-policy-service microsoft-github-policy-service Bot added the Review - Needed The PR is being reviewed label Apr 10, 2026
@SufficientDaikon

Ahmed Taha (SufficientDaikon) commented Apr 10, 2026

Copy link
Copy Markdown
Contributor Author

Oh, yea, i forgot, I'm gonna see if I can backport this

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@SufficientDaikon

Ahmed Taha (SufficientDaikon) commented Apr 16, 2026

Copy link
Copy Markdown
Contributor Author

Nice. ♥️ Will this get backported to PowerShell 5.1?

So bad news, can't back port that far

Good news, I'll just add a migration guide in the docs, you may as well update at this point.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@SufficientDaikon

Ahmed Taha (SufficientDaikon) commented Jun 6, 2026

Copy link
Copy Markdown
Contributor Author

Dustin L. Howett (@DHowett) is there something holding this up? Need to put on my CV "I'm an open source contributer" and it be true xD

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@jshigetomi

Justin Chung (jshigetomi) commented Jun 26, 2026

Copy link
Copy Markdown
Collaborator

Ahmed Taha (@SufficientDaikon) Great work here! Seems like this has been thoroughly reviewed and comments addressed.

LGTM

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

jshigetomi
Justin Chung (jshigetomi) approved these changes Jun 26, 2026
View reviewed changes
iSazonov
Ilya (iSazonov) reviewed Jun 26, 2026
View reviewed changes
Comment thread src/System.Management.Automation/engine/Interop/Windows/AllocConsoleWithOptions.cs Resolved

Uh oh!

There was an error while loading. Please reload this page.

Comment thread test/powershell/Host/WindowStyleHidden.Tests.ps1 Resolved

Uh oh!

There was an error while loading. Please reload this page.

Ahmed Taha (SufficientDaikon) and others added 3 commits July 22, 2026 17:20
@SufficientDaikon
Merge branch 'master' into fix/windowstyle-hidden-console-flash
4025927
@SufficientDaikon
Address review feedback on console allocation
6b44701
Cache AllocConsoleWithOptions availability in a static field so later calls
skip the P/Invoke and its exception once the API is known to be missing,
matching the s_WNetApiNotAvailable pattern in WNetGetConnection.cs.

Restore the foreground window on the AllocateHiddenConsole early-return path.
AllocConsole() can shift focus even when GetConsoleWindow() returns zero, so
the restore now runs on every path that captured it.

Remove the AllocConsoleWithOptions probe test. It asserted only that a
bool-returning method returns a bool, so it passed regardless of the fix.
@SufficientDaikon
Merge branch 'master' into fix/windowstyle-hidden-console-flash
8b2913a
@DHowett

Dustin L. Howett (DHowett) commented Jul 28, 2026

Copy link
Copy Markdown

(FYI: I am not on the powershell team, and so I cannot actually meaningfully approve this PR such that it would merge.)

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@SufficientDaikon
Merge branch 'master' into fix/windowstyle-hidden-console-flash
29560fa
@SufficientDaikon

Ahmed Taha (SufficientDaikon) commented Aug 3, 2026

Copy link
Copy Markdown
Contributor Author

(FYI: I am not on the powershell team, and so I cannot actually meaningfully approve this PR such that it would merge.)

i see.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

jshigetomi
Justin Chung (jshigetomi) approved these changes Aug 14, 2026
View reviewed changes
Ahmed Taha (SufficientDaikon) added 2 commits August 15, 2026 00:26
@SufficientDaikon
Merge branch 'master' into fix/windowstyle-hidden-console-flash
76e8650
@SufficientDaikon
Merge branch 'master' into fix/windowstyle-hidden-console-flash
c938459
@mklement0

Michael Klement (mklement0) commented Nov 9, 2026

Copy link
Copy Markdown
Contributor

Dustin L. Howett (@DHowett), as an aside re:

whereas AllocConsoleWithOptions with ALLOC_CONSOLE_MODE_DEFAULT will respect DETACHED_PROCESS.

As of this writing, PowerShell actually quietly aborts on startup when launched with DETACHED_PROCESS, as it unconditionally looks for a console and aborts if it cannot find one, without logging a WER event and with spurious exit code 0

  • Launching pwsh.exe without a console (DETACHED_PROCESS) results in quiet startup failure #28383
All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@DHowett

Dustin L. Howett (DHowett) commented Nov 9, 2026

Copy link
Copy Markdown

As of this writing, PowerShell actually quietly aborts on startup when launched with DETACHED_PROCESS,

That seems significantly less than ideal. 😱

mklement0 reacted with thumbs up emoji
All reactions
  • 👍 1 reaction

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

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

Reviewers

@daxian-dbw Dongbo Wang (daxian-dbw) daxian-dbw left review comments
@iSazonov Ilya (iSazonov) iSazonov left review comments
Copilot code review Copilot
Copilot review effort
Applies to this pull request for everyone.Learn more about Copilot code review.
Copilot left review comments
@jshigetomi Justin Chung (jshigetomi) jshigetomi approved these changes
+2 more reviewers
@DHowett Dustin L. Howett (DHowett) DHowett left review comments
@6c6bshmpqs-cell 6c6bshmpqs-cell 6c6bshmpqs-cell left review comments
Reviewers whose approvals may not affect merge requirements

Uh oh!

There was an error while loading. Please reload this page.

Assignees

No one assigned

Labels

CL-Engine Indicates that a PR should be marked as an engine change in the Change Log Review - Needed The PR is being reviewed WG-Engine core PowerShell engine, interpreter, and runtime WG-NeedsReview Needs a review by the labeled Working Group

Projects

None yet

Milestone

No milestone

Development

Successfully merging this pull request may close these issues.

Powershell -WindowStyle Hidden still shows a window briefly

Uh oh!

There was an error while loading. Please reload this page.

10 participants

@SufficientDaikon @DHowett @htcfreek @jshigetomi @mklement0 @daxian-dbw @iSazonov @6c6bshmpqs-cell @kilasuit
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
You are visitor 01402503 — GeezerVison does not store the pages you look up.
Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.