|
Trouver une ressource
Vous ne trouvez pas de réponse à votre problème ? Alors posez la question dans le forum. Souvenez-vous qu'il n'y a jamais de question bête, mais rester dans l'ignorance parce que l'on n'ose pas poser une question, ça c'est une erreur !
Sujet : Récupération "au fil de l'eau" du résulat d'une commande DOS [ Windows / System ] (10MilleSabords)
Informations & options pour cette discussion
jeudi 10 janvier 2008 à 15:11:14 |
Récupération "au fil de l'eau" du résulat d'une commande DOS

10MilleSabords
|
Bonjour,
Tout est dans le sujet. Est-ce possible? Voici ou j'en suis: Je lance ma ligne de commande par un CreateProcess puis je récupère le résulat dans un buffer par un CreatePipe puis ReadFile. Cela fonctionne très bien mais le buffer est rempli une fois que l'exécution dans la console est terminée or j'aimerai pouvoir récupérer les informations au fil de l'exécution de la commande. Quelqu'un a-t-il déjà fait ca? Merci d'avance pour votre aide. Voici mon code:
STARTUPINFO si; PROCESS_INFORMATION pi; unsigned long dwExitCode;
HANDLE PipeInputRead; HANDLE PipeInputWrite; HANDLE PipeOutputRead; HANDLE PipeOutputWrite;
SECURITY_ATTRIBUTES securityattribs = {sizeof(SECURITY_ATTRIBUTES),NULL,TRUE}; DWORD dwRead; DWORD NumByte; char buffer[BUFSIZE];
memset(&si, 0, sizeof(si)); memset(&pi, 0, sizeof(pi)); si.cb = sizeof(si);
// Create pipe for standard output redirection CreatePipe(&PipeOutputRead, &PipeOutputWrite, &securityattribs, 0); // Create pipe for standard input redirection. CreatePipe(&PipeInputRead, &PipeInputWrite, &securityattribs, 0);
si.dwFlags = STARTF_USESHOWWINDOW+STARTF_USESTDHANDLES; si.hStdInput = PipeInputRead; si.hStdOutput = PipeOutputWrite; si.hStdError = PipeOutputWrite; si.wShowWindow = SW_SHOW;
bool pSuccess = CreateProcess( NULL,"C:\\_prov\\avr prog\\AVROSP.exe -dATmega128 -e" , NULL, NULL, true, CREATE_NEW_CONSOLE, NULL, NULL, &si, &pi);
if (pSuccess) { CloseHandle(pi.hThread); // fermer le handle de thread dès qu'il devient inutile WaitForSingleObject(pi.hProcess, INFINITE); // attente jusqu'à la signalisation de la fermeture GetExitCodeProcess(pi.hProcess, &dwExitCode); // le processus notepad est terminé if (dwExitCode != STILL_ACTIVE) CloseHandle(pi.hProcess); // fermer le handle de process } else { CloseHandle(PipeOutputWrite); CloseHandle(PipeInputRead); } CloseHandle(PipeOutputWrite); CloseHandle(PipeInputRead); CloseHandle(PipeInputWrite);
while (ReadFile(PipeOutputRead, buffer, BUFSIZE-1, &dwRead, NULL) && (dwRead != 0)) { buffer[dwRead] = '\0'; } SetDlgItemText(Handle,IDC_EDIT1,buffer); // Affichage dans la ComboBox
CloseHandle(PipeOutputRead);
|
|
|
vendredi 11 janvier 2008 à 12:48:42 |
Re : Récupération "au fil de l'eau" du résulat d'une commande DOS
|
vendredi 11 janvier 2008 à 14:42:16 |
Re : Récupération "au fil de l'eau" du résulat d'une commande DOS

rt15
|
Ca à l'air presque bon, mais ça bloque sur le dernier Read. Le pipe est
encore là (Donc pas d'erreur), la fin n'est pas atteinte... Read attend
des nouvelles entrées...
Voilou une appli qui fait un ping dans une nouvelle fenêtre mais qui fait sa sortie sur la première : #include "windows.h"
#define BUFSIZE 256
void ReadPipe(HANDLE hPipeRead) { CHAR lpBuffer[256]; DWORD nBytesRead; DWORD nCharsWritten;
while (ReadFile(hPipeRead, lpBuffer, sizeof(lpBuffer), &nBytesRead, NULL) && nBytesRead) WriteConsole(GetStdHandle(STD_OUTPUT_HANDLE), lpBuffer, nBytesRead, &nCharsWritten, NULL); }
int main() { STARTUPINFO si; PROCESS_INFORMATION pi; BOOL pSuccess;
HANDLE PipeInputRead; HANDLE PipeInputWrite; HANDLE PipeOutputRead; HANDLE PipeOutputWrite;
SECURITY_ATTRIBUTES securityattribs = {sizeof(SECURITY_ATTRIBUTES),NULL,TRUE};
CreatePipe(&PipeOutputRead, &PipeOutputWrite, &securityattribs, 0); CreatePipe(&PipeInputRead, &PipeInputWrite, &securityattribs, 0);
memset(&si, 0, sizeof(si)); si.cb = sizeof(si); si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES; si.hStdInput = PipeInputRead; si.hStdOutput = PipeOutputWrite; si.hStdError = PipeOutputWrite; si.wShowWindow = SW_SHOW;
pSuccess = CreateProcess(NULL, "ping 127.0.0.1" , NULL, NULL, TRUE, CREATE_NEW_CONSOLE, NULL, NULL, &si, &pi);
if (pSuccess) { while (WaitForSingleObject(pi.hProcess, 1) == WAIT_TIMEOUT) { ReadPipe(PipeOutputRead); } ReadPipe(PipeOutputRead); }
CloseHandle(PipeInputRead); CloseHandle(PipeInputWrite); CloseHandle(PipeOutputRead); CloseHandle(PipeOutputWrite);
return 0; }
|
|
|
vendredi 11 janvier 2008 à 14:44:20 |
Re : Récupération "au fil de l'eau" du résulat d'une commande DOS
|
vendredi 11 janvier 2008 à 15:07:35 |
Re : Récupération "au fil de l'eau" du résulat d'une commande DOS

10MilleSabords
|
Merci rt15 pour ta réponse!
J'avais effectivement pensé à la lecture dans une boucle d'attente mais je n'avais pas approfondit. J'ai testé et ça s'exécute bien mais je pense en fait que j'ai 2 problèmes à régler car le but final est d'afficher ces résultats dans une EditBox (Appli windows) 1) Récupérer les résultats au fil de l'eau: je pense que ta solution résoud ce problème 2) Afficher au fil de l'eau dans l'EditBox: Et là ça se complique car la fenêtre se raffraichit une fois l'exécution de la console terminée J'utilise SetDlgItemText dans la boucle pour raffraichir.
Merci encore, ça m'a décoincer pas mal!
|
|
|
vendredi 11 janvier 2008 à 15:38:37 |
Re : Récupération "au fil de l'eau" du résulat d'une commande DOS

rt15
|
Tu peux passer par des threads.
J'en ai fait un pour corriger le bug cité plus haut.
Il faudrat que tu en fasse un deuxième qui attende la fin du processus pour tuer le premier thread.
#include "windows.h"
#include "stdlib.h"
#define BUFSIZE 256
typedef struct _ReadPipeThreadParam
{
HANDLE hPipe;
} ReadPipeThreadParam;
DWORD __stdcall ReadPipe(ReadPipeThreadParam* param)
{
CHAR lpBuffer[256];
DWORD nBytesRead;
DWORD nCharsWritten;
while (ReadFile(param->hPipe, lpBuffer, sizeof(lpBuffer), &nBytesRead, NULL) && nBytesRead)
WriteConsole(GetStdHandle(STD_OUTPUT_HANDLE), lpBuffer, nBytesRead, &nCharsWritten, NULL);
return 0;
}
int main()
{
STARTUPINFO si;
PROCESS_INFORMATION pi;
BOOL pSuccess;
ReadPipeThreadParam param;
DWORD nThreadId;
HANDLE hThread;
HANDLE PipeInputRead;
HANDLE PipeInputWrite;
HANDLE PipeOutputRead;
HANDLE PipeOutputWrite;
SECURITY_ATTRIBUTES securityattribs = {sizeof(SECURITY_ATTRIBUTES),NULL,TRUE};
CreatePipe(&PipeOutputRead, &PipeOutputWrite, &securityattribs, 0);
CreatePipe(&PipeInputRead, &PipeInputWrite, &securityattribs, 0);
memset(&si, 0, sizeof(si));
si.cb = sizeof(si);
si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
si.hStdInput = PipeInputRead;
si.hStdOutput = PipeOutputWrite;
si.hStdError = PipeOutputWrite;
si.wShowWindow = SW_SHOW;
pSuccess = CreateProcess(NULL, "ping 127.0.0.1" , NULL, NULL, TRUE, CREATE_NEW_CONSOLE, NULL, NULL, &si, &pi);
if (pSuccess)
{
param.hPipe = PipeOutputRead;
hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)&ReadPipe, ¶m, 0, &nThreadId);
WaitForSingleObject(pi.hProcess, INFINITE);
TerminateThread(hThread, 0);
}
CloseHandle(hThread);
CloseHandle(PipeInputRead);
CloseHandle(PipeInputWrite);
CloseHandle(PipeOutputWrite);
CloseHandle(PipeOutputRead);
system("pause");
return 0;
}
|
|
|
vendredi 11 janvier 2008 à 16:12:45 |
Re : Récupération "au fil de l'eau" du résulat d'une commande DOS

10MilleSabords
|
Effectivement je n'avais pas pensé aux threads, je vais testé ça... Merci.
|
|
|
vendredi 11 janvier 2008 à 17:14:19 |
Re : Récupération "au fil de l'eau" du résulat d'une commande DOS

10MilleSabords
|
J'ai pu testé les threads grâce à ton code et à l'exécution le résultat est le même: l'affichage parvient une fois l'exécution de la console terminée. En fait, j'ai pu vérifier que la thread récupère bien les résultats en parallèle de l'exécution de la console mais l'affichage n'arrive qu'à la fin. D'autre part, j'ai compté le nombre de fois que je vais dans la boucle du ReadFile (= nbre de fois qu'il vient récupérer des caractères dans la console): 2 fois! alors qu'il faudrait plusieurs 10n de fois pour être réellement au fil de l'eau... Ca veut donc dire que le temps d'exécution du ReadFile est bien trop longue pour récupérer véritablement au fil de l'eau (en même temps, je suis sous windows et pas un OS temps réel!) Je crains que je vais me contenter de l'affichage en fin d'exécution....
|
|
|
samedi 12 janvier 2008 à 22:31:58 |
Re : Récupération "au fil de l'eau" du résulat d'une commande DOS

rt15
|
Bah pour un ping, on les voit bien arriver les uns après les autres. Voilà une appli avec un champ de texte où on peut entrer des commandes, et un champ de texte où les résultats sont affichés. #include "windows.h"
#define BUFFER_SIZE 65536
HINSTANCE _hThisInstance; // Handle du module HWND _hWnd; // Handle de la fenêtre HWND _hInput; // Handle de l'EDIT où l'utilisateur tape les commandes HWND _hOutput; // Handle de l'EDIT où la sortie de la console est affichée LPSTR _lpAppName = "ConsoleInWindow"; // Nom de l'appli HANDLE _hConsole; // Handle de l'appli lancée CHAR lpPipeContent[BUFFER_SIZE]; // Contenu du pipe
HANDLE hReadPipe; // Thread de lecture du pipe HANDLE hClosePipe; // Thread qui détruit le thread de lecture
// Les Pipe de lecture et d'écriture fournis à la console HANDLE hPipeInputRead; HANDLE hPipeInputWrite; HANDLE hPipeOutputRead; HANDLE hPipeOutputWrite;
// // Affiche le message d'erreur associé à la dernière // erreur Win32 et ferme l'appli. // void ShowLastError() { DWORD nLastError; LPSTR lpMessageBuffer;
// Récupération du numéro de l'erreur nLastError = GetLastError();
// Formatage du message FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, nLastError, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &lpMessageBuffer, 0, NULL);
// Affichage du message et fin de l'appli MessageBox(NULL, lpMessageBuffer, "ERROR", MB_OK | MB_ICONERROR); ExitProcess(nLastError); }
// // Détruit le thread de lecture dès que la console est fermée. // DWORD __stdcall ClosePipe(LPVOID null) { WaitForSingleObject(_hConsole, INFINITE); TerminateThread(hReadPipe, 0);
CloseHandle(hPipeInputRead); CloseHandle(hPipeInputWrite); CloseHandle(hPipeOutputWrite); CloseHandle(hPipeOutputRead);
CloseHandle(hReadPipe); CloseHandle(hClosePipe); return 0; }
// // Lit le contenu du pipe et le copie dans la fenêtre. // DWORD __stdcall ReadPipe(HANDLE hPipe) { CHAR* lpCurrentPos; // Position courante de l'écriture dans le buffer DWORD nBytesRead; // Nombre d'octets lus dans le pipe
// On va concaténer lpCurrentPos = lpPipeContent;
// Lecture du pipe while (ReadFile(hPipe, lpCurrentPos, BUFFER_SIZE - 1, &nBytesRead, NULL) && nBytesRead) { // Mise en place du zéro terminal lpCurrentPos[nBytesRead - 1] = '\0'; SetWindowText(_hOutput, lpPipeContent);
// On va concaténer la suite au niveau du zéro terminal lpCurrentPos = lpCurrentPos + nBytesRead - 1; }
return 0; }
// // Lance la commande demandée. // void Execute(CHAR* lpCommandLine) { STARTUPINFO si; // Info de lancement du processus PROCESS_INFORMATION pi; // Récupération d'handles sur le processus lancé DWORD nThreadId; // Récupération du thread ID lors des créations de thread
SECURITY_ATTRIBUTES securityattribs = {sizeof(SECURITY_ATTRIBUTES),NULL,TRUE};
if (! CreatePipe(&hPipeOutputRead, &hPipeOutputWrite, &securityattribs, 0)) ShowLastError(); if (! CreatePipe(&hPipeInputRead, &hPipeInputWrite, &securityattribs, 0)) ShowLastError();
ZeroMemory(&si, sizeof(si)); si.cb = sizeof(si); si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES; si.hStdInput = hPipeInputRead; si.hStdOutput = hPipeOutputWrite; si.hStdError = hPipeOutputWrite; si.wShowWindow = SW_SHOW;
if (CreateProcess(NULL, lpCommandLine, NULL, NULL, TRUE, CREATE_NEW_CONSOLE, NULL, NULL, &si, &pi)) { // Lancement du thread de lecture du pipe hReadPipe = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)&ReadPipe, hPipeOutputRead, 0, &nThreadId);
// Lancement du thread qui va tuer le thread de lecture _hConsole = pi.hProcess; hClosePipe = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)&ClosePipe, NULL, 0, &nThreadId); } }
// // Traitement des messages. // LRESULT CALLBACK WindowProcedure(HWND hWnd, UINT nMessage, WPARAM wParam, LPARAM lParam) { RECT rect; // Récupération de la taille de la cliente pour redimenssionner les contrôles
switch (nMessage) { case WM_MOVE: case WM_ACTIVATE: case WM_SIZING: GetClientRect(_hWnd, &rect); SetWindowPos(_hInput, 0, 0, rect.bottom - 20, rect.right, 20, SWP_NOZORDER); SetWindowPos(_hOutput, 0, 0, 0, rect.right, rect.bottom - 20, SWP_NOZORDER); return DefWindowProc(hWnd, nMessage, wParam, lParam); case WM_DESTROY: // On signale que le thread va s'arrêter PostQuitMessage(0); break; default: // Application du traitement par défaut return DefWindowProc(hWnd, nMessage, wParam, lParam); } return 0; }
// // Initialise la fenêtre principale de l'appli. // void InitWindow() { WNDCLASSEX wincl; // Classe de la fenêtre utilisée
// Création de la classe de fenêtre wincl.cbSize = sizeof(WNDCLASSEX); wincl.style = CS_OWNDC; wincl.lpfnWndProc = WindowProcedure; wincl.cbClsExtra = 0; wincl.cbWndExtra = 0; wincl.hInstance = _hThisInstance; wincl.hIcon = LoadIcon(NULL, IDI_APPLICATION); wincl.hCursor = LoadCursor(NULL, IDC_ARROW); wincl.hbrBackground = (HBRUSH) COLOR_BACKGROUND; wincl.lpszMenuName = 0; wincl.lpszClassName = _lpAppName; wincl.hIconSm = NULL;
// Enregistrement de la classe if (!RegisterClassEx(&wincl)) ShowLastError();
// Création de la fenêtre _hWnd = CreateWindowEx(0, _lpAppName, _lpAppName, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 600, 400, HWND_DESKTOP, NULL, _hThisInstance, NULL); _hInput = CreateWindowEx(0, "EDIT", "ping 127.0.0.1", WS_VISIBLE | WS_CHILD | WS_BORDER, 0, 0, 0, 0, _hWnd, NULL, _hThisInstance, NULL); _hOutput = CreateWindowEx(0, "EDIT", "", WS_VISIBLE | WS_CHILD | WS_BORDER | WS_VSCROLL | ES_MULTILINE | ES_READONLY | ES_OEMCONVERT, 0, 0, 0, 0, _hWnd, NULL, _hThisInstance, NULL);
ShowWindow(_hWnd, SW_SHOW); }
#pragma comment(linker, "/entry:main") INT32 _cdecl main() { MSG message; // Réception des messages envoyés à l'application CHAR lpCommandLine[1024]; // Rédaction de la commande à executé CHAR lpInputContent[1024]; // Récupération de la commande tapée par l'utilisateur
// Récupération du handle du module _hThisInstance = GetModuleHandle(NULL);
InitWindow();
// Boucle de traitement des messages while (GetMessage(&message, NULL, 0, 0)) { // On execute la commande lors d'un appui sur entrée if (((message.hwnd == _hInput) || (message.hwnd == _hOutput)) && (message.wParam == VK_RETURN) && (message.message == WM_KEYUP)) { SendMessage(_hInput, WM_GETTEXT, 1024, (LPARAM)lpInputContent); wsprintf(lpCommandLine, "cmd /C \"%s\"", lpInputContent); Execute(lpCommandLine); }
// Traduit certains messages TranslateMessage(&message);
// Distribution des messages aux fenêtres DispatchMessage(&message); }
// Code d'erreur en sortie return message.wParam; }
|
|
|
lundi 14 janvier 2008 à 10:20:12 |
Re : Récupération "au fil de l'eau" du résulat d'une commande DOS

10MilleSabords
|
Ouah! Encore merci de consacrer de ton temps à mon problème!
Effectivement ton appli fonctionne très bien, le ping remonte bien au fur et à mesure. J'ai testé ma ligne de commande avec mon programme DOS et là, bizarrement le résultats ne remontent qu'une fois le programme terminé. En fait, ce programme DOS programme un microcontroleur (je suis électronicien à la base) et renvoie un état d'avancement au fur et mesure. En bref, je n'observe pas le même comportement entre le ping et mon programme dos. Peut-être un problème de priorité car le programme dos prend peut-être plus de ressources pendant la programmation et ne permet pas à l'affichage de s'exécuter.
|
|
|
Cette discussion est classé dans : buffer, handle, pi, closehandle, pipeoutputwrite
Répondre à ce message
Sujets en rapport avec ce message
getoenfilename -> ??? [ par stefbuet ]
salut,sur une source (http://www.cppfrance.com/code.aspx?ID=28478)j'ai extrait une fonction de la librairy créé et ais essayé de la faire fonctioner,
Pipes sous windows [ par ssmint ]
Bonjour à tous, Voilà je voudrais piloter CMD.EXE gràce à mon prog pour au final pouvoir réaliser une sorte de telnet...J'ai redirigé l'entrée et la s
Redirection sortie [ par M5i9k ]
Bonjour à tous,je voudrais lire la sortie d'une console lancée à partir de mon programme (j'utilise CreateProcess), je voudrais savoir si je suis sur
CreateProcess et processus infini [ par Rankin ]
Salut à tous,Je suis en train de développer une appli qui lance pas mal de commandes système pour récupérer notamment la configuration du réseau. Pour
Comment utiliser un buffer [ par sofoot ]
Bonjour,Je travail sous C++Builder 6 et je souhaite faire communiquer un système (un monnayeur) avec mon pc via un port COM. Afin de récupérer les inf
Obtenir l'handle d'une DLL [ par TryToHelpMe ]
Bonjour,J'ai un nouveau problème que je n'arrive pas à résoudre.J'ai besoin de récupérer l'handle de ma DLL.Je fait appel à ma DLL depuis un programme
Problème création handle [ par nicolasmaicheul ]
Bonjour,Cette simple ligne :string^ s = gcnew string("test");provoques ces ereurs à la compilation (visual c++ express) :error C3193: '^'*: requiert l
[Maple]Problème Tracé de champ magnétique [ par Nethernat ]
Bonjour à tous, à vrai dire je ne sais pas très bien où placer ce post ... J'essaye de tracer les lignes de champ magnétique crées par une spire de
Info sur les include [ par jose12 ]
Bonjour, contexte : Je ne suis pas développeur mais admin réseau. Je connais un peu le VB et divers langage Web, et j'ai une vision très très succint
Double buffer win32 [ par Stepharcher ]
Bonjour à tous !J'ai récemment tenté le double buffer sous window avec GDI... Mais je ne comprend pas trop mon erreur. Quand je dessine directement su
Livres en rapport
|
Téléchargements
Logiciels à télécharger sur le même thème :
Comparez les prix Nouvelle version
|