31

c#.netでタイマー付きのWindowsサービスを作成しました。Visual Studioでプロジェクトをデバッグ/ビルドしている間は正常に動作しますが、インストール後に操作は実行されません。

この背後にある理由は何でしょうか?

コード:

public partial class Service1 : ServiceBase
{
        FileStream fs;
        StreamWriter m_streamWriter;
        Timer tm = new Timer();

        public Service1()
        {
            InitializeComponent();

            this.ServiceName = "timerservice";

            tm.Interval = 2000;
            tm.Tick += new EventHandler(PerformOperations);
            tm.Start();

            fs = new FileStream(@"c:\mcWindowsService.txt", FileMode.OpenOrCreate, FileAccess.Write);

            m_streamWriter = new StreamWriter(fs);
            m_streamWriter.BaseStream.Seek(0, SeekOrigin.End);
        }

        private void PerformOperations(object sener, EventArgs e)
        {
            //StreamWriter swr = new StreamWriter("c:\\test_from_database.txt",true);

            try
            {
                OdbcConnection con = new OdbcConnection("DSN=liquor_data");

                OdbcDataAdapter adp = new OdbcDataAdapter("", con);

                DataSet ds = new DataSet();

                string sql = "select * from item_group";
                adp.SelectCommand.CommandText = sql;

                adp.Fill(ds, "item_group");

                foreach (DataRow dr in ds.Tables["item_group"].Rows)
                {
                    //      swr.Write(dr["group_name"].ToString() + "\t\t" + DateTime.Now.TimeOfDay.ToString() + "\n");

                    //Console.WriteLine(dr["group_name"].ToString() + "\t\t" + DateTime.Now.TimeOfDay.ToString() + "\n");
                    m_streamWriter.WriteLine(dr["group_name"].ToString() + "\t\t" + DateTime.Now.TimeOfDay.ToString() + "\n");
                }

                m_streamWriter.Flush();
            }

            catch (Exception ex)
            {
                // swr.Write("Error :"+ ex.Message + "\t\t" + DateTime.Now.TimeOfDay.ToString() + "\n"); }
            }
        }
    }
4

3 に答える 3

61

Windowsサービスを使用した最初のアプローチは簡単ではありません。

ずっと前に、私はC#サービスを作成しました。

これはServiceクラスのロジックです(テスト済み、正常に動作します):

namespace MyServiceApp
{
    public class MyService : ServiceBase
    {
        private System.Timers.Timer timer;

        protected override void OnStart(string[] args)
        {
            this.timer = new System.Timers.Timer(30000D);  // 30000 milliseconds = 30 seconds
            this.timer.AutoReset = true;
            this.timer.Elapsed += new System.Timers.ElapsedEventHandler(this.timer_Elapsed);
            this.timer.Start();
        }

        protected override void OnStop()
        {
            this.timer.Stop();
            this.timer = null;
        }

        private void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
            MyServiceApp.ServiceWork.Main(); // my separate static method for do work
        }

        public MyService()
        {
            this.ServiceName = "MyService";
        }

        // service entry point
        static void Main()
        {
            System.ServiceProcess.ServiceBase.Run(new MyService());
        }
    }
}

デバッグを簡素化し、サービスコードをクリーンアップするために、実際のサービス作業を別の静的メソッドで作成することをお勧めします(コンソールアプリケーションでは、参照を追加するだけです)。

間隔が十分であることを確認し、OnStartおよびOnStopオーバーライドでのみログに書き込みます。

お役に立てれば!

于 2012-10-14T20:10:19.463 に答える
7

メソッドにメインコードを配置する必要がありますOnStart

私のこの他のSOの答えは役立つかもしれません。

アプリケーションをWindowsサービスとして有効に維持しながら、visual-studio内でデバッグを有効にするためのコードを配置する必要があります。この他のSOスレッドは、Windowsサービスのデバッグの問題をカバーしています。

編集

これを読むことができるMSDNのメソッドについては、ここで入手可能なドキュメントも参照してください。OnStart

OnStartにあるはずの処理を実行するためにコンストラクターを使用しないで ください。OnStartを使用して、サービスのすべての初期化を処理します。コンストラクターは、サービスの実行時ではなく、アプリケーションの実行可能ファイルの実行時に呼び出されます。実行可能ファイルはOnStartの前に実行されます。たとえば、続行すると、SCMがすでにオブジェクトをメモリに保持しているため、コンストラクタは再度呼び出されません。OnStopがOnStartではなくコンストラクターで割り当てられたリソースを解放する場合、サービスが2回呼び出されたときに、必要なリソースが再度作成されることはありません。

于 2012-10-14T19:41:37.380 に答える
0

これは、ServiceBaseクラスのデリゲートとして実装されているTimerのOnTimedEventでサービスの実行が開始され、TimerロジックがSetupProcessingTimer()というメソッドにカプセル化されている実際の例です。

public partial class MyServiceProject: ServiceBase
{

private Timer _timer;

public MyServiceProject()
{
    InitializeComponent();
}

private void SetupProcessingTimer()
{
    _timer = new Timer();
    _timer.AutoReset = true;
    double interval = Settings.Default.Interval;
    _timer.Interval = interval * 60000;
    _timer.Enabled = true;
    _timer.Elapsed += new ElapsedEventHandler(OnTimedEvent);
}

private void OnTimedEvent(object source, ElapsedEventArgs e)
{
    // begin your service work
    MakeSomething();
}

protected override void OnStart(string[] args)
{
    SetupProcessingTimer();
}

...
}

間隔は、app.configで分単位で定義されます。

<userSettings>
    <MyProject.Properties.Settings>
        <setting name="Interval" serializeAs="String">
            <value>1</value>
        </setting>
    </MyProject.Properties.Settings>
</userSettings>
于 2017-11-24T11:47:51.530 に答える