From 7fe54c0785a194e34a8e3016ab0045af5351e9c6 Mon Sep 17 00:00:00 2001 From: mr_sc Date: Wed, 19 Aug 2026 19:27:41 +0200 Subject: [PATCH] =?UTF-8?q?Projektdateien=20hinzuf=C3=BCgen.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- BUILD_INFO.txt | 13 + FileinterfaceCronScheduler.sln | 21 ++ FileinterfaceCronScheduler/App.config | 43 +++ .../FileinterfaceCronScheduler.csproj | 96 ++++++ .../FileinterfaceCronSchedulerService.cs | 46 +++ .../IMSApi/ImsApiClient.cs | 229 +++++++++++++++ .../ImsCustomFunctionInvoker.cs | 37 +++ FileinterfaceCronScheduler/Program.cs | 44 +++ .../Properties/AssemblyInfo.cs | 15 + FileinterfaceCronScheduler/RuntimeFactory.cs | 47 +++ .../Scheduler/CronExpression.cs | 131 +++++++++ .../Scheduler/CronJobConfig.cs | 69 +++++ .../Scheduler/CronJobExecutor.cs | 145 +++++++++ .../Scheduler/CronJobRepository.cs | 120 ++++++++ .../Scheduler/CronScheduler.cs | 106 +++++++ .../Scheduler/CustomFunctionInvoker.cs | 45 +++ .../Scheduler/FileSystemWatcherManager.cs | 172 +++++++++++ .../Scheduler/JobLog.cs | 60 ++++ .../Scheduler/SchedulerRuntime.cs | 57 ++++ .../Scheduler/WatcherJobConfig.cs | 56 ++++ .../Scheduler/WatcherJobExecutor.cs | 149 ++++++++++ .../Scheduler/WatcherJobRepository.cs | 109 +++++++ .../Scheduler/WebAdminServer.cs | 278 ++++++++++++++++++ FileinterfaceCronScheduler/cronjobs.json | 23 ++ FileinterfaceCronScheduler/ihas.properties | 0 .../lib/IMSApiDotNet.dll | Bin 0 -> 566272 bytes FileinterfaceCronScheduler/lib/README.txt | 14 + FileinterfaceCronScheduler/watcherjobs.json | 28 ++ README.md | 220 ++++++++++++++ scripts/allow-webinterface-network.bat | 4 + scripts/install-service.bat | 22 ++ scripts/uninstall-service.bat | 7 + 32 files changed, 2406 insertions(+) create mode 100644 BUILD_INFO.txt create mode 100644 FileinterfaceCronScheduler.sln create mode 100644 FileinterfaceCronScheduler/App.config create mode 100644 FileinterfaceCronScheduler/FileinterfaceCronScheduler.csproj create mode 100644 FileinterfaceCronScheduler/FileinterfaceCronSchedulerService.cs create mode 100644 FileinterfaceCronScheduler/IMSApi/ImsApiClient.cs create mode 100644 FileinterfaceCronScheduler/ImsCustomFunctionInvoker.cs create mode 100644 FileinterfaceCronScheduler/Program.cs create mode 100644 FileinterfaceCronScheduler/Properties/AssemblyInfo.cs create mode 100644 FileinterfaceCronScheduler/RuntimeFactory.cs create mode 100644 FileinterfaceCronScheduler/Scheduler/CronExpression.cs create mode 100644 FileinterfaceCronScheduler/Scheduler/CronJobConfig.cs create mode 100644 FileinterfaceCronScheduler/Scheduler/CronJobExecutor.cs create mode 100644 FileinterfaceCronScheduler/Scheduler/CronJobRepository.cs create mode 100644 FileinterfaceCronScheduler/Scheduler/CronScheduler.cs create mode 100644 FileinterfaceCronScheduler/Scheduler/CustomFunctionInvoker.cs create mode 100644 FileinterfaceCronScheduler/Scheduler/FileSystemWatcherManager.cs create mode 100644 FileinterfaceCronScheduler/Scheduler/JobLog.cs create mode 100644 FileinterfaceCronScheduler/Scheduler/SchedulerRuntime.cs create mode 100644 FileinterfaceCronScheduler/Scheduler/WatcherJobConfig.cs create mode 100644 FileinterfaceCronScheduler/Scheduler/WatcherJobExecutor.cs create mode 100644 FileinterfaceCronScheduler/Scheduler/WatcherJobRepository.cs create mode 100644 FileinterfaceCronScheduler/Scheduler/WebAdminServer.cs create mode 100644 FileinterfaceCronScheduler/cronjobs.json create mode 100644 FileinterfaceCronScheduler/ihas.properties create mode 100644 FileinterfaceCronScheduler/lib/IMSApiDotNet.dll create mode 100644 FileinterfaceCronScheduler/lib/README.txt create mode 100644 FileinterfaceCronScheduler/watcherjobs.json create mode 100644 README.md create mode 100644 scripts/allow-webinterface-network.bat create mode 100644 scripts/install-service.bat create mode 100644 scripts/uninstall-service.bat diff --git a/BUILD_INFO.txt b/BUILD_INFO.txt new file mode 100644 index 0000000..52603d8 --- /dev/null +++ b/BUILD_INFO.txt @@ -0,0 +1,13 @@ +FileInterface Watcher + CronScheduler - COMPLETE +Date: 2026-08-19 +Target: .NET Framework 4.8, x86 +IMS API: IMSApiDotNet.dll 10.0.0.3 included under FileinterfaceCronScheduler/lib +Features: +- FileSystemWatcher jobs configurable through HTTP web client +- Cron jobs configurable through HTTP web client +- Both subsystems run concurrently and share the IMS API client/session +- Unlimited inArgs per job +- Optional file move after successful customFunction +- Watcher Created/Changed/Renamed selection, recursion and debounce +- Live watcher reload after saving/deleting configuration +- HTTP Basic Authentication; default admin/admin; configurable in App.config diff --git a/FileinterfaceCronScheduler.sln b/FileinterfaceCronScheduler.sln new file mode 100644 index 0000000..9d0d4d3 --- /dev/null +++ b/FileinterfaceCronScheduler.sln @@ -0,0 +1,21 @@ +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.0.31903.59 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FileinterfaceCronScheduler", "FileinterfaceCronScheduler\FileinterfaceCronScheduler.csproj", "{D7E916B9-969E-4CFD-B6A3-527B7091D45A}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {D7E916B9-969E-4CFD-B6A3-527B7091D45A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D7E916B9-969E-4CFD-B6A3-527B7091D45A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D7E916B9-969E-4CFD-B6A3-527B7091D45A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D7E916B9-969E-4CFD-B6A3-527B7091D45A}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/FileinterfaceCronScheduler/App.config b/FileinterfaceCronScheduler/App.config new file mode 100644 index 0000000..0a719bc --- /dev/null +++ b/FileinterfaceCronScheduler/App.config @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/FileinterfaceCronScheduler/FileinterfaceCronScheduler.csproj b/FileinterfaceCronScheduler/FileinterfaceCronScheduler.csproj new file mode 100644 index 0000000..b287fda --- /dev/null +++ b/FileinterfaceCronScheduler/FileinterfaceCronScheduler.csproj @@ -0,0 +1,96 @@ + + + + + Debug + AnyCPU + {D7E916B9-969E-4CFD-B6A3-527B7091D45A} + Exe + FileinterfaceCronScheduler + FileinterfaceCronScheduler + v4.8 + 512 + true + true + 7.3 + + + x86 + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + false + + + x86 + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + false + + + FileinterfaceCronScheduler.Program + + + false + + + + lib\IMSApiDotNet.dll + true + + + + + + + + + + + + Component + + + + + + + + + + + + + + + + + + + + + + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + + + + + \ No newline at end of file diff --git a/FileinterfaceCronScheduler/FileinterfaceCronSchedulerService.cs b/FileinterfaceCronScheduler/FileinterfaceCronSchedulerService.cs new file mode 100644 index 0000000..40444e4 --- /dev/null +++ b/FileinterfaceCronScheduler/FileinterfaceCronSchedulerService.cs @@ -0,0 +1,46 @@ +using System; +using System.ServiceProcess; +using FileInterface.Scheduler; + +namespace FileinterfaceCronScheduler +{ + public sealed class FileinterfaceCronSchedulerService : ServiceBase + { + private SchedulerRuntime _runtime; + + public FileinterfaceCronSchedulerService() + { + ServiceName = "FileinterfaceCronScheduler"; + CanStop = true; + CanPauseAndContinue = false; + AutoLog = true; + } + + protected override void OnStart(string[] args) + { + try + { + _runtime = RuntimeFactory.Create(); + _runtime.Start(); + } + catch + { + if (_runtime != null) + { + _runtime.Dispose(); + _runtime = null; + } + throw; + } + } + + protected override void OnStop() + { + if (_runtime != null) + { + _runtime.Dispose(); + _runtime = null; + } + } + } +} diff --git a/FileinterfaceCronScheduler/IMSApi/ImsApiClient.cs b/FileinterfaceCronScheduler/IMSApi/ImsApiClient.cs new file mode 100644 index 0000000..27fba7e --- /dev/null +++ b/FileinterfaceCronScheduler/IMSApi/ImsApiClient.cs @@ -0,0 +1,229 @@ +using System; +using System.Configuration; +using System.Diagnostics; +using System.IO; +using System.Reflection; +using FileInterface.Scheduler; +using com.itac.mes.imsapi.client.dotnet; +using com.itac.mes.imsapi.domain.container; + +namespace FileinterfaceCronScheduler.IMSApi +{ + /// + /// Initializes IMSApiDotNet, logs in once and exposes customFunction to the scheduler. + /// Configuration is read from App.config. + /// + public sealed class ImsApiClient : ICustomFunctionInvoker, IDisposable + { + private readonly object _sync = new object(); + private readonly object _callSync = new object(); + private IIMSApiDotNet _imsapi; + private IMSApiSessionContextStruct _sessionContext; + private bool _initialized; + private bool _disposed; + private readonly bool _serializeCalls = String.Equals(ConfigurationManager.AppSettings["IMS.SerializeCalls"], "true", StringComparison.OrdinalIgnoreCase); + + public bool IsInitialized { get { lock (_sync) return _initialized; } } + public bool IsLoggedIn { get { lock (_sync) return _sessionContext != null; } } + public long SessionId { get { lock (_sync) return _sessionContext == null ? 0L : _sessionContext.sessionId; } } + + public void Connect() + { + lock (_sync) + { + ThrowIfDisposed(); + EnsureInitializedNoLock(); + EnsureLoggedInNoLock(); + } + } + + private void EnsureInitializedNoLock() + { + if (_initialized && _imsapi != null) + return; + + string appId = Required("IMS.AppID", "AppID"); + string serverUrl = Required("IMS.ServerUrl", "Server_URL"); + string baseDir = AppDomain.CurrentDomain.BaseDirectory; + string propDir = Get("IMS.PropertyDirectory", baseDir); + if (!Path.IsPathRooted(propDir)) + propDir = Path.Combine(baseDir, propDir); + + Directory.CreateDirectory(propDir); + string ihas = Path.Combine(propDir, "ihas.properties"); + if (!File.Exists(ihas)) + File.WriteAllText(ihas, String.Empty); + + Trace.TraceInformation("Initializing IMSApiDotNet. AppID={0}, Server={1}, PropDir={2}", appId, serverUrl, propDir); + + IMSApiDotNet.setProperty("itac.appid", appId); + IMSApiDotNet.setProperty("itac.artes.clusternodes", serverUrl); + IMSApiDotNet.setProperty("itac.propdir", propDir); + + _imsapi = IMSApiDotNet.loadLibrary(); + if (_imsapi == null) + throw new InvalidOperationException("IMSApiDotNet.loadLibrary() returned null."); + + string version; + int versionResult = _imsapi.imsapiGetLibraryVersion(out version); + if (versionResult == IMSApiDotNetConstants.RES_OK) + Trace.TraceInformation("IMSApiDotNet library version: " + version); + else + Trace.TraceWarning("imsapiGetLibraryVersion returned " + versionResult); + + int initResult = _imsapi.imsapiInit(); + if (initResult != IMSApiDotNetConstants.RES_OK) + throw new InvalidOperationException("imsapiInit failed. Result=" + initResult); + + _initialized = true; + Trace.TraceInformation("IMSApiDotNet initialized successfully."); + } + + private void EnsureLoggedInNoLock() + { + if (_sessionContext != null) + return; + + string station = Required("IMS.StationNumber", "StationNr"); + // Original FileInterface contains the historic typo 'CleintNO'. Both names are supported. + string client = FirstNonEmpty( + ConfigurationManager.AppSettings["IMS.ClientNumber"], + ConfigurationManager.AppSettings["ClientNO"], + ConfigurationManager.AppSettings["CleintNO"]); + if (String.IsNullOrWhiteSpace(client)) + throw new ConfigurationErrorsException("Missing IMS client number. Configure IMS.ClientNumber (or legacy CleintNO)."); + + string registrationType = Get("IMS.RegistrationType", "S"); + var validation = new IMSApiSessionValidationStruct + { + stationNumber = station, + client = client, + registrationType = registrationType + }; + + Trace.TraceInformation("Calling regLogin(). Station={0}, Client={1}, RegistrationType={2}", station, client, registrationType); + + IMSApiSessionContextStruct newSessionContext; + int loginResult = _imsapi.regLogin(validation, out newSessionContext); + if (loginResult != IMSApiDotNetConstants.RES_OK || newSessionContext == null) + throw new InvalidOperationException("IMS regLogin failed. Result=" + loginResult); + + _sessionContext = newSessionContext; + Trace.TraceInformation("IMS login successful. SessionId=" + _sessionContext.sessionId); + } + + public CustomFunctionCallResult Invoke(string customFunctionName, string[] inArgs) + { + if (String.IsNullOrWhiteSpace(customFunctionName)) + return CustomFunctionCallResult.Fail("CustomFunction is empty."); + + try + { + IIMSApiDotNet api; + IMSApiSessionContextStruct session; + + // Only connection/login state is protected. The actual CustomFunction call + // can run concurrently for independent cron jobs. + lock (_sync) + { + ThrowIfDisposed(); + EnsureInitializedNoLock(); + EnsureLoggedInNoLock(); + api = _imsapi; + session = _sessionContext; + } + + if (_serializeCalls) + { + lock (_callSync) + return InvokeCore(api, session, customFunctionName, inArgs); + } + + return InvokeCore(api, session, customFunctionName, inArgs); + } + catch (Exception ex) + { + Trace.TraceError("IMS customFunction failed: " + ex); + return CustomFunctionCallResult.Fail(ex.ToString()); + } + } + + private static CustomFunctionCallResult InvokeCore( + IIMSApiDotNet api, + IMSApiSessionContextStruct session, + string customFunctionName, + string[] inArgs) + { + string[] outArgs; + string customErrorString; + int result = api.customFunction( + session, + customFunctionName, + inArgs ?? new string[0], + out outArgs, + out customErrorString); + + string outText = outArgs == null || outArgs.Length == 0 + ? String.Empty + : String.Join(" | ", outArgs); + + if (result != IMSApiDotNetConstants.RES_OK) + { + return CustomFunctionCallResult.Fail( + "IMS result=" + result + + (String.IsNullOrWhiteSpace(customErrorString) ? String.Empty : "; Error=" + customErrorString) + + (String.IsNullOrWhiteSpace(outText) ? String.Empty : "; OutArgs=" + outText)); + } + + return CustomFunctionCallResult.Ok( + "IMS result=0" + + (String.IsNullOrWhiteSpace(customErrorString) ? String.Empty : "; Info=" + customErrorString) + + (String.IsNullOrWhiteSpace(outText) ? String.Empty : "; OutArgs=" + outText)); + } + + public void Dispose() + { + lock (_sync) + { + if (_disposed) return; + _disposed = true; + + // The FileInterface source currently has no regLogout/imsapiFinish call. + // We therefore release managed references here. If the deployed IMSAPI + // version exposes an explicit logout method, it can safely be added here. + _sessionContext = null; + _imsapi = null; + _initialized = false; + } + } + + private static string Get(string key, string fallback) + { + string value = ConfigurationManager.AppSettings[key]; + return String.IsNullOrWhiteSpace(value) ? fallback : value.Trim(); + } + + private static string Required(string preferredKey, string legacyKey) + { + string value = FirstNonEmpty( + ConfigurationManager.AppSettings[preferredKey], + ConfigurationManager.AppSettings[legacyKey]); + if (String.IsNullOrWhiteSpace(value)) + throw new ConfigurationErrorsException("Missing setting '" + preferredKey + "' (legacy: '" + legacyKey + "')."); + return value.Trim(); + } + + private static string FirstNonEmpty(params string[] values) + { + if (values == null) return null; + foreach (string value in values) + if (!String.IsNullOrWhiteSpace(value)) return value.Trim(); + return null; + } + + private void ThrowIfDisposed() + { + if (_disposed) throw new ObjectDisposedException(GetType().FullName); + } + } +} diff --git a/FileinterfaceCronScheduler/ImsCustomFunctionInvoker.cs b/FileinterfaceCronScheduler/ImsCustomFunctionInvoker.cs new file mode 100644 index 0000000..15931db --- /dev/null +++ b/FileinterfaceCronScheduler/ImsCustomFunctionInvoker.cs @@ -0,0 +1,37 @@ +using System; +using FileInterface.Scheduler; +using FileinterfaceCronScheduler.IMSApi; + +namespace FileinterfaceCronScheduler +{ + /// + /// Thin scheduler adapter around the real IMSApiClient. + /// + public sealed class ImsCustomFunctionInvoker : ICustomFunctionInvoker, IDisposable + { + private readonly ImsApiClient _client; + + public ImsCustomFunctionInvoker() + { + _client = new ImsApiClient(); + } + + public void Connect() + { + _client.Connect(); + } + + public bool IsLoggedIn { get { return _client.IsLoggedIn; } } + public long SessionId { get { return _client.SessionId; } } + + public CustomFunctionCallResult Invoke(string customFunctionName, string[] inArgs) + { + return _client.Invoke(customFunctionName, inArgs); + } + + public void Dispose() + { + _client.Dispose(); + } + } +} diff --git a/FileinterfaceCronScheduler/Program.cs b/FileinterfaceCronScheduler/Program.cs new file mode 100644 index 0000000..905bf3e --- /dev/null +++ b/FileinterfaceCronScheduler/Program.cs @@ -0,0 +1,44 @@ +using System; +using System.Linq; +using System.ServiceProcess; +using System.Threading; + +namespace FileinterfaceCronScheduler +{ + internal static class Program + { + private static int Main(string[] args) + { + bool forceService = args.Any(a => String.Equals(a, "--service", StringComparison.OrdinalIgnoreCase)); + + if (!Environment.UserInteractive || forceService) + { + ServiceBase.Run(new FileinterfaceCronSchedulerService()); + return 0; + } + + Console.Title = "FileInterface Watcher + CronScheduler"; + Console.WriteLine("FileInterface Watcher + CronScheduler"); + Console.WriteLine("===================================="); + Console.WriteLine("Konsole/Debug-Modus. Mit --service als Windows-Dienst starten."); + Console.WriteLine(); + + using (var runtime = RuntimeFactory.Create()) + using (var quit = new ManualResetEvent(false)) + { + Console.CancelKeyPress += (s, e) => + { + e.Cancel = true; + quit.Set(); + }; + + runtime.Start(); + Console.WriteLine("FileSystemWatcher, CronScheduler und Webinterface gestartet."); + Console.WriteLine("Beenden mit Strg+C."); + quit.WaitOne(); + } + + return 0; + } + } +} diff --git a/FileinterfaceCronScheduler/Properties/AssemblyInfo.cs b/FileinterfaceCronScheduler/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..1d35219 --- /dev/null +++ b/FileinterfaceCronScheduler/Properties/AssemblyInfo.cs @@ -0,0 +1,15 @@ +using System.Reflection; +using System.Runtime.InteropServices; + +[assembly: AssemblyTitle("FileinterfaceCronScheduler")] +[assembly: AssemblyDescription("Cron-based FileInterface for iTAC IMS CustomFunctions")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("FileinterfaceCronScheduler")] +[assembly: AssemblyCopyright("")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] +[assembly: ComVisible(false)] +[assembly: Guid("e0d85515-96cb-4f8c-97c3-9ec7079780fc")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/FileinterfaceCronScheduler/RuntimeFactory.cs b/FileinterfaceCronScheduler/RuntimeFactory.cs new file mode 100644 index 0000000..afd6fdf --- /dev/null +++ b/FileinterfaceCronScheduler/RuntimeFactory.cs @@ -0,0 +1,47 @@ +using System; +using System.Configuration; +using System.IO; +using FileInterface.Scheduler; + +namespace FileinterfaceCronScheduler +{ + internal static class RuntimeFactory + { + public static SchedulerRuntime Create() + { + string baseDir = AppDomain.CurrentDomain.BaseDirectory; + string cronConfigFile = Get("Scheduler.ConfigFile", "cronjobs.json"); + string watcherConfigFile = Get("Watcher.ConfigFile", "watcherjobs.json"); + + if (!Path.IsPathRooted(cronConfigFile)) cronConfigFile = Path.Combine(baseDir, cronConfigFile); + if (!Path.IsPathRooted(watcherConfigFile)) watcherConfigFile = Path.Combine(baseDir, watcherConfigFile); + + var options = new SchedulerOptions + { + ConfigFile = cronConfigFile, + WatcherConfigFile = watcherConfigFile, + WebPrefix = Get("Scheduler.WebPrefix", "http://127.0.0.1:8095/"), + WebUser = Get("Scheduler.WebUser", "admin"), + WebPassword = Get("Scheduler.WebPassword", "admin") + }; + + var invoker = new ImsCustomFunctionInvoker(); + try + { + invoker.Connect(); + return new SchedulerRuntime(invoker, options, invoker); + } + catch + { + invoker.Dispose(); + throw; + } + } + + private static string Get(string key, string fallback) + { + string value = ConfigurationManager.AppSettings[key]; + return String.IsNullOrWhiteSpace(value) ? fallback : value.Trim(); + } + } +} diff --git a/FileinterfaceCronScheduler/Scheduler/CronExpression.cs b/FileinterfaceCronScheduler/Scheduler/CronExpression.cs new file mode 100644 index 0000000..348cfa9 --- /dev/null +++ b/FileinterfaceCronScheduler/Scheduler/CronExpression.cs @@ -0,0 +1,131 @@ +using System; +using System.Collections.Generic; +using System.Globalization; + +namespace FileInterface.Scheduler +{ + /// + /// Standard 5-field cron expression: minute hour day-of-month month day-of-week. + /// Supported: *, */n, a,b,c, a-b, a-b/n. Day-of-week: 0 or 7 = Sunday. + /// + public sealed class CronExpression + { + private readonly HashSet _minutes; + private readonly HashSet _hours; + private readonly HashSet _days; + private readonly HashSet _months; + private readonly HashSet _daysOfWeek; + + public string Expression { get; private set; } + + private CronExpression(string expression, + HashSet minutes, + HashSet hours, + HashSet days, + HashSet months, + HashSet daysOfWeek) + { + Expression = expression; + _minutes = minutes; + _hours = hours; + _days = days; + _months = months; + _daysOfWeek = daysOfWeek; + } + + public static CronExpression Parse(string expression) + { + if (String.IsNullOrWhiteSpace(expression)) + throw new FormatException("Cron expression is empty."); + + string[] parts = expression.Trim().Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); + if (parts.Length != 5) + throw new FormatException("Cron must contain exactly 5 fields: minute hour day month day-of-week."); + + return new CronExpression( + expression.Trim(), + ParseField(parts[0], 0, 59, false), + ParseField(parts[1], 0, 23, false), + ParseField(parts[2], 1, 31, false), + ParseField(parts[3], 1, 12, false), + ParseField(parts[4], 0, 7, true)); + } + + public bool IsMatch(DateTime localTime) + { + int dow = (int)localTime.DayOfWeek; + return _minutes.Contains(localTime.Minute) + && _hours.Contains(localTime.Hour) + && _days.Contains(localTime.Day) + && _months.Contains(localTime.Month) + && _daysOfWeek.Contains(dow); + } + + private static HashSet ParseField(string text, int min, int max, bool normalizeSunday) + { + var result = new HashSet(); + string[] segments = text.Split(','); + foreach (string rawSegment in segments) + { + string segment = rawSegment.Trim(); + if (segment.Length == 0) + throw new FormatException("Empty cron field segment."); + + int step = 1; + string rangePart = segment; + int slash = segment.IndexOf('/'); + if (slash >= 0) + { + rangePart = segment.Substring(0, slash); + string stepText = segment.Substring(slash + 1); + if (!Int32.TryParse(stepText, NumberStyles.Integer, CultureInfo.InvariantCulture, out step) || step <= 0) + throw new FormatException("Invalid cron step: " + segment); + } + + int start; + int end; + if (rangePart == "*") + { + start = min; + end = max; + } + else + { + int dash = rangePart.IndexOf('-'); + if (dash >= 0) + { + start = ParseNumber(rangePart.Substring(0, dash), min, max); + end = ParseNumber(rangePart.Substring(dash + 1), min, max); + if (start > end) + throw new FormatException("Cron range start is greater than end: " + segment); + } + else + { + start = ParseNumber(rangePart, min, max); + end = start; + } + } + + for (int value = start; value <= end; value += step) + { + int normalized = normalizeSunday && value == 7 ? 0 : value; + result.Add(normalized); + } + } + + if (result.Count == 0) + throw new FormatException("Cron field produced no values: " + text); + return result; + } + + private static int ParseNumber(string text, int min, int max) + { + int value; + if (!Int32.TryParse(text, NumberStyles.Integer, CultureInfo.InvariantCulture, out value)) + throw new FormatException("Invalid cron number: " + text); + if (value < min || value > max) + throw new FormatException("Cron value out of range: " + value + " (allowed " + min + "-" + max + ")"); + return value; + } + } +} diff --git a/FileinterfaceCronScheduler/Scheduler/CronJobConfig.cs b/FileinterfaceCronScheduler/Scheduler/CronJobConfig.cs new file mode 100644 index 0000000..e50670d --- /dev/null +++ b/FileinterfaceCronScheduler/Scheduler/CronJobConfig.cs @@ -0,0 +1,69 @@ +using System; +using System.Collections.Generic; + +namespace FileInterface.Scheduler +{ + public sealed class CronJobConfig + { + public string Id { get; set; } + public string Name { get; set; } + public bool Enabled { get; set; } + public string Cron { get; set; } + + // File processing. If CallOnceWithoutFile=true, SourceDirectory/SearchPattern are ignored. + public bool CallOnceWithoutFile { get; set; } + public string SourceDirectory { get; set; } + public string SearchPattern { get; set; } + public bool IncludeSubdirectories { get; set; } + + // Existing FileInterface-style preprocessing. + public bool RemoveEmptyLines { get; set; } + public string JoinSeparator { get; set; } + + // iTAC CustomFunction. + public string CustomFunction { get; set; } + public List InArgs { get; set; } + + // File handling after successful CF call. + public bool MoveFileAfterSuccess { get; set; } + public string MoveTargetDirectory { get; set; } + public bool OverwriteTargetFile { get; set; } + + public CronJobConfig() + { + Id = Guid.NewGuid().ToString("N"); + Name = "New job"; + Enabled = true; + Cron = "*/5 * * * *"; + CallOnceWithoutFile = false; + SourceDirectory = ""; + SearchPattern = "*.*"; + IncludeSubdirectories = false; + RemoveEmptyLines = true; + JoinSeparator = ";"; + CustomFunction = ""; + InArgs = new List(); + MoveFileAfterSuccess = false; + MoveTargetDirectory = ""; + OverwriteTargetFile = false; + } + } + + public sealed class SchedulerOptions + { + public string ConfigFile { get; set; } + public string WatcherConfigFile { get; set; } + public string WebPrefix { get; set; } + public string WebUser { get; set; } + public string WebPassword { get; set; } + + public SchedulerOptions() + { + ConfigFile = "cronjobs.json"; + WatcherConfigFile = "watcherjobs.json"; + WebPrefix = "http://127.0.0.1:8095/"; + WebUser = ""; + WebPassword = ""; + } + } +} diff --git a/FileinterfaceCronScheduler/Scheduler/CronJobExecutor.cs b/FileinterfaceCronScheduler/Scheduler/CronJobExecutor.cs new file mode 100644 index 0000000..a0be2bb --- /dev/null +++ b/FileinterfaceCronScheduler/Scheduler/CronJobExecutor.cs @@ -0,0 +1,145 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; + +namespace FileInterface.Scheduler +{ + public sealed class CronJobExecutor + { + private readonly ICustomFunctionInvoker _invoker; + private readonly JobLog _log; + + public CronJobExecutor(ICustomFunctionInvoker invoker, JobLog log) + { + _invoker = invoker; + _log = log; + } + + public void Execute(CronJobConfig job) + { + if (job.CallOnceWithoutFile) + { + ExecuteSingle(job, null); + return; + } + + if (!Directory.Exists(job.SourceDirectory)) + { + _log.Error(job, "Source directory does not exist: " + job.SourceDirectory); + return; + } + + SearchOption option = job.IncludeSubdirectories ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly; + string[] files; + try + { + files = Directory.GetFiles(job.SourceDirectory, String.IsNullOrWhiteSpace(job.SearchPattern) ? "*.*" : job.SearchPattern, option) + .OrderBy(f => f, StringComparer.OrdinalIgnoreCase) + .ToArray(); + } + catch (Exception ex) + { + _log.Error(job, "Cannot enumerate source files: " + ex.Message); + return; + } + + _log.Info(job, "Found " + files.Length + " file(s)."); + foreach (string file in files) + { + try { ExecuteSingle(job, file); } + catch (Exception ex) { _log.Error(job, "File failed: " + file + " - " + ex.Message); } + } + } + + private void ExecuteSingle(CronJobConfig job, string file) + { + string rawContent = ""; + string processedContent = ""; + + if (file != null) + { + // Opening with FileShare.ReadWrite prevents common producer/consumer lock issues. + using (var stream = new FileStream(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) + using (var reader = new StreamReader(stream, Encoding.UTF8, true)) + rawContent = reader.ReadToEnd(); + + processedContent = ProcessContent(rawContent, job.RemoveEmptyLines, job.JoinSeparator); + } + + string[] inArgs = (job.InArgs ?? new List()) + .Select(arg => Expand(arg, job, file, rawContent, processedContent)) + .ToArray(); + + _log.Info(job, "Calling CustomFunction '" + job.CustomFunction + "' with " + inArgs.Length + " inArg(s)" + (file == null ? "." : " for " + Path.GetFileName(file) + ".")); + CustomFunctionCallResult result = _invoker.Invoke(job.CustomFunction, inArgs); + if (result == null) result = CustomFunctionCallResult.Fail("Invoker returned null."); + + if (!result.Success) + { + _log.Error(job, "CustomFunction failed: " + result.Message); + return; + } + + _log.Info(job, "CustomFunction succeeded: " + result.Message); + if (file != null && job.MoveFileAfterSuccess) + { + string movedTo = MoveProcessedFile(file, job.MoveTargetDirectory, job.OverwriteTargetFile); + _log.Info(job, "Moved file to: " + movedTo); + } + } + + private static string ProcessContent(string text, bool removeEmptyLines, string separator) + { + if (!removeEmptyLines) return text ?? ""; + string[] lines = (text ?? "").Replace("\r\n", "\n").Replace('\r', '\n').Split('\n'); + return String.Join(separator ?? ";", lines.Where(l => !String.IsNullOrWhiteSpace(l)).Select(l => l.Trim())); + } + + private static string Expand(string template, CronJobConfig job, string file, string rawContent, string processedContent) + { + string value = template ?? ""; + string fullPath = file ?? ""; + string fileName = file == null ? "" : Path.GetFileName(file); + string extension = file == null ? "" : Path.GetExtension(file); + string directory = file == null ? "" : Path.GetDirectoryName(file); + + return value + .Replace("{{CONTENT}}", processedContent ?? "") + .Replace("{{RAW_CONTENT}}", rawContent ?? "") + .Replace("{{FILE_NAME}}", fileName ?? "") + .Replace("{{FILE_PATH}}", fullPath) + .Replace("{{FILE_DIR}}", directory ?? "") + .Replace("{{FILE_EXT}}", extension ?? "") + .Replace("{{JOB_NAME}}", job.Name ?? "") + .Replace("{{NOW}}", DateTime.Now.ToString("yyyy-MM-ddTHH:mm:ss.fffK")); + } + + private static string MoveProcessedFile(string source, string targetDirectory, bool overwrite) + { + Directory.CreateDirectory(targetDirectory); + string target = Path.Combine(targetDirectory, Path.GetFileName(source)); + + if (File.Exists(target)) + { + if (overwrite) File.Delete(target); + else + { + string name = Path.GetFileNameWithoutExtension(source); + string ext = Path.GetExtension(source); + target = Path.Combine(targetDirectory, name + "_" + DateTime.Now.ToString("yyyyMMdd_HHmmss_fff") + ext); + int i = 1; + while (File.Exists(target)) + { + target = Path.Combine(targetDirectory, name + "_" + DateTime.Now.ToString("yyyyMMdd_HHmmss_fff") + "_" + i + ext); + i++; + } + } + } + + File.Move(source, target); + return target; + } + } +} diff --git a/FileinterfaceCronScheduler/Scheduler/CronJobRepository.cs b/FileinterfaceCronScheduler/Scheduler/CronJobRepository.cs new file mode 100644 index 0000000..305dd72 --- /dev/null +++ b/FileinterfaceCronScheduler/Scheduler/CronJobRepository.cs @@ -0,0 +1,120 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Web.Script.Serialization; + +namespace FileInterface.Scheduler +{ + public sealed class CronJobRepository + { + private readonly object _sync = new object(); + private readonly string _fileName; + private readonly JavaScriptSerializer _serializer = new JavaScriptSerializer(); + private List _jobs; + + public CronJobRepository(string fileName) + { + _fileName = Path.GetFullPath(fileName); + _serializer.MaxJsonLength = Int32.MaxValue; + _jobs = LoadInternal(); + } + + public IList GetAll() + { + lock (_sync) + { + // Clone through JSON so callers cannot mutate repository state behind our lock. + return Clone(_jobs); + } + } + + public CronJobConfig GetById(string id) + { + lock (_sync) + { + CronJobConfig job = _jobs.FirstOrDefault(j => String.Equals(j.Id, id, StringComparison.OrdinalIgnoreCase)); + return job == null ? null : Clone(job); + } + } + + public CronJobConfig Save(CronJobConfig job) + { + if (job == null) throw new ArgumentNullException("job"); + Validate(job); + + lock (_sync) + { + if (String.IsNullOrWhiteSpace(job.Id)) + job.Id = Guid.NewGuid().ToString("N"); + + int index = _jobs.FindIndex(j => String.Equals(j.Id, job.Id, StringComparison.OrdinalIgnoreCase)); + if (index >= 0) _jobs[index] = Clone(job); + else _jobs.Add(Clone(job)); + + SaveInternal(); + return Clone(job); + } + } + + public bool Delete(string id) + { + lock (_sync) + { + int count = _jobs.RemoveAll(j => String.Equals(j.Id, id, StringComparison.OrdinalIgnoreCase)); + if (count > 0) SaveInternal(); + return count > 0; + } + } + + private List LoadInternal() + { + if (!File.Exists(_fileName)) return new List(); + string json = File.ReadAllText(_fileName, Encoding.UTF8); + if (String.IsNullOrWhiteSpace(json)) return new List(); + return _serializer.Deserialize>(json) ?? new List(); + } + + private void SaveInternal() + { + string dir = Path.GetDirectoryName(_fileName); + if (!String.IsNullOrWhiteSpace(dir)) Directory.CreateDirectory(dir); + + string json = _serializer.Serialize(_jobs); + string tmp = _fileName + ".tmp"; + File.WriteAllText(tmp, json, new UTF8Encoding(false)); + + if (File.Exists(_fileName)) + { + string backup = _fileName + ".bak"; + try { File.Replace(tmp, _fileName, backup, true); } + catch + { + File.Delete(_fileName); + File.Move(tmp, _fileName); + } + } + else File.Move(tmp, _fileName); + } + + private static void Validate(CronJobConfig job) + { + if (String.IsNullOrWhiteSpace(job.Name)) throw new InvalidOperationException("Name is required."); + CronExpression.Parse(job.Cron); + if (String.IsNullOrWhiteSpace(job.CustomFunction)) throw new InvalidOperationException("CustomFunction is required."); + if (!job.CallOnceWithoutFile && String.IsNullOrWhiteSpace(job.SourceDirectory)) + throw new InvalidOperationException("SourceDirectory is required for file jobs."); + if (job.MoveFileAfterSuccess && String.IsNullOrWhiteSpace(job.MoveTargetDirectory)) + throw new InvalidOperationException("MoveTargetDirectory is required when MoveFileAfterSuccess=true."); + if (job.InArgs == null) job.InArgs = new List(); + if (String.IsNullOrWhiteSpace(job.SearchPattern)) job.SearchPattern = "*.*"; + if (job.JoinSeparator == null) job.JoinSeparator = ";"; + } + + private T Clone(T value) + { + return _serializer.Deserialize(_serializer.Serialize(value)); + } + } +} diff --git a/FileinterfaceCronScheduler/Scheduler/CronScheduler.cs b/FileinterfaceCronScheduler/Scheduler/CronScheduler.cs new file mode 100644 index 0000000..29e2154 --- /dev/null +++ b/FileinterfaceCronScheduler/Scheduler/CronScheduler.cs @@ -0,0 +1,106 @@ +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; + +namespace FileInterface.Scheduler +{ + public sealed class CronScheduler : IDisposable + { + private readonly CronJobRepository _repository; + private readonly CronJobExecutor _executor; + private readonly JobLog _log; + private readonly ConcurrentDictionary _running = new ConcurrentDictionary(StringComparer.OrdinalIgnoreCase); + private readonly ConcurrentDictionary _lastMinuteRun = new ConcurrentDictionary(StringComparer.OrdinalIgnoreCase); + private Timer _timer; + private int _checking; + + public CronScheduler(CronJobRepository repository, CronJobExecutor executor, JobLog log) + { + _repository = repository; + _executor = executor; + _log = log; + } + + public void Start() + { + if (_timer != null) return; + _timer = new Timer(CheckDueJobs, null, TimeSpan.Zero, TimeSpan.FromSeconds(5)); + } + + public bool RunNow(string jobId) + { + CronJobConfig job = _repository.GetById(jobId); + if (job == null) return false; + QueueExecution(job, "manual"); + return true; + } + + public IList GetRunningJobIds() + { + return new List(_running.Keys); + } + + private void CheckDueJobs(object state) + { + if (Interlocked.Exchange(ref _checking, 1) == 1) return; + try + { + DateTime now = DateTime.Now; + string minuteStamp = now.ToString("yyyyMMddHHmm"); + foreach (CronJobConfig job in _repository.GetAll()) + { + if (!job.Enabled) continue; + try + { + CronExpression cron = CronExpression.Parse(job.Cron); + if (!cron.IsMatch(now)) continue; + + string previous; + if (_lastMinuteRun.TryGetValue(job.Id, out previous) && previous == minuteStamp) continue; + _lastMinuteRun[job.Id] = minuteStamp; + QueueExecution(job, "cron " + job.Cron); + } + catch (Exception ex) + { + _log.Error(job, "Invalid cron/configuration: " + ex.Message); + } + } + } + finally { Interlocked.Exchange(ref _checking, 0); } + } + + private void QueueExecution(CronJobConfig job, string reason) + { + byte ignored; + if (!_running.TryAdd(job.Id, 0)) + { + _log.Info(job, "Skipped " + reason + " start because this job is still running."); + return; + } + + Task.Run(() => + { + try + { + _log.Info(job, "Job started (" + reason + ")."); + _executor.Execute(job); + _log.Info(job, "Job finished."); + } + catch (Exception ex) + { + _log.Error(job, "Job crashed: " + ex); + } + finally { _running.TryRemove(job.Id, out ignored); } + }); + } + + public void Dispose() + { + Timer timer = _timer; + _timer = null; + if (timer != null) timer.Dispose(); + } + } +} diff --git a/FileinterfaceCronScheduler/Scheduler/CustomFunctionInvoker.cs b/FileinterfaceCronScheduler/Scheduler/CustomFunctionInvoker.cs new file mode 100644 index 0000000..56fd6cb --- /dev/null +++ b/FileinterfaceCronScheduler/Scheduler/CustomFunctionInvoker.cs @@ -0,0 +1,45 @@ +using System; + +namespace FileInterface.Scheduler +{ + public sealed class CustomFunctionCallResult + { + public bool Success { get; set; } + public string Message { get; set; } + + public static CustomFunctionCallResult Ok(string message) + { + return new CustomFunctionCallResult { Success = true, Message = message ?? "OK" }; + } + + public static CustomFunctionCallResult Fail(string message) + { + return new CustomFunctionCallResult { Success = false, Message = message ?? "CustomFunction failed" }; + } + } + + public interface ICustomFunctionInvoker + { + CustomFunctionCallResult Invoke(string customFunctionName, string[] inArgs); + } + + /// + /// Lets the existing FileInterface IMS code remain untouched. Wire the current + /// IMS CustomFunction call into this delegate in Program.cs / service startup. + /// + public sealed class DelegateCustomFunctionInvoker : ICustomFunctionInvoker + { + private readonly Func _handler; + + public DelegateCustomFunctionInvoker(Func handler) + { + if (handler == null) throw new ArgumentNullException("handler"); + _handler = handler; + } + + public CustomFunctionCallResult Invoke(string customFunctionName, string[] inArgs) + { + return _handler(customFunctionName, inArgs); + } + } +} diff --git a/FileinterfaceCronScheduler/Scheduler/FileSystemWatcherManager.cs b/FileinterfaceCronScheduler/Scheduler/FileSystemWatcherManager.cs new file mode 100644 index 0000000..3774a93 --- /dev/null +++ b/FileinterfaceCronScheduler/Scheduler/FileSystemWatcherManager.cs @@ -0,0 +1,172 @@ +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Threading.Tasks; + +namespace FileInterface.Scheduler +{ + public sealed class FileSystemWatcherManager : IDisposable + { + private sealed class ActiveWatcher : IDisposable + { + public WatcherJobConfig Job; + public FileSystemWatcher Watcher; + public void Dispose() { if (Watcher != null) { Watcher.EnableRaisingEvents = false; Watcher.Dispose(); } } + } + + private readonly object _sync = new object(); + private readonly WatcherJobRepository _repository; + private readonly WatcherJobExecutor _executor; + private readonly JobLog _log; + private readonly Dictionary _watchers = new Dictionary(StringComparer.OrdinalIgnoreCase); + private readonly ConcurrentDictionary _lastEvents = new ConcurrentDictionary(StringComparer.OrdinalIgnoreCase); + private readonly ConcurrentDictionary _runningFiles = new ConcurrentDictionary(StringComparer.OrdinalIgnoreCase); + private bool _disposed; + + public FileSystemWatcherManager(WatcherJobRepository repository, WatcherJobExecutor executor, JobLog log) + { + _repository = repository; + _executor = executor; + _log = log; + } + + public void Start() { Reload(); } + + public void Reload() + { + lock (_sync) + { + ThrowIfDisposed(); + foreach (ActiveWatcher old in _watchers.Values) old.Dispose(); + _watchers.Clear(); + + foreach (WatcherJobConfig job in _repository.GetAll()) + { + if (!job.Enabled) continue; + try + { + if (!Directory.Exists(job.SourceDirectory)) + { + _log.Error(job, "Watcher source directory does not exist: " + job.SourceDirectory); + continue; + } + + var fsw = new FileSystemWatcher(job.SourceDirectory, String.IsNullOrWhiteSpace(job.SearchPattern) ? "*.*" : job.SearchPattern) + { + IncludeSubdirectories = job.IncludeSubdirectories, + NotifyFilter = NotifyFilters.FileName | NotifyFilters.LastWrite | NotifyFilters.Size | NotifyFilters.CreationTime, + EnableRaisingEvents = false + }; + + WatcherJobConfig captured = job; + if (job.WatchCreated) fsw.Created += (s, e) => OnFileEvent(captured, e.FullPath, "Created"); + if (job.WatchChanged) fsw.Changed += (s, e) => OnFileEvent(captured, e.FullPath, "Changed"); + if (job.WatchRenamed) fsw.Renamed += (s, e) => OnFileEvent(captured, e.FullPath, "Renamed"); + fsw.Error += (s, e) => _log.Error(captured, "FileSystemWatcher error: " + (e.GetException() == null ? "unknown" : e.GetException().Message)); + + var active = new ActiveWatcher { Job = job, Watcher = fsw }; + _watchers[job.Id] = active; + fsw.EnableRaisingEvents = true; + _log.Info(job, "FileSystemWatcher active: " + job.SourceDirectory + "\\" + job.SearchPattern); + } + catch (Exception ex) + { + _log.Error(job, "Cannot start FileSystemWatcher: " + ex.Message); + } + } + } + } + + public IList GetActiveWatcherIds() + { + lock (_sync) return _watchers.Keys.ToList(); + } + + public bool ProcessExistingNow(string watcherId) + { + WatcherJobConfig job = _repository.GetById(watcherId); + if (job == null) return false; + Task.Run(() => ProcessExisting(job)); + return true; + } + + private void ProcessExisting(WatcherJobConfig job) + { + if (!Directory.Exists(job.SourceDirectory)) + { + _log.Error(job, "Source directory does not exist: " + job.SourceDirectory); + return; + } + try + { + SearchOption option = job.IncludeSubdirectories ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly; + string[] files = Directory.GetFiles(job.SourceDirectory, String.IsNullOrWhiteSpace(job.SearchPattern) ? "*.*" : job.SearchPattern, option) + .OrderBy(f => f, StringComparer.OrdinalIgnoreCase).ToArray(); + _log.Info(job, "Manual watcher scan found " + files.Length + " file(s)."); + foreach (string file in files) QueueFile(job, file, "ManualScan", false); + } + catch (Exception ex) { _log.Error(job, "Manual watcher scan failed: " + ex.Message); } + } + + private void OnFileEvent(WatcherJobConfig job, string fullPath, string reason) + { + if (!job.Enabled || String.IsNullOrWhiteSpace(fullPath)) return; + if (IsMoveTarget(job, fullPath)) return; + QueueFile(job, fullPath, reason, true); + } + + private void QueueFile(WatcherJobConfig job, string fullPath, string reason, bool debounce) + { + string key = job.Id + "|" + fullPath; + DateTime now = DateTime.UtcNow; + if (debounce) + { + DateTime previous; + if (_lastEvents.TryGetValue(key, out previous) && (now - previous).TotalMilliseconds < Math.Max(0, job.DebounceMilliseconds)) + return; + _lastEvents[key] = now; + } + + byte ignored; + if (!_runningFiles.TryAdd(key, 0)) return; + Task.Run(() => + { + try + { + if (!File.Exists(fullPath)) return; + _log.Info(job, "File event queued: " + reason + " - " + fullPath); + _executor.ExecuteFile(job, fullPath, reason); + } + catch (Exception ex) { _log.Error(job, "Watcher processing failed for " + fullPath + ": " + ex); } + finally { _runningFiles.TryRemove(key, out ignored); } + }); + } + + private static bool IsMoveTarget(WatcherJobConfig job, string fullPath) + { + if (!job.MoveFileAfterSuccess || String.IsNullOrWhiteSpace(job.MoveTargetDirectory)) return false; + try + { + string file = Path.GetFullPath(fullPath).TrimEnd(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar) + Path.DirectorySeparatorChar; + string target = Path.GetFullPath(job.MoveTargetDirectory).TrimEnd(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar) + Path.DirectorySeparatorChar; + return file.StartsWith(target, StringComparison.OrdinalIgnoreCase); + } + catch { return false; } + } + + private void ThrowIfDisposed() { if (_disposed) throw new ObjectDisposedException(GetType().FullName); } + + public void Dispose() + { + lock (_sync) + { + if (_disposed) return; + _disposed = true; + foreach (ActiveWatcher w in _watchers.Values) w.Dispose(); + _watchers.Clear(); + } + } + } +} diff --git a/FileinterfaceCronScheduler/Scheduler/JobLog.cs b/FileinterfaceCronScheduler/Scheduler/JobLog.cs new file mode 100644 index 0000000..b2b885e --- /dev/null +++ b/FileinterfaceCronScheduler/Scheduler/JobLog.cs @@ -0,0 +1,60 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +namespace FileInterface.Scheduler +{ + public sealed class JobLogEntry + { + public DateTime Timestamp { get; set; } + public string JobType { get; set; } + public string JobId { get; set; } + public string JobName { get; set; } + public string Level { get; set; } + public string Message { get; set; } + } + + public sealed class JobLog + { + private readonly object _sync = new object(); + private readonly Queue _entries = new Queue(); + private readonly int _maxEntries; + + public JobLog(int maxEntries) + { + _maxEntries = Math.Max(100, maxEntries); + } + + public void Info(CronJobConfig job, string message) { Add("CRON", job == null ? "" : job.Id, job == null ? "" : job.Name, "INFO", message); } + public void Error(CronJobConfig job, string message) { Add("CRON", job == null ? "" : job.Id, job == null ? "" : job.Name, "ERROR", message); } + public void Info(WatcherJobConfig job, string message) { Add("WATCHER", job == null ? "" : job.Id, job == null ? "" : job.Name, "INFO", message); } + public void Error(WatcherJobConfig job, string message) { Add("WATCHER", job == null ? "" : job.Id, job == null ? "" : job.Name, "ERROR", message); } + public void SystemInfo(string message) { Add("SYSTEM", "", "System", "INFO", message); } + public void SystemError(string message) { Add("SYSTEM", "", "System", "ERROR", message); } + + public IList GetLatest(int limit) + { + lock (_sync) + { + return _entries.Reverse().Take(Math.Max(1, Math.Min(limit, _maxEntries))).ToList(); + } + } + + private void Add(string jobType, string jobId, string jobName, string level, string message) + { + lock (_sync) + { + _entries.Enqueue(new JobLogEntry + { + Timestamp = DateTime.Now, + JobType = jobType ?? "", + JobId = jobId ?? "", + JobName = jobName ?? "", + Level = level, + Message = message ?? "" + }); + while (_entries.Count > _maxEntries) _entries.Dequeue(); + } + } + } +} diff --git a/FileinterfaceCronScheduler/Scheduler/SchedulerRuntime.cs b/FileinterfaceCronScheduler/Scheduler/SchedulerRuntime.cs new file mode 100644 index 0000000..02e6f12 --- /dev/null +++ b/FileinterfaceCronScheduler/Scheduler/SchedulerRuntime.cs @@ -0,0 +1,57 @@ +using System; + +namespace FileInterface.Scheduler +{ + public sealed class SchedulerRuntime : IDisposable + { + private readonly CronScheduler _scheduler; + private readonly FileSystemWatcherManager _watcherManager; + private readonly WebAdminServer _web; + private readonly IDisposable _ownedResource; + private bool _disposed; + + public SchedulerRuntime(ICustomFunctionInvoker invoker, SchedulerOptions options) + : this(invoker, options, null) + { + } + + public SchedulerRuntime(ICustomFunctionInvoker invoker, SchedulerOptions options, IDisposable ownedResource) + { + if (invoker == null) throw new ArgumentNullException("invoker"); + if (options == null) options = new SchedulerOptions(); + + _ownedResource = ownedResource; + var cronRepository = new CronJobRepository(options.ConfigFile); + var watcherRepository = new WatcherJobRepository(options.WatcherConfigFile); + var log = new JobLog(5000); + var cronExecutor = new CronJobExecutor(invoker, log); + var watcherExecutor = new WatcherJobExecutor(invoker, log); + _scheduler = new CronScheduler(cronRepository, cronExecutor, log); + _watcherManager = new FileSystemWatcherManager(watcherRepository, watcherExecutor, log); + _web = new WebAdminServer(cronRepository, _scheduler, watcherRepository, _watcherManager, log, options); + } + + public void Start() + { + _scheduler.Start(); + _watcherManager.Start(); + _web.Start(); + } + + public void Dispose() + { + if (_disposed) return; + _disposed = true; + try { _web.Dispose(); } + finally + { + try { _watcherManager.Dispose(); } + finally + { + try { _scheduler.Dispose(); } + finally { if (_ownedResource != null) _ownedResource.Dispose(); } + } + } + } + } +} diff --git a/FileinterfaceCronScheduler/Scheduler/WatcherJobConfig.cs b/FileinterfaceCronScheduler/Scheduler/WatcherJobConfig.cs new file mode 100644 index 0000000..80bb491 --- /dev/null +++ b/FileinterfaceCronScheduler/Scheduler/WatcherJobConfig.cs @@ -0,0 +1,56 @@ +using System; +using System.Collections.Generic; + +namespace FileInterface.Scheduler +{ + public sealed class WatcherJobConfig + { + public string Id { get; set; } + public string Name { get; set; } + public bool Enabled { get; set; } + + public string SourceDirectory { get; set; } + public string SearchPattern { get; set; } + public bool IncludeSubdirectories { get; set; } + + public bool WatchCreated { get; set; } + public bool WatchChanged { get; set; } + public bool WatchRenamed { get; set; } + public int DebounceMilliseconds { get; set; } + public int FileReadyRetries { get; set; } + public int FileReadyDelayMilliseconds { get; set; } + + public bool RemoveEmptyLines { get; set; } + public string JoinSeparator { get; set; } + + public string CustomFunction { get; set; } + public List InArgs { get; set; } + + public bool MoveFileAfterSuccess { get; set; } + public string MoveTargetDirectory { get; set; } + public bool OverwriteTargetFile { get; set; } + + public WatcherJobConfig() + { + Id = Guid.NewGuid().ToString("N"); + Name = "New watcher"; + Enabled = true; + SourceDirectory = ""; + SearchPattern = "*.*"; + IncludeSubdirectories = false; + WatchCreated = true; + WatchChanged = true; + WatchRenamed = true; + DebounceMilliseconds = 1000; + FileReadyRetries = 10; + FileReadyDelayMilliseconds = 250; + RemoveEmptyLines = true; + JoinSeparator = ";"; + CustomFunction = ""; + InArgs = new List(); + MoveFileAfterSuccess = false; + MoveTargetDirectory = ""; + OverwriteTargetFile = false; + } + } +} diff --git a/FileinterfaceCronScheduler/Scheduler/WatcherJobExecutor.cs b/FileinterfaceCronScheduler/Scheduler/WatcherJobExecutor.cs new file mode 100644 index 0000000..6fe7edb --- /dev/null +++ b/FileinterfaceCronScheduler/Scheduler/WatcherJobExecutor.cs @@ -0,0 +1,149 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading; + +namespace FileInterface.Scheduler +{ + public sealed class WatcherJobExecutor + { + private readonly ICustomFunctionInvoker _invoker; + private readonly JobLog _log; + + public WatcherJobExecutor(ICustomFunctionInvoker invoker, JobLog log) + { + _invoker = invoker; + _log = log; + } + + public void ExecuteFile(WatcherJobConfig job, string file, string reason) + { + if (job == null) throw new ArgumentNullException("job"); + if (String.IsNullOrWhiteSpace(file)) return; + if (!WaitUntilReadable(file, job.FileReadyRetries, job.FileReadyDelayMilliseconds)) + { + _log.Error(job, "File is not readable after retries: " + file); + return; + } + + string rawContent; + using (var stream = new FileStream(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) + using (var reader = new StreamReader(stream, Encoding.UTF8, true)) + rawContent = reader.ReadToEnd(); + + string processedContent = ProcessContent(rawContent, job.RemoveEmptyLines, job.JoinSeparator); + string[] inArgs = (job.InArgs ?? new List()) + .Select(arg => Expand(arg, job, file, rawContent, processedContent, reason)) + .ToArray(); + + _log.Info(job, "Calling CustomFunction '" + job.CustomFunction + "' with " + inArgs.Length + " inArg(s) for " + Path.GetFileName(file) + " (" + reason + ")."); + CustomFunctionCallResult result = _invoker.Invoke(job.CustomFunction, inArgs); + if (result == null) result = CustomFunctionCallResult.Fail("Invoker returned null."); + + if (!result.Success) + { + _log.Error(job, "CustomFunction failed: " + result.Message); + return; + } + + _log.Info(job, "CustomFunction succeeded: " + result.Message); + if (job.MoveFileAfterSuccess && File.Exists(file)) + { + string movedTo = MoveProcessedFile(file, job.MoveTargetDirectory, job.OverwriteTargetFile); + _log.Info(job, "Moved file to: " + movedTo); + } + } + + private static bool WaitUntilReadable(string file, int retries, int delayMs) + { + retries = Math.Max(2, retries); + delayMs = Math.Max(10, delayMs); + long previousLength = -1; + DateTime previousWrite = DateTime.MinValue; + int stableChecks = 0; + + for (int i = 0; i < retries; i++) + { + if (!File.Exists(file)) return false; + try + { + var info = new FileInfo(file); + long length = info.Length; + DateTime lastWrite = info.LastWriteTimeUtc; + using (var stream = new FileStream(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) + { + if (stream.Length != length) length = stream.Length; + } + + if (length == previousLength && lastWrite == previousWrite) + { + stableChecks++; + if (stableChecks >= 1) return true; + } + else + { + stableChecks = 0; + previousLength = length; + previousWrite = lastWrite; + } + } + catch (IOException) { stableChecks = 0; } + catch (UnauthorizedAccessException) { stableChecks = 0; } + + Thread.Sleep(delayMs); + } + return false; + } + + private static string ProcessContent(string text, bool removeEmptyLines, string separator) + { + if (!removeEmptyLines) return text ?? ""; + string[] lines = (text ?? "").Replace("\r\n", "\n").Replace('\r', '\n').Split('\n'); + return String.Join(separator ?? ";", lines.Where(l => !String.IsNullOrWhiteSpace(l)).Select(l => l.Trim())); + } + + private static string Expand(string template, WatcherJobConfig job, string file, string rawContent, string processedContent, string reason) + { + string value = template ?? ""; + string fileName = Path.GetFileName(file) ?? ""; + string extension = Path.GetExtension(file) ?? ""; + string directory = Path.GetDirectoryName(file) ?? ""; + return value + .Replace("{{CONTENT}}", processedContent ?? "") + .Replace("{{RAW_CONTENT}}", rawContent ?? "") + .Replace("{{FILE_NAME}}", fileName) + .Replace("{{FILE_PATH}}", file ?? "") + .Replace("{{FILE_DIR}}", directory) + .Replace("{{FILE_EXT}}", extension) + .Replace("{{JOB_NAME}}", job.Name ?? "") + .Replace("{{EVENT}}", reason ?? "") + .Replace("{{NOW}}", DateTime.Now.ToString("yyyy-MM-ddTHH:mm:ss.fffK")); + } + + private static string MoveProcessedFile(string source, string targetDirectory, bool overwrite) + { + Directory.CreateDirectory(targetDirectory); + string target = Path.Combine(targetDirectory, Path.GetFileName(source)); + if (File.Exists(target)) + { + if (overwrite) File.Delete(target); + else + { + string name = Path.GetFileNameWithoutExtension(source); + string ext = Path.GetExtension(source); + target = Path.Combine(targetDirectory, name + "_" + DateTime.Now.ToString("yyyyMMdd_HHmmss_fff") + ext); + int i = 1; + while (File.Exists(target)) + { + target = Path.Combine(targetDirectory, name + "_" + DateTime.Now.ToString("yyyyMMdd_HHmmss_fff") + "_" + i + ext); + i++; + } + } + } + File.Move(source, target); + return target; + } + } +} diff --git a/FileinterfaceCronScheduler/Scheduler/WatcherJobRepository.cs b/FileinterfaceCronScheduler/Scheduler/WatcherJobRepository.cs new file mode 100644 index 0000000..f105a9a --- /dev/null +++ b/FileinterfaceCronScheduler/Scheduler/WatcherJobRepository.cs @@ -0,0 +1,109 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Web.Script.Serialization; + +namespace FileInterface.Scheduler +{ + public sealed class WatcherJobRepository + { + private readonly object _sync = new object(); + private readonly string _fileName; + private readonly JavaScriptSerializer _serializer = new JavaScriptSerializer(); + private List _jobs; + + public WatcherJobRepository(string fileName) + { + _fileName = Path.GetFullPath(fileName); + _serializer.MaxJsonLength = Int32.MaxValue; + _jobs = LoadInternal(); + } + + public IList GetAll() + { + lock (_sync) return Clone(_jobs); + } + + public WatcherJobConfig GetById(string id) + { + lock (_sync) + { + WatcherJobConfig job = _jobs.FirstOrDefault(j => String.Equals(j.Id, id, StringComparison.OrdinalIgnoreCase)); + return job == null ? null : Clone(job); + } + } + + public WatcherJobConfig Save(WatcherJobConfig job) + { + if (job == null) throw new ArgumentNullException("job"); + Validate(job); + lock (_sync) + { + if (String.IsNullOrWhiteSpace(job.Id)) job.Id = Guid.NewGuid().ToString("N"); + int index = _jobs.FindIndex(j => String.Equals(j.Id, job.Id, StringComparison.OrdinalIgnoreCase)); + if (index >= 0) _jobs[index] = Clone(job); else _jobs.Add(Clone(job)); + SaveInternal(); + return Clone(job); + } + } + + public bool Delete(string id) + { + lock (_sync) + { + int count = _jobs.RemoveAll(j => String.Equals(j.Id, id, StringComparison.OrdinalIgnoreCase)); + if (count > 0) SaveInternal(); + return count > 0; + } + } + + private List LoadInternal() + { + if (!File.Exists(_fileName)) return new List(); + string json = File.ReadAllText(_fileName, Encoding.UTF8); + if (String.IsNullOrWhiteSpace(json)) return new List(); + return _serializer.Deserialize>(json) ?? new List(); + } + + private void SaveInternal() + { + string dir = Path.GetDirectoryName(_fileName); + if (!String.IsNullOrWhiteSpace(dir)) Directory.CreateDirectory(dir); + string json = _serializer.Serialize(_jobs); + string tmp = _fileName + ".tmp"; + File.WriteAllText(tmp, json, new UTF8Encoding(false)); + if (File.Exists(_fileName)) + { + string backup = _fileName + ".bak"; + try { File.Replace(tmp, _fileName, backup, true); } + catch { File.Delete(_fileName); File.Move(tmp, _fileName); } + } + else File.Move(tmp, _fileName); + } + + private static void Validate(WatcherJobConfig job) + { + if (String.IsNullOrWhiteSpace(job.Name)) throw new InvalidOperationException("Name is required."); + if (String.IsNullOrWhiteSpace(job.SourceDirectory)) throw new InvalidOperationException("SourceDirectory is required."); + if (String.IsNullOrWhiteSpace(job.CustomFunction)) throw new InvalidOperationException("CustomFunction is required."); + if (!job.WatchCreated && !job.WatchChanged && !job.WatchRenamed) + throw new InvalidOperationException("At least one watcher event (Created, Changed, Renamed) must be enabled."); + if (job.MoveFileAfterSuccess && String.IsNullOrWhiteSpace(job.MoveTargetDirectory)) + throw new InvalidOperationException("MoveTargetDirectory is required when MoveFileAfterSuccess=true."); + if (job.InArgs == null) job.InArgs = new List(); + if (String.IsNullOrWhiteSpace(job.SearchPattern)) job.SearchPattern = "*.*"; + if (job.JoinSeparator == null) job.JoinSeparator = ";"; + if (job.DebounceMilliseconds < 0) job.DebounceMilliseconds = 0; + if (job.FileReadyRetries < 1) job.FileReadyRetries = 1; + if (job.FileReadyRetries > 1000) job.FileReadyRetries = 1000; + if (job.FileReadyDelayMilliseconds < 10) job.FileReadyDelayMilliseconds = 10; + } + + private T Clone(T value) + { + return _serializer.Deserialize(_serializer.Serialize(value)); + } + } +} diff --git a/FileinterfaceCronScheduler/Scheduler/WebAdminServer.cs b/FileinterfaceCronScheduler/Scheduler/WebAdminServer.cs new file mode 100644 index 0000000..a20819a --- /dev/null +++ b/FileinterfaceCronScheduler/Scheduler/WebAdminServer.cs @@ -0,0 +1,278 @@ +using System; +using System.IO; +using System.Net; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using System.Web.Script.Serialization; + +namespace FileInterface.Scheduler +{ + public sealed class WebAdminServer : IDisposable + { + private readonly HttpListener _listener = new HttpListener(); + private readonly CronJobRepository _cronRepository; + private readonly CronScheduler _scheduler; + private readonly WatcherJobRepository _watcherRepository; + private readonly FileSystemWatcherManager _watcherManager; + private readonly JobLog _log; + private readonly SchedulerOptions _options; + private readonly JavaScriptSerializer _json = new JavaScriptSerializer(); + private CancellationTokenSource _cts; + + public WebAdminServer( + CronJobRepository cronRepository, + CronScheduler scheduler, + WatcherJobRepository watcherRepository, + FileSystemWatcherManager watcherManager, + JobLog log, + SchedulerOptions options) + { + _cronRepository = cronRepository; + _scheduler = scheduler; + _watcherRepository = watcherRepository; + _watcherManager = watcherManager; + _log = log; + _options = options; + _listener.Prefixes.Add(options.WebPrefix); + _json.MaxJsonLength = Int32.MaxValue; + } + + public void Start() + { + if (_listener.IsListening) return; + _cts = new CancellationTokenSource(); + _listener.Start(); + Task.Run(() => AcceptLoop(_cts.Token)); + } + + private async Task AcceptLoop(CancellationToken token) + { + while (!token.IsCancellationRequested) + { + HttpListenerContext context; + try { context = await _listener.GetContextAsync(); } + catch when (token.IsCancellationRequested) { break; } + catch { continue; } + Task.Run(() => Handle(context)); + } + } + + private void Handle(HttpListenerContext ctx) + { + try + { + if (!IsAuthorized(ctx)) + { + ctx.Response.StatusCode = 401; + ctx.Response.AddHeader("WWW-Authenticate", "Basic realm=FileInterface Admin"); + ctx.Response.Close(); + return; + } + + string path = ctx.Request.Url.AbsolutePath.TrimEnd('/'); + if (path == "") path = "/"; + + if (ctx.Request.HttpMethod == "GET" && path == "/") { WriteHtml(ctx, Html); return; } + + if (ctx.Request.HttpMethod == "GET" && (path == "/api/cronjobs" || path == "/api/jobs")) + { WriteJson(ctx, _cronRepository.GetAll()); return; } + + if (ctx.Request.HttpMethod == "POST" && (path == "/api/cronjobs/save" || path == "/api/jobs/save")) + { + CronJobConfig job = _json.Deserialize(ReadBody(ctx.Request)); + WriteJson(ctx, _cronRepository.Save(job)); return; + } + + if (ctx.Request.HttpMethod == "POST" && (path == "/api/cronjobs/delete" || path == "/api/jobs/delete")) + { WriteJson(ctx, new { deleted = _cronRepository.Delete(ctx.Request.QueryString["id"] ?? "") }); return; } + + if (ctx.Request.HttpMethod == "POST" && (path == "/api/cronjobs/run" || path == "/api/jobs/run")) + { WriteJson(ctx, new { started = _scheduler.RunNow(ctx.Request.QueryString["id"] ?? "") }); return; } + + if (ctx.Request.HttpMethod == "GET" && path == "/api/watchers") + { WriteJson(ctx, _watcherRepository.GetAll()); return; } + + if (ctx.Request.HttpMethod == "POST" && path == "/api/watchers/save") + { + WatcherJobConfig job = _json.Deserialize(ReadBody(ctx.Request)); + WatcherJobConfig saved = _watcherRepository.Save(job); + _watcherManager.Reload(); + WriteJson(ctx, saved); return; + } + + if (ctx.Request.HttpMethod == "POST" && path == "/api/watchers/delete") + { + bool deleted = _watcherRepository.Delete(ctx.Request.QueryString["id"] ?? ""); + _watcherManager.Reload(); + WriteJson(ctx, new { deleted = deleted }); return; + } + + if (ctx.Request.HttpMethod == "POST" && path == "/api/watchers/reload") + { _watcherManager.Reload(); WriteJson(ctx, new { reloaded = true }); return; } + + if (ctx.Request.HttpMethod == "POST" && path == "/api/watchers/scan") + { WriteJson(ctx, new { started = _watcherManager.ProcessExistingNow(ctx.Request.QueryString["id"] ?? "") }); return; } + + if (ctx.Request.HttpMethod == "GET" && path == "/api/logs") + { + int limit = 300; + int parsed; + if (Int32.TryParse(ctx.Request.QueryString["limit"], out parsed) && parsed > 0) limit = parsed; + WriteJson(ctx, _log.GetLatest(limit)); return; + } + + if (ctx.Request.HttpMethod == "GET" && path == "/api/status") + { + WriteJson(ctx, new + { + runningCronJobIds = _scheduler.GetRunningJobIds(), + activeWatcherIds = _watcherManager.GetActiveWatcherIds(), + serverTime = DateTime.Now + }); + return; + } + + ctx.Response.StatusCode = 404; + WriteJson(ctx, new { error = "Not found" }); + } + catch (Exception ex) + { + try { ctx.Response.StatusCode = 500; WriteJson(ctx, new { error = ex.Message }); } + catch { try { ctx.Response.Close(); } catch { } } + } + } + + private bool IsAuthorized(HttpListenerContext ctx) + { + if (String.IsNullOrWhiteSpace(_options.WebUser)) return true; + string header = ctx.Request.Headers["Authorization"]; + if (String.IsNullOrWhiteSpace(header) || !header.StartsWith("Basic ", StringComparison.OrdinalIgnoreCase)) return false; + try + { + string decoded = Encoding.UTF8.GetString(Convert.FromBase64String(header.Substring(6).Trim())); + int colon = decoded.IndexOf(':'); + if (colon < 0) return false; + return decoded.Substring(0, colon) == _options.WebUser && decoded.Substring(colon + 1) == (_options.WebPassword ?? ""); + } + catch { return false; } + } + + private static string ReadBody(HttpListenerRequest request) + { + using (var reader = new StreamReader(request.InputStream, request.ContentEncoding ?? Encoding.UTF8)) + return reader.ReadToEnd(); + } + + private void WriteJson(HttpListenerContext ctx, object value) + { + byte[] data = Encoding.UTF8.GetBytes(_json.Serialize(value)); + ctx.Response.ContentType = "application/json; charset=utf-8"; + ctx.Response.ContentLength64 = data.Length; + ctx.Response.OutputStream.Write(data, 0, data.Length); + ctx.Response.Close(); + } + + private static void WriteHtml(HttpListenerContext ctx, string html) + { + byte[] data = Encoding.UTF8.GetBytes(html); + ctx.Response.ContentType = "text/html; charset=utf-8"; + ctx.Response.ContentLength64 = data.Length; + ctx.Response.OutputStream.Write(data, 0, data.Length); + ctx.Response.Close(); + } + + public void Dispose() + { + if (_cts != null) _cts.Cancel(); + try { _listener.Stop(); } catch { } + try { _listener.Close(); } catch { } + } + + private const string Html = @" + + + +FileInterface Admin + +

FileInterface – HTTP Administration

FileSystemWatcher + CronScheduler · iTAC IMS CustomFunctions
+
+
+ +
+

Watcher

+

Watcher bearbeiten

+ + +
+ +
+
+
+ +
+
Platzhalter: {{CONTENT}}, {{RAW_CONTENT}}, {{FILE_NAME}}, {{FILE_PATH}}, {{FILE_DIR}}, {{FILE_EXT}}, {{JOB_NAME}}, {{EVENT}}, {{NOW}}
+
+ +
+
+
+ +
+

Cronjobs

+

Cronjob bearbeiten

+ +
+ +
+ +
+ +
+
Platzhalter: {{CONTENT}}, {{RAW_CONTENT}}, {{FILE_NAME}}, {{FILE_PATH}}, {{FILE_DIR}}, {{FILE_EXT}}, {{JOB_NAME}}, {{NOW}}
+
+ +
+
+
+ +

Runtime / Log

+
+"; + } +} diff --git a/FileinterfaceCronScheduler/cronjobs.json b/FileinterfaceCronScheduler/cronjobs.json new file mode 100644 index 0000000..756a689 --- /dev/null +++ b/FileinterfaceCronScheduler/cronjobs.json @@ -0,0 +1,23 @@ +[ + { + "Id": "example_cogi_import", + "Name": "Beispiel - COGI Import", + "Enabled": false, + "Cron": "*/5 * * * *", + "CallOnceWithoutFile": false, + "SourceDirectory": "C:\\FileInterface\\Input", + "SearchPattern": "*.xml", + "IncludeSubdirectories": false, + "RemoveEmptyLines": true, + "JoinSeparator": ";", + "CustomFunction": "BroseREST.restCallCogi1", + "InArgs": [ + "RPCServices-WS", + "{{CONTENT}}", + "{{FILE_NAME}}" + ], + "MoveFileAfterSuccess": true, + "MoveTargetDirectory": "C:\\FileInterface\\Archive", + "OverwriteTargetFile": false + } +] diff --git a/FileinterfaceCronScheduler/ihas.properties b/FileinterfaceCronScheduler/ihas.properties new file mode 100644 index 0000000..e69de29 diff --git a/FileinterfaceCronScheduler/lib/IMSApiDotNet.dll b/FileinterfaceCronScheduler/lib/IMSApiDotNet.dll new file mode 100644 index 0000000000000000000000000000000000000000..89e0ab418bda81174329b1be260f2654f4396c1d GIT binary patch literal 566272 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

p|sVF>Xo+kRFdi(Aa5YdJ(i=z$cGSgijG?V$Bi8 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 + +``` + +Wichtig: Fuer den produktiven Betrieb sollte das Standardkennwort geaendert werden. + +Eigenständiges Visual-Studio-/C#-Projekt für ereignisbasierte **und** zeitgesteuerte Datei-Verarbeitung über iTAC IMSAPI CustomFunctions. + +## Architektur + +Beide Mechanismen laufen gleichzeitig und unabhängig voneinander: + +```text +HTTP Webclient + | + +-- FileSystemWatcher-Konfiguration --> beliebig viele FileSystemWatcher + | + +-- Cron-Konfiguration ---------------> beliebig viele Cronjobs + | + +-----------------------------+ + | + gemeinsame IMSAPI Session + | + customFunction(...) +``` + +## Enthalten + +- `FileinterfaceCronScheduler.sln` +- .NET Framework 4.8 / x86 +- Windows-Dienst und Konsolenmodus +- enthaltene `IMSApiDotNet.dll` Version 10.0.0-3 +- IMSAPI Initialisierung und `regLogin(...)` +- beliebig viele FileSystemWatcher +- beliebig viele Cronjobs +- zentrale HTTP-Administration +- beliebig viele `inArgs` pro Watcher/Cronjob +- eigene CustomFunction pro Watcher/Cronjob +- Datei nach Erfolg optional verschieben +- Laufzeit-Log und Status im Browser + +## HTTP Webclient + +Standard: + +```text +http://127.0.0.1:8095/ +``` + +Für Zugriff aus dem Netzwerk in `App.config`: + +```xml + +``` + +Danach `scripts\allow-webinterface-network.bat` als Administrator ausführen. Für Netzwerkzugriff sollten `Scheduler.WebUser` und `Scheduler.WebPassword` gesetzt werden. + +Der Webclient besitzt zwei Bereiche: + +### FileSystemWatcher + +Pro Watcher konfigurierbar: + +- Aktiv / Inaktiv +- Quellverzeichnis +- Dateifilter, z. B. `*.xml` +- Unterverzeichnisse +- Events `Created`, `Changed`, `Renamed` +- Debounce in Millisekunden +- File-Ready Wiederholungen / Wartezeit +- CustomFunction +- beliebig viele `inArgs` +- leere Zeilen entfernen +- Zeilentrenner +- Datei nach Erfolg verschieben Ja/Nein +- Zielverzeichnis +- bestehende Zieldatei überschreiben Ja/Nein +- vorhandene Dateien manuell verarbeiten +- Watcher ohne Dienstneustart neu laden + +Änderungen werden beim Speichern sofort persistent geschrieben und die FileSystemWatcher werden automatisch neu aufgebaut. + +### CronScheduler + +Pro Cronjob konfigurierbar: + +- Aktiv / Inaktiv +- Cron-Ausdruck mit 5 Feldern +- optional CustomFunction ohne Datei aufrufen +- Quellverzeichnis / Filter / Unterverzeichnisse +- CustomFunction +- beliebig viele `inArgs` +- Datei nach Erfolg verschieben Ja/Nein +- manuell `Jetzt ausführen` + +Beispiele: + +```text +*/5 * * * * +0 */2 * * * +15 2 * * * +0 6 * * 1-5 +``` + +## Platzhalter + +Für Watcher und Cronjobs: + +```text +{{CONTENT}} +{{RAW_CONTENT}} +{{FILE_NAME}} +{{FILE_PATH}} +{{FILE_DIR}} +{{FILE_EXT}} +{{JOB_NAME}} +{{NOW}} +``` + +Nur beim FileSystemWatcher zusätzlich: + +```text +{{EVENT}} +``` + +`{{EVENT}}` enthält z. B. `Created`, `Changed`, `Renamed` oder `ManualScan`. + +## Persistente Konfiguration + +Die Jobs sind getrennt gespeichert: + +```text +cronjobs.json +watcherjobs.json +``` + +Pfade können in `App.config` geändert werden: + +```xml + + +``` + +## IMSAPI + +`IMSApiDotNet.dll` liegt bereits unter: + +```text +FileinterfaceCronScheduler\lib\IMSApiDotNet.dll +``` + +Beim Programmstart: + +1. `IMSApiDotNet.setProperty(...)` +2. `IMSApiDotNet.loadLibrary()` +3. `imsapiInit()` +4. `regLogin(...)` +5. Start FileSystemWatcher + CronScheduler + HTTP-Webclient + +Die Aufrufe verwenden anschließend dieselbe Session: + +```csharp +imsapi.customFunction( + sessionContext, + customFunctionName, + inArgs, + out outArgs, + out customErrorString +); +``` + +## IMS-Konfiguration + +In `FileinterfaceCronScheduler\App.config`: + +```xml + + + + + + + +``` + +`IMS.SerializeCalls=false` erlaubt unabhängigen Watchern und Cronjobs parallele CustomFunction-Aufrufe. Wenn die eingesetzte IMSAPI-Umgebung das nicht verträgt, kann auf `true` gestellt werden. + +## Visual Studio + +1. `FileinterfaceCronScheduler.sln` öffnen. +2. `App.config` konfigurieren. +3. Build `Debug` oder `Release`; das Projekt kompiliert als x86. +4. Starten. +5. Browser auf `http://127.0.0.1:8095/` öffnen. + +## Windows-Dienst + +Unter `scripts`: + +- `install-service.bat` +- `uninstall-service.bat` +- `allow-webinterface-network.bat` + +Vor der Dienstinstallation zuerst Release bauen. diff --git a/scripts/allow-webinterface-network.bat b/scripts/allow-webinterface-network.bat new file mode 100644 index 0000000..83caa3f --- /dev/null +++ b/scripts/allow-webinterface-network.bat @@ -0,0 +1,4 @@ +@echo off +REM Als Administrator ausfuehren, wenn Scheduler.WebPrefix = http://+:8095/ genutzt wird. +netsh http add urlacl url=http://+:8095/ user=Everyone +netsh advfirewall firewall add rule name="FileInterface HTTP Admin 8095" dir=in action=allow protocol=TCP localport=8095 diff --git a/scripts/install-service.bat b/scripts/install-service.bat new file mode 100644 index 0000000..3b00571 --- /dev/null +++ b/scripts/install-service.bat @@ -0,0 +1,22 @@ +@echo off +setlocal +set SERVICE_NAME=FileinterfaceCronScheduler +set EXE=%~dp0..\FileinterfaceCronScheduler\bin\Release\FileinterfaceCronScheduler.exe + +if not exist "%EXE%" ( + echo EXE nicht gefunden: %EXE% + echo Bitte Solution zuerst im Release-Modus bauen. + exit /b 1 +) + +sc.exe query "%SERVICE_NAME%" >nul 2>&1 +if %errorlevel%==0 ( + echo Dienst %SERVICE_NAME% existiert bereits. + exit /b 1 +) + +sc.exe create "%SERVICE_NAME%" binPath= "\"%EXE%\" --service" start= auto DisplayName= "FileInterface Watcher + CronScheduler" +if errorlevel 1 exit /b 1 +sc.exe description "%SERVICE_NAME%" "FileSystemWatcher und CronScheduler fuer iTAC IMS CustomFunctions mit HTTP-Administration" +sc.exe start "%SERVICE_NAME%" +endlocal diff --git a/scripts/uninstall-service.bat b/scripts/uninstall-service.bat new file mode 100644 index 0000000..5a50341 --- /dev/null +++ b/scripts/uninstall-service.bat @@ -0,0 +1,7 @@ +@echo off +setlocal +set SERVICE_NAME=FileinterfaceCronScheduler +sc.exe stop "%SERVICE_NAME%" +timeout /t 2 /nobreak >nul +sc.exe delete "%SERVICE_NAME%" +endlocal