Changing culture settings is not taken into account in the PowerShell Extension's PowerShell instance
Prerequisites
- [X] I have written a descriptive issue title.
- [X] I have searched all open and closed issues to ensure it has not already been reported.
- [X] I have read the troubleshooting guide.
- [X] I am sure this issue is with the extension itself and does not reproduce in a standalone PowerShell instance.
- [X] I have verified that I am using the latest version of Visual Studio Code and the PowerShell extension.
- [X] If this is a security issue, I have read the security issue reporting guidance.
Summary
Changing the culture's settings such as the time format has no effect in the PowerShell Extension:
PowerShell Version
PSVersion 7.3.7
PSEdition Core
GitCommitId 7.3.7
OS Microsoft Windows 10.0.22621
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.82.2
abd2f3db4bdb28f9e95536dfa84d8479f1eb312d
x64
Extension Version
[email protected]
[email protected]
Steps to Reproduce
From the PowerShell Extension's PowerShell prompt, run the following script:
# derived from https://github.com/PowerShell/PowerShell/issues/19536#issuecomment-1515140128
# Save the original culture.
$global:originalculture = [cultureinfo]::CurrentCulture
# Temporarily replace it with a read/write copy.
[cultureinfo]::CurrentCulture = [cultureinfo] $global:originalculture.Name
# Modify the LongTimePattern format to include milliseconds.
[cultureinfo]::CurrentCulture.DateTimeFormat.LongTimePattern += ([cultureinfo]::CurrentCulture.NumberFormat.CurrencyDecimalSeparator + 'fff')
This has no effect to e.g. the output from Get-Date:
PS> Set-LongTimePatternToIncludeMilliseconds.ps1
PS> Get-Date
Saturday, September 30, 2023 12:23:05
Whereas the result is correct in a "normal" PowerShell instance:
PS> Set-LongTimePatternToIncludeMilliseconds.ps1
PS> get-date
Saturday, September 30, 2023 12:24:17.297
Visuals
No response
Logs
No response
I'm not sure your script does what you think it does. When I try to run it line-by-line in a PowerShell 7 Extension Terminal, I get an error:
> $global:originalculture = [cultureinfo]::CurrentCulture
> [cultureinfo]::CurrentCulture = [cultureinfo] $global:originalculture.Name
> [cultureinfo]::CurrentCulture.DateTimeFormat.LongTimePattern += ([cultureinfo]::CurrentCulture.NumberFormat.CurrencyDecimalSeparator + 'fff')
SetValueInvocationException: Exception setting "LongTimePattern": "Instance is read-only."
Ok so I took a modified version of the script and found something interesting. If I run this in its entirety (as in like via F5) it works as expected, but when run line-by-line the culture seems to get reset and is no longer writable when we try to modify it (like what I saw with your script):
# Save the original culture.
$original = [cultureinfo]::CurrentCulture
# Temporarily replace it with a read/write copy.
[cultureinfo]::CurrentCulture = $original.Clone()
[cultureinfo]::CurrentCulture.DateTimeFormat.LongTimePattern = 'HH\:mm\:ss.fff'
Get-Date
Ok I think that's my recommendation: run what you're trying to do in a single-go so that the thread-specific changes stick to the CurrentCulture for when you need them. While every task is supposed to be on the same PSES Pipeline Thread, something about how the REPL loop works is making CurrentCulture read-only again on each invocation. Which means you can do something like this (where Get-Date is run in the same REPL as updating the culture) and it works:
$original = [cultureinfo]::CurrentCulture
$newCulture = $original.Clone()
$newCulture.DateTimeFormat.LongTimePattern = 'HH\:mm\:ss.fff'
[cultureinfo]::CurrentCulture = $newCulture; Get-Date
That script works line by line.
This still doesn't fit my bill.
What I need is a way to change the behavior of all commands within the session so that DateTime's are displayed / exported with milliseconds.
With the original script, this works in "standard" PowerShell, but not in the PowerShell Extension Terminal.
Why not pass a format string to Get-Date, or change the culture on the system, or use a pwsh instance other than the Extension Terminal?
The point is that I'm developing (and thus debugging) a bunch of scripts that manipulate, compute, extract from application logs, export to Excel or CSV... DateTime object properties from various sources / equations, and it would be very much impractical to modify each and every piece of code to explicitly specify a time format with milliseconds.
It would be equally impractical to request that each and every user of that set of scripts on the team change their system's global configuration to include milliseconds in their time format (not to mention the inconvenience in getting milliseconds everywhere where you don't want/need them).
How would I debug those scripts with a non-Extension Terminal pwsh instance?
@SteveL-MSFT, do you think the behavior I'm experiencing in "standard" PowerShell is "officially expected"? If so, IMVHO the Extension Terminal should align its culture handling with that...
The Extension Terminal does not (read: cannot) always behave exactly the same as a regular pwsh instance because its primary function is the hosting of the LSP server powering all of the extension's features. In this case, I highly suggest you just use a separate pwsh terminal, which can be created with ease of clicking the + button in the Terminal Pane of VS Code; you can then still use "run selection" to execute your code line-by-line in that terminal. I might suggest you set powershell.integratedConsole.startInBackground to true so that the Extension Terminal does not show up at all, eliminating any confusion.
I also verified that running the script as given in the debugger works exactly as it should, so you can debug it 😀 Note that you actually need to use the debugger (set a breakpoint) and not just the "run" button (which does not start the debugger but instead pastes the script into the focused terminal, which again could be a regular pwsh terminal if you switch to that).
This doesn't fit my bill. When debugging one of my scripts (that's what I need to debug, of course, not the Set-LongTimePatternToIncludeMilliseconds.ps1 script itself), the interaction via the VScode terminal is done via the Extension's terminal, where changing the culture's format doesn't work.
Would there be a way to have the time format for Extension instances different from the one in non-Extension instances? This could be an acceptable workaround, even though I'd get milliseconds all the time when debugging scripts, not only when debugging the specific scripts where I need that... I've tried calling Set-LongTimePatternToIncludeMilliseconds.ps1 from Microsoft.VSCode_profile.ps1 but that doesn't work 😢