/// <summary>
		/// Stop the service.
		/// </summary>
		protected override void OnStop()
		{
			StatusReporter.OnPreStopping();

			// Clean up the directory watcher and crash processor threads
			foreach (var Processor in Processors)
			{
				Processor.RequestStop();
			}
			foreach (var Processor in Processors)
			{
				Processor.Dispose();
			}
			Processors.Clear();

			Watcher.Dispose();
			Watcher = null;

			StatusReporter.Dispose();
			StatusReporter = null;

			Slack.Dispose();
			Slack = null;

			// Flush the log to disk
			Log.Dispose();
			Log = null;
		}
		/// <summary>
		/// Start the service, and stop the service if there were any errors found.
		/// </summary>
		/// <param name="Arguments">Command line arguments (unused).</param>
		protected override void OnStart( string[] Arguments )
		{
			// Create a log file for any start-up messages
			Log = new LogWriter("CrashReportProcess", LogFolder);

			Config.LoadConfig();

			Slack = new SlackWriter
			{
				WebhookUrl = Config.Default.SlackWebhookUrl,
				Channel = Config.Default.SlackChannel,
				Username = Config.Default.SlackUsername,
				IconEmoji = Config.Default.SlackEmoji
			};

			Symbolicator = new Symbolicator();

			StatusReporter = new StatusReporting();

			// Add directory watchers
			WriteEvent("Creating ReportWatcher");
			Watcher = new ReportWatcher();

			WriteEvent("Creating ReportProcessors");
			for (int ProcessorIndex = 0; ProcessorIndex < Config.Default.ProcessorThreadCount; ProcessorIndex++)
			{
				var Processor = new ReportProcessor(Watcher, ProcessorIndex);
				Processors.Add(Processor);
			}

			// Init events by enumerating event names
			WriteEvent("Initializing Event Counters");
			FieldInfo[] EventNameFields = typeof(StatusReportingEventNames).GetFields(BindingFlags.Static | BindingFlags.Public);
			StatusReporter.InitCounters(EventNameFields.Select(EventNameField => (string)EventNameField.GetValue(null)));

			WriteEvent("Initializing Folder Monitors");
			Dictionary<string, string> FoldersToMonitor = new Dictionary<string, string>();
			FoldersToMonitor.Add(Config.Default.ProcessedReports, "Processed Reports");
			FoldersToMonitor.Add(Config.Default.ProcessedVideos, "Processed Videos");
			FoldersToMonitor.Add(Config.Default.DepotRoot, "P4 Workspace");
			FoldersToMonitor.Add(Config.Default.InternalLandingZone, "CRR Landing Zone");
			FoldersToMonitor.Add(Config.Default.DataRouterLandingZone, "Data Router Landing Zone");
			FoldersToMonitor.Add(Config.Default.InvalidReportsDirectory, "Invalid Reports");
			FoldersToMonitor.Add(Assembly.GetExecutingAssembly().Location, "CRP Binaries and Logs");
			FoldersToMonitor.Add(Config.Default.MDDPDBCachePath, "MDD PDB Cache");
			StatusReporter.InitFolderMonitors(FoldersToMonitor);

			WriteEvent("Starting StatusReporter");
			StatusReporter.Start();

			// Start the threads now
			Watcher.Start();
			foreach (var Processor in Processors)
			{
				Processor.Start();
			}

			DateTime StartupTime = DateTime.UtcNow;
			WriteEvent("Successfully started at " + StartupTime);
		}