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"); }
}
}
}
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オーバーライドでのみログに書き込みます。
お役に立てれば!
メインコードをOnStart
メソッドに配置する必要があります。
この他の SOの答え は私の助けになるかもしれません。
Windowsサービスとして有効なアプリケーションを維持しながら、visual-studio内でデバッグを有効にするコードを配置する必要があります。この他の SOスレッド は、Windowsサービスのデバッグの問題をカバーします。
[〜#〜] edit [〜#〜]:
また、MSDNのOnStart
メソッドについては、こちらのドキュメントをご覧ください here
OnStartにあるべき処理を実行するためにコンストラクターを使用しないでください。 OnStartを使用して、サービスのすべての初期化を処理します。コンストラクターは、サービスの実行時ではなく、アプリケーションの実行可能ファイルの実行時に呼び出されます。実行可能ファイルは、OnStartの前に実行されます。たとえば、続行すると、SCMがすでにオブジェクトをメモリに保持しているため、コンストラクタは再度呼び出されません。 OnStopがOnStartではなくコンストラクターに割り当てられたリソースを解放する場合、必要なリソースは、サービスが2回呼び出されたときに再び作成されることはありません。
ServiceBaseクラスのデリゲートとして実装されているTimerのOnTimedEventでサービスの実行が開始され、タイマーロジックが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>