5

私はこれを機能させることができないようです。

そのため、ゲーム名/タイプ/プレーヤーなどのいくつかのパラメーターを渡してサーバーに接続するゲームのスクリプトを作成しようとしています。次に、サーバースクリプトは、必要に応じてゲームサーバーの新しいインスタンスを設定し、サーバーの新しいインスタンスを実行し、実行されているポートを見つけて、そのすべての情報をゲームに送り返します。

スクリプトがサーバーゲームのexeを実行し、PIDを取得する必要がある部分に到達しました(使用しているポートなどを取得できます)。

サーバースクリプトは、サーバーの新しいインスタンスを実行するためのPHPスクリプトです。(PHPは良い選択のように思われ、比較的私の知識ではあります)。


スクリプトは、ゲームサーバーをバックグラウンドで実行したまま、実行を終了できる必要があります。

複数のゲームサーバーを同時に実行できることが必要です。


使用してみましproc_openたが、プロセスのPIDが間違っているため、使用できません。(ただし、プログラムは正しく実行されます)

<?php

    $startDir = "C:/Torque/My Projects/Grim/game";
    $runExe = "$startDir/Grimwood.exe";
    $envars = " -dedicated -mission \"core/levels/Empty Terrain.mis\"";

    $runPath = $runExe . $envars;

    chdir($startDir);

    $descriptorspec = array(
        0 => array("pipe", "r"),  // stdin is a pipe that the child will read from
        1 => array("pipe", "w"),  // stdout is a pipe that the child will write to
    );

    $prog = proc_open($runPath, $descriptorspec, $pipes, $startDir, NULL);

    sleep(4);

    if (is_resource($prog)) 
    {
        $stats = proc_get_status($prog);
        $pid = $stats['pid'];

        $task = shell_exec("tasklist /fi \"PID eq $pid\"");

        echo("\nProcess: \n$task"); // echos cmd.exe, not process ran
    }

?>

印刷するPIDは、実際に実行したプログラムではなく、実行元のコンソールウィンドウに属します。


次に、MSスクリプトホストWScript.Shellとそのexec/runメソッドを使用してみました。

<?php

    $startDir = "C:/Torque/My Projects/Grim/game";
    $runExe = "$startDir/Grimwood.exe";
    $envars = " -dedicated -mission \"core/levels/Empty Terrain.mis\"";

    $runPath = $runExe . $envars;

    chdir($startDir);    

    try
    {
        $WshShell = new COM("WScript.Shell");

        // gets right process ID
        // but process doesn't start properly with params
        $oExec = $WshShell->exec($runPath);
        echo("PID: " . $oExec->ProcessId);

        sleep(4);

        // executes properly
        // but doesn't return PID
        $oExec = $WshShell->run($runPath);
        echo("PID: " . $oExec->ProcessId);

    }
    catch (Exception $e)
    {
        // never gets hit
        echo("Failed to execute");
    }

?>

execコマンドを実行すると、正しいPIDが得られますが、プログラムが正しく起動しません(空白のターミナルウィンドウが表示され、何も実行されません)。

runコマンドを実行すると、プログラムが正しく起動します(ターミナルウィンドウに表示されるはずのすべてのテキストが表示されます)が、コマンドはPIDを返しません。


この件に関するご協力をいただければ幸いです。WScript.Shell->execコマンドが正しく実行されないようにするために、コマンドで何が間違っているのかわからないので、その問題に関するすべての助けをいただければ幸いです。

可能であれば、proc_openサーバーのものを* nixに移動したい場合は、もう少しクロスプラットフォームであるため、このメソッドを使用したいと思います。

お時間をいただきありがとうございます。明るい心が私を正しい方向に向けてくれることを願っています。


PHPバージョン:5.4.3

開発マシン:SP1を搭載したWindows 7 Ultimate

サーバーマシン:Windows Server 2008 R2

4

2 に答える 2

9

なんとか手に入れました。proc_openを使用して実行しました。これにより、実行されたゲームサーバー(cmd.exe実行可能ファイル)のPPIDが返されます。

start /bプログラムを実行すると、exitはcmd.exeになるため、PPIDが必要なのはゲームサーバーだけです。したがって、残りのPIDを見つけるのは比較的簡単でした。

これは、複数のインスタンスが一度に作成された場合、および複数のインスタンスがすでに実行されている場合にも機能します。

これは、他の誰かがこのスレッド全体で疑問に思って、たまたまそれを必要とする可能性がある場合に、proc_openでPIDを取得するための終了スクリプトです。

<?php

    $startDir = "C:/Torque/My Projects/Grim/game";
    $runExe   = "$startDir/Grimwood.exe";
    $envars   = " -dedicated -mission \"core/levels/Empty Terrain.mis\"";

    $runPath = $runExe . $envars;

    chdir($startDir);

    $descriptorspec = array (
        0 => array("pipe", "r"),
        1 => array("pipe", "w"),
    );

    if ( is_resource( $prog = proc_open("start /b " . $runPath, $descriptorspec, $pipes, $startDir, NULL) ) )
    {
        $ppid = proc_get_status($prog)['pid'];
    }
    else
    {
        echo("Failed to execute!");
        exit();
    }

    $output = array_filter(explode(" ", shell_exec("wmic process get parentprocessid,processid | find \"$ppid\"")));
    array_pop($output);
    $pid = end($output);

    echo("\nProcess ID: $pid ; Parent's Process ID: $ppid\n");

    // returns right process
    $task = shell_exec("tasklist /fi \"PID eq $pid\"");
    echo("\n\nProcess: \n$task\n\n");

    // returns no process found
    $task = shell_exec("tasklist /fi \"PID eq $ppid\"");
    echo("\n\nParent Process: \n$task\n\n");

?>
于 2012-11-12T04:07:45.247 に答える
1

Windows OS向けに開発しているので、この方法で希望する結果を得ることができると思います。

まず、.exeをサービスとして実行するようにします。(これが構文だと思います)

sc create SERVICENAME binpath=PATH_TO_EXE

それなら私はあなたができると信じています:

win32_start_service('SERVICENAME');

sleep(4);

$serviceStatus = win32_query_Service_status('SERVICENAME');
var_dump($serviceStatus);

// or
echo $serviceStatus[ProcessId];

PS-私はこれをテストしなかったことを考慮に入れてください。しかし、私はこれがうまくいくと信じています。試してみる。

一方、Windowsサービスの詳細については、このリンクhttp://www.php.net/manual/en/book.win32service.phpにアクセスしてください。

于 2012-11-08T14:02:29.197 に答える