2009-07-16 4 views

Répondre

32

Oui, la redirection de l'utilisation de la sortie standard vers un fichier:

[Code] 

function NextButtonClick(CurPage: Integer): Boolean; 
var 
    TmpFileName, ExecStdout: string; 
    ResultCode: integer; 
begin 
    if CurPage = wpWelcome then begin 
    TmpFileName := ExpandConstant('{tmp}') + '\ipconfig_results.txt'; 
    Exec('cmd.exe', '/C ipconfig /ALL > "' + TmpFileName + '"', '', SW_HIDE, 
     ewWaitUntilTerminated, ResultCode); 
    if LoadStringFromFile(TmpFileName, ExecStdout) then begin 
     MsgBox(ExecStdout, mbInformation, MB_OK); 
     { do something with contents of file... } 
    end; 
    DeleteFile(TmpFileName); 
    end; 
    Result := True; 
end; 

Notez qu'il peut y avoir plus d'un adaptateur réseau, et par conséquent plusieurs adresses MAC à choisir.

+2

Notez que plutôt que de coder en dur « cmd.exe "il est préférable d'utiliser' ExpandConstant ('{cmd}') '. (Bien sûr, il vaut mieux utiliser les API appropriées au lieu d'essayer de capturer la sortie des commandes de la console, car celles-ci peuvent changer sans préavis, puisqu'elles sont destinées aux humains.) – Miral

+4

Pour clarifier: vous devez exécuter votre programme via la commande invite à obtenir la redirection. J'ai d'abord regardé cette réponse et a été confus pourquoi cela ne fonctionnait pas pour moi, la raison était parce que je ne savais pas que la redirection est une fonction de l'invite de commande plutôt que Windows, donc vous devez Exec sur cmd.exe/c

+0

pour l'installation unicode, doit utiliser: 'var ExecStdout: AnsiString;' – papo

12

Je devais faire la même chose (exécuter des appels en ligne de commande et obtenir le résultat) et trouver une solution plus générale.

Il corrige également des bogues étranges si des chemins entre guillemets sont utilisés dans les appels réels en utilisant l'indicateur /S pour cmd.exe.

{ Exec with output stored in result. } 
{ ResultString will only be altered if True is returned. } 
function ExecWithResult(const Filename, Params, WorkingDir: String; const ShowCmd: Integer; 
    const Wait: TExecWait; var ResultCode: Integer; var ResultString: String): Boolean; 
var 
    TempFilename: String; 
    Command: String; 
begin 
    TempFilename := ExpandConstant('{tmp}\~execwithresult.txt'); 
    { Exec via cmd and redirect output to file. Must use special string-behavior to work. } 
    Command := 
    Format('"%s" /S /C ""%s" %s > "%s""', [ 
     ExpandConstant('{cmd}'), Filename, Params, TempFilename]); 
    Result := Exec(ExpandConstant('{cmd}'), Command, WorkingDir, ShowCmd, Wait, ResultCode); 
    if not Result then 
    Exit; 
    LoadStringFromFile(TempFilename, ResultString); { Cannot fail } 
    DeleteFile(TempFilename); 
    { Remove new-line at the end } 
    if (Length(ResultString) >= 2) and (ResultString[Length(ResultString) - 1] = #13) and 
    (ResultString[Length(ResultString)] = #10) then 
    Delete(ResultString, Length(ResultString) - 1, 2); 
end; 

Utilisation:

Success := 
    ExecWithResult('ipconfig', '/all', '', SW_HIDE, ewWaitUntilTerminated, 
    ResultCode, ExecStdout) or 
    (ResultCode <> 0); 

Le résultat peut également être chargé dans un objet TStringList pour obtenir toutes les lignes:

Lines := TStringList.Create; 
Lines.Text := ExecStdout; 
{ ... some code ... } 
Lines.Free; 
+0

Merci beaucoup de fournir un tel exemple détaillé. Vous avez évidemment travaillé sur beaucoup de problèmes pour aller aussi loin et m'a fait gagner beaucoup de temps. J'utilise ceci avec 'tasklist' et' taskkill' pour détecter et tuer une application en cours d'exécution lors de l'installation et de la désinstallation. –

+0

Un problème mineur dans votre exemple d'utilisation: si l'Exec réussit mais ResultCode <> 0, ResultCode sera rempli avec le code de sortie du programme appelé, pas avec une erreur Windows, donc SysErrorMessage n'obtiendra pas le bon message. En outre, un code de sortie différent de zéro peut parfois convenir. Je vous recommande de tester ResultCode séparément en fonction du contexte. Plus d'informations sur cette confusion: https://github.com/jrsoftware/issrc/issues/190. –

+0

Oui le message d'exception dans l'exemple repose sur windows exit-codes => https://msdn.microsoft.com/en-us/library/windows/desktop/ms681382.aspx – Tobias81