我试图使用带有重定向I/O的Process.Start
调用带有字符串的PowerShell.exe
,并将输出返回到UTF-8中。但我似乎无法做到这一点。
我试过的是:
-Command
参数运行的命令$OutputEncoding
中设置PowerShellProcess.StartInfo.StandardOutputEncoding
Encoding.Unicode
而不是Encoding.UTF8
来完成的在任何情况下,当我检查给定的字节时,都会得到与原始字符串不同的值。我真的很想解释一下为什么这不管用。
这是我的代码:
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);
}
}
更新1
我发现如果我做这个剧本:
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
Write-Host "Héllo!"
[Console]::WriteLine("Héllo")
然后通过以下方式调用它:
ExecuteCommand("PowerShell.exe", "-File C:\\Users\\Paul\\Desktop\\Foo.ps1",
Environment.CurrentDirectory, DumpBytes, DumpBytes);
第一行已损坏,但第二行未损坏:
H?llo! 48,EF,BF,BD,6C,6C,6F,21
Héllo 48,C3,A9,6C,6C,6F
这表明我的重定向代码运行良好;当我在Console.WriteLine
中使用PowerShell时,我得到了UTF-8。
这意味着PowerShell的Write-Output
和Write-Host
命令必须对输出执行不同的操作,而不是简单地调用Console.WriteLine
。
更新2
我甚至尝试使用以下方法将PowerShell控制台代码页强制到UTF-8,但是Write-Host
和Write-Output
在[Console]::WriteLine
工作时继续产生坏结果。
$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
发布于 2014-03-12 20:57:18
这是.NET中的一个bug,当PowerShell启动时,它会缓存输出句柄(Console.Out)。该文本写入器的“编码”属性不会获取值StandardOutputEncoding属性。
在PowerShell中更改它时,缓存输出写入器的编码属性将返回缓存的值,因此输出仍然使用默认编码进行编码。
作为解决办法,我建议不要更改编码。它将作为Unicode字符串返回给您,此时您可以自己管理编码。
缓存示例:
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
发布于 2017-01-05 02:16:47
将[Console]::OuputEncoding
设置为任意编码,并使用[Console]::WriteLine
打印出来。
如果powershell ouput方法有问题,那么就不要使用它。它感觉有点糟糕,但效果就像一种魅力:)
发布于 2018-05-13 00:23:41
花了一些时间来解决我的问题,并认为这可能是有意义的。我遇到了一个问题,试图在Windows8上使用PowerShell 3.0自动生成代码。目标IDE是使用MDK基本工具链5.24.1的Keil编译器。与OP有一点不同,因为我在构建前的步骤中本机使用PowerShell。当我试图包含生成的文件时,我收到了错误
致命错误: UTF-16 (LE)字节顺序标记检测到'..\GITVersion.h‘,但不支持编码。
通过更改生成输出文件的行,我解决了这个问题:
out-file -FilePath GITVersion.h -InputObject $result
至:
out-file -FilePath GITVersion.h -Encoding ascii -InputObject $result
https://stackoverflow.com/questions/22349139
复制相似问题