18

バッチ ファイルを呼び出すサービスがあります。バッチ ファイルの実行には 5 ~ 10 秒かかります。

System.Diagnostics.Process proc = new System.Diagnostics.Process(); // Declare New Process
    proc.StartInfo.FileName = fileName;
    proc.StartInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
    proc.StartInfo.CreateNoWindow = true;
    proc.Start();
    proc.WaitForExit();

ファイルは存在し、同じコードをコンソールで実行するとコードが機能します。ただし、サービス内で実行すると、 でハングアップしWaitForExit()ます。続行するには、プロセスからバッチ ファイルを強制終了する必要があります。(プロセスリストで確認できるので、ファイルが存在することは確かです。)

このハングアップを修正するにはどうすればよいですか?

更新 #1:

Kevin のコードを使用すると、出力を取得できます。バッチ ファイルの 1 つがまだハングしています。

"C:\EnterpriseDB\Postgres\8.3\bin\pg_dump.exe" -i -h localhost -p 5432 -U postgres -F p -a -D -v -f "c:\backupcasecocher\backupdateevent2008.sql" -t "\"public\".\"dateevent\"" "DbTest"

他のバッチ ファイルは次のとおりです。

"C:\EnterpriseDB\Postgres\8.3\bin\vacuumdb.exe" -U postgres -d DbTest

パスを確認しましたが、postgresqlパスは問題ありません。出力ディレクトリは存在し、サービスの外部でも機能します。何か案は?

更新 #2:

バッチ ファイルのパスの代わりに、「C:\EnterpriseDB\Postgres\8.3\bin\pg_dump.exe」をproc.StartInfo.FileName記述し、すべてのパラメーターを に追加しましたproc.StartInfo.Arguments。結果は変わりませんがpg_dump.exe、プロセス ウィンドウに が表示されます。繰り返しますが、これはサービス内でのみ発生します。

更新 #3:

管理者グループのユーザーでサービスを実行しましたが、役に立ちませんでした。nullサービスのユーザー名とパスワードを復元しました

更新 #4:

イベント ログにトレースを書き込み、"dir" を含むバッチ ファイルを実行する簡単なサービスを作成しました。でハングしますproc.Start();-アカウントをLocalSystemからユーザーに変更しようとしましたが、管理者のユーザーとパスワードを設定しましたが、まだ何もありません。

4

8 に答える 8

28

バッチファイルを実行するために使用するものは次のとおりです。

proc.StartInfo.FileName                 = target;
proc.StartInfo.RedirectStandardError    = true;
proc.StartInfo.RedirectStandardOutput   = true;
proc.StartInfo.UseShellExecute          = false;

proc.Start();

proc.WaitForExit
    (
        (timeout <= 0)
            ? int.MaxValue : timeout * NO_MILLISECONDS_IN_A_SECOND *
                NO_SECONDS_IN_A_MINUTE
    );

errorMessage = proc.StandardError.ReadToEnd();
proc.WaitForExit();

outputMessage = proc.StandardOutput.ReadToEnd();
proc.WaitForExit();

それがうまくいくかどうかはわかりませんが、ぶら下がっているという問題はありません。

于 2008-12-11T21:54:43.730 に答える
11
using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Diagnostics;
    namespace VG
    {
        class VGe
        {
            [STAThread]
            static void Main(string[] args)
            {
                Process proc = null;
                try
                {                
                    string targetDir = string.Format(@"D:\adapters\setup");//this is where mybatch.bat lies
                    proc = new Process();
                    proc.StartInfo.WorkingDirectory = targetDir;
                    proc.StartInfo.FileName = "mybatch.bat";
                    proc.StartInfo.Arguments = string.Format("10");//this is argument
                    proc.StartInfo.CreateNoWindow = false;
                    proc.Start();
                    proc.WaitForExit();
                }
                catch (Exception ex)
                {
                    Console.WriteLine("Exception Occurred :{0},{1}", ex.Message,ex.StackTrace.ToString());
                }
            }
        }
    }
于 2010-01-07T09:47:59.020 に答える
4
            string targetDir = string.Format(@"D:\");//PATH
            proc = new Process();
            proc.StartInfo.WorkingDirectory = targetDir;
            proc.StartInfo.FileName = "GetFiles.bat";
            proc.StartInfo.Arguments = string.Format("10");//argument
            proc.StartInfo.CreateNoWindow = false;
            proc.Start();
            proc.WaitForExit();

テスト済み、クリアに動作します。

于 2013-05-09T05:13:26.640 に答える
3

次のステップは、デバッガーを起動して、プログラムが何を待っているかを確認できるかどうかを確認することです。アセンブリでのデバッグに慣れている場合は、ProcExp、FileMon などのツールを使用して、何が起こっているのかを理解できるかもしれません。

Web サービスではなく Windows サービスであることは、かなりの違いを生みます。とにかく、「サービスがデスクトップと対話することを許可する」を設定するという私の提案を試しましたか?

やむを得ない場合は、バッチ ファイルの代わりに cmd.exe を起動してみてください。次に、cmd.exe のコマンド ライン パラメーターを使用して、IT 部門にバッチ ファイルを開始させることができます。デスクトップとの対話をオンにすると、実際の出力を表示するための cmd プロンプト ウィンドウが表示される可能性があります。

cmd.exe の完全なヘルプについては、「cmd /?」と入力してください。任意のコマンド プロンプトで。

ラリー

于 2008-12-12T18:51:16.197 に答える
3

バッチファイルは何をしますか? プロセスがバッチ ファイルを実行するのに十分な特権で起動されていることは確かですか? サービスは、許可されていることを制限できます。

また、次のようなファイルを上書きするために copy コマンドを使用しているかどうかを確認してください。

echo Y | copy foo.log c:\backup\

また、バッチ コマンドなどにフル パスを使用していることを確認してください。バッチ ファイルがある種の「コンソール」モードで GUI アプリを起動している場合、それも問題になる可能性があります。サービスには、あらゆる種類のウィンドウまたはメッセージ ボックスを描画するための「デスクトップ」がありません (「デスクトップとの対話」を有効にしない限り)。プログラムでは、stdout パイプと stderr パイプを開いて、実行中にエラー メッセージなどを受け取った場合に備えてそれらから読み取ることができます。

WebServices はおそらく IUSR アカウントまたは匿名アカウントとして実行されているため、問題になる可能性があります。コンソールで実行したときに機能する場合、それは最初のステップにすぎません。:)

System.Diagnostics かどうかは覚えていません。デバッグでのみ使用可能かどうか。おそらくそうではありませんが、それらのいくつかはそうかもしれません。私はあなたのためにそれをチェックする必要があります。

これがあなたにいくつかのアイデアを与えることを願っています。

ラリー

于 2008-12-11T21:58:52.317 に答える
1

Daok、変更したのは最初の WaitForExit() のタイムアウト期間だけだったようです。あなたはそれについて非常に注意する必要があります。何かがあなたのサービスをハングさせた場合、それは決して戻りません(そして、これまでのようにほとんど機能します..へー)が、エンドユーザーにとっては良くありません...

これで、ハングの原因がわかったので、さらにデバッグして完全な解決策を見つけることができます...

それ、または監視できるスレッドでこれをスピンオフし、ハングが長すぎる場合は強制終了します。

私の 2 セントの価値だけで、通常は大したことはありません。;)

于 2008-12-15T23:53:46.207 に答える
1

これが解決策です。コードを何度も変更したため、解決策は明確ではありませんが、現在は機能しています!

ユーザーのアカウントを使用しようとしましたが、うまくいきませんでした。LocalSystem を使用します。これが実行するコードで、主に Kevin から提供されたものです。

            System.Diagnostics.Process proc = new System.Diagnostics.Process();
            proc.StartInfo.FileName = fileName;
            proc.StartInfo.RedirectStandardError = true;
            proc.StartInfo.RedirectStandardOutput = true;
            proc.StartInfo.UseShellExecute = false;


            proc.Start();
            proc.WaitForExit();
            output1 = proc.StandardError.ReadToEnd();
            proc.WaitForExit();
            output2 = proc.StandardOutput.ReadToEnd();
            proc.WaitForExit();

みんなありがとう。ケビンは最初から私を助けてくれたので、みんなに賛成票を投じて受け入れます。それは今動作するので、非常に奇妙です...

于 2008-12-13T19:35:24.450 に答える