2016-11-29 4 views
0

質問をConvertTo-CSV -UseCultureは、現在のスレッドの文化

を無視することがen-GB文化とWindowsのセッションで実行したときにフランスの形式でCSVにエクスポートするためのPowerShellを強制することは可能ですか?

詳細

私はフランス文化のルールを使用してCSVにいくつかのデータをエクスポートするために願っています(つまり、CSVの区切り文字はセミコロンに設定するだけでなく、小数点以下の桁数カンマを使用して番号を持つ、などの文化のフォーマットの違い; -Delimiterパラメータを使用するだけでは不十分です)。

私は、次のコードは、このメソッドが機能することを意味します(https://stackoverflow.com/a/7052955/361842に基づいて)以下のコード

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 
     } 
    } 
} 

を思い付いた:

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 

しかしPowerShellは

何が起こっているのは独自の考えを持っています
Invoke-CommandInCulture -CultureCode 'fr' -Code { 
    get-culture 
    "PSCulture: $PSCulture" 
    "PSUICulture: $PSUICulture"   
} #returns my default (en-GB) culture; not the thread's culture 

これはCSVに変換するロジックに影響します。

Invoke-CommandInCulture -CultureCode 'fr' -Code { 
    get-process | ConvertTo-CSV -UseCulture 
} #again, uses my default culture's formatting rules; not the FR ones 
+0

このブログでは、奇妙な動作のいくつかについて説明します。すなわち、培養は、現在のパイプラインが完了した後にリセットされる。私はこれまでにも、この知識/私が見ている振る舞いは、これと矛盾しているように見えても、「Export-Csv」の問題を回避することはできませんでした。 – JohnLBevan

+0

http:// www .xipher.dk/WordPress /?p = 706 – JohnLBevan

答えて

0

回避策#1:カスタム関数は、与えられた文化の中で文字列に値を変換する

ここでは、回避策ソリューションです。 CSVに文字列値を変換し、その後、所定の培養を使用して文字列に、各フィールドの変換:

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 ';' 

回避策#2:別のオプションを変更することで、ターゲットの文化に

にマッチするように、現在の文化をオーバーライド必要な文化のものを共有するように現在の文化の設定。これはもっとハッキリと感じます。シナリオに応じて、上記よりもより洗練された/より実用的に機能するかもしれません。

私たちは、現在のカルチャの数値の書式は、FRのと一致するように更新FRの番号形式を使用する:

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

を...そして、我々は残りの(設定可能)の特性のためにも同様に行うことができます。

function Set-CurrentCulture { 
    [CmdletBinding()] 
    param (
     [string]$CultureCode 
    ) 
    begin { 
     $Global:FakedCurrentCulture = $CultureCode #in case we need a reference to the current culture's name 
     [System.Globalization.CultureInfo]$NewCulture = [System.Globalization.CultureInfo]::GetCultureInfo($CultureCode) 
     [System.Globalization.CultureInfo]$ReferenceToCurrentCulture = Get-Culture 
     Write-Verbose "Switching Defintion to $($NewCulture.Name)" 
    } 
    process { 
     #NB: At time of writing, the only settable properties are NumberFormatInfo & DateTimeFormatInfo 
     $ReferenceToCurrentCulture.psobject.properties | ?{$_.isSettable} | %{ 
      $propertyName = $_.Name 
      write-verbose "Setting property $propertyName" 
      write-verbose "- from: $($ReferenceToCurrentCulture."$propertyName")" 
      write-verbose "- to: $($NewCulture."$propertyName")" 
      $ReferenceToCurrentCulture."$propertyName" = $NewCulture."$propertyName" 
     } 
     #ListSeparator 
     $ReferenceToCurrentCulture.TextInfo.psobject.properties | ?{$_.isSettable} | %{ 
      $propertyName = $_.Name 
      write-verbose "Setting property TextInfo.$propertyName" 
      write-verbose "- from: $($ReferenceToCurrentCulture.TextInfo."$propertyName")" 
      write-verbose "- to: $($NewCulture.TextInfo."$propertyName")" 
      $ReferenceToCurrentCulture.TextInfo."$propertyName" = $NewCulture."$propertyName" 
     } 
     #for some reason this errors 
     #Localized, TwoDigitYearMax 
     <# 
     $ReferenceToCurrentCulture.Calendar.psobject.properties | ?{$_.isSettable} | %{ 
      $propertyName = $_.Name 
      write-verbose "Setting property Calendar.$propertyName" 
      write-verbose "- from: $($ReferenceToCurrentCulture.Calendar."$propertyName")" 
      write-verbose "- to: $($NewCulture.Calendar."$propertyName")" 
      $ReferenceToCurrentCulture.Calendar."$propertyName" = $NewCulture."$propertyName" 
     } 
     #> 
    } 
} 

function Reset-CurrentCulture { 
    [CmdletBinding()] 
    param() 
    process { 
     Set-CurrentCulture -CultureCode ((get-culture).Name) 
    } 
} 

function Test-It { 
    [CmdletBinding()] 
    param() 
    begin { 
     write-verbose "Current Culture: $Global:FakedCurrentCulture" 
    } 
    process { 
     1..5 | %{ 
      New-Object -TypeName PSObject -Property @{ 
       Integer = $_ 
       String = "Hello $_" 
       Numeric = 2.139 * $_ 
       Money = (2.139 * $_).ToString('c') 
       Date = (Get-Date).AddDays($_) 
      } 
     } | ConvertTo-Csv -NoTypeInformation 
    } 
} 


Set-CurrentCulture 'fr' -Verbose 
Test-It 
Set-CurrentCulture 'en-GB' -Verbose 
Test-It 
Set-CurrentCulture 'en-US' -Verbose 
Test-It 
Set-CurrentCulture 'ar-DZ' -Verbose 
Test-It 

Reset-CurrentCulture -Verbose 
Test-It 

我々は、潜在的可能性さらに進んで、読み取り専用のプロパティを上書きすることを見てください(これは可能です:https://learn-powershell.net/2016/06/27/quick-hits-writing-to-a-read-only-property/)...これは既に非常に厄介です。私のニーズに十分であったので、私はそこに行くつもりはない。

+0

ps。このコードに関するコメントについてはhttp://codereview.stackexchange.com/questions/148463/powershell-export-csv-with-cultural-awarenessを参照してください。また、文化サポートを追加するConvertTo-CSVのProxy Funcitonもご覧ください。 – JohnLBevan

関連する問題