2

eventLogとを使用して Windows サービスを実装しました。FileSystemWatcherこれは、特定のディレクトリの変更を検索し、メッセージを に書き込みますMyLog

奇妙なこと1:
installUtil.exeを介してインストールし(VS2012にはインストーラーテンプレートがないため)、「サービス」に移動してサービスを開始すると、次のような状況が発生します。

ローカル コンピューターの [サービス名] サービスが開始され、その後停止されました。一部のサービスは、別のサービスまたはプログラムによって使用されていない場合、自動的に停止します。

私はすでにこの質問を見ました。この投稿からの2つの回答がなぜそうなのか:

OnStart()1)メソッドで開始するスレッドがありません。
私はデザイナーを使用し、[プロパティ] ウィンドウでほとんどのプロパティを設定します。手動でスレッドを開始したことはありませんが、場合によってはすべてが機能していたので、そうではないと思います。

2) メソッドで例外が発生しOnStart()ます。コードを変更していないため、そうではないと思います。同じサービスをアンインストール、ビルド、および再インストールするだけで、実行される場合と実行されない場合があります。

このことで 2 時間ほど立ち往生したとき、「FilesMonitoringServices」のSourceプロパティが長すぎることに気付きました。eventLog「MonitorSource」に変更すると、すべてが機能し始めました。何回か再インストールしたところ、上記と同じ警告が表示されました。Sourceプロパティを再度変更したところ、サービスが実行されるようになりました。
これが最初の奇妙なことです。

奇妙なこと 2:もっと悪い。ログOnStart()OnStop()メソッドのみを実行しても、fileSystemWatcher イベント ハンドラーが実行されないことを意味します。今日、このサービス mabby を 100 回再インストールしましたが、3 回は機能していましたが、もう一度再インストールすると停止しました。そして、再インストールの間にコードをまったく変更していません。

継承する私のクラス(MonitoringService)のメソッドとコンストラクターは次のServiceBaseとおりです。

public MonitoringService()
    {
        InitializeComponent();

        if (!EventLog.SourceExists(eventLog.Source))
        {
            EventLog.CreateEventSource(eventLog.Source, eventLog.Log);
        }
        // haven't changed it between the reinstallations
        fileWatcher.Path = @"path";                
    }

protected override void OnStart(string[] args)
    {
        fileWatcher.EnableRaisingEvents = true;
        eventLog.WriteEntry("start", EventLogEntryType.Information);
        base.OnStart(args);
    }

    protected override void OnStop()
    {
        fileWatcher.EnableRaisingEvents = false;
        fileWatcher.Dispose();
        eventLog.WriteEntry("stop", EventLogEntryType.Information);
        base.OnStop();
    }

ファイル システム ウォッチャー イベント ハンドラ:

private void fileSystemWatcher1_Changed(object sender, FileSystemEventArgs e)
    {
        using (var conn = new SqlConnection(GetConnectionString()))
        {
            conn.Open();
            var productId = Convert.ToInt32(Regex.Match(e.Name, @"\d+").Value);
            const string cmd = "UPDATE Products SET ImageModifiedDate=@date WHERE ProductId=@productId";
            using (var command = new SqlCommand(cmd, conn))
            {
                command.Parameters.AddWithValue("@productId", productId);
                command.Parameters.AddWithValue("@date", DateTime.Now);
                command.ExecuteNonQuery();
            }                   
        }
        eventLog.WriteEntry(string.Format("{0} has been changed: {1}", e.Name, DateTime.Now), EventLogEntryType.Information);             
    }

質問:この動作は私のコードではなく、オペレーティング システムの設定が原因のようです。そうでしょうか?

****編集:より具体的なものを発見しました:**

1) メッセージが表示された場合 (サービスを開始したい場合):

The [service name] service on local computer started and then stopped. ....

Sourceのプロパティを変更し、再構築して再インストールする必要がありeventLogます。このメッセージは表示されません。次回はマビー。

2) 次のフォルダ階層があります: images/prod-images. imagesディレクトリとprod-imagesディレクトリの両方に画像ファイルが含まれています。サービスの実行中にフォルダーからイメージを変更すると、必要に応じprod-imagesてメッセージがログに書き込まれ、データベースが更新されます。しかし、このイベントの後、サービスは停止します! (私はこれを3回チェックしました)。そして、再起動してこれを数回繰り返すと、データベースが更新され、ログが書き込まれ、3 番目の時間に取得されます

The [service name] service on local computer started and then stopped. ....

しかし、これは最良の部分ではありません) ディレクトリにある画像を変更するimagesと、何度でも変更できますが、サービスは停止しません。(からの画像のみimages/prod-imagesがデータベースのエントリにバインドされます)。

それで、この機能はどういうわけかデータベースへのアクセスを指しているでしょうか?

編集 2:ビジュアル スタジオではDEBUG -> Attach to Process、サービスのデバッグに使用します。ブレークポイントを設定して画像を変更します。初めてイベント ハンドラーが問題なく実行されます。データベースが更新され、ログ メッセージが書き込まれます。しかし、F11 (ステップ イン) を押し続けると、このイベント ハンドラーが 2 回目に実行されます。ラインで

var productId = Convert.ToInt32(Regex.Match(e.Name, @"\d+").Value); 

「処理されていません」とFormatException表示されます。この後、デバッグを停止すると、サービスが停止します! それだけです: 例外はイベント ハンドラーで発生します。

なぜ2回目に実行されるのか分かりますか? ありがとう!

PS私はすでにDavut Gürbüzの回答を提出しました.彼は私を正しい方向に向けました.
とにかく、実際の問題を説明する私自身の答えをチェックしてください。

4

2 に答える 2

2

start-stop エラーが発生した場合は、コンストラクターにエラーがあることを意味します。

あなたのctorにtry catchを入れてください。catch ブロックのイベントログにエラーを記録できます。

これに加えて、main メソッドを作成し、コンソール アプリとして win サービスを開始します。メイン メソッドでサービスのインスタンスを取得すると、それをデバッグすることもできます。

//You should select Console Application from Application properties
static void Main(string[] args)
    {
        MyWindowsService service = new MyWindowsService();

        if (Environment.UserInteractive)
        {
            service.OnStart(args);
            Console.WriteLine("Press any key to stop program");
            Console.Read();
            service.OnStop();
        }
        else
        {
            ServiceBase.Run(service);
        }

    } 

希望が役立ちます

于 2013-02-25T20:02:21.893 に答える
0

イベント ハンドラー メソッドが 2 回実行された理由は、フォルダーに含まれるサブディレクトリfileSystemWatcher1_Changedを監視していたためです。imagesそして、このイベント ハンドラーはすべてのLastWriteイベントを監視していました。

そのため、images/prod-imagesディレクトリ内の画像を変更すると、このハンドラーは画像の変更とフォルダーの変更に反応しました。

この状況では、監視パスを変更するか、DB を更新するときにステートメントを prod-images挿入することができます。if

そのようなばかげた間違いは、それを見つけるのに数日かかりました))

于 2013-02-26T10:12:38.407 に答える