utf8 acentos powershell encoding utf-8 character-encoding io-redirection

acentos - Salida UTF-8 de PowerShell



powershell acentos (4)

Establezca [Console]::OuputEncoding como codificación lo que desee e imprima con [Console]::WriteLine .

Si el método de salida de PowerShell tiene un problema, entonces no lo use. Se siente un poco mal, pero funciona como un encanto :)

Estoy tratando de usar Process.Start con E / S redirigida para llamar a PowerShell.exe con una cadena, y para recuperar la salida, todo en UTF-8 . Pero parece que no puedo hacer que esto funcione.

Lo que he intentado:

  • Pasar el comando para ejecutar a través del parámetro -Command
  • Escribir el script de PowerShell como un archivo en el disco con codificación UTF-8
  • Escribir el script de PowerShell como un archivo en el disco con UTF-8 con codificación BOM
  • Escribir el script de PowerShell como un archivo en el disco con UTF-16
  • Configuración de Console.OutputEncoding tanto en mi aplicación de consola como en la secuencia de comandos de PowerShell
  • Estableciendo $OutputEncoding en PowerShell
  • Configuración de Process.StartInfo.StandardOutputEncoding
  • Haciendo todo con Encoding.Unicode lugar de Encoding.UTF8

En todos los casos, cuando inspecciono los bytes que me dan, obtengo valores diferentes a mi cadena original. Realmente me encantaría una explicación de por qué esto no funciona.

Aquí está mi código:

static void Main(string[] args) { DumpBytes("Héllo"); ExecuteCommand("PowerShell.exe", "-Command /"$OutputEncoding = [System.Text.Encoding]::UTF8 ; Write-Output ''Héllo'';/"", Environment.CurrentDirectory, DumpBytes, DumpBytes); Console.ReadLine(); } static void DumpBytes(string text) { Console.Write(text + " " + string.Join(",", Encoding.UTF8.GetBytes(text).Select(b => b.ToString("X")))); Console.WriteLine(); } static int ExecuteCommand(string executable, string arguments, string workingDirectory, Action<string> output, Action<string> error) { try { using (var process = new Process()) { process.StartInfo.FileName = executable; process.StartInfo.Arguments = arguments; process.StartInfo.WorkingDirectory = workingDirectory; process.StartInfo.UseShellExecute = false; process.StartInfo.CreateNoWindow = true; process.StartInfo.RedirectStandardOutput = true; process.StartInfo.RedirectStandardError = true; process.StartInfo.StandardOutputEncoding = Encoding.UTF8; process.StartInfo.StandardErrorEncoding = Encoding.UTF8; using (var outputWaitHandle = new AutoResetEvent(false)) using (var errorWaitHandle = new AutoResetEvent(false)) { process.OutputDataReceived += (sender, e) => { if (e.Data == null) { outputWaitHandle.Set(); } else { output(e.Data); } }; process.ErrorDataReceived += (sender, e) => { if (e.Data == null) { errorWaitHandle.Set(); } else { error(e.Data); } }; process.Start(); process.BeginOutputReadLine(); process.BeginErrorReadLine(); process.WaitForExit(); outputWaitHandle.WaitOne(); errorWaitHandle.WaitOne(); return process.ExitCode; } } } catch (Exception ex) { throw new Exception(string.Format("Error when attempting to execute {0}: {1}", executable, ex.Message), ex); } }

Actualización 1

Descubrí que si hago este script:

[Console]::OutputEncoding = [System.Text.Encoding]::UTF8 Write-Host "Héllo!" [Console]::WriteLine("Héllo")

Luego invocarlo a través de:

ExecuteCommand("PowerShell.exe", "-File C://Users//Paul//Desktop//Foo.ps1", Environment.CurrentDirectory, DumpBytes, DumpBytes);

La primera línea está dañada, pero la segunda no es:

H?llo! 48,EF,BF,BD,6C,6C,6F,21 Héllo 48,C3,A9,6C,6C,6F

Esto me sugiere que mi código de redireccionamiento funciona bien; cuando uso Console.WriteLine en PowerShell obtengo UTF-8 como esperaba.

Esto significa que los comandos Write-Output y Write-Host PowerShell deben hacer algo diferente con la salida y no simplemente llamar a Console.WriteLine .

Actualización 2

Incluso he intentado lo siguiente para forzar la página de códigos de la consola PowerShell a UTF-8, pero Write-Host y Write-Output continúan produciendo resultados rotos mientras [Console]::WriteLine funciona.

$sig = @'' [DllImport("kernel32.dll")] public static extern bool SetConsoleCP(uint wCodePageID); [DllImport("kernel32.dll")] public static extern bool SetConsoleOutputCP(uint wCodePageID); ''@ $type = Add-Type -MemberDefinition $sig -Name Win32Utils -Namespace Foo -PassThru $type::SetConsoleCP(65001) $type::SetConsoleOutputCP(65001) Write-Host "Héllo!" & chcp # Tells us 65001 (UTF-8) is being used


Este es un error en .NET. Cuando se inicia PowerShell, almacena en caché el manejador de salida (Console.Out). La propiedad de Codificación de ese escritor de texto no recoge el valor de la propiedad StandardOutputEncoding.

Cuando lo cambia desde PowerShell, la propiedad Codificación del escritor de salida en caché devuelve el valor en caché, por lo que la salida sigue codificada con la codificación predeterminada.

Como solución alternativa, sugeriría no cambiar la codificación. Se le devolverá como una cadena Unicode, en cuyo punto puede administrar la codificación usted mismo.

Ejemplo de almacenamiento en caché:

102 [C:/Users/leeholm] >> $r1 = [Console]::Out 103 [C:/Users/leeholm] >> $r1 Encoding FormatProvider -------- -------------- System.Text.SBCSCodePageEncoding en-US 104 [C:/Users/leeholm] >> [Console]::OutputEncoding = [System.Text.Encoding]::UTF8 105 [C:/Users/leeholm] >> $r1 Encoding FormatProvider -------- -------------- System.Text.SBCSCodePageEncoding en-US


No es un experto en codificación, pero después de leer estos ...

... parece bastante claro que la variable $ OutputEncoding solo afecta los datos transmitidos a las aplicaciones nativas.

Si se envía a un archivo desde PowerShell, la codificación se puede controlar mediante el parámetro -encoding en el cmdlet out-file por ejemplo

write-output "hello" | out-file "enctest.txt" -encoding utf8

No hay nada más que pueda hacer en el frente de PowerShell, pero la siguiente publicación puede ayudarle:


Pasé algún tiempo trabajando en una solución a mi problema y pensé que podría ser de interés. Me encontré con un problema al tratar de automatizar la generación de código utilizando PowerShell 3.0 en Windows 8. El IDE de destino era el compilador Keil que utilizaba MDK-ARM Essential Toolchain 5.24.1. Un poco diferente de OP, ya que estoy usando PowerShell de forma nativa durante el paso previo a la compilación. Cuando traté de #incluir el archivo generado, recibí el error

error fatal: marca de orden de byte UTF-16 (LE) detectada ''.. / GITVersion.h'' pero la codificación no es compatible

Resolví el problema cambiando la línea que generó el archivo de salida desde:

out-file -FilePath GITVersion.h -InputObject $result

a:

out-file -FilePath GITVersion.h -Encoding ascii -InputObject $result