Skip to content

Refactor the module path construction code to make it more robust and easier to maintain#26565

Merged
daxian-dbw merged 9 commits intoPowerShell:masterfrom
daxian-dbw:debug
Dec 12, 2025
Merged

Refactor the module path construction code to make it more robust and easier to maintain#26565
daxian-dbw merged 9 commits intoPowerShell:masterfrom
daxian-dbw:debug

Conversation

@daxian-dbw
Copy link
Copy Markdown
Member

@daxian-dbw daxian-dbw commented Dec 3, 2025

PR Summary

Fix #26536

There are 2 issues surfaced from #26536 that we need to address:

  1. The error reporting in the method ReportExceptionFallback(Exception e, string header) does not write out stack trace of the exception, which makes it hard to diagnose failures like ShellCannotBeStarted.
  2. The UpdatePath method used in module path construction doesn't handle the case where personalModulePathToUse may contain multiple paths separated by the PathSperator (user can define PSModulePath in powershell.config.json with such a value).

The fixes are:

  1. Write out stack trace of the exception in ReportExceptionFallback(Exception e, string header), at the end.
  2. Refactored the module path construction code to make it more robust and easier to maintain
    • Removed the old existing UpdatePath method.
    • Removed the old PathContainsSubstring method. Change to a difference approach that is much more efficient.
    • Refactored the AddPath method and rename it to be UpdatePath
    • Updated SetModulePath() to not blindly add a path separator when the environment variable PSModulePath is initially not set in all scopes.
    • Call SetModulePath() in the static constructor of ModuleIntrinsics instead of the instance constructor. So, we only need to construct the module path once per process (instead of once per a new Runspace).

With the changes, PowerShell won't crash even if the personal module path is like C:\Users\marcv\OneDrive - company & name namepart2\Dokumente\PowerShell\Modules as reported in the issue.

PR Checklist

@microsoft-github-policy-service microsoft-github-policy-service Bot added the Waiting on Author The PR was reviewed and requires changes or comments from the author before being accept label Dec 7, 2025
@daxian-dbw daxian-dbw changed the title [debug] Print the stack trace of the ShellCannotBeStarted error Refactor the module path construction code to make it more robust and easier to maintain Dec 9, 2025
@daxian-dbw daxian-dbw added the CL-Engine Indicates that a PR should be marked as an engine change in the Change Log label Dec 9, 2025
@microsoft-github-policy-service microsoft-github-policy-service Bot removed the Waiting on Author The PR was reviewed and requires changes or comments from the author before being accept label Dec 9, 2025
@daxian-dbw daxian-dbw marked this pull request as ready for review December 10, 2025 00:07
Copy link
Copy Markdown
Contributor

Copilot AI left a 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 refactors the module path construction code in PowerShell to fix issue #26536, which involves two main problems: insufficient error diagnostics in exception fallback handling and incorrect handling of multi-path PSModulePath values from configuration files. The refactoring moves module path initialization to a static constructor, consolidates path manipulation methods, and improves error reporting by including stack traces.

Key Changes

  • Moved module path initialization from instance constructor to static constructor for earlier, one-time initialization
  • Refactored UpdatePath method (previously split between AddToPath and a wrapper UpdatePath) to handle multiple semicolon/colon-separated paths in a single call
  • Enhanced ReportExceptionFallback to output complete stack traces including inner exceptions
  • Added test coverage for PSModulePath configuration with multiple paths

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 10 comments.

File Description
test/powershell/Host/ConsoleHost.Tests.ps1 Added test for PSModulePath with multiple paths from config file; contains platform-specific path separator issues
src/System.Management.Automation/engine/Modules/ModuleIntrinsics.cs Refactored module path construction: moved initialization to static constructor, consolidated UpdatePath logic, improved PathContainsSubstring with better return semantics
src/Microsoft.PowerShell.ConsoleHost/host/msh/ConsoleHost.cs Enhanced exception reporting to include stack traces for debugging ShellCannotBeStarted errors; contains potential null reference issues

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/Microsoft.PowerShell.ConsoleHost/host/msh/ConsoleHost.cs Outdated
Comment thread src/Microsoft.PowerShell.ConsoleHost/host/msh/ConsoleHost.cs Outdated
Comment thread test/powershell/Host/ConsoleHost.Tests.ps1 Outdated
Comment thread test/powershell/Host/ConsoleHost.Tests.ps1 Outdated
Comment thread src/System.Management.Automation/engine/Modules/ModuleIntrinsics.cs Outdated
Comment thread src/System.Management.Automation/engine/Modules/ModuleIntrinsics.cs Outdated
Comment thread test/powershell/Host/ConsoleHost.Tests.ps1 Outdated
Comment thread src/System.Management.Automation/engine/Modules/ModuleIntrinsics.cs Outdated
Comment thread src/System.Management.Automation/engine/Modules/ModuleIntrinsics.cs Outdated
Comment thread src/System.Management.Automation/engine/Modules/ModuleIntrinsics.cs Outdated
Comment thread src/Microsoft.PowerShell.ConsoleHost/host/msh/ConsoleHost.cs Outdated
Comment thread src/Microsoft.PowerShell.ConsoleHost/host/msh/ConsoleHost.cs Outdated
Comment thread src/System.Management.Automation/engine/Modules/ModuleIntrinsics.cs Outdated
Comment thread src/System.Management.Automation/engine/Modules/ModuleIntrinsics.cs Outdated
Comment thread src/System.Management.Automation/engine/Modules/ModuleIntrinsics.cs Outdated
Comment thread src/System.Management.Automation/engine/Modules/ModuleIntrinsics.cs Outdated
Comment thread src/System.Management.Automation/engine/Modules/ModuleIntrinsics.cs Outdated
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 3 out of 3 changed files in this pull request and generated 4 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread test/powershell/Host/ConsoleHost.Tests.ps1
Comment thread src/System.Management.Automation/engine/Modules/ModuleIntrinsics.cs
Comment thread src/System.Management.Automation/engine/Modules/ModuleIntrinsics.cs Outdated
Comment thread src/System.Management.Automation/engine/Modules/ModuleIntrinsics.cs
Copy link
Copy Markdown
Collaborator

@iSazonov iSazonov left a comment

Choose a reason for hiding this comment

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

On top of ModuleIntrinsics.cs I see we define Tracer. It would be nice to add to the trace source and result path strings for more easy diagnostics.

Comment thread src/System.Management.Automation/engine/Modules/ModuleIntrinsics.cs
// Local function to normalize a path by removing trailing directory separators.
static string NormalizePath(string path)
{
string normalizedPath = path.TrimEnd(Path.DirectorySeparatorChar);
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Why not use NormalizePath method from FileSystemProvider? Then we will follow the basic PowerShell behavior regarding directory separators.
Otherwise, we could use Path.TrimEndingDirectorySeparator()

Copy link
Copy Markdown
Member Author

@daxian-dbw daxian-dbw Dec 11, 2025

Choose a reason for hiding this comment

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

Path.TrimEndingDirectorySeparator doesn't remove duplicate trailing directory separators. It only removes the ending one. But I think it should be practically fine, and also, I favor over simplicity. We can get back to it if it turns out to be an issue.

Comment thread src/Microsoft.PowerShell.ConsoleHost/host/msh/ConsoleHost.cs
Comment thread src/System.Management.Automation/engine/Modules/ModuleIntrinsics.cs Outdated
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 3 out of 3 changed files in this pull request and generated no new comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread test/powershell/Host/ConsoleHost.Tests.ps1 Outdated
@iSazonov
Copy link
Copy Markdown
Collaborator

Ready to merge.

@daxian-dbw daxian-dbw merged commit 592668b into PowerShell:master Dec 12, 2025
36 checks passed
@daxian-dbw daxian-dbw deleted the debug branch December 12, 2025 17:43
@daxian-dbw
Copy link
Copy Markdown
Member Author

@iSazonov Thanks for the review!

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

Labels

CL-Engine Indicates that a PR should be marked as an engine change in the Change Log

Projects

None yet

3 participants