Possible binding issue with `DateTime` ?
Prerequisites
- [X] Write a descriptive title.
- [X] Make sure you are able to repro it on the latest released version
- [X] Search the existing issues.
- [X] Refer to the FAQ.
- [X] Refer to Differences between Windows PowerShell 5.1 and PowerShell.
Steps to reproduce
There seem to be a binding issue on parameters typed DateTime on PowerShell functions however no such issue happens on binary cmdlets:
Add-Type @'
using System;
using System.Management.Automation;
[Cmdlet("Test", "DateCs")]
public class TestDateCs : PSCmdlet
{
[Parameter(Position = 0)]
public DateTime Date { get; set; }
protected override void EndProcessing() => WriteObject(Date);
}
'@ -PassThru | Import-Module -Assembly { $_.Assembly }
function Test-DatePwsh {
[CmdletBinding()]
param([datetime] $Date)
$Date
}
& {
[System.Threading.Thread]::CurrentThread.CurrentCulture = [cultureinfo]::GetCultureInfo('es-AR')
Test-DatePwsh '28/05/2023 15:05:29' # fails
Test-DateCs '28/05/2023 15:05:29' # works????
}
Looking at the traces for both, we can see that for the binary cmdlet the coercion happens instantly:
ParameterBinding Information: 0 : BIND NAMED cmd line args [Test-DateCs]
ParameterBinding Information: 0 : BIND POSITIONAL cmd line args [Test-DateCs]
ParameterBinding Information: 0 : BIND arg [28/05/2023 15:05:29] to parameter [Date]
ParameterBinding Information: 0 : BIND arg [28/05/2023 15:05:29] to param [Date] SKIPPED
ParameterBinding Information: 0 : BIND arg [28/05/2023 15:05:29] to parameter [Date]
ParameterBinding Information: 0 : COERCE arg to [System.DateTime]
ParameterBinding Information: 0 : Trying to convert argument value from System.String to System.DateTime
ParameterBinding Information: 0 : CONVERT arg type to param type using LanguagePrimitives.ConvertTo
ParameterBinding Information: 0 : CONVERT SUCCESSFUL using LanguagePrimitives.ConvertTo: [28/5/2023 15:05:29]
ParameterBinding Information: 0 : BIND arg [28/5/2023 15:05:29] to param [Date] SUCCESSFUL
ParameterBinding Information: 0 : MANDATORY PARAMETER CHECK on cmdlet [Test-DateCs]
ParameterBinding Information: 0 : CALLING BeginProcessing
ParameterBinding Information: 0 : CALLING ProcessRecord
ParameterBinding Information: 0 : CALLING EndProcessing
However for the pwsh function, doesn't seem to attempt a coercion to System.DateTime:
& {
[System.Threading.Thread]::CurrentThread.CurrentCulture = [cultureinfo]::GetCultureInfo('es-AR')
Trace-Command ParameterBinding { Test-DatePwsh '28/05/2023 15:05:29' } -FilePath trace.txt
Select-String -Path trace.txt -Pattern 'COERCE arg to \[.+]' | ForEach-Object { $_.Matches.Value }
Remove-Item trace.txt -EA 0
}
# COERCE arg to [System.Object]
# COERCE arg to [System.Management.Automation.SwitchParameter]
# COERCE arg to [System.String[]]
# COERCE arg to [System.String]
# COERCE arg to [System.Management.Automation.ActionPreference]
# COERCE arg to [System.Version]
# COERCE arg to [System.Version]
Expected behavior
& {
[System.Threading.Thread]::CurrentThread.CurrentCulture = [cultureinfo]::GetCultureInfo('es-AR')
Test-DatePwsh '28/05/2023 15:05:29'
}
domingo, 28 de mayo de 2023 15:05:29
Actual behavior
Cannot process argument transformation on parameter 'Date'. Cannot convert value "28/05/2023 15:05:29" to type "System.DateTime". Error: "String '' was not recognized as a valid DateTime."
Error details
Exception :
Type : System.Management.Automation.ParameterBindingArgumentTransformationException
Message : Cannot process argument transformation on parameter 'Date'. Cannot convert value "28/05/2023 15:05:29" to type
"System.DateTime". Error: "String '' was not recognized as a valid DateTime."
ParameterName : Date
ParameterType : datetime
TypeSpecified : string
ErrorId : ParameterArgumentTransformationError
Line : 3
Offset : 19
CommandInvocation :
MyCommand : Test-DatePwsh
ScriptLineNumber : 3
OffsetInLine : 5
HistoryId : 26
Line : Test-DatePwsh '28/05/2023 15:05:29'
Statement : Test-DatePwsh '28/05/2023 15:05:29'
PositionMessage : At line:3 char:5
+ Test-DatePwsh '28/05/2023 15:05:29'
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
InvocationName : Test-DatePwsh
PipelineLength : 1
PipelinePosition : 1
CommandOrigin : Internal
ErrorRecord :
Exception :
Type : System.Management.Automation.ParentContainsErrorRecordException
Message : Cannot process argument transformation on parameter 'Date'. Cannot convert value "28/05/2023 15:05:29" to type
"System.DateTime". Error: "String '' was not recognized as a valid DateTime."
HResult : -2146233087
CategoryInfo : InvalidData: (:) [Test-DatePwsh], ParentContainsErrorRecordException
FullyQualifiedErrorId : ParameterArgumentTransformationError,Test-DatePwsh
InvocationInfo :
MyCommand : Test-DatePwsh
ScriptLineNumber : 3
OffsetInLine : 19
HistoryId : 26
Line : Test-DatePwsh '28/05/2023 15:05:29'
Statement : '28/05/2023 15:05:29'
PositionMessage : At line:3 char:19
+ Test-DatePwsh '28/05/2023 15:05:29'
+ ~~~~~~~~~~~~~~~~~~~~~
CommandOrigin : Internal
ScriptStackTrace : at <ScriptBlock>, <No file>: line 3
at <ScriptBlock>, <No file>: line 1
TargetSite :
Name : BindPositionalParametersInSet
DeclaringType : System.Management.Automation.ParameterBinderController, System.Management.Automation, Version=7.4.0.500,
Culture=neutral, PublicKeyToken=31bf3856ad364e35
MemberType : Method
Module : System.Management.Automation.dll
Data : System.Collections.ListDictionaryInternal
InnerException :
Type : System.Management.Automation.ArgumentTransformationMetadataException
ErrorRecord :
Exception :
Type : System.Management.Automation.ParentContainsErrorRecordException
Message : Cannot convert value "28/05/2023 15:05:29" to type "System.DateTime". Error: "String '' was not recognized as a
valid DateTime."
HResult : -2146233087
CategoryInfo : MetadataError: (:) [], ParentContainsErrorRecordException
FullyQualifiedErrorId : RuntimeException
TargetSite :
Name : Transform
DeclaringType : System.Management.Automation.ArgumentTypeConverterAttribute, System.Management.Automation, Version=7.4.0.500,
Culture=neutral, PublicKeyToken=31bf3856ad364e35
MemberType : Method
Module : System.Management.Automation.dll
Message : Cannot convert value "28/05/2023 15:05:29" to type "System.DateTime". Error: "String '' was not recognized as a
valid DateTime."
InnerException :
Type : System.Management.Automation.PSInvalidCastException
ErrorRecord :
Exception :
Type : System.Management.Automation.ParentContainsErrorRecordException
Message : Cannot convert value "28/05/2023 15:05:29" to type "System.DateTime". Error: "String '' was not recognized
as a valid DateTime."
HResult : -2146233087
CategoryInfo : InvalidArgument: (:) [], ParentContainsErrorRecordException
FullyQualifiedErrorId : InvalidCastParseTargetInvocationWithFormatProvider
TargetSite :
Name : ConvertWithCulture
DeclaringType : System.Management.Automation.LanguagePrimitives+ConvertViaParseMethod, System.Management.Automation,
Version=7.4.0.500, Culture=neutral, PublicKeyToken=31bf3856ad364e35
MemberType : Method
Module : System.Management.Automation.dll
Message : Cannot convert value "28/05/2023 15:05:29" to type "System.DateTime". Error: "String '' was not recognized as
a valid DateTime."
InnerException :
Type : System.FormatException
TargetSite :
Name : Parse
DeclaringType : System.DateTimeParse, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral,
PublicKeyToken=7cec85d7bea7798e
MemberType : Method
Module : System.Private.CoreLib.dll
Message : String '' was not recognized as a valid DateTime.
Source : System.Private.CoreLib
HResult : -2146233033
StackTrace :
at System.DateTimeParse.Parse(ReadOnlySpan`1 s, DateTimeFormatInfo dtfi, DateTimeStyles styles)
at System.DateTime.Parse(String s, IFormatProvider provider)
at InvokeStub_DateTime.Parse(Object, Span`1)
at System.Reflection.MethodBaseInvoker.InvokeWithFewArgs(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters,
CultureInfo culture)
Source : System.Management.Automation
HResult : -2147467262
StackTrace :
at System.Management.Automation.LanguagePrimitives.ConvertViaParseMethod.ConvertWithCulture(Object valueToConvert, Type resultType,
Boolean recursion, PSObject originalValueToConvert, IFormatProvider formatProvider, TypeTable backupTable)
at System.Management.Automation.LanguagePrimitives.ConvertTo(Object valueToConvert, Type resultType, Boolean recursion, IFormatProvider
formatProvider, TypeTable backupTypeTable)
at System.Management.Automation.ArgumentTypeConverterAttribute.Transform(EngineIntrinsics engineIntrinsics, Object inputData, Boolean
bindingParameters, Boolean bindingScriptCmdlet)
Source : System.Management.Automation
HResult : -2146233087
StackTrace :
at System.Management.Automation.ArgumentTypeConverterAttribute.Transform(EngineIntrinsics engineIntrinsics, Object inputData, Boolean
bindingParameters, Boolean bindingScriptCmdlet)
at System.Management.Automation.ParameterBinderBase.BindParameter(CommandParameterInternal parameter, CompiledCommandParameter
parameterMetadata, ParameterBindingFlags flags)
Source : System.Management.Automation
HResult : -2146233087
StackTrace :
at System.Management.Automation.ParameterBinderController.BindPositionalParametersInSet(UInt32 validParameterSets, Dictionary`2
nextPositionalParameters, CommandParameterInternal argument, ParameterBindingFlags flags, ParameterBindingException& bindingException)
at System.Management.Automation.ParameterBinderController.BindPositionalParameters(Collection`1 unboundArguments, UInt32
validParameterSets, UInt32 defaultParameterSet, ParameterBindingException& outgoingBindingException)
at System.Management.Automation.CmdletParameterBinderController.BindCommandLineParametersNoValidation(Collection`1 arguments)
at System.Management.Automation.CmdletParameterBinderController.BindCommandLineParameters(Collection`1 arguments)
at System.Management.Automation.CommandProcessor.BindCommandLineParameters()
at System.Management.Automation.CommandProcessor.Prepare(IDictionary psDefaultParameterValues)
at System.Management.Automation.CommandProcessorBase.DoPrepare(IDictionary psDefaultParameterValues)
at System.Management.Automation.Internal.PipelineProcessor.Start(Boolean incomingStream)
at System.Management.Automation.Internal.PipelineProcessor.SynchronousExecuteEnumerate(Object input)
--- End of stack trace from previous location ---
at System.Management.Automation.Internal.PipelineProcessor.SynchronousExecuteEnumerate(Object input)
at System.Management.Automation.PipelineOps.InvokePipeline(Object input, Boolean ignoreInput, CommandParameterInternal[][]
pipeElements, CommandBaseAst[] pipeElementAsts, CommandRedirection[][] commandRedirections, FunctionContext funcContext)
at System.Management.Automation.Interpreter.ActionCallInstruction`6.Run(InterpretedFrame frame)
at System.Management.Automation.Interpreter.EnterTryCatchFinallyInstruction.Run(InterpretedFrame frame)
CategoryInfo : InvalidData: (:) [Test-DatePwsh], ParameterBindingArgumentTransformationException
FullyQualifiedErrorId : ParameterArgumentTransformationError,Test-DatePwsh
InvocationInfo :
MyCommand : Test-DatePwsh
ScriptLineNumber : 3
OffsetInLine : 19
HistoryId : 26
Line : Test-DatePwsh '28/05/2023 15:05:29'
Statement : '28/05/2023 15:05:29'
PositionMessage : At line:3 char:19
+ Test-DatePwsh '28/05/2023 15:05:29'
+ ~~~~~~~~~~~~~~~~~~~~~
CommandOrigin : Internal
ScriptStackTrace : at <ScriptBlock>, <No file>: line 3
at <ScriptBlock>, <No file>: line 1
Environment data
Name Value
---- -----
PSVersion 7.4.0
PSEdition Core
GitCommitId 7.4.0
OS Microsoft Windows 10.0.19045
Platform Win32NT
PSCompatibleVersions {1.0, 2.0, 3.0, 4.0…}
PSRemotingProtocolVersion 2.3
SerializationVersion 1.1.0.1
WSManStackVersion 3.0
Visuals
No response
After a chat with @SeeminglyScience, for PowerShell functions, the issue seem to happen on: https://github.com/PowerShell/PowerShell/blob/e453c006d39a2fa57a903df2d0ea33ddd0cb43dd/src/System.Management.Automation/engine/ArgumentTypeConverterAttribute.cs#L138
I understand changing this line to use CultureInfo.CurrentCulture could cause issues, so this can be closed 😁
Given PowerShell's generally culture-invariant behavior, it is the behavior of binary cmdlets that is the anomaly; see:
- #6989
- #8129
📣 Hey @santisq, how did we do? We would love to hear your feedback with the link below! 🗣️
🔗 https://aka.ms/PSRepoFeedback