public void IdenticalResultMatcher_MatchesResults_DifferingOnIdOrStatus_Multiple() { ExtractedResult resultAA = new ExtractedResult(ResultMatchingTestHelpers.CreateMatchingResult("file://test", "file://test2", "test context"), null); Result changedResultA = resultAA.Result.DeepClone(); changedResultA.CorrelationGuid = Guid.NewGuid().ToString(); changedResultA.BaselineState = BaselineState.Unchanged; ExtractedResult resultBA = new ExtractedResult(changedResultA, null); ExtractedResult resultAB = new ExtractedResult(ResultMatchingTestHelpers.CreateMatchingResult("file://test", "file://test2", "test context2"), null); Result changedResultB = resultAB.Result.DeepClone(); changedResultA.CorrelationGuid = Guid.NewGuid().ToString(); changedResultA.BaselineState = BaselineState.New; ExtractedResult resultBB = new ExtractedResult(changedResultB, null); IEnumerable <MatchedResults> matchedResults = matcher.Match(new ExtractedResult[] { resultAA, resultAB }, new ExtractedResult[] { resultBA, resultBB }); matchedResults.Should().HaveCount(2); matchedResults.Where(f => f.PreviousResult == resultAA && f.CurrentResult == resultBA).Should().HaveCount(1); matchedResults.Where(f => f.PreviousResult == resultAB && f.CurrentResult == resultBB).Should().HaveCount(1); }
private void LinkResultsWithIdenticalWhere() { // Walk Results sorted by where, linking those with identical positions and a matching category. int beforeIndex = 0, afterIndex = 0; while (beforeIndex < Before.Count && afterIndex < After.Count) { ExtractedResult left = Before[beforeIndex]; ExtractedResult right = After[afterIndex]; int whereCmp = WhereComparer.CompareWhere(left, right); if (whereCmp < 0) { // Left is in a 'Where' before Right - look at the next Result in 'Before'. beforeIndex++; } else if (whereCmp > 0) { // Right is in a 'Where' before Left - look at the next Result in 'After'. afterIndex++; } else { // The Results have a matching where. If the category matches, link them. if (left.MatchesCategory(right)) { LinkIfSimilar(beforeIndex, afterIndex); } // Look at the next pair of Results. beforeIndex++; afterIndex++; } } }
public void FullFingerprintMatcher_DoesNotMatchOnChangedFingerprints() { Result resultA = ResultMatchingTestHelpers.CreateMatchingResult(@"http://testtesttest", @"file://testa", "contextual contexty contexts"); Result resultB = ResultMatchingTestHelpers.CreateMatchingResult(@"http://testtesttest", @"file://testa", "contextual contexty contexts"); resultA.Fingerprints = new Dictionary <string, string>() { { "FingerprintAlgorithm1", "FingerprintValue1" }, { "FingerprintAlgorithm2", "FingerprintValue2" } }; resultB.Fingerprints = new Dictionary <string, string>() { { "FingerprintAlgorithm1", "FingerprintValue3" }, { "FingerprintAlgorithm2", "FingerprintValue4" } }; ExtractedResult matchingResultA = new ExtractedResult() { Result = resultA }; ExtractedResult matchingResultB = new ExtractedResult() { Result = resultB }; IEnumerable <MatchedResults> matchedResults = matcher.Match(new ExtractedResult[] { matchingResultA }, new ExtractedResult[] { matchingResultB }); matchedResults.Should().HaveCount(0); }
public void FullFingerprintMatcher_MatchesIdenticalFingerprints() { Result resultA = ResultMatchingTestHelpers.CreateMatchingResult(@"http://testtesttest", @"file://testa", "contextual contexty contexts"); Result resultB = ResultMatchingTestHelpers.CreateMatchingResult(@"http://notasmuchatest", @"file://differentpath", "different contexty contexts"); resultA.Fingerprints = new Dictionary <string, string>() { { "FingerprintAlgorithm1", "FingerprintValue1" }, { "FingerprintAlgorithm2", "FingerprintValue2" } }; resultB.Fingerprints = new Dictionary <string, string>() { { "FingerprintAlgorithm1", "FingerprintValue1" } }; ExtractedResult matchingResultA = new ExtractedResult() { Result = resultA }; ExtractedResult matchingResultB = new ExtractedResult() { Result = resultB }; IEnumerable <MatchedResults> matchedResults = matcher.Match(new ExtractedResult[] { matchingResultA }, new ExtractedResult[] { matchingResultB }); matchedResults.Should().HaveCount(1); matchedResults.First().PreviousResult.Should().BeEquivalentTo(matchingResultA); matchedResults.First().CurrentResult.Should().BeEquivalentTo(matchingResultB); }
public bool Equals(ExtractedResult x, ExtractedResult y) { IEnumerable <ArtifactContent> xContextRegions = x.Result.Locations.Select(loc => loc.PhysicalLocation.ContextRegion.Snippet); HashSet <ArtifactContent> yContextRegions = new HashSet <ArtifactContent>(ArtifactContentEqualityComparer.Instance); foreach (ArtifactContent content in y.Result.Locations.Select(loc => loc.PhysicalLocation.ContextRegion.Snippet)) { yContextRegions.Add(content); } if (xContextRegions.Count() != yContextRegions.Count) { return(false); } foreach (ArtifactContent content in xContextRegions) { if (!yContextRegions.Contains(content)) { return(false); } } return(true); }
private void Add(ExtractedResult result, int index) { foreach (WhatComponent component in result.WhatProperties()) { Add(component, index); } }
public void PartialFingerprintResultMatcher_SamePartialFingerprints_Matches() { ExtractedResult resultA = new ExtractedResult(ResultMatchingTestHelpers.CreateMatchingResult("file://test1", "file://test2", null), null); resultA.Result.PartialFingerprints = new Dictionary <string, string>() { { "Fingerprint1", "Value1" } }; ExtractedResult resultB = new ExtractedResult(ResultMatchingTestHelpers.CreateMatchingResult("file://test3", "file://test4", null), null); resultA.Result.PartialFingerprints = new Dictionary <string, string>() { { "Fingerprint1", "Value1" } }; IEnumerable <MatchedResults> matchedResults = matcher.Match(new List <ExtractedResult>() { resultA }, new List <ExtractedResult>() { resultB }); matchedResults.Should().BeEmpty(); }
/// <summary> /// Match the 'Category' of two ExtractedResults (Tool and RuleId). /// </summary> /// <param name="other">ExtractedResult to match</param> /// <returns>True if Category is identical, False otherwise</returns> public bool MatchesCategory(ExtractedResult other) { return(this.RuleId == other.RuleId); // Tool contributes to category, but SarifLogMatcher ensures only Runs with matching Tools are compared, // so we don't check here. }
public OperateResult <string> Extract(string extensionName, byte[] data) { OperateResult <string> operateResult = new OperateResult <string>(); try { if (extensionName.IsNullOrWhiteSpace()) { operateResult.Status = OperateStatus.Failure; operateResult.Description = "extension不能为空"; } else if (data == null || data.Length == 0) { operateResult.Status = OperateStatus.Failure; operateResult.Description = "fileData不能为空"; } else { ICollection <DocumentExtractor> extractors = ExtractorFactory.GetExtractors(extensionName); if (extractors == null || extractors.Count == 0) { operateResult.Status = OperateStatus.Failure; operateResult.Description = "没有对应的处理程序"; } else { bool flag = false; foreach (DocumentExtractor extractor in extractors) { try { ExtractedResult extractedResult = extractor.Extract(extensionName, data, ExtractOption.Text); if (extractedResult != null && extractedResult.Text != null) { operateResult.Data = extractedResult.Text; flag = true; break; } } catch (Exception exception) { flag = false; LoggerWrapper.Logger.Warn("抽取时发生错误", exception); } } if (!flag) { operateResult.Status = OperateStatus.Failure; operateResult.Description = "抽取出错"; } } } } catch (Exception exception) { operateResult.Description = "抽取出错"; LoggerWrapper.Logger.Error("ExtractText", exception); } return(operateResult); }
public void IdenticalResultMatcher_DoesNotMatchDifferentResults_Multiple() { ExtractedResult resultAA = new ExtractedResult() { Result = ResultMatchingTestHelpers.CreateMatchingResult("file://test", "file://test2", "test context1") }; ExtractedResult resultBA = new ExtractedResult() { Result = ResultMatchingTestHelpers.CreateMatchingResult("file://test", "file://test2", "test context2") }; ExtractedResult resultAB = new ExtractedResult() { Result = ResultMatchingTestHelpers.CreateMatchingResult("file://test", "file://test2", "test context3") }; ExtractedResult resultBB = new ExtractedResult() { Result = ResultMatchingTestHelpers.CreateMatchingResult("file://test", "file://test2", "test context4") }; IEnumerable <MatchedResults> matchedResults = matcher.Match(new ExtractedResult[] { resultAA, resultAB }, new ExtractedResult[] { resultBA, resultBB }); matchedResults.Should().BeEmpty(); }
public static IEnumerable <WhatComponent> WhatProperties(this ExtractedResult result) { if (result?.Result == null) { yield break; } // Add Guid if (result.Result.Guid != null) { yield return(new WhatComponent(result.RuleId, PropertySetBase, "Guid", result.Result.Guid)); } // Add Message Text string messageText = result.Result.GetMessageText(result.Result.GetRule(result.OriginalRun)); if (!string.IsNullOrEmpty(messageText)) { yield return(new WhatComponent(result.RuleId, PropertySetBase, "Message", messageText)); } // Add each Fingerprint if (result.Result.Fingerprints != null) { foreach (var fingerprint in result.Result.Fingerprints) { yield return(new WhatComponent(result.RuleId, "Fingerprint", "Fingerprint/" + fingerprint.Key, fingerprint.Value)); } } // Add each PartialFingerprint if (result.Result.PartialFingerprints != null) { foreach (var fingerprint in result.Result.PartialFingerprints) { yield return(new WhatComponent(result.RuleId, "PartialFingerprint", "PartialFingerprint/" + fingerprint.Key, fingerprint.Value)); } } if (result.Result.Locations != null) { foreach (Location location in result.Result.Locations) { string snippet = location?.PhysicalLocation?.Region?.Snippet?.Text; if (!string.IsNullOrEmpty(snippet)) { yield return(new WhatComponent(result.RuleId, PropertySetBase, "Location.Snippet", snippet)); } } } // Add each Property if (result.Result.Properties != null) { foreach (var property in result.Result.Properties) { yield return(new WhatComponent(result.RuleId, "Property", "PropertyBag/" + property.Key, property.Value.SerializedValue)); } } }
public void IdenticalResultMatcher_MatchesIdenticalResults_Multiple() { ExtractedResult resultAA = new ExtractedResult() { Result = ResultMatchingTestHelpers.CreateMatchingResult("file://test", "file://test2", "test context") }; ExtractedResult resultBA = new ExtractedResult() { Result = resultAA.Result.DeepClone() }; ExtractedResult resultAB = new ExtractedResult() { Result = ResultMatchingTestHelpers.CreateMatchingResult("file://test", "file://test2", "test context2") }; ExtractedResult resultBB = new ExtractedResult() { Result = resultAB.Result.DeepClone() }; IEnumerable <MatchedResults> matchedResults = matcher.Match(new ExtractedResult[] { resultAA, resultAB }, new ExtractedResult[] { resultBA, resultBB }); matchedResults.Should().HaveCount(2); matchedResults.Where(f => f.PreviousResult == resultAA && f.CurrentResult == resultBA).Should().HaveCount(1); matchedResults.Where(f => f.PreviousResult == resultAB && f.CurrentResult == resultBB).Should().HaveCount(1); }
private ExtractedResult LastWithUri(ExtractedResult desiredUri, IList <ExtractedResult> set, ref int fromIndex) { ExtractedResult lastMatch = null; // Find the first Result at fromIndex or later with a Uri *after* the desired one, saving the last Result that matched as we go for (; fromIndex < set.Count; ++fromIndex) { int whereCmp = WhereComparer.CompareFirstArtifactUri(set[fromIndex], desiredUri); if (whereCmp == 0) { lastMatch = set[fromIndex]; } else if (whereCmp > 0) { break; } } // Ensure the index ends at the last match if (fromIndex > 0) { fromIndex--; } return(lastMatch); }
public void IdenticalResultMatcher_DoesNotMatchDifferentResults_Single() { ExtractedResult resultA = new ExtractedResult(ResultMatchingTestHelpers.CreateMatchingResult("file://test", "file://test2", "test context"), null); ExtractedResult resultB = new ExtractedResult(ResultMatchingTestHelpers.CreateMatchingResult("file://test", "file://test2", "test context2"), null); IEnumerable <MatchedResults> matchedResults = matcher.Match(new ExtractedResult[] { resultA }, new ExtractedResult[] { resultB }); matchedResults.Should().BeEmpty(); }
public static IEnumerable <WhatComponent> WhatProperties(this ExtractedResult result, string locationSpecifier = LocationNonSpecific) { if (result?.Result == null) { yield break; } // Add Guid if (result.Result.Guid != null) { yield return(new WhatComponent(result.RuleId, locationSpecifier, PropertySetBase, "Guid", result.Result.Guid)); } // Add Message Text string messageText = result.Result.GetMessageText(result.Result.GetRule(result.OriginalRun)); if (!string.IsNullOrEmpty(messageText)) { yield return(new WhatComponent(result.RuleId, locationSpecifier, PropertySetBase, "Message", messageText)); } // Add each Fingerprint if (result.Result.Fingerprints != null) { foreach (KeyValuePair <string, string> fingerprint in result.Result.Fingerprints) { yield return(new WhatComponent(result.RuleId, locationSpecifier, PropertySetFingerprint, fingerprint.Key, fingerprint.Value)); } } // Add each PartialFingerprint if (result.Result.PartialFingerprints != null) { foreach (KeyValuePair <string, string> fingerprint in result.Result.PartialFingerprints) { yield return(new WhatComponent(result.RuleId, locationSpecifier, PropertySetPartialFingerprint, fingerprint.Key, fingerprint.Value)); } } string snippet = GetFirstSnippet(result); if (snippet != null) { yield return(new WhatComponent(result.RuleId, locationSpecifier, PropertySetBase, "Location.Snippet", snippet)); } // Add each Property if (result.Result.Properties != null) { foreach (KeyValuePair <string, SerializedPropertyInfo> property in result.Result.Properties) { yield return(new WhatComponent(result.RuleId, locationSpecifier, PropertySetProperty, property.Key, property.Value?.SerializedValue)); } } }
public void IdenticalResultMatcher_MatchesIdenticalResults_Single() { ExtractedResult resultA = new ExtractedResult(ResultMatchingTestHelpers.CreateMatchingResult("file://test", "file://test2", "test context"), null); ExtractedResult resultB = new ExtractedResult(resultA.Result.DeepClone(), null); IEnumerable <MatchedResults> matchedResults = matcher.Match(new ExtractedResult[] { resultA }, new ExtractedResult[] { resultB }); matchedResults.Should().HaveCount(1); matchedResults.First().PreviousResult.Should().BeEquivalentTo(resultA); matchedResults.First().CurrentResult.Should().BeEquivalentTo(resultB); }
internal static void Filter(ExtractedResult result) { if (result == null || Filters == null || !Filters.Any()) { return; } foreach (IExtractedFilter filter in Filters) { filter.Filter(result); } }
private void Add(ExtractedResult result, HashSet <string> otherRunLocations, int index) { // Find the LocationSpecifier for the Result (the first Uri or FQN also in the other Run) string locationSpecifier = WhereComparer.LocationSpecifier(result, otherRunLocations); // Add Result attributes used as matching hints in a "bucket" for the Rule x LocationSpecifier x AttributeName foreach (WhatComponent component in result.WhatProperties(locationSpecifier)) { Add(component, index); } }
public int GetHashCode(ExtractedResult obj) { int hashCode = -187510987; IEnumerable <ArtifactContent> contextRegions = obj.Result.Locations.Select(loc => loc.PhysicalLocation.ContextRegion.Snippet); foreach (ArtifactContent content in contextRegions) { hashCode ^= ArtifactContentEqualityComparer.Instance.GetHashCode(content); } return(hashCode); }
//TODO Add microtransaction/permission system to collections /// <summary> /// Fuzzy finds an audio entry with the given name/collection:name pair. /// </summary> /// <param name="audioName">Audio name (key) or collection:name pair.</param> /// <returns>The audio entry with the highest search score that passes the minimum score.</returns> /// <exception cref="CollectionNotFoundException"></exception> public static AudioEntry FindAudio(string audioName, bool exact = false) { Dictionary <string, AudioEntry> searchDictEntries = AudioEntries; Dictionary <string, AudioEntry> searchDictAliases = Aliases; if (audioName.Contains(":")) { string[] quantized = audioName.Split(':'); string collectionName = quantized[0]; audioName = quantized[1].Trim(); if (AudioCollections.TryGetValue(collectionName, out AudioCollection audioCollection)) { searchDictEntries = audioCollection.AudioEntries; searchDictAliases = audioCollection.Aliases; } else { throw new CollectionNotFoundException(); } } if (audioName == "random" || audioName == "") { return(searchDictEntries.Values.ElementAt(new Random().Next(searchDictEntries.Count))); } if (searchDictEntries.TryGetValue(audioName, out AudioEntry returnVal) || searchDictAliases.TryGetValue(audioName, out returnVal)) { return(returnVal); } if (exact) { throw new AudioEntryNotFoundException(); } ExtractedResult <string> result = null; if ((result = FuzzySharp.Process.ExtractOne(audioName, searchDictEntries.Keys)) != null && result.Score >= MinimumScore) { return(searchDictEntries.Values.ElementAt(result.Index)); } else if ((result = FuzzySharp.Process.ExtractOne(audioName, searchDictAliases.Keys)) != null && result.Score >= MinimumScore) { return(searchDictAliases.Values.ElementAt(result.Index)); } else { throw new AudioEntryNotFoundException(); } }
public void Filter(ExtractedResult result) { if (string.IsNullOrEmpty(result.Text)) { return; } StringBuilder stringBuilder = new StringBuilder(result.Text); foreach (KeyValuePair <string, string> replacementRule in ReplacementRules) { stringBuilder.Replace(replacementRule.Key, replacementRule.Value); } result.Text = stringBuilder.ToString(); }
public void ContextRegionHeuristicMatcher_SameRegion_MatchesResults() { ExtractedResult resultA = new ExtractedResult(ResultMatchingTestHelpers.CreateMatchingResult("file://test1", "file://test2", null, "region contents"), null); ExtractedResult resultB = new ExtractedResult(ResultMatchingTestHelpers.CreateMatchingResult("file://test3", "file://test4", null, "region contents"), null); IEnumerable <MatchedResults> matchedResults = matcher.Match(new List <ExtractedResult>() { resultA }, new List <ExtractedResult>() { resultB }); matchedResults.Should().HaveCount(1); }
public void PartialFingerprintResultMatcher_WithoutPartialFingerprints_DoesNotMatch() { ExtractedResult resultA = new ExtractedResult(ResultMatchingTestHelpers.CreateMatchingResult("file://test1", "file://test2", null), null); ExtractedResult resultB = new ExtractedResult(ResultMatchingTestHelpers.CreateMatchingResult("file://test3", "file://test4", null), null); IEnumerable <MatchedResults> matchedResults = matcher.Match(new List <ExtractedResult>() { resultA }, new List <ExtractedResult>() { resultB }); matchedResults.Should().BeEmpty(); }
public void ContextRegionHeuristicMatcher_DifferentRegion_DoesNotMatchResults() { ExtractedResult resultA = new ExtractedResult(ResultMatchingTestHelpers.CreateMatchingResult("file://test1", "file://test2", null, "test one"), null); ExtractedResult resultB = new ExtractedResult(ResultMatchingTestHelpers.CreateMatchingResult("file://test3", "file://test4", null, "test two"), null); IEnumerable <MatchedResults> matchedResults = matcher.Match(new List <ExtractedResult>() { resultA }, new List <ExtractedResult>() { resultB }); matchedResults.Should().BeEmpty(); }
private static string GetFirstSnippet(ExtractedResult result) { if (result.Result.Locations != null) { foreach (Location loc in result.Result.Locations) { string snippet = loc?.PhysicalLocation?.Region?.Snippet?.Text; if (snippet != null) { return(snippet); } } } return(null); }
public ExtractedResult Extract(string extensionName, byte[] data, ExtractOption extractOptions) { if (!CanBeExtracted(extensionName, data)) { return(null); } ExtractedResult extractedResult1 = new ExtractedResult(); if ((extractOptions & ExtractOption.Text) == ExtractOption.Text) { try { extractedResult1.Text = ExtractText(extensionName, data); if ((extractOptions & ExtractOption.Image) == ExtractOption.Image) { try { extractedResult1.Images = ExtractAndCompressImages(extensionName, data); } catch (Exception exception) { LoggerWrapper.Logger.Error("抽取图片", exception); } } ExtractedFilterFactory.Filter(extractedResult1); return(extractedResult1); } catch (Exception exception1) { LoggerWrapper.Logger.Error("抽取文本", exception1); } return(null); } if ((extractOptions & ExtractOption.Image) == ExtractOption.Image) { try { extractedResult1.Images = ExtractAndCompressImages(extensionName, data); } catch (Exception exception) { LoggerWrapper.Logger.Error("抽取图片", exception); } } ExtractedFilterFactory.Filter(extractedResult1); return(extractedResult1); }
public static bool AreSufficientlySimiliar(SarifLog baseline, string baselineResultGuid, SarifLog current, string currentResultGuid) { Result bResult = baseline.FindByGuid(baselineResultGuid); Result cResult = current.FindByGuid(currentResultGuid); if (bResult == null || cResult == null) { return(false); } ExtractedResult bExtractedResult = new ExtractedResult(bResult, bResult.Run); ExtractedResult cExtractedResult = new ExtractedResult(cResult, cResult.Run); bool outcome = bExtractedResult.IsSufficientlySimilarTo(cExtractedResult); return(outcome); }
public void IdenticalResultMatcher_MatchesResults_DifferingOnIdOrStatus_Single() { ExtractedResult resultA = new ExtractedResult(ResultMatchingTestHelpers.CreateMatchingResult("file://test", "file://test2", "test context"), null); Result changedResultA = resultA.Result.DeepClone(); changedResultA.CorrelationGuid = Guid.NewGuid().ToString(); changedResultA.BaselineState = BaselineState.Unchanged; ExtractedResult resultB = new ExtractedResult(changedResultA, null); IEnumerable <MatchedResults> matchedResults = matcher.Match(new ExtractedResult[] { resultA }, new ExtractedResult[] { resultB }); matchedResults.Should().HaveCount(1); matchedResults.First().PreviousResult.Should().BeEquivalentTo(resultA); matchedResults.First().CurrentResult.Should().BeEquivalentTo(resultB); }
public void IdenticalResultMatcher_MatchesResults_DifferingOnResultMatchingProperties_Multiple() { ExtractedResult resultAA = new ExtractedResult() { Result = ResultMatchingTestHelpers.CreateMatchingResult("file://test", "file://test2", "test context") }; Result changedResultA = resultAA.Result.DeepClone(); changedResultA.CorrelationGuid = Guid.NewGuid().ToString(); changedResultA.BaselineState = BaselineState.Unchanged; changedResultA.SetProperty(SarifLogResultMatcher.ResultMatchingResultPropertyName, new Dictionary <string, string> { { "property", "value" } }); ExtractedResult resultBA = new ExtractedResult() { Result = changedResultA }; ExtractedResult resultAB = new ExtractedResult() { Result = ResultMatchingTestHelpers.CreateMatchingResult("file://test", "file://test2", "test context2") }; Result changedResultB = resultAB.Result.DeepClone(); changedResultA.CorrelationGuid = Guid.NewGuid().ToString(); changedResultA.BaselineState = BaselineState.New; changedResultB.SetProperty(SarifLogResultMatcher.ResultMatchingResultPropertyName, new Dictionary <string, string> { { "property1", "value1" } }); ExtractedResult resultBB = new ExtractedResult() { Result = changedResultB }; IEnumerable <MatchedResults> matchedResults = matcher.Match(new ExtractedResult[] { resultAA, resultAB }, new ExtractedResult[] { resultBA, resultBB }); matchedResults.Should().HaveCount(2); matchedResults.Where(f => f.PreviousResult == resultAA && f.CurrentResult == resultBA).Should().HaveCount(1); matchedResults.Where(f => f.PreviousResult == resultAB && f.CurrentResult == resultBB).Should().HaveCount(1); }
private static string GetCanonicalizedMessage(ExtractedResult result) { string rawMessage = result.Result.GetMessageText(result.Result.GetRule(result.OriginalRun)); // Canonicalize the message by replacing any line numbers in it with consistent markers Region firstRegion = result.Result?.Locations?.FirstOrDefault()?.PhysicalLocation?.Region; if (firstRegion != null) { rawMessage = rawMessage .Replace(firstRegion.StartLine.ToString(CultureInfo.InvariantCulture), "~SL~") .Replace(firstRegion.StartColumn.ToString(CultureInfo.InvariantCulture), "~SC~") .Replace(firstRegion.EndLine.ToString(CultureInfo.InvariantCulture), "~EL~") .Replace(firstRegion.EndColumn.ToString(CultureInfo.InvariantCulture), "~EC~"); } return(rawMessage); }