Encoding UTF8-C# - Prozess
Ich habe eine Anwendung, die Prozess des vbscript und erzeugt die Ausgabe.
private static string processVB(string command, string arguments)
{
Process Proc = new Process();
Proc.StartInfo.UseShellExecute = false;
Proc.StartInfo.RedirectStandardOutput = true;
Proc.StartInfo.RedirectStandardError = true;
Proc.StartInfo.RedirectStandardInput = true;
Proc.StartInfo.StandardOutputEncoding = Encoding.UTF8;
Proc.StartInfo.StandardErrorEncoding = Encoding.UTF8;
Proc.StartInfo.FileName = command;
Proc.StartInfo.Arguments = arguments;
Proc.StartInfo.WindowStyle = ProcessWindowStyle.Hidden; //prevent console window from popping up
Proc.Start();
string output = Proc.StandardOutput.ReadToEnd();
string error = Proc.StandardError.ReadToEnd();
if (String.IsNullOrEmpty(output) && !String.IsNullOrEmpty(error))
{
output = error;
}
//Console.Write(ping_output);
Proc.WaitForExit();
Proc.Close();
return output;
}
Ich denke, ich habe alles, was mit Encoding-Eigenschaft korrekt ist. processVB Methode get-Befehl als VBscript-Datei und deren Argumenten.
Die C# - Methode processVB ist die Verarbeitung, die VBScript-Datei produzieren nun die Ausgabe wie folgt.
"����?"
Aber ich sollte original text
"äåéö€"
Habe ich die Codierung korrekt. Aber ich bin nicht in der Lage, es richtig zu machen.
Was mache ich falsch?
- Haben Sie dies erlebt? stackoverflow.com/questions/7520706/... - ich glaube, das ist genau Ihr problem.
- Ja, ich habe es gesehen. Vielen Dank für die Referenz. Nein, Es hat nicht lösen, mein Problem.
- Der link erklärt die Wurzel des Problems.
- Was bedeutet CurrentEncoding-Eigenschaft hat für die StandardOutput-direkt nach dem Start des Prozesses?
- System.Text.Bei UTF8Encoding
Du musst angemeldet sein, um einen Kommentar abzugeben.
Diese Antwort ist nicht die Beantwortung der direkten Frage, aber ich bemerkte eine deadlock-potential in Ihrem code und somit dachte, es wäre würdig zu posten es trotzdem.
Deadlock-Gefahr besteht, durch deinen code versuchen zu tun, synchrones Lesen von Ausgabe umgeleitet, und Sie tun es für beide, StdOut und StdErr. I. e. dieser Abschnitt des Codes.
Was passieren kann, ist, dass der Kind-Prozess schreibt eine Menge von Daten nach StdErr und füllt den Puffer. Sobald Puffer wird gefüllt, wird der Kind-Prozess wird blockiert, auf das schreiben auf StdErr (ohne Signalisierung noch Ende des StdOut-stream). Und so Kind blockiert ist und nichts zu tun, und der Prozess blockiert, wartet für das Kind zu beenden. Deadlock!!!
Um dies zu beheben, mindestens eine (oder besser beide) streams sollten gewechselt werden, um den asynchronen Modus.
Sehen zweites Beispiel in der MSDN, die reden, speziell über diesen Fall, und wie Umschalten in den asynchronen Modus.
Als für die
UTF-8
Frage, sind Sie sicher, dass Ihr Kind-Prozess wird die Ausgabe in dieses encoding und nicht sagen, inUTF-16
oder einige andere? Möchten Sie vielleicht zu prüfen, die bytes zu versuchen, rückwärts aus welchem encoding-stream geliefert, so können Sie die richtige Codierung für die Interpretation der stream umgeleitet.BEARBEITEN
Hier ist, wie ich denke, können Sie beheben die encoding-Problem. Die grundlegende Idee basiert auf etwas, was ich einmal tun musste, hatte ich mir den Russischen text in unbekannter Codierung, und notwendig, um herauszufinden, wie es zu konvertieren, so dass es zeigt die richtige Zeichen - nehmen Sie die bytes erfasst von StdOut und versuchen zu Dekodieren, die Sie über alle bekannten Codepages, die auf dem system verfügbar. Die eine, die sieht Recht ist wahrscheinlich (aber nicht notwendigerweise) die Codierung, die Standardausgabe verschlüsselt mit. Der Grund ist es nicht garantiert das man auch wenn es richtig aussieht, mit Ihren Daten, ist, weil viele-Codierung haben, die überlappen über einige Bereiche der bytes, die es machen würde, die gleiche Arbeit. E. g. ASCII und utf-8 die gleiche Byte bei der Kodierung der basic-Latin-Zeichen. So exakt überein, können Sie brauchen, um kreativ und testen Sie mit einigen atypischen text.
Hier ist der basic-code, es zu tun - die Anpassungen, die notwendig sein kann:
Führen Sie den code und manuell überprüfen Sie die Ausgabe. Alle diejenigen, die mit der erwarteten text werden die Kandidaten für die Codierung verwendet, die in StdOut.
Das problem ist, dass die Konsole nicht standardmäßig UTF-8. Es läuft in der selben Codepage wie Ihre locale-Einstellungen in Windows. Eine einfache Möglichkeit, dies zu lösen, ist die Verwendung des
chcp
console-Befehl. Beispiel:Dadurch wird die Ausgabe in UTF-8 und sicherzustellen, dass Sie Lesen es richtig von Ihr .NET-Anwendung.
Beachten Sie, dass ich habe getestet dieses mit einem
bat
Skript anstelle von VB-script, aber wenn das VB-script unterstützt UTF-8, es sollte gut funktionieren. Möglicherweise haben Sie auch explizit aufrufen, die VB-script-execution-engine, statt nuryourScript.vbs
. Aber Sie sollten in der Lage sein, diese zu lösen, leicht auf Ihre eigenen 🙂Lucida Console
oderConsolas
- nicht verwendenRaster Fonts
), es scheint, dass es einfach nicht funktioniert, auch wenn Sie nicht wirklich brauchen, die Konsole sichtbar zu sein, für überhaupt nichts.AttachConsole
undSetConsoleCP
. Aber das scheint nicht zu funktionieren. Und wir können Sie nicht direkt aufrufen chcp 65001 && yourScript.vbs mit Prozess, in C# richtig?chcp 65001 && yourScript.vbs
"Befehl". Das ist vielleicht genug. Nun, da Sie nicht verwenden könnenUseShellExecute
Sie ausführen müssenchcp 65001
ersten (oder verwenden SieSetConsoleCP
?) und Ihr Skript, getrennt nach, dass - die&&
operand ist Teil der shell, kein "richtiger" Prozess. Versuchen Sie außerdem, die Einstellung der Standard-schriftart für die Konsole zuConsolas
oderLucida Console
um zu sehen, ob es das Problem behebt. Wie ich vorher gesagt habe, es funktioniert nicht bei mir mit der Standard -Raster Fonts
Einstellung aus irgendeinem Grund.SetCurrentConsoleFontEx
.SetConsoleCP
hat nicht funktioniert. Ich habe versucht, es zu 65001. Aber es funktionierte nicht für die Konsole, die dem Prozess zugeordnet.CreateProcess
direkt an den params. Dann wie du schon erwähnt hast ichSetConsoleOutputCP
zu 65001.(Ich kann das chcp Wert für die Konsole belegt durch den Prozess nur durch die Verwendung von Native-API-Funktion CreateProcess()) Jetzt habe ich die erwartete Ausgabe in der Konsole :). Aber wie kann ich es umleiten und sammeln Sie in einer variable, wieProc.StandardOutput.ReadToEnd()
? Haben Sie eine Idee?Dass die Annahme, dass immer Sie in Schwierigkeiten hier, es ist einfach nicht utf-8. Noch können Sie es sein, die scripting-engine unterstützt nicht die Einstellung. Etwas, was Sie können versuchen, für sich selbst, verwenden Sie diese Anweisung in einer Probe .vbs-Datei:
Kaboom, es akzeptiert nur LCID-Werte, und Sie decken nicht die utf-Codierungen. Stattdessen cscript.exe scripting-engine, die bereits änderungen der Standard-code der Seite selbst. Anstelle der Standard-OEM-Codepage (HKEY_LOCAL_MACHINE\SYSTEM\ControlSet\Control\Nls\CodePage\OEMCP-Wert), schaltet die Standard-Windows-Codepage. Die AKP-Wert in der oben dokumentierte registry-Schlüssel. Abhängig von Ihrem Standort, es wird 1252 zum Beispiel in Nord-und Südamerika und Westeuropa.
Einige VBScript-code, um mit zu spielen, speichern Sie die Datei mit der Standard-Codierung, die entsprechend für Ihr Gebietsschema oder die Skript-interpreter selbst wird mis-interpretieren die strings im Quelltext. Die in sich selbst erklären kann dein problem so gut:
Ausgabe auf meinem Rechner:
Also die richtige code-Zeile in Ihrem Programm:
Tun, beachten Sie, dass dies nicht die Standardeinstellung, die die Process-Klasse verwendet, es wird davon ausgegangen, dass eine Konsole-Modus-Anwendung verwendet die OEM-Codepage. Wie 437 auf einer Maschine in Nord-Amerika und West-Europa. Sie können wählen Sie eine andere LCID in Ihr .vbs-Programm und ändern Sie Ihre C# - code zu entsprechen, aber das sollte nicht notwendig sein.
Und halten Sie den Fehler-Modus mit dem .vbs-Quellcode-Datei kodiert falsch im Hinterkopf. Die scripting-engine unterstützt nicht utf-8 mit BOM-entweder, leider.
Locale: 1033 ,+,"? Changing locale to US-English: ,+,"?
Wenn ich ausgeführt das gleiche mitProc.StartInfo.StandardOutputEncoding = Encoding.Default;
🙁Den anderen Prozess (vbscript) erzeugt und der Ausgang in einigen Codierung. Durch die Einstellung der StandardOutputEncoding teilen Sie dem system mit, wie zu Lesen ist, dass stream. Das wird sich nicht ändern die Codierung durch den anderen Prozess.
So dass Sie brauchen, um herauszufinden, die genaue Codierung verwendet, die durch die anderen Verfahren (VBScript). Für das, dass ich das Skript ausführen direkt von der shell aus und leite die Ausgabe in eine Datei und öffnen Sie Sie in einem tool, das zeigt die Codierung (z.B. notepad2) Und wenn ich Recht habe, das wäre etwas anderes als UTF8.
Dann setzen Sie den Proc.StartInfo.StandardOutputEncoding zu, dass die Kodierung im code und dann sollte alles funktionieren.
Ich bin mit Ihrer Funktion wie folgt:
Und meine vbs-Datei ist
Meine vbs-Datei ist kodiert als UTF-8 ohne BOM
Und es funktioniert wie erwartet. Ich sehe
äåéö€
auf meine form.Sollten Sie vielleicht ändern Sie die Art und Weise, wie Sie Ihre Funktion, die Codierung Ihres vbs-Datei und wie Sie die Ausgabe von Daten an stdout.