Skip to content

$PROFILE variable has changed type and behavior #3653

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
5 tasks done
sburbano opened this issue Oct 29, 2021 · 7 comments
Closed
5 tasks done

$PROFILE variable has changed type and behavior #3653

sburbano opened this issue Oct 29, 2021 · 7 comments
Assignees
Labels
Area-Extension Terminal Bug: Pre-release Bugs reproducing only in the pre-release extension. Issue-Bug A bug to squash. Resolution-Fixed Will close automatically.

Comments

@sburbano
Copy link

Prerequisites

  • I have written a descriptive issue title.
  • I have searched all issues to ensure it has not already been reported.
  • I have read the troubleshooting guide.
  • I am sure this issue is with the extension itself and does not reproduce in a standalone PowerShell instance.
  • I have verified that I am using the latest version of Visual Studio Code and the PowerShell extension.

Summary

Since updating to the latest preview, the $PROFILE variable in the Integrated Console has changed its type, from String to PSCustomObject.

Before:

PS>$PROFILE.GetType()

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------     
True     True     String                                   System.Object

After:

PS>$PROFILE.GetType()

IsPublic IsSerial Name                                     BaseType     
-------- -------- ----                                     --------     
True     False    PSCustomObject                           System.Object

This change in type also changes the way the variable is coerced to other types, output to console etc possibly breaking any script that use this variable.

Before:

PS>$PROFILE

C:\Users\sburbano\Documents\PowerShell\Microsoft.VSCode_profile.ps1

After:

PS>$PROFILE

AllUsersAllHosts                          AllUsersCurrentHost                                        CurrentUserAllHosts                                CurrentUserCurrentHost
----------------                          -------------------                                        -------------------                                ----------------------
C:\Program Files\PowerShell\7\profile.ps1 C:\Program Files\PowerShell\7\Microsoft.VSCode_profile.ps1 C:\Users\sburbano\Documents\PowerShell\profile.ps1 C:\Users\sburbano\Documents\PowerShell\Microsoft.VSCode_profile.ps1

In my case, for example, custom theme loading in the profile has stopped working, because this function has stopped working.

PS>Get-ThemesLocation
Join-Path: C:\Users\sburbano\Documents\PowerShell\Modules\oh-my-posh\2.0.487\defaults.ps1:5:17
Line |
   5 |          return (Join-Path (Split-Path -Parent $PROFILE) $folderName)
     |                  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     | Cannot find drive. A drive with the name '@{AllUsersAllHosts=C' does not exist.

Might be related to #3650

PowerShell Version

PS>$PSVersionTable

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

Visual Studio Code Version

1.62.0-insider
ff1e16eebb93af79fd6d7af1356c4003a120c563
x64

Extension Version

Steps to Reproduce

Compare the output of

PS>$PROFILE

in the PS Integrated Console and any other Powershell Console (regular pwsh.exe, Windows Terminal, ...)

Visuals

No response

Logs

No response

@sburbano sburbano added the Issue-Bug A bug to squash. label Oct 29, 2021
@ghost ghost added the Needs: Triage Maintainer attention needed! label Oct 29, 2021
@SeeminglyScience
Copy link
Collaborator

Needs to be a PSObject wrapped string with additional PSNotePropertys:

PSObject profile = PSObject.AsPSObject("C:\CurrentUserCurrentHostPathEtc");
profile.Properties.Add(new PSNoteProperty("AllUsersAllHosts", "pathhere"));
profile.Properties.Add(new PSNoteProperty("AllUsersCurrentHost", "pathhere"));
profile.Properties.Add(new PSNoteProperty("CurrentUserAllHosts", "pathhere"));
profile.Properties.Add(new PSNoteProperty("CurrentUserCurrentHost", "pathhere"));

@sburbano
Copy link
Author

This is inconsistent with pswh.exe .

Try this in a regular PS console.

PS>$PROFILE.GetType()

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     True     String                                   System.Object

PS>$PROFILE | Get-Member

   TypeName: System.String

Name                   MemberType            Definition
----                   ----------            ----------
[...]
AllUsersAllHosts       NoteProperty          string AllUsersAllHosts=C:\Program Files\PowerShell\7\profile.ps1
AllUsersCurrentHost    NoteProperty          string AllUsersCurrentHost=C:\Program Files\PowerShell\7\Microsoft.PowerShell_profile.ps1
CurrentUserAllHosts    NoteProperty          string CurrentUserAllHosts=C:\Users\sburbano\Documents\PowerShell\profile.ps1
CurrentUserCurrentHost NoteProperty          string CurrentUserCurrentHost=C:\Users\sburbano\Documents\PowerShell\Microsoft.PowerShell_profile.ps1
[...]

May be pwsh.exe is doing something under the covers or treating $PROFILE differently, idk. In fact, I have tried to Add-Member a simple string variable to no avail.

PS>$test = "Some string"
PS>$test.GetType()

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     True     String                                   System.Object

PS>Add-Member -InputObject $test -NotePropertyName "SomeProperty" -NotePropertyValue "SomeValue"
PS>Get-Member -InputObject $test

   TypeName: System.String

Name                 MemberType            Definition
----                 ----------            ----------
[ ommitted for brevity, but NO SomeProperty]

@sburbano
Copy link
Author

Just for the sake of completeness...

This is even mentioned in the official documentation

image

@SeeminglyScience
Copy link
Collaborator

SeeminglyScience commented Oct 29, 2021

@sburbano strings are unfortunately very complicated when it comes to ETS properties. When handled in C#, it's pretty simple since no PowerShell engine magic gets in the way. In PowerShell you gotta be a bit explicit. More specifically the first line needs to be:

$test = [psobject]"Some string"

So typically any reference type object has it's manually added ETS members preserved between PSObject wrapper instances. When the engine inevitably unwraps the wrapper and later rewraps it, it looks up the base object in a member resurrection table and sticks them on the new wrapper. That makes it look and feel like it was never wrapped in the first place since all of this is supposed to be mostly invisible.

Strings specifically are special cased to work a bit more like primitives/other structs (most likely because they are immutable and can be interned). So if you want to add ETS members to a string you must preserve the PSObject wrapper instance.

In general that's not super feasible to do which is why I typically tell folks to just not do it, but it works fine for a automatic variable (and it's what SMA's ConsoleHost does, and what we did previously).

@sburbano
Copy link
Author

@SeeminglyScience Wow!! I see!

PS>$test = [psobject]"Some string"
PS>$test.GetType()

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     True     String                                   System.Object

PS>Add-Member -InputObject $test -NotePropertyName "SomeProperty" -NotePropertyValue "Some value"
PS>Get-Member -InputObject $test

   TypeName: System.String

Name                 MemberType            Definition
----                 ----------            ----------
[...]
SomeProperty         NoteProperty          string SomeProperty=Some value

PS is like a box of chocolates... 😄

@andyleejordan andyleejordan added the Bug: Pre-release Bugs reproducing only in the pre-release extension. label Oct 29, 2021
@SeeminglyScience
Copy link
Collaborator

Yeah PSObject is kind of hard to inspect since a pretty significant amount of objects are going to be invisibly wrapped in PSObject many times throughout their lifetime. Really when you call .GetType(), that's routed through the PSInvokeMemberBinder which controls method invocations are dynamically bound. For the most part, GetType() will never lie. Except with PSObjects when they're wrapping other objects.

One thing that never lies (currently) though is -is. $test -is [psobject] will return true if the object is currently wrapped in a PSObject.

It gets very confusing but thankfully it doesn't come up as a problem unless you look real close 😁

@andyleejordan andyleejordan removed the Needs: Triage Maintainer attention needed! label Nov 1, 2021
@andyleejordan andyleejordan added this to the Committed-vNext milestone Nov 1, 2021
@andyleejordan andyleejordan self-assigned this Nov 1, 2021
@ghost ghost added the Needs: Maintainer Attention Maintainer attention needed! label Nov 1, 2021
@andyleejordan andyleejordan added Resolution-Fixed Will close automatically. and removed Needs: Maintainer Attention Maintainer attention needed! labels Nov 3, 2021
@andyleejordan andyleejordan changed the title $PROFILE variable has changed type and behavior $PROFILE variable has changed type and behavior Nov 3, 2021
@ghost
Copy link

ghost commented Nov 4, 2021

This issue has been marked as fixed. It has been automatically closed for housekeeping purposes.

@ghost ghost closed this as completed Nov 4, 2021
This issue was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area-Extension Terminal Bug: Pre-release Bugs reproducing only in the pre-release extension. Issue-Bug A bug to squash. Resolution-Fixed Will close automatically.
Projects
None yet
Development

No branches or pull requests

3 participants