如何解决 VBA 和 Powershell 之间的这个特殊字符编码问题?

How can I solve this special character encoding problem between VBA and Powershell?

对于更大的 vba 应用程序,我需要使用 powershell 脚本为我提供共享上的文件名。因为我住在德国,所以这些文件名包含很多德语特殊字符,例如 üä 等。

powershell 脚本的输出,应该(并且在 PS 控制台上)正确显示这些字符 而不是 在 VBA 中正确显示.我编造了这个最小的例子来证明这一点。

感谢任何回馈 für 而不是 fr 的解决方案。

Option Explicit
Const HK = """"

Sub ScanDrive()
    Dim s As String, command As String
   
    command = "echo 'für'"
    Debug.Print (command)
    'Method1: start PS in CMD with /u parameter
    s = CreateObject("Wscript.Shell").exec("cmd /u /c powershell.exe -command " & HK & command & HK).StdOut.ReadAll
    Debug.Print (s)
    'Method2: start PS directly (preferred)
    s = CreateObject("Wscript.Shell").exec("powershell.exe -command " & HK & command & HK).StdOut.ReadAll
    Debug.Print (s)
End Sub

我的输出看起来像这样(尽管 vba 根本不显示 `````` 字符):

echo 'für'
fr

fr

我已经知道我可以在写入文件输出时更改 PS 输出编码。不幸的是,这不是一个选项。

据我所知,我必须让 Excel 读取 UTF-8(我想,就是这样)或让 PS 控制台写出 Win-1252(也只是一个猜猜,这就是 Excel 使用的内容)。

因为我必须在公司中部署此脚本,所以我不能依赖 PS 控制台的任何全局开关。

更新

根据 JosefZ 的评论,我将命令作为 [System.Console]::OutputEncoding 并在 VBA 中得到以下内容:

IsSingleByte      : True
BodyName          : ibm850
EncodingName      : Westeurop„isch (DOS)
HeaderName        : ibm850
WebName           : ibm850
WindowsCodePage   : 1252
IsBrowserDisplay  : False
IsBrowserSave     : False
IsMailNewsDisplay : False
IsMailNewsSave    : False
EncoderFallback   : System.Text.InternalEncoderBestFitFallback
DecoderFallback   : System.Text.InternalDecoderBestFitFallback
IsReadOnly        : True
CodePage          : 850

与 运行 相反,它直接在 powershell 中声明:

IsSingleByte      : True
BodyName          : iso-8859-1
EncodingName      : Westeuropäisch (Windows)
HeaderName        : Windows-1252
WebName           : Windows-1252
WindowsCodePage   : 1252
IsBrowserDisplay  : True
IsBrowserSave     : True
IsMailNewsDisplay : True
IsMailNewsSave    : True
EncoderFallback   : System.Text.InternalEncoderBestFitFallback
DecoderFallback   : System.Text.InternalDecoderBestFitFallback
IsReadOnly        : True
CodePage          : 1252

CreateObject("Wscript.Shell") 似乎适用于 Dos 编码和 CP850。

幸运的是,我找到了解决方案。

JosefZ's comment put me on the right track and led me to this underrated answer from Garric另一个问题。

将他的解决方案改编为我最初的最小示例代码给出了这个:

Option Explicit
Const HK = """"

Sub ScanDrive()
    Dim s As String, command As String
    Dim codepage As String
    codepage = "windows-1252"
    command = "$OutputEncoding = [Console]::outputEncoding = [System.Text.Encoding]::GetEncoding('" + codepage + "'); echo 'für'"
    Debug.Print (command)
    s = CreateObject("Wscript.Shell").Exec("powershell.exe -command " & HK & command & HK).StdOut.ReadAll
    Debug.Print (s)
End Sub

Et Voilá - 我们的德语元音变音正确:)