string GenerateMtFileWatchConfig(FileWatchElement inputFile, int i)
        {
            var inputFileEscaped = PrepareFilePaths(inputFile.Files);
            var mainModulePath = new Uri(Process.GetCurrentProcess().MainModule.FileName).LocalPath;
            var exePath = Path.Combine(Path.GetDirectoryName(mainModulePath), "MtLogTailer.exe");
            var exePathEscaped = exePath.Replace(@"\", @"\\");

            var res = string.Format(@"
            <Input in_file{0}>
            Module im_exec
            Command ""{1}""
            Arg ""{2}""
            Arg -readFromLast:{5}
            Restart True
            Exec $Message = string($raw_event);
            Exec $path = ""{3}""; $type = ""{4}"";
            Exec if $Message =~ /^(([^\t]+)\t)/ {{ $fullPath = $2; $Message = substr($Message, size($1)); }}
            Exec if $Message $Message = substr($Message, 0, 1040000);
            ", i, exePathEscaped, inputFileEscaped, inputFile.Files, inputFile.Type, inputFile.ReadFromLast.ToString().ToLower());

            res += AppendCustomFields(inputFile);
            res += GetSessionId();
            res += @"</Input>" + Environment.NewLine;

            return res;
        }
        string GenerateNormalFileWatchConfig(FileWatchElement inputFile, int i)
        {
            var res = "";
            var inputFileEscaped = PrepareFilePaths(inputFile.Files);

            _log.InfoFormat("Receiving data from file: {0}", inputFile.Files);
            res += string.Format(@"
            <Input in_file{0}>
            Module	im_file
            InputType	{8}
            File	""{1}""
            ReadFromLast {2}
            SavePos	TRUE
            CloseWhenIdle {7}
            PollInterval {5}
            DirCheckInterval {6}
            Exec	$path = ""{3}""; $type = ""{4}"";
            ",
                i,
                inputFileEscaped,
                inputFile.ReadFromLast.ToString().ToUpper(),
                inputFile.Files,
                inputFile.Type,
                FilePollIntervalSeconds,
                FilePollIntervalSeconds * 2,
                inputFile.CloseWhenIdle.ToString().ToUpper(),
                inputFile.MultilineRule);

            res += AppendCustomFields(inputFile);

            // Limit maximum message size to just less than 1MB; or NXLog dies with: ERROR string limit (1048576 bytes) reached
            res += @"	Exec if $Message $Message = substr($raw_event, 0, 1040000);" + Environment.NewLine;

            if (inputFile.CustomNxlogConfig != null)
            {
                var customNxlog = inputFile.CustomNxlogConfig.Value;
                if (!string.IsNullOrWhiteSpace(customNxlog))
                    res += "\t" + customNxlog + Environment.NewLine;
            }

            res += GetSessionId();
            res += @"</Input>" + Environment.NewLine;

            return res;
        }
        private static string AppendCustomFields(FileWatchElement inputFile)
        {
            if (inputFile.Fields.Count == 0)
                return "";
            var buf = new StringBuilder();
            foreach (FieldElement field in inputFile.Fields)
            {
                if (!field.Key.All(ch => Char.IsLetterOrDigit(ch) || ch == '/' || ch == '_'))
                {
                    var message = string.Format("fileWatch: '{0}' contains invalid field name '{1}' (must contain letters, digits, slashes and underscores only)",
                        inputFile.Files, field.Key);
                    throw new ApplicationException(message);
                }

                buf.AppendFormat(@"${0} = ""{1}""; ", field.Key, field.Value);
            }
            return "	Exec " + buf + Environment.NewLine;
        }