6 Stimmen

Beenden eines Systems() nach einer bestimmten Zeit unter Windows

Ich führe eine Kommandozeilenanwendung aus dem Perl-Skript heraus aus (unter Verwendung von system()), die manchmal nicht zurückkehrt, um genau zu sein, wirft sie eine Ausnahme, die die Benutzereingabe erfordert, um die Anwendung abzubrechen. Dieses Skript wird für automatisierte Tests der Anwendung verwendet, die ich mit dem system()-Befehl ausführe. Da es sich um einen Teil der automatisierten Tests handelt, muss der system()-Befehl zurückkehren, wenn die Ausnahme auftritt und der Test als fehlgeschlagen betrachtet wird.

Ich möchte ein Codestück schreiben, das diese Anwendung ausführt, und wenn eine Ausnahme auftritt, muss das Skript fortgesetzt werden, wobei dieser Test als fehlgeschlagen betrachtet wird.

Eine Möglichkeit, dies zu tun, besteht darin, die Anwendung für eine bestimmte Zeit laufen zu lassen, und wenn der Systemaufruf in dieser Zeit nicht zurückkehrt, sollten wir das system() beenden und mit dem Skript fortfahren. ( Wie kann ich in Perl einen Systembefehl mit Alarm beenden? )

Code, um dies zu erreichen:

my @output;
eval {
    local $SIG{ALRM} = sub { die "Timeout\n" };
    alarm 60;
    return = system("testapp.exe");
    alarm 0;
};
if ($@) {
    print "Test Failed";
} else {
    #compare the returned value with expected
}

aber dieser Code funktioniert nicht unter Windows. Ich habe einige Nachforschungen angestellt und herausgefunden, dass SIG nicht für Windows funktioniert (Buch Programmierung Perl). Könnte jemand vorschlagen, wie ich dies unter Windows erreichen kann?

7voto

Jonah Bishop Punkte 12069

Ich würde empfehlen, sich die Win32::Prozess Modul. Es ermöglicht Ihnen, einen Prozess zu starten, eine bestimmte Zeit auf ihn zu warten und ihn gegebenenfalls sogar zu beenden. Dem Beispiel in der Dokumentation nach zu urteilen, sieht es recht einfach aus:

use Win32::Process;
use Win32;

sub ErrorReport{
    print Win32::FormatMessage( Win32::GetLastError() );
}

Win32::Process::Create($ProcessObj,
                       "C:\\path\\to\\testapp.exe",
                       "",
                       0,
                       NORMAL_PRIORITY_CLASS,
                       ".")|| die ErrorReport();

if($ProcessObj->Wait(60000)) # Timeout is in milliseconds
{
    # Wait succeeded (process completed within the timeout value)
}
else
{
    # Timeout expired. $! is set to WAIT_FAILED in this case
}

Sie können auch die entsprechende Anzahl von Sekunden schlafen und die Funktion kill Methode in diesem Modul. Ich bin mir nicht ganz sicher, ob die NORMAL_PRIORITY_CLASS Erstellungs-Flag ist diejenige, die Sie verwenden wollen; die Dokumentation für dieses Modul ist ziemlich schlecht. Ich sehe einige Beispiele, die das DETACHED_PROCESS Flagge. Sie müssen mit diesem Teil herumspielen, um zu sehen, was funktioniert.

2voto

ProcBackground Punkte 21

Siehe Proc::Background Es abstrahiert den Code sowohl für Win32 als auch für Linux, die Funktion ist timeout_system( $seconds, $command, $arg, $arg, $arg )

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X