Skip to content

ModuleIntrinsics.GetPSModulePath returns a hard-coded path, rather than the one PowerShell is actually using #24274

Description

@Jaykul

Prerequisites

Steps to reproduce

Set your user's powershell.config.json PSModulePath

The example here is Windows-specific:

$configPath = Join-Path (Split-Path $Profile) powershell.config.json
if (Test-Path $configPath) {
  $config = Get-Content $configPath | ConvertFrom-Json
  $config.PSModulePath = "%LOCALAPPDATA%\powershell\Modules"
} else {
  $config = @{ PSModulePath = "%LOCALAPPDATA%\powershell\Modules" }
}

$config | ConvertTo-Json | Set-Content $configPath

In a new PowerShell instance:

$Actual = cmd /c "echo %LOCALAPPDATA%\powershell\Modules"
$Api = [Management.Automation.ModuleIntrinsics]::GetPSModulePath('User')
Compare-Object $Api $Actual -IncludeEqual

Expected behavior

GetPSModulePath('User') should return the path the user has configured, so the two values should be the same.

InputObject                                         SideIndicator
-----------                                         -------------
S:\OneDrive - PoshCode\Documents\PowerShell\Modules ==

Actual behavior

InputObject                                         SideIndicator
-----------                                         -------------
C:\Users\Jaykul\AppData\Local\powershell\Modules    =>
S:\OneDrive\Documents\PowerShell\Modules            <=

Environment data

Name                           Value
----                           -----
PSVersion                      7.4.5
PSEdition                      Core
GitCommitId                    7.4.5
OS                             Microsoft Windows 10.0.22635
Platform                       Win32NT
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0…}
PSRemotingProtocolVersion      2.3
SerializationVersion           1.1.0.1
WSManStackVersion              3.0

Activity

  1. Jaykul commented on Sep 11, 2024

    @Jaykul
    ContributorAuthor

    I'm not sure why this API (added in #19422) is ignoring the config.json. Maybe James Truher (@JamesWTruher) remembers?

    If the purpose is to "allow PSResourceGet to simplify code for installations in PowerShell 7" this oversight means that people can't actually use the config.json, because changing the config does affect where PowerShell looks, but doesn't affect PSResourceGet or anyone else using this API.

  2. JustinGrote commented on Sep 11, 2024

    @JustinGrote
    Contributor

    This is in my opinion the expected behavior for this API, it could be accomplished with a method override.

    #Fetches the module path for the current user or all users
    function Get-PSModulePath ([Switch]$AllUsers) {
    	$scopeType = [Management.Automation.Configuration.ConfigScope]
    	$pscType = $scopeType.
    	Assembly.
    	GetType('System.Management.Automation.Configuration.PowerShellConfig')
    
    	$pscInstance = $pscType.
    	GetField('Instance', [Reflection.BindingFlags]'Static,NonPublic').
    	GetValue($null)
    
    	$getModulePathMethod = $pscType.GetMethod('GetModulePath', [Reflection.BindingFlags]'Instance,NonPublic')
    
    	if ($AllUsers) {
    		$getModulePathMethod.Invoke($pscInstance, $scopeType::AllUsers) ?? [Management.Automation.ModuleIntrinsics]::GetPSModulePath('BuiltIn')
    	} else {
    		$getModulePathMethod.Invoke($pscInstance, $scopeType::CurrentUser) ?? [Management.Automation.ModuleIntrinsics]::GetPSModulePath('User') 
    	}
    }
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

    Needs-TriageThe issue is new and needs to be triaged by a work group.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions