ConvertTo-CSV -UseCulture忽略当前线程的文化

时间:2016-11-29 15:40:39

标签: export-to-csv cultureinfo powershell-v4.0 uiculture

问题

在具有2 Go<br>文化的Windows会话中运行时,是否可以强制PowerShell以法语格式导出为CSV?

更多信息

我希望使用法国文化规则将一些数据导出为CSV(即CSV的分隔符设置为分号,但也使用逗号表示小数位数,以及其他文化格式差异;所以只使用{{1} }参数是不够的。)

我提出了以下代码(基于https://stackoverflow.com/a/7052955/361842

en-GB

以下代码表示此方法有效:

-Delimiter

然而,PowerShell有自己的想法

function Set-Culture
{
    [CmdletBinding(DefaultParameterSetName='ByCode')]
    param (
        [Parameter(Mandatory,ParameterSetName='ByCode',Position=1)]
        [string] $CultureCode
        ,
        [Parameter(Mandatory,ParameterSetName='ByCulture',Position=1)]
        [System.Globalization.CultureInfo] $Culture
    )
    begin {
        [System.Globalization.CultureInfo] $Culture = [System.Globalization.CultureInfo]::GetCultureInfo($CultureCode) 
    }
    process {
        [System.Threading.Thread]::CurrentThread.CurrentUICulture = $Culture
        [System.Threading.Thread]::CurrentThread.CurrentCulture = $Culture
    }
}

function Invoke-CommandInCulture {
    [CmdletBinding()]
    param (
        [Parameter(Mandatory,ParameterSetName='ByCode',Position=1)]
        [string]$CultureCode
        ,
        [Parameter(Mandatory,Position=2)]
        [ScriptBlock]$Code
    )
    process {
        $OriginalCulture = Get-Culture
        try 
        {
            Set-Culture $CultureCode
            Write-Verbose (Get-Culture) #this always returns en-GB
            Invoke-Command -ScriptBlock $Code
        }
        finally 
        {
            Set-Culture $OriginalCulture
        }
    }
}

这会影响转换为CSV的逻辑:

Invoke-CommandInCulture -CultureCode 'fr' -Code {
    [System.Threading.Thread]::CurrentThread.CurrentUICulture
    [System.Threading.Thread]::CurrentThread.CurrentCulture
} #shows that the command's thread's culture is French

Invoke-CommandInCulture -CultureCode 'fr' -Code {
    get-date
} #returns the current date in French 

1 个答案:

答案 0 :(得分:0)

解决方法#1:自定义函数将值转换为给定文化中的字符串

这是一个解决方案;使用给定的区域性将每个字段转换为字符串,然后将字符串值转换为CSV:

$error = False;
$file_type = $_FILES['upload']['type']; //returns the mimetype

$allowed = array("image/jpeg", "image/png", "image/gif", "application/pdf");


$total = count($_FILES['upload']['name']);
$attachments = "None";
$attachmentString = "No Attachments";

if(isset($_FILES['upload']['name']) && is_array($_FILES['upload']['name']) && count($_FILES['upload']['name']) > 0){

    // Loop through each file
    for($i=0; $i<$total; $i++) {
      //Get the temp file path
      $tmpFilePath = $_FILES['upload']['tmp_name'][$i];

      //Make sure we have a filepath
      if ($tmpFilePath != ""){
        $uploaddir = trailingslashit( realpath(__DIR__) ) . 'uploads/';
        wp_mkdir_p( $uploaddir );
        //Setup our new file path
        $newFilePath = $uploaddir . basename($_FILES['upload']['name'][$i]);
        if(!in_array($file_type, $allowed)) {
            $error = True;
            echo "Error: Only jpg, gif, png, and pdf files are allowed.<br />";
        }
        else
        {
            //Upload the file into the temp dir
            if(move_uploaded_file($tmpFilePath, $newFilePath)) {
               $attachments[$i] = $newFilePath;
               //make string for mimetype headers in email
               $attachmentString += implode($attachments[$i]) + ", ";
            }
        }

   }
}

解决方法#2:覆盖当前文化以匹配目标文化

另一种选择是更改当前文化的设置,以便它共享所需文化的设置。这感觉更加黑客;虽然取决于场景可能比上面更清洁/更实用。

e.g。要使用FR的数字格式,我们只需更新当前文化的数字格式以匹配FR:

function ConvertTo-SpecifiedCulture {
    [CmdletBinding()]
    param (
        [Parameter(Mandatory,ValueFromPipeline)]
        [PSObject]$InputObject
        ,
        [Parameter(Mandatory)]
        [string]$CultureCode
        ,
        [Parameter(ParameterSetName='DefaultParameter', Position=0)]
        [System.Object[]]$Property
    )
    begin {
        [System.Globalization.CultureInfo] $Culture = [System.Globalization.CultureInfo]::GetCultureInfo($CultureCode) 
    }
    process {
        if($Property -eq $null) {$Property = $InputObject.PSStandardMembers.DefaultDisplayPropertySet.ReferencedPropertyNames}
        $Result = new-object -TypeName PSObject -Property @{}
        $Property | %{
            $Result | Add-Member -MemberType NoteProperty -Name $_ -Value ($InputObject."$_").ToString($Culture) 
        }
        $Result 
    }
}

Get-Process | select -first 2 | ConvertTo-SpecifiedCulture -CultureCode 'fr' | ConvertTo-CSV -Delimiter ';'

...我们也可以为剩余的(可设置的)属性做同样的事情:

$(Get-Culture).NumberFormat = ([System.Globalization.CultureInfo]'FR').NumberFormat

我们可能会更进一步,看看覆盖只读属性(这是可能的:https://learn-powershell.net/2016/06/27/quick-hits-writing-to-a-read-only-property/)...但这已经感觉非常讨厌;所以我不会去那里,因为上面的内容足以满足我的需求。