Nasıl Windows cmd kabuk çıkış yakalayabilir?

5 Cevap php

Ben Windows çıktılar bir süreçten çıktı kapmak Perl veya PHP, kabuk kıl demek olan herhangi bir yolu var mı? Ben örneğin söylemek, belirli bilgi çıktılar bir oyun sunucusu var 'oyuncu 43S içinde parça bitti' ve ben bu satırı kapmak ve bir web sayfası üzerinde saflarına güncellemek için bir web sunucusuna bir istek göndermek için Perl ve PHP kullanmak istiyorum. Perl ve PHP bu çıkış boru kapmak için bir yolu var mı? Ya da belki bu kullanarak C + + Windows API elde edebiliriz?

Bana burada açıklığa kavuşturalım: Ben shell, Windows cmd çıktı kapmak ayrı bir Perl veya PHP komut dosyası ve farklı bir süreç geliyor, Windows cmd kabuk görüntülenen ediliyor çıktı yürütmek istiyor.

5 Cevap

Sen Perl içinde sunucusunu başlatmak gerekir:

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

Şimdi $ server_out Server.exe çıkışını içerir. Ama burada hüner server.exe söndürmek almak için çıkıncaya kadar beklemek zorunda olmasıdır.

(Çekirdek bir modül değil) IPC::Run Dene

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

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

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

Not: Kod test değil.

Bulunan bilgi here.

Sen IPC::Open3 diğer süreç 'standart çıkış okumak için kullanabilirsiniz. Süreçler arası iletişim süreçleri arasında bir ebeveyn / çocuk ilişkisi varsayar. Bu durumda değilse ... Ben önceden varolan bir sürecin çıkışına bağlamak için bir mekanizmanın farkında değilim. Bu durumda uygulama okuyabileceği bir günlük dosyasına (veya veritabanı) veri yazmak için yapımcı değiştirmek gerekebilir.

Eğer umurumda tüm STDOUT ise, sadece gelen open2 kullanmak IPC::Open2 yapabilirsiniz:

#!/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";
}

: Perl çıkış yakalama gibi basit

$output = qx(command);

veya

$output = `command`;  # backticks

Refer: perldoc perlop

Bu kod, örneğin bir not üzerinde kullanabileceğiniz bir StringList için bir konsol uygulaması STDOUT'a, yönlendirir. Bu Delphi kod, ancak C + + temel fikir tam olarak aynıdır.

Benim kendi uygulama çıkış yönlendirme yaparken bir bölmede göstermek için, gizli konsol uygulamaları çalıştırmak için kullanabilirsiniz. Bu kısa sürede veri gelir olarak AStrings için yeni bir satır ekler, bu nedenle tamamlanmadan önce diğer uygulama çıkışına erişebilirsiniz.

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}