Encodage du processus UTF8 C #

J’ai une application qui traite le vbscript et produit la sortie.

private static ssortingng processVB(ssortingng command, ssortingng 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(); ssortingng output = Proc.StandardOutput.ReadToEnd(); ssortingng error = Proc.StandardError.ReadToEnd(); if (Ssortingng.IsNullOrEmpty(output) && !Ssortingng.IsNullOrEmpty(error)) { output = error; } //Console.Write(ping_output); Proc.WaitForExit(); Proc.Close(); return output; } 

Je pense avoir réglé tout ce qui concerne la propriété Encoding. La méthode processVB obtiendra la commande en tant que fichier VBScript et ses arguments.

La méthode C #, processVB, qui traite ce fichier VBScript qui génère maintenant le résultat, comme suit.

” ?”

Mais je devrais avoir le texte original

“äåéö €”

J’ai réglé l’encodage correctement. Mais je ne suis pas capable de bien faire les choses.

Qu’est-ce que je fais mal?

Cette réponse ne répond pas à une question directe – mais j’ai remarqué un potentiel d’impasse dans votre code et j’ai donc pensé qu’il serait utile de l’afficher de toute façon.

Le potentiel d’interblocage existe du fait que votre code tente d’effectuer une lecture synchrone à partir d’une sortie redirigée et qu’il le fait pour les deux StdOut et StdErr. C’est à dire cette section du code.

 Proc.Start(); ssortingng output = Proc.StandardOutput.ReadToEnd(); ssortingng error = Proc.StandardError.ReadToEnd(); ... Proc.WaitForExit(); 

Ce qui peut arriver, c’est que le processus enfant écrit beaucoup de données dans StdErr et remplit le tampon. Une fois la mémoire tampon remplie, le processus enfant bloquera l’écriture dans StdErr (sans signaler la fin du stream StdOut). Et si l’enfant est bloqué et ne fait rien, et votre processus est bloqué en attente de la sortie de l’enfant. Impasse!!!

Pour résoudre ce problème, au moins un stream (ou mieux les deux) doit être basculé en mode asynchrone.

Voir le deuxième exemple dans MSDN qui traite spécifiquement de ce scénario et de la procédure à suivre pour passer en mode asynchrone.

En ce qui concerne le problème UTF-8 , êtes-vous sûr que votre processus enfant produit en sortie dans cet encodage et non pas en UTF-16 ou un autre? Vous voudrez peut-être examiner les octets pour essayer d’inverser le stream de codage fourni afin de pouvoir définir le codage approprié pour interpréter le stream redirigé.

MODIFIER

Voici comment je pense que vous pouvez résoudre le problème d’encodage. L’idée de base est basée sur quelque chose que j’avais autrefois besoin de faire – j’avais du texte russe en codage inconnu et devais trouver le moyen de le convertir pour qu’il affiche les caractères appropriés – prenez les octets capturés à partir de StdOut et essayez de les décoder à l’aide de toutes les pages de codes connues disponibles sur le système. Celui qui semble correct est probablement (mais pas nécessairement) le codage avec lequel StdOut est codé. La raison pour laquelle ce n’est pas garanti, même si cela semble correct avec vos données, est parce que de nombreux encodages se chevauchent sur certaines plages d’octets qui le rendraient identique. Par exemple, ASCII et UTF8 auront les mêmes octets lors du codage des caractères latins de base. Donc, pour obtenir une correspondance exacte, vous devrez peut-être faire preuve de créativité et tester un texte atypique.

Voici le code de base pour le faire – des ajustements peuvent être nécessaires:

  byte[] text =  foreach(System.Text.EncodingInfo encodingInfo in System.Text.Encoding.GetEncodings()) { System.Text.Encoding encoding = encodingInfo.GetEncoding(); ssortingng decodedBytes = encoding.GetSsortingng(bytes); System.Console.Out.WriteLine("Encoding: {0}, Decoded Bytes: {1}", encoding.EncodingName, decodedBytes); } 

Exécutez le code et examinez manuellement le résultat. Tous ceux qui correspondent au texte attendu sont candidats au codage utilisé dans StdOut.

Le problème est que la console n’est pas UTF-8 par défaut. Il s’exécute dans la même page de code que vos parameters régionaux dans Windows. Un moyen simple de résoudre ce problème consiste à utiliser la commande chcp console. Exemple:

 chcp 65001 && yourScript.vbs 

La sortie sera en UTF-8 et vous permettra de la lire correctement à partir de votre application .NET.

Notez que j’ai testé cela avec un script bat au lieu de VB-script, mais si VB-script prend en charge UTF-8, cela devrait fonctionner correctement. En outre, vous devrez peut-être appeler explicitement le moteur d’exécution VB-script au lieu de simplement yourScript.vbs . Mais vous devriez être capable de résoudre cela facilement vous-même 🙂

Parce que la sortie générée par VBScript est UTF8

C’est l’hypothèse qui vous cause des problèmes ici, ce n’est tout simplement pas utf-8. Cela ne peut pas non plus être le cas, le moteur de script ne prend pas en charge le réglage. Pour essayer vous-même, utilisez cette instruction dans un exemple de fichier .vbs:

  SetLocale 65001 

Kaboom, il accepte uniquement les valeurs LCID et ne couvre pas les codages utf. Au lieu de cela, le moteur de script cscript.exe modifie déjà la page de code par défaut elle-même. Au lieu de la page de code OEM par défaut (valeur HKEY_LOCAL_MACHINE \ SYSTEM \ ControlSet \ Control \ Nls \ CodePage \ OEMCP), il bascule vers la page de code Windows par défaut. La valeur ACP dans la clé de registre documentée ci-dessus. Cela dépend de votre emplacement, il sera 1252 par exemple dans les Amériques et en Europe occidentale.

Pour jouer avec du code VBScript, veillez à enregistrer le fichier avec le codage par défaut approprié à votre environnement local, sinon l’interpréteur de script interprète mal les chaînes du code source. Ce qui en soi peut aussi expliquer votre problème:

 WScript.Echo "Locale: " & GetLocale WScript.Echo "äåéö€" WScript.Echo "Changing locale to US-English:" SetLocale 1033 WScript.Echo "äåéö€" 

Sortie sur ma machine:

 C:\temp>cscript test.vbs Microsoft (R) Windows Script Host Version 5.8 Copyright (C) Microsoft Corporation. All rights reserved. Locale: 1033 äåéö€ Changing locale to US-English: äåéö€ 

La ligne de code appropriée dans votre programme devrait donc être:

 Proc.StartInfo.StandardOutputEncoding = Encoding.Default; 

Notez que ce n’est pas la valeur par défaut utilisée par la classe Process. Elle suppose qu’un programme en mode console utilise la page de code OEM. Comme 437 sur une machine en Amérique du Nord et en Europe occidentale. Vous pouvez choisir un autre LCID dans votre programme .vbs et modifier votre code C # afin qu’il corresponde, mais cela ne devrait pas être nécessaire.

Et gardez à l’esprit le mode de défaillance qui consiste à coder le fichier source .vbs de mauvais code. Le moteur de script ne supporte pas non plus utf-8 avec une nomenclature, malheureusement.

L’autre processus (vbscript) génère et génère un encodage. En définissant StandardOutputEncoding, vous indiquez au système comment lire ce stream. Cela ne changera pas l’encodage effectué par l’autre processus.

Vous devez donc déterminer le codage exact utilisé par l’autre processus (VBScript). Pour cela, je lancerais le script directement à partir du shell, puis redirectais la sortie vers un fichier et l’ouvrirais dans un outil affichant l’encodage (c’est-à-dire notepad2). Et si je ne me trompe pas, ce serait autre chose qu’UTF8.

Ensuite, vous définissez Proc.StartInfo.StandardOutputEncoding sur cet encodage dans votre code, puis tout devrait fonctionner.

J’utilise votre fonction comme ceci:

 label1.Text = processVB("wscript.exe", "c:\\s.vbs"); 

Et mon fichier vbs est

 Set fso = CreateObject ("Scripting.FileSystemObject") Set stdout = fso.GetStandardStream (1) stdout.WriteLine "äåéö€" 

Mon fichier vbs est encodé en UTF-8 sans nomenclature

Et cela fonctionne comme prévu. Je vois äåéö€ sur mon formulaire.

Peut-être devriez-vous changer la façon dont vous utilisez votre fonction, l’encodage de votre fichier vbs et la manière dont vous exportez les données sur stdout.