PS> Add-Type -TypeDefinition @'
using System;
using System.Management.Automation;
[Cmdlet("Test", "Compiled")]
public class TestCompiled : PSCmdlet {
[Parameter(Position = 0)]
public DateTime DT;
protected override void EndProcessing() {
WriteObject(DT);
}
}
'@ -PassThru | Select-Object -First 1 -ExpandProperty Assembly | Import-Module
PS> function Test-Script {
param(
[DateTime]$DT
)
$DT
}
PS> @(
[CultureInfo]::CurrentCulture = 'ru-RU'
Test-Compiled 1/11/1111
Test-Script 1/11/1111
[CultureInfo]::CurrentCulture = 'en-US'
)
Wednesday, November 1, 1111 12:00:00 AM
Wednesday, January 11, 1111 12:00:00 AM
Same dates in both cases.
Strings get parsed with different culture in mind.
> $PSVersionTable
Name Value
---- -----
GitCommitId v6.0.0-alpha.17-18-gedecf7e04d65f7183cd1d278daa5ebed2970813f
PSRemotingProtocolVersion 2.3
PSEdition Core
WSManStackVersion 3.0
CLRVersion
BuildVersion 3.0.0.0
PSVersion 6.0.0-alpha
PSCompatibleVersions {1.0, 2.0, 3.0, 4.0, 5.0, 5.1.10032.0, 6.0.0}
SerializationVersion 1.1.0.1
I think the problem happens due to PowerShell automatically adds ArgumentTypeConverterAttribute to typed parameters for script cmdlets:
PS> (Get-Command Test-Script).Parameters.DT.Attributes | % GetType | % FullName
System.Management.Automation.ParameterAttribute
System.Management.Automation.ArgumentTypeConverterAttribute
but not doing the same for compiled cmdlets:
PS> (Get-Command Test-Compiled).Parameters.DT.Attributes | % GetType | % FullName
System.Management.Automation.ParameterAttribute
That attribute make conversion use InvariantCulture, while compiled cmdlets use CurrentCulture for conversion.
@SteveL-MSFT I think we should fix this before RTM.
@PetSerAl Thanks for the analysis!
ArgumentTypeConverterAttribute uses InvariantCulture when calling LanguagePrimitives.ConvertTo, while ParameterBinderBase.CoerceTypeAsNeeded uses CurrentCulture when calling LanguagePrimitives.ConvertTo.
I will submit a PR to change ArgumentTypeConverterAttribute to use CurrentCulture as well.
@daxian-dbw
I will submit a PR to change
ArgumentTypeConverterAttributeto useCurrentCultureas well.
Should it be other way around? Since PowerShell explicit cast use InvariantCulture:
@(
[CultureInfo]::CurrentCulture = 'ru-RU'
[DateTime] '1/11/1111'
[String] 1.1
[CultureInfo]::CurrentCulture = 'en-US'
)
I would expect that implicit cast to parameter type should also use InvariantCulture.
@PetSerAl That's a good point. I will change ParameterBinderBase.CoerceTypeAsNeeded to use InvariantCulture.
It seems strange that PowerShell ignores Culture.
We need more discussion - it is breaking change.
@iSazonov I guess it's for the scripts to be more portable. I added the breaking change label.
I think it is not documented. We need good description for this "portability" with InvariantCulture in argument convertion and parameter binding. Otherwise we'll have a big misunderstanding and many negative feedbacks.
Also we need @powershell-committee approvement for a breaking change.
Both my comment is for your PR.
@PowerShell/powershell-committee has rejected the PR #5106. Quote the decision here:
@PowerShell/powershell-committee reviewed this and due to the potential for breaking many existing modules, it's too risky to make this change so that c# and script cmdlets are alike for this case. We should keep the current behavior.
I will close this issue as 'Won't Fix'.
Does anyone know how many (module) breaking changes we've already made? It seems so much that talking about these changes is no longer relevant.
Also if we already is InvariantCulture for arguments and casting in scripts where is entry points where customers can catch problems?
@iSazonov One example I got from the committee was the C# modules running on, for example, Japanese machines. After this change, it may happen that some cmdlets are broken with the same input arguments because the conversion has changed.
But I do agree with you that this inconsistency is unpleasant 馃
I have another example - EMS (Microsoft Exchange server Management Shell).
If you is not on English culture session it's always a huge mystery for you to make a search request! The situation is even worse if you try to make such a request dynamically in a script. In essence, you cannot create a script that you can trust. :disappointed:
I think we should consider this Issue more closely.
Interesting, I presume the EMS example is where the current CurrentCulture conversion behavior causes a usability issue, right? So in this case, it's preferable to have InvariantCulture conversion so that things can work on non-english culture environment?
Proxies certainly make this issue more complicated - something may work when calling the cmdlet, but a proxy is introduced (e.g. for RBAC) and now it doesn't.