Skip to content

Use of script blocks can result in different output behavior with respect to culture-sensitivity #4558

@mklement0

Description

@mklement0

Follow-up to #4545.

  • With expressions, simply wrapping a script block in another script block changes the output behavior with respect to culture-sensitivity, at least with respect to passing a number literal to an unconstrained parameter.

  • With commands - e.g., Write-Host and Write-Output a single script block is enough.

@lzybkr's assessment of this problem:

I forget exact details, but the current culture is reset for reasons I never understood. I thought it was done in the host after each command line, but it looks like it's done more often than that.

This resetting isn't categorical: as the command below shows, the default output of a literal is still localized, and [cultureinfo]::currentculture still reports the specified culture.

So the questions is: In what way is the culture reset (if that's what's going on) and what are the implications?


With commands using cmdlets Write-Host and Write-Output and a single script block:

Steps to reproduce

# The only difference between the 2 commands is that the 2nd one is wrapped in an 
# script block.
[cultureinfo]::CurrentCulture = 'de-DE';  [cultureinfo]::CurrentCulture.Name; Write-Host 1.2; Write-Output 1.2
[cultureinfo]::CurrentCulture = 'de-DE';  & { [cultureinfo]::CurrentCulture.Name; Write-Host 1.2; Write-Output 1.2 }

Expected behavior

1,2
1,2
de-DE
---
1,2
1,2
de-DE

Actual behavior

de-DE
1,2
1,2
---
de-DE
1.2   # !! Due to calling a script block, the output of the unconstrained parameter value changed.
1.2   # ditto

As an aside: Moving the [cultureinfo]::CurrentCulture = 'de-DE' statement into the script block would make the problem go away.


With expressions and nested script blocks:

While the nesting of the script blocks in the example command below is contrived, I actually ran into this problem in a real-world scenario:
I'm using a function called Use-Culture (inspired by this oldie-but-goodie blog post by @rkeithhill) that accepts a script block to be executed in the context of a specified culture that is temporarily switched to, with invocations such as Use-Culture de-DE { & { $Args[0] } 1.2 }, in which script blocks are nested.

Steps to reproduce

# The only difference between the 2 commands is that the 2nd one is wrapped in an 
# extra script block.
[cultureinfo]::CurrentCulture = 'de-DE'; & { $Args[0]; 1.2; [cultureinfo]::currentculture.Name } 1.2
'---'
[cultureinfo]::CurrentCulture = 'de-DE'; & { & { $Args[0]; 1.2; [cultureinfo]::currentculture.Name } 1.2 } 

Expected behavior

1,2
1,2
de-DE
---
1,2
1,2
de-DE

Actual behavior

1,2
1,2
de-DE
---
1.2   # !! Due to the nested script block, the output of the unconstrained parameter value changed.
1,2
de-DE

Note that the fact that the non-nested invocation's unconstrained parameter value is output in culture-sensitive format - it uses , as the decimal mark - is actually a bug - see #4557.

Environment data

PowerShell Core v6.0.0-beta.5 on macOS 10.12.6
PowerShell Core v6.0.0-beta.5 on Ubuntu 16.04.3 LTS
PowerShell Core v6.0.0-beta.5 on Microsoft Windows 10 Pro (64-bit; v10.0.15063)
Windows PowerShell v5.1.15063.483 on Microsoft Windows 10 Pro (64-bit; v10.0.15063)

Metadata

Metadata

Assignees

No one assigned

    Labels

    Issue-Discussionthe issue may not have a clear classification yet. The issue may generate an RFC or may be reclassifResolution-No ActivityIssue has had no activity for 6 months or moreWG-Enginecore PowerShell engine, interpreter, and runtime

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions