gpt4 book ai didi

powershell - PowerShell 的 UTF-8 输出

转载 作者:行者123 更新时间:2023-12-03 06:40:43 29 4
gpt4 key购买 nike

我正在尝试使用Process.Start通过重定向 I/O 来调用 PowerShell.exe带有字符串,并获取输出,全部在 UTF-8 中。但我似乎无法完成这项工作。

我尝试过的:

  • 通过 -Command 传递要运行的命令参数
  • 使用 UTF-8 编码将 PowerShell 脚本作为文件写入磁盘
  • 使用 UTF-8 将 PowerShell 脚本作为文件写入磁盘 BOM编码
  • 使用 UTF-16 将 PowerShell 脚本作为文件写入磁盘
  • 设置Console.OutputEncoding在我的控制台应用程序和 PowerShell 脚本中
  • 设置$OutputEncoding在 PowerShell 中
  • 设置Process.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-OutputWrite-Host命令必须对输出执行不同的操作,而不是简单地调用 Console.WriteLine .

更新2

我什至尝试过以下方法来强制 PowerShell 控制台代码页为 UTF-8,但是 Write-HostWrite-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

最佳答案

不是编码方面的专家,但阅读完这些之后...

...似乎相当清楚 $OutputEncoding 变量仅影响通过管道传输到 native 应用程序的数据。

如果使用 PowerShell 发送到文件,则可以通过 out-file cmdlet 上的 -encoding 参数来控制编码,例如

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

那么您在 PowerShell 前端无能为力,但以下帖子可能会对您有所帮助:。

关于powershell - PowerShell 的 UTF-8 输出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22349139/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com