2009-06-16 16 views
1

PerlやPHPなど、Windowsのcmdシェルに出力する別のプロセスから出力を取得できる方法はありますか?私は特定の情報を出力するゲームサーバーを持っています。例えば、 '43年のプレーヤー終了トラック'と言います。私はその行をつかみ、PerlやPHPを使ってWebサーバーに要求を送り、Webページのランクを更新します。 PerlやPHPで出力パイプを取得する方法はありますか?または、C++ Windows APIを使用してこれを実現できますか?Windowsのcmdシェルからどのように出力をキャプチャできますか?

ここではっきりさせておきます:私は、Windowsのcmdシェルから出力された別のPerlまたはPHPスクリプトを実行し、Windowsのcmdシェルに表示されている出力は別のプロセスから来ています。

$output = qx(command); 

または

$output = `command`; # backticks 

参照してください:perldoc perlop

答えて

2

あなたはPerlの中に、あなたのサーバを起動する必要があります。

my $server_out = `server.exe`; # Note the backticks. 

今$ server_outはSERVER.EXEの出力が含まれています。しかし、ここでのトリックは、出力を得るためにserver.exeが終了するまで待たなければならないということです。 (コアモジュールではない)

試行IPC::Run

use English; 
use IPC::Run; 
my ($stdout, $stderr); 

IPC::Run::run([$cmd, $arg1, $arg2, $argN], \undef, \$stdout, $stderr); 

while(<$stdout>) { 
    print "Cmd said $_\n"; 
} 

注:コードはテストされていません。ここでは情報here.

1

は同じくらい簡単です。プロセス間通信では、プロセス間の親子関係が想定されています。そうでない場合は...私は、既存のプロセスの出力に接続するためのメカニズムを認識していません。その場合、アプリケーションが読み込めるログファイル(またはデータベース)にデータを書き込むために、プロデューサを変更する必要があります。

+0

コマンドが終了したら$出力にしかアクセスできないため、サーバープロセスは完了しません。 – user105033

4

をあなたが他のプロセスの標準出力から読み取るIPC::Open3を使用することができますPerlで出力をキャプチャ

3

あなたが気にすべてがSTDOUTであれば、あなただけのIPC::Open2からopen2を使用することができます。

#!/usr/bin/perl 

use strict; 
use warnings; 

use IPC::Open2; 

#if there are arguments pretend to be the server 
#for this example 
if (@ARGV) { 
    local $| = 1; 
    for my $i (1 .. 100) { 
     print "pid $$ iter $i\n"; 
     sleep 1; 
    } 
    exit; 
}   

#run perl with the current script as its argument, 
#pass in an arg so that we trigger the behaviour 
#above 
open2 my $out, my $in, $^X, $0, 1 
    or die "could not run '$^X $0 1': $!\n"; 

while (<$out>) { 
    s/[\r\n]//g; 
    print "pid $$ saw [$_]\n"; 
} 
+0

私が家に帰ると、これを行けます。 – user105033

+0

- | Windowsでは動作しません。 –

+0

@Alexandr Ciorniiうわー、少なくともIPC :: Open2とIPC :: Open3があります。 –

1

このコードは、次の例のメモに使用することができますSTRINGLISTにコンソールアプリケーションのSTDOUTをリダイレクトします。 Delphiのコードですが、C++では基本的な考え方はまったく同じです。

コンソールアプリケーションを非表示にして、出力を自分のアプリケーションにリダイレクトしてペインに表示します。データが入るとすぐにAStringsに新しい行が追加されるので、終了する前に他のアプリケーションの出力にアクセスできます。

procedure RunConsoleApp(const CommandLine: string; AStrings: TStrings); 
type 
    TCharBuffer = array[0..MaxInt div SizeOf(Char) - 1] of Char; 
const 
    MaxBufSize = 1024; 
var 
    I: Longword; 
    SI: TStartupInfo; 
    PI: TProcessInformation; 
    SA: PSecurityAttributes; 
    SD: PSECURITY_DESCRIPTOR; 
    NewStdIn: THandle; 
    NewStdOut: THandle; 
    ReadStdOut: THandle; 
    WriteStdIn: THandle; 
    Buffer: ^TCharBuffer; 
    BufferSize: Cardinal; 
    Last: WideString; 
    Str: WideString; 
    ExitCode_: DWORD; 
    Bread: DWORD; 
    Avail: DWORD; 
begin 
    GetMem(SA, SizeOf(TSecurityAttributes)); 

    case Win32Platform of 
    VER_PLATFORM_WIN32_NT: 
     begin 
     GetMem(SD, SizeOf(SECURITY_DESCRIPTOR)); 
     SysUtils.Win32Check(InitializeSecurityDescriptor(SD, SECURITY_DESCRIPTOR_REVISION)); 
     SysUtils.Win32Check(SetSecurityDescriptorDacl(SD, True, nil, False)); 
     SA.lpSecurityDescriptor := SD; 
     end; {end VER_PLATFORM_WIN32_NT} 
    else 
    SA.lpSecurityDescriptor := nil; 
    end; {end case} 

    SA.nLength := SizeOf(SECURITY_ATTRIBUTES); 
    SA.bInheritHandle := True; 

    SysUtils.Win32Check(CreatePipe(NewStdIn, WriteStdIn, SA, 0)); 

    if not CreatePipe(ReadStdOut, NewStdOut, SA, 0) then 
    begin 
    CloseHandle(NewStdIn); 
    CloseHandle(WriteStdIn); 
    SysUtils.RaiseLastWin32Error; 
    end; {end if} 

    GetStartupInfo(SI); 
    SI.dwFlags := STARTF_USESTDHANDLES or STARTF_USESHOWWINDOW; 
    SI.wShowWindow := {SW_SHOWNORMAL} SW_HIDE; 
    SI.hStdOutput := NewStdOut; 
    SI.hStdError := NewStdOut; 
    SI.hStdInput := NewStdIn; 

    if not CreateProcess(nil, PChar(CommandLine), nil, nil, True, CREATE_NEW_CONSOLE, nil, nil, SI, PI) then 
    begin 
    CloseHandle(NewStdIn); 
    CloseHandle(NewStdOut); 
    CloseHandle(ReadStdOut); 
    CloseHandle(WriteStdIn); 
    SysUtils.RaiseLastWin32Error; 
    end; {end if} 

    Last := ''; 
    BufferSize := MaxBufSize; 
    Buffer := AllocMem(BufferSize); 

    try 
    repeat 
     SysUtils.Win32Check(GetExitCodeProcess(PI.hProcess, ExitCode_)); 
     PeekNamedPipe(ReadStdOut, Buffer, BufferSize, @Bread, @Avail, nil); 

     if (Bread <> 0) then 
     begin 
     if (BufferSize < Avail) then 
     begin 
      BufferSize := Avail; 
      ReallocMem(Buffer, BufferSize); 
     end; {end if} 
     FillChar(Buffer^, BufferSize, #0); 
     Windows.ReadFile(ReadStdOut, Buffer^, BufferSize, Bread, nil); 
     Str := Last; 
     I := 0; 

     while (I < Bread) do 
     begin 

      case Buffer^[I] of 
      #0: inc(I); 
      #7: begin 
        inc(I); 
        Windows.Beep(800, 50); 
        Str := Str + '^'; 
       end; 
      #10: 
       begin 
       inc(I); 
       AStrings.Add(Str); 
       Str := ''; 
       end; {end #10} 
      #13: 
       begin 
       inc(I); 
       if (I < Bread) and (Buffer^[I] = #10) then 
        inc(I); 
       AStrings.Add(Str); 
       Str := ''; 
       end; {end #13} 
      else 
      begin 
       Str := Str + Buffer^[I]; 
       inc(I); 
      end; {end else} 
      end; {end case} 
     end; {end while} 
     Last := Str; 
     end; {end if} 
     Sleep(1); 
     Application.ProcessMessages; 

    until (ExitCode_ <> STILL_ACTIVE); 

    if Last <> '' then 
     AStrings.Add(Last); 

    finally 
    FreeMem(Buffer); 
    end; {end try/finally} 

    CloseHandle(PI.hThread); 
    CloseHandle(PI.hProcess); 
    CloseHandle(NewStdIn); 
    CloseHandle(NewStdOut); 
    CloseHandle(ReadStdOut); 
    CloseHandle(WriteStdIn); 

end; {end procedure} 
+0

誰かがこれをAwsomeとなるCPPに変換できれば。 – user105033

0

を発見

プロジェクトはPHPを入手し、実際のCMD端子を使用して動的に対話することができ、PHP具体的な解決策です。ここでそれを取得します。

//if you prefer Powershell, replace 'cmd' with 'powershell' 
$shellObj = \MTS\Factories::getDevices()->getLocalHost()->getShell('cmd'); 

$strCmd1 = 'some_app.exe -param "test"'; 
$return1 = $shellObj->exeCmd($strCmd1); 

リターンはあなたがコンソールに座っているかのように、あなたのCMDからのコマンド・リターンまたはエラーを与える:あなたは、単に次のコードを使用しますダウンロードした後https://github.com/merlinthemagic/MTS

を。

さらに、$ shellObjに対して好きなコマンドを実行することができます。環境はPHPスクリプトの全期間を通じて維持されます。したがって、スクリプトファイルでコマンドを束ねるのではなく、exeCmd()メソッドを使って1つずつ発行するだけで、リターンと例外を処理することもできます。

関連する問題