redirection de sortie CreateProcessW

redirection de sortie CreateProcessW - C++ - Programmation

Marsh Posté le 29-06-2012 à 09:21:32    

Plop !
 
J'ai un petit problème en ce moment, je fais tourner un programme qui fait appel à la fonction CreateProcess pour lancer des programmes en ligne de commande externes. Pour récupérer la sortie de ces programmes, jusqu'à présent je lançais "CMD /C commande.exe >> c:\logs.txt", de cette façon, je peut récupérer les sorties des programmes ... sauf que cette sortie n'inclut pas tout ce qu'on voit quand on lance la commande dans le cmd de windows ... J'ai besoin d'accéder au flux d'erreurs stdErr ... Sur Java, j'avais juste besoin de faire à un moment un truc comme process.redirectErrorStream(true).
J'ai cherché sur c++ et je suis tombé sur ça entres autres, et j'ai essayé de faire un mix de tout, ou même d'en mettre le minimum, mais ça ne marche désespérément pas x)
 

Code :
  1. ;
  2.     STARTUPINFO siStartupInfo;
  3.     PROCESS_INFORMATION piProcessInfo;
  4.     memset(&siStartupInfo, 0, sizeof(siStartupInfo));
  5.     memset(&piProcessInfo, 0, sizeof(piProcessInfo));
  6.     SECURITY_ATTRIBUTES sa;
  7.     sa.bInheritHandle = true;
  8.     HANDLE h = CreateFile(TEXT("c:\\temp\\logs.txt" ),
  9.                           GENERIC_WRITE|GENERIC_READ,
  10.                           FILE_SHARE_READ,
  11.                           &sa,
  12.                           CREATE_ALWAYS,
  13.                           FILE_ATTRIBUTE_NORMAL,
  14.                           NULL);
  15.     siStartupInfo.cb = sizeof(siStartupInfo);
  16.     if(h != INVALID_HANDLE_VALUE)
  17.     {
  18.         SetFilePointer(h, 0L, NULL, FILE_END);
  19.         siStartupInfo.dwFlags |= STARTF_USESTDHANDLES;
  20.         siStartupInfo.hStdOutput = h;
  21.         siStartupInfo.hStdError = h;
  22.     }
  23.     if (CreateProcessW(const_cast<LPCWSTR>(FullPathToExe.c_str()),
  24.                        pwszParam, 0, 0, true,
  25.                        /*CREATE_DEFAULT_ERROR_MODE*/CREATE_NO_WINDOW, 0, 0,
  26.                        &siStartupInfo, &piProcessInfo) != false)


 
 
avec un "cout", j'ai remarqué que le programme n'entrait même pas dans  "if(h != INVALID_HANDLE_VALUE)", donc il y a au moins un bug avant ça.
J'ai du surement mal initialiser mon HANDLE, mais je vois pas trop comment ... :(
Je mix des choses qui me paraissent logiques mais au fond je comprends pas assez pour résoudre les bugs s'il y en a qui surviennent x) Des DWORD, des HANDLE, des STARTUPINFO, ... charabia tout ça!
 
merci d'avance :)


Message édité par gilou le 29-06-2012 à 11:42:30
Reply

Marsh Posté le 29-06-2012 à 09:21:32   

Reply

Marsh Posté le 29-06-2012 à 11:52:04    

Pour tes deux premiers memset, perso, je ferais memset(&siStartupInfo, 0, sizeof(STARTUPINFO)) et memset(&piProcessInfo, 0, sizeof(PROCESS_INFORMATION)) mais c'est peut être juste une question de goûts.
 
A tout hasard, tu a essayé de faire un remplissage a zéro aussi pour le sécurity attribute?
 
    SECURITY_ATTRIBUTES sa;
    memset(&sa, 0, sizeof(SECURITY_ATTRIBUTES));
    sa.nLength = sizeof(SECURITY_ATTRIBUTES);
    sa.bInheritHandle = true;
 
A+,


Message édité par gilou le 29-06-2012 à 11:54:30

---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Marsh Posté le 29-06-2012 à 11:53:51    

D'après http://msdn.microsoft.com/en-us/li [...] 85%29.aspx et la doc, tu as mal initialise ton SECURITY_ATTRIBUTES:
SECURITY_ATTRIBUTES sa;  
sa.nLength = sizeof(SECURITY_ATTRIBUTES);  
sa.bInheritHandle = TRUE;  
sa.lpSecurityDescriptor = NULL;  
 
 
Ensuite tu dis que si il ne rentre pas dans le if ligne 20, c'est que h doit avoir une autre valeur: il te suffit donc de lire la doc de createfile() et de traiter tous les cas d'erreur (utilise la fonction ErrorExit() du lien ci dessus pour voir un descriptif de l'erreur)
 
edit: grilled!


Message édité par breizhbugs le 29-06-2012 à 11:54:18

---------------
Seul Google le sait...
Reply

Marsh Posté le 29-06-2012 à 11:56:00    

A moitié grilled, le temps que j'ajoute une ligne d'initialisation manquante ( sa.nLength = sizeof(SECURITY_ATTRIBUTES); )  tu avais posté ;)
A+,


---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Marsh Posté le 29-06-2012 à 14:55:15    

Merci pour la correction :) Ça marche mieux mais il y a encore un petit truc que je n'arrive pas à cerner :/ je sais pas si vous auriez une idée ^^ :
quand le programme lancé est : "psexec \\monpc ipconfig", le programme reste bloqué sur WaitForSingleObject( , ), le processus semble ne pas se finir...
alors que quand je fais "psexec \\monpc echo && ipconfig" tout se passe bien !
(je précise que ça ne vient pas de psexec a priori, ces commandes marchent très bien dans l’interpréteur de Windows).

 

Étant donné que ça ne vient pas forcément du code, je peux m'arranger pour ajouter simplement "echo && " au début de chaque commande au pire :/

 
Code :
  1. ;
  2.     STARTUPINFO siStartupInfo;
  3.     PROCESS_INFORMATION piProcessInfo;
  4.     memset(&siStartupInfo, 0, sizeof(STARTUPINFO));
  5.     memset(&piProcessInfo, 0, sizeof(PROCESS_INFORMATION));
  6.     SECURITY_ATTRIBUTES sa;
  7.     memset(&sa, 0, sizeof(SECURITY_ATTRIBUTES));
  8.     sa.nLength = sizeof(SECURITY_ATTRIBUTES);
  9.     sa.bInheritHandle = true;
  10.     sa.lpSecurityDescriptor = NULL;
  11.     HANDLE h = CreateFile(L"c:\\temp\\logs.radm",
  12.                           GENERIC_WRITE|GENERIC_READ,
  13.                           FILE_SHARE_READ|FILE_SHARE_WRITE,
  14.                           &sa,
  15.                           CREATE_NEW,
  16.                           FILE_ATTRIBUTE_NORMAL,
  17.                           NULL);
  18.     SetFilePointer(h, 0L, NULL, FILE_END);
  19.     siStartupInfo.cb = sizeof(STARTUPINFO);
  20.     siStartupInfo.dwFlags |= STARTF_USESTDHANDLES;
  21.     siStartupInfo.hStdOutput = h;
  22.     siStartupInfo.hStdError = h;
  23.    
  24.     if (CreateProcessW(const_cast<LPCWSTR>(FullPathToExe.c_str()),
  25.                        pwszParam,
  26.                        0,
  27.                        0,
  28.                        true,
  29.                        /*CREATE_NO_WINDOW*/CREATE_NEW_CONSOLE,
  30.                        0,
  31.                        0,
  32.                        &siStartupInfo,
  33.                        &piProcessInfo
  34.                       )
  35.         ) dwExitCode = WaitForSingleObject(piProcessInfo.hProcess, (SecondsToWait * 1000));
  36.     else iReturnVal = GetLastError();
  37.     delete[]pwszParam;
  38.     pwszParam = 0;
  39.     CloseHandle(piProcessInfo.hProcess);
  40.     CloseHandle(piProcessInfo.hThread);
  41.     if(h != INVALID_HANDLE_VALUE) CloseHandle(h);
 

Merci quand même si vous avez quelque intuition passagère :D


Message édité par zownierd le 29-06-2012 à 14:56:59
Reply

Marsh Posté le 29-06-2012 à 15:46:56    

Est ce que \\monpc est bien l'ordinateur local? Si oui pourquoi le précises- tu?
Pour le reste, pas d'idée...


---------------
Seul Google le sait...
Reply

Marsh Posté le 29-06-2012 à 16:54:24    

en fait je viens de réaliser que en écrivant :
psexec \\monpc.corp.lan echo && ipconfig  
... ça marche ... mais la commande ipconfig est exécutée sur mon pc a moi et non a distance x) en fait ça marche pas mieux avec le echo && :( (c'était un peu zarb après tout ^^)
 
donc ainsi aucune commande ne passe mais j'ai quand même quelques résultats dans mon fichier de log :
 

Code :
  1. PsExec v1.98 - Execute processes remotely
  2. Copyright (C) 2001-2010 Mark Russinovich
  3. Sysinternals - www.sysinternals.com
  4. Le volume dans le lecteur C s'appelle Windows


 
alors que la commande donne ça
 
 

Code :
  1. C:\Users\dpiffre>psexec \\monPC.corp.lan  CMD /C "dir"
  2. PsExec v1.98 - Execute processes remotely
  3. Copyright (C) 2001-2010 Mark Russinovich
  4. Sysinternals - www.sysinternals.com
  5. Starting CMD on hektor17...ice on hektor17...
  6. Le volume dans le lecteur C s'appelle Windows
  7. Le numéro de série du volume est E48B-2034
  8. Répertoire de C:\Windows\system32
  9. 26/06/2012  14:44    <REP>          .
  10. 26/06/2012  14:44    <REP>          ..
  11. 12/04/2011  03:32    <REP>          040C


 
La commande bloque à mi-chemin je ne sais pas trop pourquoi mais ca semble lié à PSExec :( (psinfos marche très bien :/)

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed