diff --git a/Duplicati/Library/Utility/DefaultFilters.cs b/Duplicati/Library/Utility/DefaultFilters.cs
index 2b59e67eb..b88a7be8b 100644
--- a/Duplicati/Library/Utility/DefaultFilters.cs
+++ b/Duplicati/Library/Utility/DefaultFilters.cs
@@ -178,7 +178,7 @@ namespace Duplicati.Library.Utility
/// Windows filters
private static string[] CreateWindowsFilters()
{
- return new[]
+ var filters = new[]
{
DefaultFilters.CreateWildcardFilter(@"*.rbf"),
DefaultFilters.CreateWildcardFilter(@"*.tmp"),
@@ -233,6 +233,12 @@ namespace Duplicati.Library.Utility
DefaultFilters.CreateWildcardFilter(@"?:/Windows/Installer*"),
DefaultFilters.CreateWildcardFilter(@"?:/Windows/Temp*"),
};
+
+ var extra = GetWindowsRegistryFilters();
+ if (extra == null || extra.Length == 0)
+ return filters;
+
+ return filters.Union(extra).ToArray();
}
///
@@ -368,5 +374,62 @@ namespace Duplicati.Library.Utility
string escaped = System.Text.RegularExpressions.Regex.Escape(System.IO.Path.DirectorySeparatorChar.ToString());
return "[" + filter.Replace(escapedAlt, escaped) + "]";
}
+
+ ///
+ /// Wrapper method for getting a list of exclude paths from the Windows registry.
+ /// This method guards the call to to avoid loader errors.
+ ///
+ /// The list of paths to exclude.
+ private static string[] GetWindowsRegistryFilters()
+ {
+ try
+ {
+ return GetWindowsRegistryFiltersInternal();
+ }
+ catch
+ {
+ }
+
+ return new string[0];
+ }
+
+ ///
+ /// Helper method that reads the Windows registry and finds paths to exclude.
+ /// This method should not be called directly as that could cause loader errors on Mono.
+ ///
+ /// The list of paths to exclude.
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]
+ private static string[] GetWindowsRegistryFiltersInternal()
+ {
+ var rk = Microsoft.Win32.RegistryKey.OpenBaseKey(Microsoft.Win32.RegistryHive.LocalMachine, Microsoft.Win32.RegistryView.Default);
+ if (rk == null)
+ return new string[0];
+
+ var sk = rk.OpenSubKey(@"SYSTEM\CurrentControlSet\Control\BackupRestore\FilesNotToBackup");
+ if (sk == null)
+ return new string[0];
+
+ // Each value in this key is a potential path
+ return sk.GetValueNames()
+ .Where(x => x != null)
+ .SelectMany(x =>
+ {
+ var v = sk.GetValue(x);
+ if (v is string)
+ return new string[] { (string)v };
+ else if (v is string[])
+ return (string[])v;
+ else
+ return new string[0];
+ })
+ .Where(x => !string.IsNullOrWhiteSpace(x))
+ .Select(x => Environment.ExpandEnvironmentVariables(x))
+ .Where(x => !string.IsNullOrWhiteSpace(x))
+ .Where(x => x.IndexOfAny(System.IO.Path.GetInvalidPathChars()) < 0)
+ .Where(x => System.IO.Path.IsPathRooted(x))
+ .Select(x => x.EndsWith(" /s", StringComparison.OrdinalIgnoreCase) ? x.Substring(0, x.Length - 3).TrimEnd() : x)
+ .ToArray();
+ }
+
}
}