web-dev-qa-db-ja.com

バッチファイルを呼び出した後、サービスがWaitForExitでハングアップする

バッチファイルを呼び出すサービスがあります。バッチファイルの実行には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:

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

アップデート#3:

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

アップデート#4:

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

18

これが私がバッチファイルを実行するために使用するものです:

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();

それでうまくいくかどうかはわかりませんが、ハングアップする問題はありません。

29
kemiller2002
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());
                }
            }
        }
    }
11
samir
            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();

テスト済み、動作します。

4
suresh

pg_dump.exeはおそらくユーザー入力を求めています。このデータベースには認証が必要ですか?サービスに存在しないENVIRONMENT変数に依存していますか? pg_dumpはわかりませんが、入力を求める他の理由は何ですか?

3
Stephen Martin

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

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

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

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

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

System.Diagnosticsかどうか覚えていません。デバッグでのみ使用できます。おそらくそうではありませんが、一部はそうかもしれません。私はそれを確認する必要があります。

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

ラリー

3
LarryF

次のステップは、デバッガーを起動して、プログラムが待機しているものを確認できるかどうかを確認することです。アセンブリでのデバッグに精通している場合は、ProcExp、FileMonなどのツールを使用して、何が起こっているかIDEAを取得できる可能性があります。

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

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

Cmd.exeの完全なヘルプを表示するには、cmd /?と入力してください。任意のコマンドプロンプト。

ラリー

3
LarryF

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

ユーザーアカウントを使用しようとしましたが、うまくいきませんでした。 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();

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

1

Daok、変更したのは最初のWaitForExit()のタイムアウト期間だけだったようです。あなたはそれに非常に注意する必要があります。もし何か[〜#〜] does [〜#〜]があなたのサービスをハングさせた場合、それは決して返ってきません(そして、まあ、これまでのようにかなりの作業は.. hehですが)。エンドユーザーには良くありません...

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

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

私の2セント相当ですが、通常はそれほど多くありません。 ;)

1
LarryF