Windowsのサービスとインストーラを作成して、変更のファイルコレクションを監視し、WatchlistConfig.xmlファイルで指定された宛先ディレクトリに変更されたファイルをコピーします。Windowsサービスで致命的なエラーを処理する
私はサービスにいくつかの問題があります: 1.それはある機会に実行を停止しました。 (受け入れられない) 2.サービスを開始する前に、何度かサービスを開始しなければならないことがあります。
問題#1はおそらく、アプリケーションの致命的なエラーを処理していないためと思われます。私はMain()メソッドに組み込もうとしたコードを見つけましたが、コンソールアプリケーション用に書かれています(アプリケーションは認識されたクラスではありません)ので、今はコメントアウトされています。これをサービスに実装するための適切なクラスであることは何ですか?
問題#2はおそらく私が推測しているタイムアウトです。ウォッチリストは現在、ネットワーク上の異なるマシン上に9つの異なるファイルで構成されています。これらのソースへの接続は即時ではありません(単一ドメイン上のすべてではありません)。サービスの起動時に異なるタイムアウト値を設定する方法はありますか?
ここに関連コードがあります。追加のクラスはリクエストに応じます。
ありがとうございます。
編集:誤ってデバッグに使用するテストハーネス(コンソール)からMain()を投稿しました。私は場所に残し、推測する必要は本当にありませんWinSvcプロジェクト
//Console Test harness
class Program
{
[STAThread]
static void Main(string[] args)
{
//AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
//Application.ThreadException += new System.Threading.ThreadExceptionEventHandler(Application_ThreadException);
//Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);
//Application.EnableVisualStyles();
//Application.SetCompatibleTextRenderingDefault(false);
//Application.Run(new Form1());
TimedWatchList twl = new TimedWatchList(new PSU_Config(Helpers.GetConfigFile()));
Console.WriteLine("Press \'q\' to quit the sample.");
while (Console.Read() != 'q') ;
}
static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
HandleException((Exception)e.ExceptionObject);
}
static void HandleException(Exception e)
{
//Handle/Log Exception Here
}
static void Application_ThreadException(object sender, System.Threading.ThreadExceptionEventArgs e)
{
Logger.Loggit(e.Exception.Message);
}
}
//Actual Service
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
static void Main()
{
ServiceBase[] ServicesToRun;
ServicesToRun = new ServiceBase[]
{
new Psu()
};
ServiceBase.Run(ServicesToRun);
}
}
public partial class Psu : ServiceBase
{
public Psu()
{
InitializeComponent();
TimedWatchList twl = new TimedWatchList(new PSU_Config(Helpers.GetConfigFile()));
}
protected override void OnStart(string[] args)
{
}
protected override void OnStop()
{
}
}
public class TimedWatchList
{
public static PSU_Config Config { get; set; }
List<WatchFile> WatchList = new List<WatchFile>();
public TimedWatchList(PSU_Config config)
{
Config = config;
if (Config.PrintDebugMsgs) Logger.Loggit("Attempting to create TimedWatchList object");
WatchList = WatchListFactory.GetWatchList(Helpers.GetWatchListFile());
if (Config.PrintDebugMsgs) Logger.Loggit("TimedWatchList created");
Timer _timer = new Timer();
_timer.Interval += Config.Interval;
_timer.Enabled = true;
// register OnTimedEvent() to fire on each "tick"
_timer.Elapsed += OnTimedEvent;
}
private void OnTimedEvent(object source, ElapsedEventArgs e)
{
foreach (WatchFile file in WatchList)
{
file.PostOnUpdate();
}
}
}//TimedWatchList class
internal class WatchFile
// represents a file that is being watched
{
#region Props
public FileInfo SourceFile { get; set; }
public DirectoryInfo TargetPath { get; set; }
#endregion //Props
#region CTOR
public WatchFile() { }
public WatchFile(string fileName, string sourcePath, string destPath)
{
SourceFile = new FileInfo(Path.Combine(sourcePath, fileName));
TargetPath = new DirectoryInfo(destPath);
}
public WatchFile(FileInfo sourceFile, DirectoryInfo targetDirectory)
{
SourceFile = sourceFile;
TargetPath = targetDirectory;
}
#endregion //CTOR
public void PostOnUpdate()
{
//if (TimedWatchList.Config.PrintDebugMsgs) Logger.Loggit("WatchFile Post Event called for: " + SourceFile.Name);
//if (TimedWatchList.Config.PrintDebugMsgs) Logger.Loggit("Stored LastModified datetime: " + LastModified);
string targetPath = String.Format(@"{0}\{1}", TargetPath.FullName, SourceFile.Name);
{
try
{
//ensure directory exists
if (!Directory.Exists(TargetPath.FullName)) Directory.CreateDirectory(TargetPath.FullName);
//ensure file version is current
if (!File.Exists(targetPath) || (File.GetLastWriteTime(targetPath) != File.GetLastWriteTime(SourceFile.FullName)))
{
Logger.Loggit(String.Empty);
Logger.Loggit("Attempting to copy: " + SourceFile + " (" + File.GetLastWriteTime(SourceFile.FullName) + ")");
SourceFile.CopyTo(targetPath, true);
Logger.Loggit("\tCopy posted.\tLastModified: " + File.GetLastWriteTime(targetPath));
}
}
catch (IOException ioex)
{
Logger.Loggit("Error: " + ioex.Message);
}
catch (Exception ex)
{
Logger.Loggit("Error: " + ex.Message);
}
}
}
}// WatchFile class
私はコンソールテストハーネスからメイン()に貼り付けました。どのようにしてサービスをデバッグすることができないので、アセンブリを参照してコンソールで実行してデバッグしています。ネイティブでサービスを実行してデバッグする方法はありますか? –
@JM:少なくとも、処理されていない例外をシステムイベントログに記録する必要があります。デバッグに関しては、コンソールアプリケーションとして起動することができます。その件に関して、[こちらは別の質問です](http://stackoverflow.com/questions/5156427/how-do-you-debug-a-windows-service)。 –
Thx Ed。カスタムエラー/イベントログを作成するのは貧弱な方法ですか? –