簡體   English   中英

在Windows服務中處理致命錯誤

[英]Handling fatal error in a Windows Service

我創建了Windows服務和安裝程序,該程序監視文件集合的更改並將所有更改的文件復制到WatchlistConfig.xml文件中指定的目標目錄。

我對該服務有幾個問題:1.它一次停止運行。 (不可接受)2.我們有時不得不嘗試多次啟動服務,然后才能“使用”該服務。

我認為問題#1可能是由於未處理應用程序中的致命錯誤。 我找到了一些嘗試合並到Main()方法中的代碼,但是這些代碼是為控制台應用程序編寫的(應用程序不是公認的類),因此暫時被注釋掉了。 有什么想法是在服務中實現此目標的正確類嗎?

我猜,問題2最有可能是超時。 該監視列表當前由網絡上不同計算機上的9個不同文件組成。 連接到這些源不是立即的(並非所有都在單個域中)。 有沒有辦法為服務啟動設置不同的超時值?

這是相關的代碼。 根據要求提供其他課程。
提前致謝。

編輯:錯誤地從我用來調試的測試工具(控制台)中發布了Main()。 我將其留在原處,並從WinSvc Project中添加Program類

    //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

確實沒有必要猜測; 作為一項服務,您應該將錯誤記錄到系統事件日志中。 設置一個頂級處理程序(已完成),但是不要期望能夠處理它。

如果錯誤未解決,那么您將無法在該處執行任何操作。 記錄並退出。 趕上您可以盡快處理的錯誤,測試和設計您的代碼,以免破壞其他代碼。

您可以將服務設置為在崩潰后自動重新啟動,但這應該是最后的選擇。 用盡調試器,找出錯誤發生的確切位置以及原因。 我在這里看到很多“可能是[某物]”和“它可能是[某物]”的說法。 同樣,沒有充分的理由去猜測; 您可以使用各種工具,這些工具將幫助您准確了解正在發生的事情。

您可能希望將函數包裝在try / catch塊中,以查看可能找到的內容。

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

我建議您先在應用程序的各個位置登錄Windows事件日志,以便開始縮小錯誤的位置。

我也不確定為什么要從Windows Service上下文使用Console.Read() 從Vista開始,該服務無法與桌面進行交互。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM