Golang, вызывающий PowerShell.exe, всегда возвращает символы ASCII - PullRequest
0 голосов
/ 12 июня 2018

Я использую PowerShell из приложения, написанного на Go, но не могу заставить его возвращать символы не ASCII.Сначала я использовал go-powershell, но столкнулся с той же проблемой: https://github.com/gorillalabs/go-powershell/issues/10, а теперь использую немного более базовый подход:

package main

import (
        "bytes"
        "fmt"
        "os/exec"
)

type PowerShell struct {
        powerShell string
}

func New() *PowerShell {
        ps, _ := exec.LookPath("powershell.exe")
        return &PowerShell{
                powerShell: ps,
        }
}

func (p *PowerShell) Execute(args ...string) (stdOut string, stdErr string, err error) {
        args = append([]string{"-NoProfile", "-NonInteractive"}, args...)
        cmd := exec.Command(p.powerShell, args...)

        var stdout bytes.Buffer
        var stderr bytes.Buffer
        cmd.Stdout = &stdout
        cmd.Stderr = &stderr

        err = cmd.Run()
        stdOut, stdErr = stdout.String(), stderr.String()
        return
}

func main() {
        posh := New()
        stdout, stderr, err := posh.Execute("$OutputEncoding = [Console]::OutputEncoding; (Get-VMSwitch).Name")

        fmt.Println(stdout)
        fmt.Println(stderr)

        if err != nil {
                fmt.Println(err)
        }
}

, но происходит то же самое.Вместо получения Przełąś возвращается Przelas.Это приведет к проблемам, когда далее в коде создается виртуальная машина с использованием этого имени виртуального коммутатора.Он не распознается и ошибки.

Примечание: $OutputEncoding = [Console]::OutputEncoding; не оказало никакого влияния.Он действительно изменяется, но результат остается тем же.

Примечание 2: при вызове той же самой команды непосредственно из командной строки НЕ возникает проблем: powershell.exe -NoProfile -NonInteractive $OutputEncoding = [Console]::OutputEncoding; (Get-VMSwitch).Name") или даже powershell.exe -NoProfile -NonInteractive (Get-VMSwitch).Name").Другими словами, он делает это только из Go при использовании exec.Command.

Примечание 3: это для устранения проблемы с драйвером виртуальной машины, когда речь идет о локализованных именах.Да, вместо этого он может работать с GUID (.Id), но эта проблема сохраняется в разных частях системы.

1 Ответ

0 голосов
/ 12 июня 2018

Мужик, Powershell интересный.В основном это было результатом множества проб и ошибок.

По сути, вы хотите установить [Console]::OutputEncoding, а не захватывать его.

Однако, чтобы привести себя в порядок, не помешает восстановить исходное значение.Я не полностью обернул голову, но изменение сохраняется через несколько exec() вызовов.

Вот пример:

<... everything else is as above ...>

func main() {
        posh := New()

        fmt.Println("With encoding change:")
        stdout, stderr, err := posh.Execute(
                "$test = \"Przełąś\"\n" +
                "$old = [Console]::OutputEncoding\n" +
                "[Console]::OutputEncoding = [Text.Encoding]::UTF8\n" +
                "[Console]::OutputEncoding\n" +
                "$test\n" +
                "[Console]::OutputEncoding = $old")
        fmt.Println(stdout)
        fmt.Println(stderr)
        if err != nil {
                fmt.Println(err)
        }

        fmt.Println("Without encoding change:")
        stdout, stderr, err = posh.Execute(
                "$test = \"Przełąś\"\n" +
                "[Console]::OutputEncoding\n" +
                "$test")
        fmt.Println(stdout)
        fmt.Println(stderr)
        if err != nil {
                fmt.Println(err)
        }
}

Вывод:

$ ./exec-powershell.exe
With encoding change:


BodyName          : utf-8
EncodingName      : Unicode (UTF-8)
HeaderName        : utf-8
WebName           : utf-8
WindowsCodePage   : 1200
IsBrowserDisplay  : True
IsBrowserSave     : True
IsMailNewsDisplay : True
IsMailNewsSave    : True
IsSingleByte      : False
EncoderFallback   : System.Text.EncoderReplacementFallback
DecoderFallback   : System.Text.DecoderReplacementFallback
IsReadOnly        : False
CodePage          : 65001

Przełąś




Without encoding change:


IsSingleByte      : True
BodyName          : IBM437
EncodingName      : OEM United States
HeaderName        : IBM437
WebName           : IBM437
WindowsCodePage   : 1252
IsBrowserDisplay  : False
IsBrowserSave     : False
IsMailNewsDisplay : False
IsMailNewsSave    : False
EncoderFallback   : System.Text.InternalEncoderBestFitFallback
DecoderFallback   : System.Text.InternalDecoderBestFitFallback
IsReadOnly        : True
CodePage          : 437

Przelas
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...