Lancer plusieurs commandes sur le même processus

[Résolu]
Signaler
Messages postés
41
Date d'inscription
vendredi 31 mars 2006
Statut
Membre
Dernière intervention
11 mai 2009
-
Messages postés
41
Date d'inscription
vendredi 31 mars 2006
Statut
Membre
Dernière intervention
11 mai 2009
-
Salut,
Je cherche comment lancer un processus d'invite de commande et y exécuter plusieurs commandes pas nécessairement
consécutives et sans utiliser des fichier batch comme si je travaille directement sur l'invite de commande.
Merci
foza juve

10 réponses

Messages postés
3874
Date d'inscription
mardi 8 mars 2005
Statut
Modérateur
Dernière intervention
7 novembre 2014
15
Aaaaaaaah. Ces temps ci je comprends tout de travers. Cela dit, mon lien te donnais une piste pour une solution. Voilà ce que ça me donnerait (A compiler en MBCS, mais pas trop de boulot pour convertir en unicode).

<hr size="2" width="100%" />#include "windows.h"
#include "tchar.h"

DWORD __stdcall System_ShowLastError()
{
  DWORD nLastError;         /* Numéro de la dernière erreur                   */
  TCHAR* lpMessageBuffer;   /* Message d'erreur                               */

  /* 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, _T("ERROR"), MB_OK | MB_ICONERROR);

  LocalFree(lpMessageBuffer);
  return nLastError;
}

int main()
{
  PROCESS_INFORMATION processInfo;
  STARTUPINFO startupInfo;
  TCHAR lpCommandLine[50];
  HANDLE hPipeInputRead;
  HANDLE hPipeInputWrite;
  DWORD nNumberOfCharsWritten;
  TCHAR* lpHelpCommand = _T("help\n");
  TCHAR* lpQuitCommand = _T("quit\n");

  SECURITY_ATTRIBUTES securityattribs = {sizeof(SECURITY_ATTRIBUTES),NULL,TRUE};

  // En unicode lpCommandLine doit être en read/write
  lstrcpy(lpCommandLine, _T("netsh"));

  if (! CreatePipe(&hPipeInputRead,  &hPipeInputWrite, &securityattribs,  0)) System_ShowLastError();
  if (! SetHandleInformation(hPipeInputWrite, HANDLE_FLAG_INHERIT, 0)) System_ShowLastError();

  ZeroMemory(&startupInfo, sizeof(startupInfo));
  startupInfo.cb = sizeof(startupInfo);
  startupInfo.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
  startupInfo.wShowWindow = SW_SHOW; // Ou SW_HIDE pour cacher la fenêtre
  startupInfo.hStdInput = hPipeInputRead;
  startupInfo.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
  startupInfo.hStdError = GetStdHandle(STD_ERROR_HANDLE);

  if (! CreateProcess(NULL, lpCommandLine,
                      NULL, NULL, TRUE, 0, NULL, NULL,
                      &startupInfo, &processInfo))
  {
    ExitProcess(System_ShowLastError());
  }

  if (! WriteFile(hPipeInputWrite, lpHelpCommand, lstrlen(lpHelpCommand), &nNumberOfCharsWritten, NULL)) System_ShowLastError();
  if (! WriteFile(hPipeInputWrite, lpQuitCommand, lstrlen(lpHelpCommand), &nNumberOfCharsWritten, NULL)) System_ShowLastError();

  WaitForSingleObject(processInfo.hProcess, INFINITE);

  CloseHandle(processInfo.hProcess);
  CloseHandle(processInfo.hThread);

  CloseHandle(hPipeInputRead);
  CloseHandle(hPipeInputWrite);

  return 0;
}
Messages postés
1466
Date d'inscription
mardi 20 février 2007
Statut
Membre
Dernière intervention
7 février 2011
1
Salut,
google + "WaitForSingleObject" = 1er lien
Ca doit avoir le même effet que waitpid(); sous UNIX.

Sinon, pour répondre à ta question 3), euh... en remplaçant le main() par un nom de fonction quelconque, en incluant ce fichier (disons .cpp) dans ton projet et en appelant ladite fonction dans ton autre main, ça ne fonctionne pas ?

Cordialement, uaip.
Messages postés
3874
Date d'inscription
mardi 8 mars 2005
Statut
Modérateur
Dernière intervention
7 novembre 2014
15
1- Toutes les fonctions de Windows traitant des chaînes sont en deux versions, une travaillant sur des chaînes MBCS, l'autre sur des chaînes unicode. Un chaîne unicode doit être préfixée par L pour êter considérée comme unicode. Dans les fait on utilise _T() ou autre pour que le code compile en unicode ou MBCS. Je ne sais pas comment tu compiles, mais par défaut sous VC2005, c'est le jeu de caractère unicode qui est utilisé. Et il se trouve que mon programme ne fonctionne pas en unicode car WriteFile traite des données, pas une chaîne. Donc elle n'a pas de version unicode. Et moi je lui donne du unicode à écrire dans une console. Ca ne peut pas marcher.
Plus d'infos ici :
http://msdn.microsoft.com/en-us/library/c426s321(VS.80).aspx

3- Entre ce code et le code de mon lien du premier post, il y a l'écriture dans le flux d'entrée et la lecture du flux de sortie (Avec écriture dans une autre fenêtre). Donc il me semble que tu as tous les éléments pour faire tout et n'importe quoi.

Version compatible MBCS/unicode :
<hr size="2" width="100%" />#include "windows.h"
#include "tchar.h"

DWORD __stdcall System_ShowLastError()
{
  DWORD nLastError;         /* Numéro de la dernière erreur                   */
  TCHAR* lpMessageBuffer;   /* Message d'erreur                               */

  /* 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, _T("ERROR"), MB_OK | MB_ICONERROR);

  LocalFree(lpMessageBuffer);
  return nLastError;
}

int main()
{
  PROCESS_INFORMATION processInfo;
  STARTUPINFO startupInfo;
  TCHAR lpCommandLine[50];
  HANDLE hPipeInputRead;
  HANDLE hPipeInputWrite;
  DWORD nNumberOfCharsWritten;
  char* lpHelpCommand = "help\n";
  char* lpQuitCommand = "quit\n";

  SECURITY_ATTRIBUTES securityattribs = {sizeof(SECURITY_ATTRIBUTES),NULL,TRUE};

  // En unicode lpCommandLine doit être en read/write
  lstrcpy(lpCommandLine, _T("netsh"));

  if (! CreatePipe(&hPipeInputRead,  &hPipeInputWrite, &securityattribs,  0)) System_ShowLastError();
  if (! SetHandleInformation(hPipeInputWrite, HANDLE_FLAG_INHERIT, 0)) System_ShowLastError();

  ZeroMemory(&startupInfo, sizeof(startupInfo));
  startupInfo.cb = sizeof(startupInfo);
  startupInfo.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
  startupInfo.wShowWindow = SW_SHOW; // Ou SW_HIDE pour cacher la fenêtre
  startupInfo.hStdInput = hPipeInputRead;
  startupInfo.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
  startupInfo.hStdError = GetStdHandle(STD_ERROR_HANDLE);

  if (! CreateProcess(NULL, lpCommandLine,
                      NULL, NULL, TRUE, 0, NULL, NULL,
                      &startupInfo, &processInfo))
  {
    ExitProcess(System_ShowLastError());
  }

  if (! WriteFile(hPipeInputWrite, lpHelpCommand, lstrlenA(lpHelpCommand), &nNumberOfCharsWritten, NULL)) System_ShowLastError();
  if (! WriteFile(hPipeInputWrite, lpQuitCommand, lstrlenA(lpQuitCommand), &nNumberOfCharsWritten, NULL)) System_ShowLastError();

  WaitForSingleObject(processInfo.hProcess, INFINITE);

  CloseHandle(processInfo.hProcess);
  CloseHandle(processInfo.hThread);

  CloseHandle(hPipeInputRead);
  CloseHandle(hPipeInputWrite);

  return 0;
}
Messages postés
3874
Date d'inscription
mardi 8 mars 2005
Statut
Modérateur
Dernière intervention
7 novembre 2014
15
Salut,

CreateProcess de cmd /C :
<hr size="2" width="100%" />#define UNICODE
#define _UNICODE

#include "windows.h"
#include "tchar.h"

DWORD __stdcall System_ShowLastError()
{
  DWORD nLastError;         /* Numéro de la dernière erreur                   */
  TCHAR* lpMessageBuffer;   /* Message d'erreur                               */

  /* 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, _T("ERROR"), MB_OK | MB_ICONERROR);

  LocalFree(lpMessageBuffer);
  return nLastError;
}

int main()
{
  PROCESS_INFORMATION processInfo;
  STARTUPINFO startupInfo;
  TCHAR lpCommandLine[50];
 
  // En unicode lpCommandLine doit être en read/write
  lstrcpy(lpCommandLine, _T("cmd /C ping 127.0.0.1"));

  ZeroMemory(&startupInfo, sizeof(startupInfo));
  startupInfo.cb = sizeof(startupInfo);
  startupInfo.dwFlags = STARTF_USESHOWWINDOW;
  startupInfo.wShowWindow = SW_SHOW; // Ou SW_HIDE pour cacher la fenêtre

  if (! CreateProcess(NULL, lpCommandLine,
                      NULL, NULL, FALSE, 0, NULL, NULL,
                      &startupInfo, &processInfo))
  {
    ExitProcess(System_ShowLastError());
  }

  CloseHandle(processInfo.hProcess);
  CloseHandle(processInfo.hThread);

  return 0;
}
<hr size="2" width="100%" />Pour récupérer le résultat au fil de l'eau dans une fenêtre.
Messages postés
41
Date d'inscription
vendredi 31 mars 2006
Statut
Membre
Dernière intervention
11 mai 2009

Merci mais cela ne répond pas à mon besoin, moi je veux ouvrir une application qui marche sur l'invite des commandes ensuite appeler les fonctions de cette application.
Par exemple l'application s'appelle  "app" quand je lance le processus ça me donne
app>
pour accèder à l'aide
app>help
pour sortir
app>exit
c'est cela que je veux exécuter des commandes consécutives sur le même invite de commande.

foza juve
Messages postés
41
Date d'inscription
vendredi 31 mars 2006
Statut
Membre
Dernière intervention
11 mai 2009

Merci beaucoup cher rt15 c'est ça que je cherche
cela dit j'ai besoin de quelques explications:
1-C'est quoi le MBCS , à ce que j'ai compris il s'agit d'un type de codage mais qu'est ce qu'il a de particulier ?

2-Quel est le rôle WaitForSingleObject(processInfo.hProcess, INFINITE); ?

3-Comment faire pour éxécuter c'est commandes en temps réel par exemple à partir d'une autre fenêtre ?

Merci  infiniment

foza juve
Messages postés
41
Date d'inscription
vendredi 31 mars 2006
Statut
Membre
Dernière intervention
11 mai 2009

S'il vous plait j'ai pas compris l'utilité de WaitForSingleObject(processInfo.hProcess, INFINITE);
Après la première exécution mon application se plante.
Merci

foza juve
Messages postés
41
Date d'inscription
vendredi 31 mars 2006
Statut
Membre
Dernière intervention
11 mai 2009

Mon problème c'est que je veux lancer plusieurs commandes à partir de ma fenêtre à chaque fois que l'utilisateur appui sur un bouton, ces commandes doivent être exécuter sur le même processus qui est lancé au démarrage de mon application et non pas créer un nouveau processus à chaque fois qu'on veut exécuter une commande, alors avec ce code le problème que ça n'exécute la commande que après  la fermeture du handle du pipe, or quand je veux éxécuter une autre commande il me dit "identificateur invalide" vu que le pipe est fermé.
Y-a-t-il une méthode pour réouvrir le même handle ou existe-t-il une autre solution ?
Merci

foza juve
Messages postés
3874
Date d'inscription
mardi 8 mars 2005
Statut
Modérateur
Dernière intervention
7 novembre 2014
15
Si tu mets un MessageBox entre mes deux WriteFile, tu t'apercevras que la première command est traitée avant et la deuxième après que tu ais fermé la MessageBox.

  if (! WriteFile(hPipeInputWrite, lpHelpCommand, lstrlenA(lpHelpCommand), &nNumberOfCharsWritten, NULL)) System_ShowLastError();
  MessageBox(0, _T("Avant la fin"), _T("Ex"), MB_OK);
  if (! WriteFile(hPipeInputWrite, lpQuitCommand, lstrlenA(lpQuitCommand), &nNumberOfCharsWritten, NULL)) System_ShowLastError();

D'autre part, le WaitForSingleObject permet d'attendre la fin du processus netsh (provoquée par l'envoie de quit\n) avant de fermer les pipes. Donc ce n'est pas du tout la fermeture des pipes qui provoque l'exécution des commandes.

Il doit y avoir un souci dans ton code, mais difficile pour nous de le deviner...
Messages postés
41
Date d'inscription
vendredi 31 mars 2006
Statut
Membre
Dernière intervention
11 mai 2009

ça va j'ai apporté quelques modifications au code et ça marche
voila mon code ça permet d'exécuter plusieurs commandes sur un même processus netsh.

---------------------------------------------------------------------------------

#include <windows.h>
#include <stdlib.h>
#include <stdio.h>
#include "tchar.h"

#define ID_B_EXECUTER 0
#define ID_E_EDIT 1


HINSTANCE instance;

PROCESS_INFORMATION processInfo;
STARTUPINFO startupInfo;
TCHAR lpCommandLine[50];
HANDLE hPipeInputRead;
HANDLE hPipeInputWrite;
DWORD nNumberOfCharsWritten;
SECURITY_ATTRIBUTES securityattribs = {sizeof(SECURITY_ATTRIBUTES),NULL,TRUE};



LRESULT CALLBACK procedureFenetrePrincipale(HWND, UINT, WPARAM, LPARAM);

DWORD __stdcall System_ShowLastError()
{
DWORD nLastError; /* Numéro de la dernière erreur */
TCHAR* lpMessageBuffer; /* Message d'erreur */

/* 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, _T("ERROR"), MB_OK | MB_ICONERROR);

LocalFree(lpMessageBuffer);
return nLastError;
}


int initialiser()
{


lstrcpy(lpCommandLine, _T("netsh"));

if (! CreatePipe(&hPipeInputRead, &hPipeInputWrite, &securityattribs, 0)) System_ShowLastError();
if (! SetHandleInformation(hPipeInputWrite, HANDLE_FLAG_INHERIT, 0)) System_ShowLastError();


ZeroMemory(&startupInfo, sizeof(startupInfo));
startupInfo.cb = sizeof(startupInfo);
startupInfo.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
startupInfo.wShowWindow = SW_SHOW; // SW_HIDE ||SW_SHOW
startupInfo.hStdInput = hPipeInputRead;
startupInfo.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
startupInfo.hStdError = GetStdHandle(STD_ERROR_HANDLE);

if (! CreateProcess(NULL,lpCommandLine,
NULL, NULL, TRUE, 0, NULL, NULL,
&startupInfo, &processInfo))
{
ExitProcess(System_ShowLastError());
}



return 0;
}



int lire(char* commande)
{
char* lpHelpCommand=commande;

if (! WriteFile(hPipeInputWrite, lpHelpCommand, lstrlenA(lpHelpCommand), &nNumberOfCharsWritten, NULL)) System_ShowLastError();

return 0;
}



int WINAPI WinMain (HINSTANCE cetteInstance, HINSTANCE precedenteInstance,
LPSTR lignesDeCommande, int modeDAffichage)
{

HWND fenetrePrincipale;
MSG message;
WNDCLASS classeFenetre;



classeFenetre.style = 0;
classeFenetre.lpfnWndProc = procedureFenetrePrincipale;
classeFenetre.cbClsExtra = 0;
classeFenetre.cbWndExtra = 0;
classeFenetre.hInstance = NULL;
classeFenetre.hIcon = LoadIcon(NULL, IDI_APPLICATION);
classeFenetre.hCursor = LoadCursor(NULL, IDC_ARROW);
classeFenetre.hbrBackground =(HBRUSH)(1 + COLOR_BTNFACE);
classeFenetre.lpszMenuName = NULL;
classeFenetre.lpszClassName = TEXT("classeF");


if(!RegisterClass(&classeFenetre)) return FALSE;


fenetrePrincipale = CreateWindow(TEXT("classeF"),
TEXT("Test Pipe console"),
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
400,120,
NULL,
NULL,
cetteInstance,
NULL);


if (!fenetrePrincipale) return FALSE;

ShowWindow(fenetrePrincipale, modeDAffichage);
UpdateWindow(fenetrePrincipale);


while (GetMessage(&message, NULL, 0, 0))
{
TranslateMessage(&message);
DispatchMessage(&message);
}



return message.wParam;
}

LRESULT CALLBACK procedureFenetrePrincipale(HWND fenetrePrincipale, UINT message, WPARAM wParam, LPARAM lParam)
{
static HWND bouton=NULL;
static HWND hEdit;


SECURITY_ATTRIBUTES securityattribs = {sizeof(SECURITY_ATTRIBUTES),NULL,TRUE};

switch (message)
{
case WM_CREATE:

hEdit=CreateWindow(TEXT("EDIT"),NULL,WS_VISIBLE|WS_CHILD|WS_BORDER|ES_CENTER ,
5, 5, 383, 30,fenetrePrincipale,(HMENU)ID_E_EDIT,instance,NULL);


bouton = CreateWindow(TEXT("BUTTON"), TEXT("Executer"), WS_CHILD | WS_VISIBLE,
5, 45, 383, 30, fenetrePrincipale, (HMENU)ID_B_EXECUTER, instance, NULL);



AllocConsole();

initialiser();



return 0;


case WM_COMMAND:
switch(LOWORD(wParam))
{
case ID_B_EXECUTER:

CHAR lpText[256];
GetWindowText(hEdit,lpText,256);
strcat(lpText, "\n");
lire(lpText);


break;


}
return 0;

case WM_DESTROY:


//WaitForSingleObject(processInfo.hProcess, INFINITE);
TerminateProcess(processInfo.hProcess,0);

CloseHandle(processInfo.hProcess);
CloseHandle(processInfo.hThread);

CloseHandle(hPipeInputRead);
CloseHandle(hPipeInputWrite);

MessageBox(fenetrePrincipale, TEXT("Au revoir"),TEXT("Quitter"), MB_ICONINFORMATION);

PostQuitMessage(0);
return 0;

default:
return DefWindowProc(fenetrePrincipale, message, wParam, lParam);
}
}

-----------------------------------------------------------------------------


Merci beaucoup cher rt15 j'espère que je pourrais toujours compter sur ton aide précieuse.



foza juve