Décoder les flux standards sous windows (stdin et stdout)

Sujets variés concernant le développement en PureBasic
Avatar de l’utilisateur
Naheulf
Messages : 191
Inscription : dim. 10/mars/2013 22:22
Localisation : France

Décoder les flux standards sous windows (stdin et stdout)

Message par Naheulf »

Bonjour,
J'essaye de faire un programme qui prend des données textuelles sur l'entrée standard, fait un traitement dessus, puis recrache le résultat sur la sortie standard.
Une version simplifiée du programme donnerais quelque chose du genre :

Code : Tout sélectionner

If OpenConsole("", )
	Define Text$ = Input()
	While Text$ <> #PB_Input_Eof
		Text$ = UCase(Text$)
		PrintN(Text$)
		Text$ = Input()
	Wend 
EndIf
Si j'exécute directement le programme et que saisi des choses dans la console qui s'affiche j’obtiens bien le résultat escompté.

En revanche, si j'essaye de relier l'entrée du programme à la sortie d'un autre via un pipe ça fait juste n'importe quoi.
Pour tester j'utilise la commande suivante :

Code : Tout sélectionner

ping 127.0.0.1 | monprogramme.exe
La sortie normale de la commande ping est :

Code : Tout sélectionner

Envoi d'une requête 'Ping'  127.0.0.1 avec 32 octets de données :
Réponse de 127.0.0.1 : octets=32 temps<1ms TTL=128
Réponse de 127.0.0.1 : octets=32 temps<1ms TTL=128
Réponse de 127.0.0.1 : octets=32 temps<1ms TTL=128
Réponse de 127.0.0.1 : octets=32 temps<1ms TTL=128

Statistiques Ping pour 127.0.0.1:
    Paquets : envoyés = 4, reçus = 4, perdus = 0 (perte 0%),
Durée approximative des boucles en millisecondes :
    Minimum = 0ms, Maximum = 0ms, Moyenne = 0ms
sauf qu'après passage dans mon programme j'ai ce truc :

Code : Tout sélectionner

??????????????┼????????´????????????????????Q>????´????????????????????????´????????????????????
????´????????????????????????´????????????????????????????┼??????????????????????%??????????????
??????????????????┼┼??????????????????????
Si quelqu'un à une idée de comment régler le problème, je suis preneur.

Note :
J'ai essayé de combiner ReadConsoleData(), PeekS() et PokeS() de différentes façons, je n'arrive jamais à avoir un résultat qui conserve tous les caractères.
Avatar de l’utilisateur
Ar-S
Messages : 9476
Inscription : dim. 09/oct./2005 16:51
Contact :

Re: Décoder les flux standards sous windows (stdin et stdout

Message par Ar-S »

Ce n'est pas une histoire d'unicode, #PB_UTF8 etc avec ton openconsole et ton exe ? (avec les flag #PB_Unicode , #PB_UTF8 etc) ?
~~~~Règles du forum ~~~~
⋅.˳˳.⋅ॱ˙˙ॱ⋅.˳Ar-S ˳.⋅ॱ˙˙ॱ⋅.˳˳.⋅
W11x64 PB 6.x
Section HORS SUJET : ICI
LDV MULTIMEDIA : Dépannage informatique & mes Logiciels PB
UPLOAD D'IMAGES : Uploader des images de vos logiciels
Avatar de l’utilisateur
Naheulf
Messages : 191
Inscription : dim. 10/mars/2013 22:22
Localisation : France

Re: Décoder les flux standards sous windows (stdin et stdout

Message par Naheulf »

Bah j'ai testé mais j'ai pas réussi.

Le plus proche que j'ai réussi à faire c'est avec un code du genre :

Code : Tout sélectionner

If OpenConsole("")
	#BUFFER_SIZE = 1024
	*Buffer = AllocateMemory(#BUFFER_SIZE)
	ReadSize = ReadConsoleData(*Buffer, #BUFFER_SIZE)
	While ReadSize
		Text$ = PeekS(*Buffer, ReadSize, #PB_Ascii)
		Text$ = UCase(Text$)
		PrintN(Text$)
		ReadSize = ReadConsoleData(*Buffer, #BUFFER_SIZE)
	Wend 
EndIf
Sauf que ça ne garde pas non plus tous les caractères... (mais dans ce cas, on est cohérent entre une exécution direct et un exécution avec des pipes)
Le texte :

Code : Tout sélectionner

Je me creuse la tête.
Donne :

Code : Tout sélectionner

JE ME CREUSE LA T^TE.
Avatar de l’utilisateur
GallyHC
Messages : 1703
Inscription : lun. 17/déc./2007 12:44

Re: Décoder les flux standards sous windows (stdin et stdout

Message par GallyHC »

Code : Tout sélectionner

If OpenConsole("")
   #BUFFER_SIZE = 1024
   *Buffer = AllocateMemory(#BUFFER_SIZE)
   ReadSize = ReadConsoleData(*Buffer, #BUFFER_SIZE)
   While ReadSize
      Text$ = PeekS(*Buffer, ReadSize, #PB_Ascii)
      ;Text$ = UCase(Text$)
      PrintN(Text$)
      ReadSize = ReadConsoleData(*Buffer, #BUFFER_SIZE)
   Wend
EndIf
Configuration : Tower: Windows 10 (Processeur: i7 "x64") (Mémoire: 16Go) (GeForce GTX 760 - 2Go) - PureBasic 5.72 (x86 et x64)
Avatar de l’utilisateur
Naheulf
Messages : 191
Inscription : dim. 10/mars/2013 22:22
Localisation : France

Re: Décoder les flux standards sous windows (stdin et stdout

Message par Naheulf »

En fait t'as juste commenté la partie "utile" du code (la fonction UCase() qui représente le traitement que doit faire le programme).
Le cœur du problème reste intact : certains caractères ne sont pas conservés (ex : "ê" devient "^", UCase ou non). Donc si ces caractères visibles deviennent n'importe quoi, je n'ose imaginer ce qu'il se passera sur les caractères de contrôles (dont le traitement est le but du programme complet).
Avatar de l’utilisateur
Kwai chang caine
Messages : 6962
Inscription : sam. 23/sept./2006 18:32
Localisation : Isere

Re: Décoder les flux standards sous windows (stdin et stdout

Message par Kwai chang caine »

Je ne sais pas si c'est ce que tu cherches car c'est juste pour windows, :oops:
Mais y'a ce code de ZORRO qui marche sous W10, j'ai vérifié :wink:
http://www.purebasic.fr/french/viewtopi ... 93#p192393

Code : Tout sélectionner

prg=RunProgram("cmd.exe", "/c ipconfig /all  ", "", #PB_Program_Open|#PB_Program_Read) ; la commande "ipconfig /all" est entré dans la console
If prg
      While ProgramRunning(prg)
            If AvailableProgramOutput(prg)
                  sOEM_in_unicode.s = ReadProgramString(prg, #PB_Ascii)
                  iByteLength = Len(sOEM_in_unicode) + 2
                  sOem_in_Ascii.s = Space(iByteLength)
                  PokeS(@sOem_in_Ascii, sOEM_in_unicode, -1, #PB_Ascii)
                  sUnicode.s = Space(iByteLength)
                  OemToChar_(@sOem_in_Ascii, @sUnicode)
                  Sortie$=Sortie$+sUnicode.s+Chr(10)+Chr(13)
            EndIf
      Wend
      Sortie$ + Chr(10) + Chr(13)
      Sortie$ + "Code de retour : " + Str(ProgramExitCode(prg))      
      
      CloseProgram(prg) ; Ferme la connection vers le programme
EndIf
MessageRequester("Sortie", Sortie$)
qui donne
Console a écrit :
Utilisation : ping [-t] [-a] [-n count] [-l size] [-f] [-i TTL] [-v TOS]

[-r count] [-s count] [[-j host-list] | [-k host-list]]

[-w timeout] [-R] [-S srcaddr] [-c compartment] [-p]

[-4] [-6] nom_cible


Options :

-t Effectue un test ping sur l'hôte spécifié jusqu'à son arrêt.

Pour afficher les statistiques et continuer,

appuyez sur Ctrl+Attn.

Pour arrêter, appuyez sur Ctrl+C.

-a Résout les adresses en noms d'hôtes.

-n count Nombre de demandes d'écho à envoyer.

-l size Taille du tampon d'envoi.

-f Active l'indicateur Ne pas fragmenter dans le paquet (IPv4

uniquement).

-i TTL Durée de vie.

-v TOS Type de service (IPv4 uniquement. La

configuration de ce paramètre n'a aucun effet sur le type

de service dans l'en-tête IP).

-r count Itinéraire d'enregistrement du nombre de sauts (IPv4

uniquement).

-s count Horodatage du nombre de sauts (IPv4 uniquement).

-j host-list Itinéraire source libre parmi la liste d'hôtes (IPv4

uniquement).

-k host-list Itinéraire source strict parmi la liste d'hôtes (IPv4

uniquement).

-w timeout Délai d'attente pour chaque réponse, en millisecondes.

-R Utilise l'en-tête de routage pour tester également

l'itinéraire inverse (IPv6 uniquement).

D'après la RFC 5095, l'utilisation de cet en-tête de routage

est déconseillée. Certains systèmes peuvent supprimer des

demandes d'écho si cet en-tête est utilisé.

-S srcaddr Adresse source à utiliser.

-c compartment Identificateur de compartiment de routage.

-p Effectue un test ping sur l'adresse de fournisseur

de la virtualisation réseau Hyper-V.

-4 Force l'utilisation d'IPv4.

-6 Force l'utilisation d'IPv6.



Code de retour : 1
ImageLe bonheur est une route...
Pas une destination

PureBasic Forum Officiel - Site PureBasic
Avatar de l’utilisateur
Naheulf
Messages : 191
Inscription : dim. 10/mars/2013 22:22
Localisation : France

Re: Décoder les flux standards sous windows (stdin et stdout

Message par Naheulf »

Merci Kwai chang caine.

Gally m'as donné une solution sur discord et j'ai oublié de faire le retour sur le fofo :oops:

En fait tu lis dans mes pensées. Ta solution (enfin celle de Zorro) ne correspond pas à ce que je voulais faire pour ce programme : elle correspond à ce que je voulais faire pour une seconde variante du programme (qui utiliserait effectivement l'appel à un sous programme)

Reste à voir si je vais avoir le droit à d'autres "surprises" comme le caractère de contrôle "ESC" qui se transforme en '←' avec OemToCharW()...
Avatar de l’utilisateur
TazNormand
Messages : 1294
Inscription : ven. 27/oct./2006 12:19
Localisation : Calvados (14)

Re: Décoder les flux standards sous windows (stdin et stdout

Message par TazNormand »

@Naheulf : peux-tu poster ici la solution que t'a donné GallyHC sur Discord, car elle pourrait servir à quelqu'un d'autre plus tard. Merci
Image
Image
Avatar de l’utilisateur
GallyHC
Messages : 1703
Inscription : lun. 17/déc./2007 12:44

Re: Décoder les flux standards sous windows (stdin et stdout

Message par GallyHC »

Voila:

Code : Tout sélectionner

If OpenConsole("", #PB_Ascii)
  #BUFFER_SIZE = 1024
  Text$ = Space(#BUFFER_SIZE)
  *Buffer  = AllocateMemory(#BUFFER_SIZE)
  ReadSize = ReadConsoleData(*Buffer, #BUFFER_SIZE)
  While ReadSize
    OemToChar_(*Buffer, @Text$)
    PrintN((Mid(Text$, 1, ReadSize - 2)))
    ReadSize = ReadConsoleData(*Buffer, #BUFFER_SIZE)
  Wend
EndIf
Configuration : Tower: Windows 10 (Processeur: i7 "x64") (Mémoire: 16Go) (GeForce GTX 760 - 2Go) - PureBasic 5.72 (x86 et x64)
Répondre