2009-07-16 52 views

答えて

32

ファイルに標準出力をはい、使用リダイレクション:

[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; 

注意が複数のネットワークアダプタも、その結果、いくつかのMACから選択するアドレスこと。

+2

注意を"ExpandConstant( '{cmd}')'を使用する方が良い方法です。 (もちろん、コンソールコマンドの出力をキャプチャしようとするのではなく、適切なAPIを使用する方が良いでしょう。後者は予告なく変更される可能性があります。人間が意図しているためです) – Miral

+4

説明のために:リダイレクトを求めるプロンプトが表示されます。私は最初にこの答えを見て、なぜこれが私のために働いていないのか混乱しました。なぜなら、私はリダイレクションがウィンドウではなくコマンドプロンプトの機能であることを認識しなかったからです。cmd.exe/c

+0

ユニコードのインストールでは、以下を使用する必要があります: 'ExecStdout:AnsiString;' – papo

12

私は同じことをしなければなりませんでした(コマンドラインコールを実行して結果を得る)、もっと一般的な解決策が出ました。

cmd.exe/Sフラグを使用して、実際の呼び出しで引用符で囲まれたパスが使用されている場合、これは奇妙なバグも修正します。

{ 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; 

使用法:

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

結果はまた、すべての行を取得するためにTStringListオブジェクトにロードすることができます:「CMD.EXEをハードコーディングするのではなく

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

このような詳細な例を提供してくれてありがとうございます。あなたは明らかにこれを得るために多くの問題を解決し、私に多くの時間を節約しました。私は 'tasklist'と' taskkill'でこれを使って、インストール中とアンインストール中に実行中のアプリケーションを検出して終了させます。 –

+0

使用例の1つの軽微な問題:Execが成功し、ResultCode <> 0の場合、ResultCodeはWindowsエラーではなく呼び出されたプログラムの終了コードで埋められるため、SysErrorMessageは正しいメッセージを取得しません。また、ゼロ以外の終了コードが大丈夫かもしれません。コンテキストに応じてResultCodeを個別にテストすることをお勧めします。この混乱の詳細:https://github.com/jrsoftware/issrc/issues/190 –

+0

はいこの例の例外メッセージは、Windowsのexit-codes => https://msdn.microsoft.com/en-us/library/windows/desktop/ms681382.aspx – Tobias81

関連する問題