Обработка фатальной ошибки в службе Windows - PullRequest
0 голосов
/ 15 ноября 2011

Я создал службу Windows и установщик, который просматривает коллекцию файлов на предмет изменений и копирует любой файл, который изменяется, в каталог назначения, указанный в файле WatchlistConfig.xml.

У меня есть пара проблем со службой: 1. Однажды она перестала работать.(неприемлемо) 2. Иногда нам приходится пытаться запустить службу несколько раз, прежде чем она «заберет».

Я считаю, что проблема № 1, вероятно, связана с не обработкой фатальных ошибок в приложении.Я нашел немного кода, который я пытался включить в метод Main (), но он написан для консольного приложения (приложение не является распознанным классом) и поэтому закомментирован на данный момент.Любая идея, который является правильным классом для реализации этого в сервисе?

Проблема № 2, скорее всего, тайм-аут, я думаю.В настоящее время список наблюдения состоит из 9 различных файлов на разных компьютерах в сети.Подключение к этим источникам не является немедленным (не все в одном домене).Можно ли установить другое значение времени ожидания для запуска службы?

Вот соответствующий код.Дополнительные классы по запросу.
Заранее спасибо.

Редактировать: ошибочно выложили Main () из тестового жгута (консоли), который я использую для отладки.Я оставил его на месте и добавил класс Program из проекта 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

Ответы [ 2 ]

3 голосов
/ 15 ноября 2011

Там действительно нет необходимости угадывать; в качестве службы вы должны регистрировать свои ошибки в журнале системных событий. Установите обработчик верхнего уровня (как вы сделали), но не ожидайте, что сможете обработать его.

Если ошибка не была обработана, вы не сможете ничего с этим поделать. Войдите и выйдите. Поймай ошибки, с которыми ты можешь справиться, как можно скорее, протестируй и спроектируй свой код так, чтобы он не сломался.

Вы можете настроить автоматический запуск службы после сбоя, но это должно быть последним средством. Разберитесь с отладчиком и выясните, где именно происходят ошибки и почему. Я вижу много утверждений «это, вероятно, [что-то]» и «это может быть [что-то еще]» здесь. Опять же, нет веских причин для догадок; у вас есть инструменты, которые помогут вам точно определить, что происходит.

0 голосов
/ 15 ноября 2011

Возможно, вы захотите просто обернуть свою функцию в блок try / catch, чтобы увидеть, что вы можете найти.

try
{
  MainAppFunctionality();
}
catch (Exception e)
{
   //Not sure what you are going to do here, it's probably too late
}

Я предлагаю вам войти в журнал событий Windows в различных точках приложения какначать, чтобы вы могли начать сужать место ошибки.

Я также не уверен, почему вы используете Console.Read() из контекста службы Windows.Начиная с Vista, сервис не может взаимодействовать с рабочим столом.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...