From 2ff3fa6a8d56bc1b5d7900cc2348e9e71fe730df Mon Sep 17 00:00:00 2001 From: Kenneth Skovhede Date: Tue, 31 Oct 2017 10:57:37 +0100 Subject: [PATCH] Added support for reading the list of folder/file exclusion from the Windows registry --- Duplicati/Library/Utility/DefaultFilters.cs | 65 ++++++++++++++++++++- 1 file changed, 64 insertions(+), 1 deletion(-) 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(); + } + } }