I have a service, using topshelf, that uses FileSystemWatcher to look for created files and I do something with them.
Service Settings are stored and loaded in a JSON file.
When the service is started, settings are loaded from file and the settings class values are populated.
When debugging, it works fine, when in release and run as a service, it's using the default values for the TempFolder property.
Why is this failing and how do properly load the settings?
[JsonObject(MemberSerialization.OptIn)]
public class MonitorSettings
{
public readonly string SettingsFileName = "Settings.json";
private string SettingsFilePath;
[JsonProperty]
public string FolderToMonitor { get; set; } = @"C:\temp\";
[JsonProperty]
public string FileNameSearchWildcard { get; set; } = @"*_something.txt";
[JsonProperty]
public string TempFolder { get; set; } = @"C:\Temp_Fix_This_Path\";
public MonitorSettings()
{
SettingsFilePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData, Environment.SpecialFolderOption.None), SettingsFileName);
}
public bool Load()
{
if (!File.Exists(SettingsFilePath))
{
Save();
return false;
}
var json = File.ReadAllText(SettingsFilePath);
JsonConvert.PopulateObject(json, this);
return true;
}
Contents of the json file
{
"FolderToMonitor": "C:\\results",
"FileNameSearchWildcard": "*_blah.txt",
"TempFolder": "D:\\Temp\\temp"
}
Service start:
private volatile MonitorSettings _Settings;
public bool Start() //entry point Service Start
{
_CTS = new CancellationTokenSource();
Task.Run(()=>StartService(_CTS.Token));
return true;
}
public async Task StartService(CancellationToken token)
{
_Settings = new MonitorSettings();
if (!_Settings.Load())
{
WriteEventLog($"Settings file not setup. Go To %AppData% and edit: {_Settings.SettingsFileName}",EventLogEntryType.Error,0);
throw new Exception($"Settings File Not Found, Go To AppData and edit {_Settings.SettingsFileName}");
}
CheckSettings(_Settings);
if (!Directory.Exists(_Settings.TempFolder))
{
Directory.CreateDirectory(_TempFolder);
}
WriteEventLog($"Starting {appName}. Monitoring: {_Settings.FolderToMonitor} | Copying to: {_Settings.TempFolder}", EventLogEntryType.Information,1); //TempFolder is not the value from the JSON file
try
{
using (var watcher = new FileSystemWatcher())
{
watcher.Path = _Settings.FolderToMonitor;
watcher.NotifyFilter = NotifyFilters.LastWrite | NotifyFilters.FileName;
watcher.IncludeSubdirectories = false;//true;
watcher.Created += Watcher_Changed;
//start it
watcher.EnableRaisingEvents = true;
while (!token.IsCancellationRequested) { await Task.Delay(TimeSpan.FromSeconds(15), token); };
}
}
finally
{
WriteEventLog($"{appName} Service Stop Requested.", EventLogEntryType.Information, 1);
}
}
The immediate issue was using
Environment.SpecialFolder.ApplicationData
to save the settings file to which is user-specific.
Changing to Environment.SpecialFolder.CommonApplicationData
is non user specific and is a "common" location for this file and more appropriate for this case.