From aee3c9214d90abb8199db17f0bfcf60236aee89e Mon Sep 17 00:00:00 2001 From: KirtiRamchandani Date: Sun, 24 May 2026 19:18:43 +0530 Subject: [PATCH 1/2] Respect explicit false for CSV UseCulture --- .../commands/utility/CsvCommands.cs | 9 +++------ .../ConvertFrom-Csv.Tests.ps1 | 8 ++++++++ .../ConvertTo-Csv.Tests.ps1 | 8 ++++++++ .../Export-Csv.Tests.ps1 | 14 ++++++++++++++ .../Import-Csv.Tests.ps1 | 7 +++++++ 5 files changed, 40 insertions(+), 6 deletions(-) diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/CsvCommands.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/CsvCommands.cs index cb455417531..3c408811242 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/CsvCommands.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/CsvCommands.cs @@ -1787,12 +1787,9 @@ internal static char SetDelimiter(PSCmdlet cmdlet, string parameterSetName, char case "UseCulture": case "CulturePath": case "CultureLiteralPath": - if (useCulture) - { - // ListSeparator is apparently always a character even though the property returns a string, checked via: - // [CultureInfo]::GetCultures("AllCultures") | % { ([CultureInfo]($_.Name)).TextInfo.ListSeparator } | ? Length -ne 1 - delimiter = CultureInfo.CurrentCulture.TextInfo.ListSeparator[0]; - } + // ListSeparator is apparently always a character even though the property returns a string, checked via: + // [CultureInfo]::GetCultures("AllCultures") | % { ([CultureInfo]($_.Name)).TextInfo.ListSeparator } | ? Length -ne 1 + delimiter = useCulture ? CultureInfo.CurrentCulture.TextInfo.ListSeparator[0] : ImportExportCSVHelper.CSVDelimiter; break; default: diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/ConvertFrom-Csv.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/ConvertFrom-Csv.Tests.ps1 index b5573609fbf..87542485ca5 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Utility/ConvertFrom-Csv.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/ConvertFrom-Csv.Tests.ps1 @@ -60,6 +60,14 @@ a,b,c $actualLength | Should -Be 3 } + It "Uses the default delimiter when -UseCulture is explicitly false" { + $actualData = $testColumns | ConvertFrom-Csv -UseCulture:$false + + $actualData.a | Should -Be 1 + $actualData.b | Should -Be 2 + $actualData.c | Should -Be 3 + } + It "Should Contain the Imported Type data" { $actualData = $testTypeData | ConvertFrom-Csv $actualData.PSObject.TypeNames.Count | Should -Be 2 diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/ConvertTo-Csv.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/ConvertTo-Csv.Tests.ps1 index bfba7718272..28bc7b86363 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Utility/ConvertTo-Csv.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/ConvertTo-Csv.Tests.ps1 @@ -27,6 +27,14 @@ Describe "ConvertTo-Csv DRT Unit Tests" -Tags "CI" { $returnObject[2] | Should -BeExactly "`"1`"$($delimiter)`"2`"" } + It "Test convertto-csv with UseCulture explicitly false" { + $returnObject = $inputObject | ConvertTo-Csv -UseCulture:$false -IncludeTypeInformation + $returnObject.Count | Should -Be 3 + $returnObject[0] | Should -BeExactly "#TYPE System.Management.Automation.PSCustomObject" + $returnObject[1] | Should -BeExactly "`"First`",`"Second`"" + $returnObject[2] | Should -BeExactly "`"1`",`"2`"" + } + It "Test convertto-csv with Delimiter" { $returnObject = $inputObject | ConvertTo-Csv -Delimiter ";" -IncludeTypeInformation $returnObject.Count | Should -Be 3 diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/Export-Csv.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/Export-Csv.Tests.ps1 index aae457f2f82..ca0983cd857 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Utility/Export-Csv.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/Export-Csv.Tests.ps1 @@ -91,6 +91,20 @@ Describe "Export-Csv" -Tags "CI" { $results[0] | Should -BeExactly "#TYPE System.String" } + It "Uses the default delimiter when -UseCulture is explicitly false" { + $P1 | Export-Csv -Path $testCsv -UseCulture:$false + $results = Get-Content -Path $testCsv + + $results[0] | Should -BeExactly '"P1"' + $results[1] | Should -BeExactly '"first"' + + [pscustomobject]@{ H1 = 'V1'; H2 = 'V2' } | Export-Csv -Path $testCsv -UseCulture:$false + $results = Get-Content -Path $testCsv + + $results[0] | Should -BeExactly '"H1","H2"' + $results[1] | Should -BeExactly '"V1","V2"' + } + It "Should support -LiteralPath parameter" { $testObject | Export-Csv -LiteralPath $testCsv $results = Import-Csv -Path $testCsv diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/Import-Csv.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/Import-Csv.Tests.ps1 index debd3f3001b..4ef1609f1b3 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Utility/Import-Csv.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/Import-Csv.Tests.ps1 @@ -20,6 +20,13 @@ Describe "Import-Csv DRT Unit Tests" -Tags "CI" { $returnObject.First | Should -Be 1 $returnObject.Second | Should -Be 2 } + + It "Test import-csv with UseCulture explicitly false" { + $psObject | Export-Csv -Path $fileToGenerate + $returnObject = Import-Csv -Path $fileToGenerate -UseCulture:$false + $returnObject.First | Should -Be 1 + $returnObject.Second | Should -Be 2 + } } Describe "Import-Csv Double Quote Delimiter" -Tags "CI" { From f3acfebf654fbcbed9ef00921aee37393d216035 Mon Sep 17 00:00:00 2001 From: KirtiRamchandani Date: Sun, 24 May 2026 19:24:18 +0530 Subject: [PATCH 2/2] Use non-comma culture in CSV UseCulture tests --- .../ConvertFrom-Csv.Tests.ps1 | 23 +++++++++++---- .../ConvertTo-Csv.Tests.ps1 | 25 ++++++++++++---- .../Export-Csv.Tests.ps1 | 29 ++++++++++++++----- .../Import-Csv.Tests.ps1 | 23 +++++++++++---- 4 files changed, 76 insertions(+), 24 deletions(-) diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/ConvertFrom-Csv.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/ConvertFrom-Csv.Tests.ps1 index 87542485ca5..787e488b833 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Utility/ConvertFrom-Csv.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/ConvertFrom-Csv.Tests.ps1 @@ -61,11 +61,24 @@ a,b,c } It "Uses the default delimiter when -UseCulture is explicitly false" { - $actualData = $testColumns | ConvertFrom-Csv -UseCulture:$false - - $actualData.a | Should -Be 1 - $actualData.b | Should -Be 2 - $actualData.c | Should -Be 3 + $originalCulture = [System.Threading.Thread]::CurrentThread.CurrentCulture + $originalUICulture = [System.Threading.Thread]::CurrentThread.CurrentUICulture + + try { + [System.Threading.Thread]::CurrentThread.CurrentCulture = [CultureInfo]'de-DE' + [System.Threading.Thread]::CurrentThread.CurrentUICulture = [CultureInfo]'de-DE' + [CultureInfo]::CurrentCulture.TextInfo.ListSeparator | Should -Not -BeExactly ',' + + $actualData = $testColumns | ConvertFrom-Csv -UseCulture:$false + + $actualData.a | Should -Be 1 + $actualData.b | Should -Be 2 + $actualData.c | Should -Be 3 + } + finally { + [System.Threading.Thread]::CurrentThread.CurrentCulture = $originalCulture + [System.Threading.Thread]::CurrentThread.CurrentUICulture = $originalUICulture + } } It "Should Contain the Imported Type data" { diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/ConvertTo-Csv.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/ConvertTo-Csv.Tests.ps1 index 28bc7b86363..39751311baf 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Utility/ConvertTo-Csv.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/ConvertTo-Csv.Tests.ps1 @@ -27,12 +27,25 @@ Describe "ConvertTo-Csv DRT Unit Tests" -Tags "CI" { $returnObject[2] | Should -BeExactly "`"1`"$($delimiter)`"2`"" } - It "Test convertto-csv with UseCulture explicitly false" { - $returnObject = $inputObject | ConvertTo-Csv -UseCulture:$false -IncludeTypeInformation - $returnObject.Count | Should -Be 3 - $returnObject[0] | Should -BeExactly "#TYPE System.Management.Automation.PSCustomObject" - $returnObject[1] | Should -BeExactly "`"First`",`"Second`"" - $returnObject[2] | Should -BeExactly "`"1`",`"2`"" + It "Uses the default delimiter when -UseCulture is explicitly false" { + $originalCulture = [System.Threading.Thread]::CurrentThread.CurrentCulture + $originalUICulture = [System.Threading.Thread]::CurrentThread.CurrentUICulture + + try { + [System.Threading.Thread]::CurrentThread.CurrentCulture = [CultureInfo]'de-DE' + [System.Threading.Thread]::CurrentThread.CurrentUICulture = [CultureInfo]'de-DE' + [CultureInfo]::CurrentCulture.TextInfo.ListSeparator | Should -Not -BeExactly ',' + + $returnObject = $inputObject | ConvertTo-Csv -UseCulture:$false -IncludeTypeInformation + $returnObject.Count | Should -Be 3 + $returnObject[0] | Should -BeExactly "#TYPE System.Management.Automation.PSCustomObject" + $returnObject[1] | Should -BeExactly "`"First`",`"Second`"" + $returnObject[2] | Should -BeExactly "`"1`",`"2`"" + } + finally { + [System.Threading.Thread]::CurrentThread.CurrentCulture = $originalCulture + [System.Threading.Thread]::CurrentThread.CurrentUICulture = $originalUICulture + } } It "Test convertto-csv with Delimiter" { diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/Export-Csv.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/Export-Csv.Tests.ps1 index ca0983cd857..afe951b833c 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Utility/Export-Csv.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/Export-Csv.Tests.ps1 @@ -92,17 +92,30 @@ Describe "Export-Csv" -Tags "CI" { } It "Uses the default delimiter when -UseCulture is explicitly false" { - $P1 | Export-Csv -Path $testCsv -UseCulture:$false - $results = Get-Content -Path $testCsv + $originalCulture = [System.Threading.Thread]::CurrentThread.CurrentCulture + $originalUICulture = [System.Threading.Thread]::CurrentThread.CurrentUICulture - $results[0] | Should -BeExactly '"P1"' - $results[1] | Should -BeExactly '"first"' + try { + [System.Threading.Thread]::CurrentThread.CurrentCulture = [CultureInfo]'de-DE' + [System.Threading.Thread]::CurrentThread.CurrentUICulture = [CultureInfo]'de-DE' + [CultureInfo]::CurrentCulture.TextInfo.ListSeparator | Should -Not -BeExactly ',' - [pscustomobject]@{ H1 = 'V1'; H2 = 'V2' } | Export-Csv -Path $testCsv -UseCulture:$false - $results = Get-Content -Path $testCsv + $P1 | Export-Csv -Path $testCsv -UseCulture:$false + $results = Get-Content -Path $testCsv + + $results[0] | Should -BeExactly '"P1"' + $results[1] | Should -BeExactly '"first"' - $results[0] | Should -BeExactly '"H1","H2"' - $results[1] | Should -BeExactly '"V1","V2"' + [pscustomobject]@{ H1 = 'V1'; H2 = 'V2' } | Export-Csv -Path $testCsv -UseCulture:$false + $results = Get-Content -Path $testCsv + + $results[0] | Should -BeExactly '"H1","H2"' + $results[1] | Should -BeExactly '"V1","V2"' + } + finally { + [System.Threading.Thread]::CurrentThread.CurrentCulture = $originalCulture + [System.Threading.Thread]::CurrentThread.CurrentUICulture = $originalUICulture + } } It "Should support -LiteralPath parameter" { diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/Import-Csv.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/Import-Csv.Tests.ps1 index 4ef1609f1b3..4a08164a384 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Utility/Import-Csv.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/Import-Csv.Tests.ps1 @@ -21,11 +21,24 @@ Describe "Import-Csv DRT Unit Tests" -Tags "CI" { $returnObject.Second | Should -Be 2 } - It "Test import-csv with UseCulture explicitly false" { - $psObject | Export-Csv -Path $fileToGenerate - $returnObject = Import-Csv -Path $fileToGenerate -UseCulture:$false - $returnObject.First | Should -Be 1 - $returnObject.Second | Should -Be 2 + It "Uses the default delimiter when -UseCulture is explicitly false" { + $originalCulture = [System.Threading.Thread]::CurrentThread.CurrentCulture + $originalUICulture = [System.Threading.Thread]::CurrentThread.CurrentUICulture + + try { + [System.Threading.Thread]::CurrentThread.CurrentCulture = [CultureInfo]'de-DE' + [System.Threading.Thread]::CurrentThread.CurrentUICulture = [CultureInfo]'de-DE' + [CultureInfo]::CurrentCulture.TextInfo.ListSeparator | Should -Not -BeExactly ',' + + $psObject | Export-Csv -Path $fileToGenerate + $returnObject = Import-Csv -Path $fileToGenerate -UseCulture:$false + $returnObject.First | Should -Be 1 + $returnObject.Second | Should -Be 2 + } + finally { + [System.Threading.Thread]::CurrentThread.CurrentCulture = $originalCulture + [System.Threading.Thread]::CurrentThread.CurrentUICulture = $originalUICulture + } } }