Ошибка 1053 при запуске службы, созданной с помощью Topshelf - PullRequest
0 голосов
/ 03 февраля 2020

Я создаю сервис FileSystemWatcher, используя Topshelf. Код работает отлично, когда я запускаю его из отладчика в Visual Studio. Однако, когда я пытаюсь запустить службу из командной строки или вручную (после установки), я получаю ошибку 1053. Я читал некоторые другие посты, но я не думаю, что я использую какой-либо «бесконечный» l oop внутри моего метода Start ().

Это Program.cs

    using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;
using Topshelf;

namespace NONHR_FileSystem_Watcher_Service
{
    class Program
    {

        private static string EventLogSourceName;
        private static int ErrorId;
        private static int InfoId;
        private static XDocument xdoc;
        private static string InfoMessage;

        static void Main(string[] args)
        {
            try
            {

                // Read parameters from XML file.
                ReadConfigParametersFromXML();

                var exitCode = HostFactory.Run(x =>
                {
                    x.Service<NONHRFileSystemWatcherService>(s =>
                    {
                        s.ConstructUsing(heartbeat => new NONHRFileSystemWatcherService());
                        s.WhenStarted(heartbeat => heartbeat.Start());
                        s.WhenStopped(heartbeat => heartbeat.Stop());                        
                    });

                    //x.RunAsLocalService();
                    x.RunAsPrompt();                    
                    x.SetServiceName("NONHRFileSystemWatcher");
                    x.SetDisplayName("NONHR File System Watcher Service");
                    x.SetDescription("This is a File System Watcher service which monitors the drop directory for NONHR related data files.");

                });

                int exitCodeValue = (int)Convert.ChangeType(exitCode, exitCode.GetTypeCode());
                Environment.ExitCode = exitCodeValue;

                InfoMessage = string.Format("The service has been loaded successfully!");
                EventLogWriter.WriteEventLogEntry(InfoMessage, EventLogEntryType.Information, EventLogSourceName, InfoId);

            }
            catch (Exception Ex)
            {
                string[] errorMessage = new string[3];
                errorMessage[0] = string.Format("Error Description: {0}", Ex.Message);
                errorMessage[1] = string.Format("Error InnerException Message: {0}", Ex.InnerException.Message);
                errorMessage[2] = string.Format("Error Stack Trace: {0}", Ex.StackTrace);
                EventLogWriter.WriteEventLogEntry(string.Join("\n\n", errorMessage), EventLogEntryType.Error, EventLogSourceName, ErrorId);
            }
        }

        private static void ReadConfigParametersFromXML()
        {
            if (File.Exists("AdminParameters.xml"))
            {
                xdoc = XDocument.Load("AdminParameters.xml");
                EventLogSourceName = xdoc.Descendants("SourceName").Where(x => x.Parent.Name == "EventNotifications").Select(x => x.Value).SingleOrDefault();
                ErrorId = xdoc.Descendants("ErrorEventId").Where(x => x.Parent.Name == "EventNotifications").Select(x => Convert.ToInt32(x.Value)).SingleOrDefault();
                InfoId = xdoc.Descendants("InfoEventId").Where(x => x.Parent.Name == "EventNotifications").Select(x => Convert.ToInt32(x.Value)).SingleOrDefault();
            }
            else
            {
                throw new FileNotFoundException(string.Format("Unable to locate \"{0}\" file in the assembly directory: {1}", "AdminParameters.xml", Environment.CurrentDirectory));
            }
        }
    }
}

Это NONHRFileSystemWatcherService.cs

using System;
using System.Collections.Generic;
using System.IO;
using System.Xml.Linq;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Diagnostics;
using System.Threading;

namespace NONHR_FileSystem_Watcher_Service
{
    public class NONHRFileSystemWatcherService
    {
        private FileSystemWatcher _fsw;
        private XDocument xdoc;
        private string WatchDirectoryPath;
        private string LogFilePath;
        private string ArchiveDirectoryPath;
        private string FileExtension;
        private string EventLogSourceName;
        private int ErrorId;
        private int InfoId;
        private int WarningId;
        private string LogFile;
        private string DTEXECPath;
        private string SSISFilePath;
        private string CMNameNONHRFlatFile;
        private string CMNameFileArchive;
        private ProcessStartInfo procExecuteSSISPackageCmd;
        private Process proc;

        public enum EventType { Info, Error };


        public NONHRFileSystemWatcherService()
        {
            // Load up all supplied parameters from XML.
            ReadConfigParametersFromXML();

            _fsw = new FileSystemWatcher(WatchDirectoryPath);

            // Add notify filters
            _fsw.NotifyFilter = NotifyFilters.LastWrite | 
                                NotifyFilters.LastAccess | 
                                NotifyFilters.FileName;

            // What types of files to monitor?
            _fsw.Filter = FileExtension;

            // Add Event Handlers
            _fsw.Changed += OnChanged;      // We won't be taking any action on these.
            _fsw.Deleted += OnChanged;      // We won't be taking any action on these.
            _fsw.Created += OnChanged;      // These are the ones we are interested in.
            _fsw.Renamed += OnRenamed;      // We won't be taking any action on these.

            EventLogWriter.WriteEventLogEntry("NONHR File Watcher Service loaded successfully!", EventLogEntryType.Information, EventLogSourceName, InfoId);

        }


        private void WriteEventLogEntry(string message, EventLogEntryType eventType)
        {
            using (EventLog _eventLog = new EventLog())
            {
                //Check if the event source exists. If not, create it.
                if (!EventLog.SourceExists(EventLogSourceName))
                {
                    EventLog.CreateEventSource(EventLogSourceName, "Application");
                }

                _eventLog.Source = EventLogSourceName;

                switch (eventType)
                {
                    case EventLogEntryType.Error:
                        _eventLog.WriteEntry(message, eventType, ErrorId);
                        break;

                    case EventLogEntryType.Information:
                        _eventLog.WriteEntry(message, eventType, InfoId);
                        break;
                }
            }
        }


        private void ReadConfigParametersFromXML()
        {
            if (File.Exists("AdminParameters.xml"))
            {
                xdoc = XDocument.Load("AdminParameters.xml");
                WatchDirectoryPath = xdoc.Descendants("WatchDirectoryPath").Where(x => x.Parent.Name == "Paths").Select(x => x.Value).SingleOrDefault();
                LogFilePath = xdoc.Descendants("LogFileDirectoryPath").Where(x => x.Parent.Name == "Paths").Select(x => x.Value).SingleOrDefault();
                ArchiveDirectoryPath = xdoc.Descendants("ArchiveDirectoryPath").Where(x => x.Parent.Name == "Paths").Select(x => x.Value).SingleOrDefault();
                FileExtension = xdoc.Descendants("FileExtn").Where(x => x.Parent.Name == "FileTypes").Select(x => x.Value).SingleOrDefault();
                EventLogSourceName = xdoc.Descendants("SourceName").Where(x => x.Parent.Name == "EventNotifications").Select(x => x.Value).SingleOrDefault();
                ErrorId = xdoc.Descendants("ErrorEventId").Where(x => x.Parent.Name == "EventNotifications").Select(x => Convert.ToInt32(x.Value)).SingleOrDefault();
                InfoId = xdoc.Descendants("InfoEventId").Where(x => x.Parent.Name == "EventNotifications").Select(x => Convert.ToInt32(x.Value)).SingleOrDefault();
                WarningId = xdoc.Descendants("WarningEventId").Where(x => x.Parent.Name == "EventNotifications").Select(x => Convert.ToInt32(x.Value)).SingleOrDefault();
                SSISFilePath = xdoc.Descendants("SSISFilePath").Where(x => x.Parent.Name == "DTS").Select(x => x.Value).SingleOrDefault();
                DTEXECPath = xdoc.Descendants("DTEXECPath").Where(x => x.Parent.Name == "DTS").Select(x => x.Value).SingleOrDefault();
                CMNameNONHRFlatFile = xdoc.Descendants("NONHRFlatFile").Where(x => x.Parent.Name == "CMNames" && x.Parent.Parent.Name == "DTS").Select(x => x.Value).SingleOrDefault();
                CMNameFileArchive = xdoc.Descendants("FileArchive").Where(x => x.Parent.Name == "CMNames" && x.Parent.Parent.Name == "DTS").Select(x => x.Value).SingleOrDefault();
            }
            else
            {
                throw new FileNotFoundException(string.Format("Unable to locate \"{0}\" file in the assembly directory: {1}", "AdminParameters.xml", Environment.CurrentDirectory));
            }
        }


        private void OnRenamed(object sender, RenamedEventArgs e)
        {
            Thread.Sleep(1500);
            Log(string.Format("FileWatcher noticed an event of type \"{0}\" on file \"{1}\"", e.ChangeType, e.Name));
            Log(string.Format("Old filename: \"{0}\". New filename: \"{1}\"", e.OldName, e.Name));
            LogBlank();
        }


        private void OnChanged(object sender, FileSystemEventArgs e)
        {
            //Thread.Sleep(1500);
            Log(string.Format("FileWatcher noticed an event of type \"{0}\" on file \"{1}\"", e.ChangeType, e.Name));
            //LogBlank();


            switch (e.ChangeType)
            {
                case WatcherChangeTypes.Created:
                    {
                        // Invoke NONHR SSIS package
                        ExecuteSSISPackage(e);

                        // Call the AD Script
                        // <Method()>
                    }
                    break;

                default:
                    break;

            }
        }


        public void Start()
        {            
            LogFile = GenerateNewLogFileName(LogFilePath);
            _fsw.EnableRaisingEvents = true;
            EventLogWriter.WriteEventLogEntry(string.Format("NONHR File Watcher service is now monitoring the folder: \"{0}\" for files of type: \"{1}\".", WatchDirectoryPath, FileExtension), EventLogEntryType.Information, EventLogSourceName, InfoId);
            Log("test log...");
        }


        private string GenerateNewLogFileName(string logFilePath)
        {
            string datetimestring = DateTime.Now.ToString("yyyy-MM-dd_HH_mm_ss");
            return string.Concat(logFilePath, "Log-", datetimestring, ".txt");
        }


        public void Stop()
        {
            _fsw.EnableRaisingEvents = false;
            EventLogWriter.WriteEventLogEntry(string.Format("NONHR File Watcher service is no longer monitoring the folder: \"{0}\" for files of type: \"{1}\".", WatchDirectoryPath, FileExtension), EventLogEntryType.Warning, EventLogSourceName, WarningId);
        }


        private void Log(string message)
        {
            string logMessage = string.Concat(DateTime.Now.ToString(), " - ", message);
            string[] lines = new string[] { logMessage };
            File.AppendAllLines(LogFile, lines);
        }


        private void LogBlank()
        {
            string[] lines = new string[] { string.Empty };
            File.AppendAllLines(LogFile, lines);
        }


        private string BuildExecuteSSISPackageCommand(FileSystemEventArgs e)
        {
            return @" /FILE " + "\"" + SSISFilePath + "\"" +
                   @" /CONNECTION " + CMNameNONHRFlatFile + "\"" + e.FullPath + "\"" +
                   @" /CONNECTION " + CMNameFileArchive + "\"" + ArchiveDirectoryPath + "\"";

        }


        private void ExecuteSSISPackage(FileSystemEventArgs e)
        {
            string ExecuteSSISPackageCmd = BuildExecuteSSISPackageCommand(e);
            procExecuteSSISPackageCmd = new ProcessStartInfo(DTEXECPath, ExecuteSSISPackageCmd);
            procExecuteSSISPackageCmd.RedirectStandardOutput = true;
            procExecuteSSISPackageCmd.UseShellExecute = false;

            procExecuteSSISPackageCmd.CreateNoWindow = true;
            proc = new Process();
            proc.StartInfo = procExecuteSSISPackageCmd;
            proc.Start();

            string result = proc.StandardOutput.ReadToEnd();
            proc.WaitForExit();
            Log(string.Format("The SSIS return code was {0}", proc.ExitCode));
            proc.Dispose();
        }
    }
}

Это EventLogWriter.cs

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace NONHR_FileSystem_Watcher_Service
{
    public static class EventLogWriter
    {
        public static void WriteEventLogEntry(string message, EventLogEntryType eventType, string eventLogSourceName, int eventId)
        {
            using (EventLog _eventLog = new EventLog())
            {
                //Check if the event source exists. If not, create it.
                if (!EventLog.SourceExists(eventLogSourceName))
                {
                    EventLog.CreateEventSource(eventLogSourceName, "Application");
                }

                _eventLog.Source = eventLogSourceName;
                _eventLog.WriteEntry(message, eventType, eventId);

            }
        }
    }
}

Несколько других вещей, которые я должен упомянуть здесь. Во-первых, я поставил этот журнал («журнал испытаний ...»); внутри метода Start () специально. Когда я запускаю код из отладчика в Visual Studio, я вижу, что текст был записан в файл журнала. Когда я пытаюсь запустить службу после ее установки, я даже не вижу сгенерированный файл.

Во-вторых, это могут быть разрешения? Я намеренно установил x.RunAsPrompt (), чтобы я мог предоставить те же учетные данные, которые я использую для входа в систему на компьютере, на котором я разрабатываю это решение.

Любая помощь / совет будет принята с благодарностью.

...