Я создаю сервис 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 (), чтобы я мог предоставить те же учетные данные, которые я использую для входа в систему на компьютере, на котором я разрабатываю это решение.
Любая помощь / совет будет принята с благодарностью.