protected internal static string GetSignatureStatus(string Path) { if (!WindowsFileSystemUtils.NeedsSignature(Path)) { return(""); } string sigStatus = WinTrust.VerifyEmbeddedSignature(Path); return(sigStatus); }
/// <summary> /// Converts a FileSystemInfo into a FileSystemObject by reading in data about the file /// </summary> /// <param name="fileInfo">A reference to a file on disk.</param> /// <param name="downloadCloud">If the file is hosted in the cloud, the user has the option to include cloud files or not.</param> /// <param name="INCLUDE_CONTENT_HASH">If we should generate a hash of the file.</param> /// <returns></returns> public static FileSystemObject FileSystemInfoToFileSystemObject(FileSystemInfo fileInfo, bool downloadCloud = false, bool INCLUDE_CONTENT_HASH = false) { if (fileInfo == null) { return(null); } FileSystemObject obj = new FileSystemObject() { Path = fileInfo.FullName, PermissionsString = FileSystemUtils.GetFilePermissions(fileInfo), }; // Get Owner/Group if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { try { var fileSecurity = new FileSecurity(fileInfo.FullName, AccessControlSections.All); IdentityReference oid = fileSecurity.GetOwner(typeof(SecurityIdentifier)); IdentityReference gid = fileSecurity.GetGroup(typeof(SecurityIdentifier)); // Set the Owner and Group to the SID, in case we can't properly translate obj.Owner = oid.ToString(); obj.Group = gid.ToString(); try { // Translate owner into the string representation. obj.Owner = (oid.Translate(typeof(NTAccount)) as NTAccount).Value; } catch (IdentityNotMappedException) { Log.Verbose("Couldn't find the Owner from SID {0} for file {1}", oid.ToString(), fileInfo.FullName); } try { // Translate group into the string representation. obj.Group = (gid.Translate(typeof(NTAccount)) as NTAccount).Value; } catch (IdentityNotMappedException) { // This is fine. Some SIDs don't map to NT Accounts. Log.Verbose("Couldn't find the Group from SID {0} for file {1}", gid.ToString(), fileInfo.FullName); } var rules = fileSecurity.GetAccessRules(true, true, typeof(System.Security.Principal.SecurityIdentifier)); foreach (FileSystemAccessRule rule in rules) { string name = rule.IdentityReference.Value; try { name = rule.IdentityReference.Translate(typeof(NTAccount)).Value; } catch (IdentityNotMappedException) { // This is fine. Some SIDs don't map to NT Accounts. } foreach (var permission in rule.FileSystemRights.ToString().Split(',')) { obj.Permissions.Add(new KeyValuePair <string, string>(name, permission)); } } } catch (Exception e) when( e is ArgumentException || e is ArgumentNullException || e is DirectoryNotFoundException || e is FileNotFoundException || e is IOException || e is NotSupportedException || e is PlatformNotSupportedException || e is PathTooLongException || e is PrivilegeNotHeldException || e is SystemException || e is UnauthorizedAccessException) { Log.Verbose($"Error instantiating FileSecurity object {obj.Path} {e.GetType().ToString()}"); } } else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux) || RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) { try { var file = new UnixFileInfo(fileInfo.FullName); obj.Owner = file.OwnerUser.UserName; obj.Group = file.OwnerGroup.GroupName; obj.SetGid = file.IsSetGroup; obj.SetUid = file.IsSetUser; if (file.FileAccessPermissions.ToString().Equals("AllPermissions", StringComparison.InvariantCulture)) { obj.Permissions.Add(new KeyValuePair <string, string>("User", "Read")); obj.Permissions.Add(new KeyValuePair <string, string>("User", "Write")); obj.Permissions.Add(new KeyValuePair <string, string>("User", "Execute")); obj.Permissions.Add(new KeyValuePair <string, string>("Group", "Read")); obj.Permissions.Add(new KeyValuePair <string, string>("Group", "Write")); obj.Permissions.Add(new KeyValuePair <string, string>("Group", "Execute")); obj.Permissions.Add(new KeyValuePair <string, string>("Other", "Read")); obj.Permissions.Add(new KeyValuePair <string, string>("Other", "Write")); obj.Permissions.Add(new KeyValuePair <string, string>("Other", "Execute")); } else { foreach (var permission in file.FileAccessPermissions.ToString().Split(',').Where((x) => x.Trim().StartsWith("User", StringComparison.InvariantCulture))) { if (permission.Contains("ReadWriteExecute", StringComparison.InvariantCulture)) { obj.Permissions.Add(new KeyValuePair <string, string>("User", "Read")); obj.Permissions.Add(new KeyValuePair <string, string>("User", "Write")); obj.Permissions.Add(new KeyValuePair <string, string>("User", "Execute")); } else { obj.Permissions.Add(new KeyValuePair <string, string>("User", permission.Trim().Substring(4))); } } foreach (var permission in file.FileAccessPermissions.ToString().Split(',').Where((x) => x.Trim().StartsWith("Group", StringComparison.InvariantCulture))) { if (permission.Contains("ReadWriteExecute", StringComparison.InvariantCulture)) { obj.Permissions.Add(new KeyValuePair <string, string>("Group", "Read")); obj.Permissions.Add(new KeyValuePair <string, string>("Group", "Write")); obj.Permissions.Add(new KeyValuePair <string, string>("Group", "Execute")); } else { obj.Permissions.Add(new KeyValuePair <string, string>("Group", permission.Trim().Substring(5))); } } foreach (var permission in file.FileAccessPermissions.ToString().Split(',').Where((x) => x.Trim().StartsWith("Other", StringComparison.InvariantCulture))) { if (permission.Contains("ReadWriteExecute", StringComparison.InvariantCulture)) { obj.Permissions.Add(new KeyValuePair <string, string>("Other", "Read")); obj.Permissions.Add(new KeyValuePair <string, string>("Other", "Write")); obj.Permissions.Add(new KeyValuePair <string, string>("Other", "Execute")); } else { obj.Permissions.Add(new KeyValuePair <string, string>("Other", permission.Trim().Substring(5))); } } } } catch (Exception e) when( e is ArgumentNullException || e is ArgumentException) { Log.Verbose($"Failed to get permissions for {fileInfo.FullName} {e.GetType().ToString()}"); } } if (fileInfo is DirectoryInfo) { obj.IsDirectory = true; } else if (fileInfo is FileInfo) { obj.Size = (ulong)(fileInfo as FileInfo).Length; obj.IsDirectory = false; if (INCLUDE_CONTENT_HASH) { obj.ContentHash = FileSystemUtils.GetFileHash(fileInfo); } // Set IsExecutable and Signature Status if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { if (WindowsFileSystemUtils.IsLocal(obj.Path) || downloadCloud) { if (WindowsFileSystemUtils.NeedsSignature(obj.Path)) { obj.SignatureStatus = WindowsFileSystemUtils.GetSignatureStatus(fileInfo.FullName); obj.Characteristics.AddRange(WindowsFileSystemUtils.GetDllCharacteristics(fileInfo.FullName)); obj.IsExecutable = FileSystemUtils.IsExecutable(obj.Path); } } } else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux) || RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) { obj.IsExecutable = FileSystemUtils.IsExecutable(obj.Path); } } return(obj); }
public override void Execute() { if (!CanRunOnPlatform()) { return; } Start(); if (roots == null || !roots.Any()) { if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { foreach (var driveInfo in DriveInfo.GetDrives()) { if (driveInfo.IsReady && driveInfo.DriveType == DriveType.Fixed) { roots.Add(driveInfo.Name); } } } else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) { roots.Add("/"); // @TODO Improve this } else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) { roots.Add("/"); // @TODO Improve this } } foreach (var root in roots) { Log.Information("{0} root {1}", Strings.Get("Scanning"), root.ToString()); //Ensure the transaction is started to prevent collisions on the multithreaded code ahead _ = DatabaseManager.Transaction; try { var fileInfoEnumerable = DirectoryWalker.WalkDirectory(root); Parallel.ForEach(fileInfoEnumerable, (fileInfo => { try { FileSystemObject obj = null; if (fileInfo is DirectoryInfo) { obj = new FileSystemObject() { Path = fileInfo.FullName, Permissions = FileSystemUtils.GetFilePermissions(fileInfo), IsDirectory = true }; if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux) || RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) { var file = new UnixFileInfo(fileInfo.FullName); obj.Owner = file.OwnerUser.UserName; obj.Group = file.OwnerGroup.GroupName; obj.SetGid = file.IsSetGroup; obj.SetUid = file.IsSetUser; } } else { obj = new FileSystemObject() { Path = fileInfo.FullName, Permissions = FileSystemUtils.GetFilePermissions(fileInfo), Size = (ulong)(fileInfo as FileInfo).Length, IsDirectory = false }; if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux) || RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) { var file = new UnixFileInfo(fileInfo.FullName); obj.Owner = file.OwnerUser.UserName; obj.Group = file.OwnerGroup.GroupName; obj.SetGid = file.IsSetGroup; obj.SetUid = file.IsSetUser; } if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { if (WindowsFileSystemUtils.IsLocal(obj.Path) || downloadCloud) { if (WindowsFileSystemUtils.NeedsSignature(obj.Path)) { obj.SignatureStatus = WindowsFileSystemUtils.GetSignatureStatus(fileInfo.FullName); obj.Characteristics = WindowsFileSystemUtils.GetDllCharacteristics(fileInfo.FullName); } else { obj.SignatureStatus = "Cloud"; } } } if (INCLUDE_CONTENT_HASH) { obj.ContentHash = FileSystemUtils.GetFileHash(fileInfo); } if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux) || RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) { if (obj.Permissions.Contains("Execute")) { obj.IsExecutable = true; } } else { try { if (WindowsFileSystemUtils.IsLocal(obj.Path) || downloadCloud) { if (WindowsFileSystemUtils.NeedsSignature(obj.Path)) { obj.IsExecutable = true; } } } catch (System.UnauthorizedAccessException ex) { Log.Verbose(ex, "Couldn't access {0} to check if signature is needed.", fileInfo.FullName); } } } if (obj != null) { DatabaseManager.Write(obj, runId); if (examineCertificates && fileInfo.FullName.EndsWith(".cer", StringComparison.CurrentCulture) || fileInfo.FullName.EndsWith(".der", StringComparison.CurrentCulture) || fileInfo.FullName.EndsWith(".p7b", StringComparison.CurrentCulture)) { var certificate = X509Certificate.CreateFromCertFile(fileInfo.FullName); var certObj = new CertificateObject() { StoreLocation = fileInfo.FullName, StoreName = "Disk", CertificateHashString = certificate.GetCertHashString(), Subject = certificate.Subject, Pkcs7 = certificate.Export(X509ContentType.Cert).ToString() }; DatabaseManager.Write(certObj, runId); } } } catch (System.UnauthorizedAccessException e) { Log.Verbose(e, "Access Denied {0}", fileInfo?.FullName); } catch (System.IO.IOException e) { Log.Verbose(e, "Couldn't parse {0}", fileInfo?.FullName); } catch (Exception e) { Logger.DebugException(e); } })); } catch (Exception e) { Log.Warning(e, "Error collecting file system information: {0}", e.Message); } DatabaseManager.Commit(); } Stop(); }
public static FileSystemObject FileSystemInfoToFileSystemObject(FileSystemInfo fileInfo, bool downloadCloud = false, bool INCLUDE_CONTENT_HASH = false) { FileSystemObject obj = null; try { if (fileInfo is DirectoryInfo) { obj = new FileSystemObject() { Path = fileInfo.FullName, Permissions = FileSystemUtils.GetFilePermissions(fileInfo), IsDirectory = true }; if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux) || RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) { var file = new UnixFileInfo(fileInfo.FullName); obj.Owner = file.OwnerUser.UserName; obj.Group = file.OwnerGroup.GroupName; obj.SetGid = file.IsSetGroup; obj.SetUid = file.IsSetUser; } } else { obj = new FileSystemObject() { Path = fileInfo.FullName, Permissions = FileSystemUtils.GetFilePermissions(fileInfo), Size = (ulong)(fileInfo as FileInfo).Length, IsDirectory = false }; if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux) || RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) { var file = new UnixFileInfo(fileInfo.FullName); obj.Owner = file.OwnerUser.UserName; obj.Group = file.OwnerGroup.GroupName; obj.SetGid = file.IsSetGroup; obj.SetUid = file.IsSetUser; } if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { if (WindowsFileSystemUtils.IsLocal(obj.Path) || downloadCloud) { if (WindowsFileSystemUtils.NeedsSignature(obj.Path)) { obj.SignatureStatus = WindowsFileSystemUtils.GetSignatureStatus(fileInfo.FullName); obj.Characteristics = WindowsFileSystemUtils.GetDllCharacteristics(fileInfo.FullName); } else { obj.SignatureStatus = "Cloud"; } } } if (INCLUDE_CONTENT_HASH) { obj.ContentHash = FileSystemUtils.GetFileHash(fileInfo); } if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux) || RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) { if (obj.Permissions.Contains("Execute")) { obj.IsExecutable = true; } } else { try { if (WindowsFileSystemUtils.IsLocal(obj.Path) || downloadCloud) { if (WindowsFileSystemUtils.NeedsSignature(obj.Path)) { obj.IsExecutable = true; } } } catch (System.UnauthorizedAccessException ex) { Log.Verbose(ex, "Couldn't access {0} to check if signature is needed.", fileInfo.FullName); } } } } catch (System.UnauthorizedAccessException e) { Log.Verbose(e, "Access Denied {0}", fileInfo?.FullName); } catch (System.IO.IOException e) { Log.Verbose(e, "Couldn't parse {0}", fileInfo?.FullName); } catch (Exception e) { Log.Warning(e, "Error collecting file system information: {0}", e.Message); } return(obj); }
/// <summary> /// Converts a FileSystemInfo into a FileSystemObject by reading in data about the file /// </summary> /// <param name="fileInfo">A reference to a file on disk.</param> /// <param name="downloadCloud">If the file is hosted in the cloud, the user has the option to include cloud files or not.</param> /// <param name="INCLUDE_CONTENT_HASH">If we should generate a hash of the file.</param> /// <returns></returns> public static FileSystemObject FileSystemInfoToFileSystemObject(FileSystemInfo fileInfo, bool downloadCloud = false, bool INCLUDE_CONTENT_HASH = false) { FileSystemObject obj = new FileSystemObject() { Path = fileInfo.FullName, PermissionsString = FileSystemUtils.GetFilePermissions(fileInfo), }; try { // Get Owner/Group if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { var fileSecurity = new FileSecurity(fileInfo.FullName, AccessControlSections.All); IdentityReference oid = fileSecurity.GetOwner(typeof(SecurityIdentifier)); IdentityReference gid = fileSecurity.GetGroup(typeof(SecurityIdentifier)); // Set the Owner and Group to the SID, in case we can't properly translate obj.Owner = oid.ToString(); obj.Group = gid.ToString(); try { // Translate owner into the string representation. obj.Owner = (oid.Translate(typeof(NTAccount)) as NTAccount).Value; } catch (IdentityNotMappedException) { Log.Verbose("Couldn't find the Owner from SID {0} for file {1}", oid.ToString(), fileInfo.FullName); } try { // Translate group into the string representation. obj.Group = (gid.Translate(typeof(NTAccount)) as NTAccount).Value; } catch (IdentityNotMappedException) { // This is fine. Some SIDs don't map to NT Accounts. Log.Verbose("Couldn't find the Group from SID {0} for file {1}", gid.ToString(), fileInfo.FullName); } obj.Permissions = new List <KeyValuePair <string, string> >(); var rules = fileSecurity.GetAccessRules(true, true, typeof(System.Security.Principal.SecurityIdentifier)); foreach (FileSystemAccessRule rule in rules) { string name = rule.IdentityReference.Value; try { name = rule.IdentityReference.Translate(typeof(NTAccount)).Value; } catch (IdentityNotMappedException) { // This is fine. Some SIDs don't map to NT Accounts. } foreach (var permission in rule.FileSystemRights.ToString().Split(',')) { obj.Permissions.Add(new KeyValuePair <string, string>(name, permission)); } } } else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux) || RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) { var file = new UnixFileInfo(fileInfo.FullName); obj.Owner = file.OwnerUser.UserName; obj.Group = file.OwnerGroup.GroupName; obj.SetGid = file.IsSetGroup; obj.SetUid = file.IsSetUser; obj.Permissions = new List <KeyValuePair <string, string> >(); if (file.FileAccessPermissions.ToString().Equals("AllPermissions")) { obj.Permissions.Add(new KeyValuePair <string, string>("User", "Read")); obj.Permissions.Add(new KeyValuePair <string, string>("User", "Write")); obj.Permissions.Add(new KeyValuePair <string, string>("User", "Execute")); obj.Permissions.Add(new KeyValuePair <string, string>("Group", "Read")); obj.Permissions.Add(new KeyValuePair <string, string>("Group", "Write")); obj.Permissions.Add(new KeyValuePair <string, string>("Group", "Execute")); obj.Permissions.Add(new KeyValuePair <string, string>("Other", "Read")); obj.Permissions.Add(new KeyValuePair <string, string>("Other", "Write")); obj.Permissions.Add(new KeyValuePair <string, string>("Other", "Execute")); } else { foreach (var permission in file.FileAccessPermissions.ToString().Split(',').Where((x) => x.Trim().StartsWith("User"))) { if (permission.Contains("ReadWriteExecute")) { obj.Permissions.Add(new KeyValuePair <string, string>("User", "Read")); obj.Permissions.Add(new KeyValuePair <string, string>("User", "Write")); obj.Permissions.Add(new KeyValuePair <string, string>("User", "Execute")); } else { obj.Permissions.Add(new KeyValuePair <string, string>("User", permission.Trim().Substring(4))); } } foreach (var permission in file.FileAccessPermissions.ToString().Split(',').Where((x) => x.Trim().StartsWith("Group"))) { if (permission.Contains("ReadWriteExecute")) { obj.Permissions.Add(new KeyValuePair <string, string>("Group", "Read")); obj.Permissions.Add(new KeyValuePair <string, string>("Group", "Write")); obj.Permissions.Add(new KeyValuePair <string, string>("Group", "Execute")); } else { obj.Permissions.Add(new KeyValuePair <string, string>("Group", permission.Trim().Substring(5))); } } foreach (var permission in file.FileAccessPermissions.ToString().Split(',').Where((x) => x.Trim().StartsWith("Other"))) { if (permission.Contains("ReadWriteExecute")) { obj.Permissions.Add(new KeyValuePair <string, string>("Other", "Read")); obj.Permissions.Add(new KeyValuePair <string, string>("Other", "Write")); obj.Permissions.Add(new KeyValuePair <string, string>("Other", "Execute")); } else { obj.Permissions.Add(new KeyValuePair <string, string>("Other", permission.Trim().Substring(5))); } } } } if (fileInfo is DirectoryInfo) { obj.IsDirectory = true; } else if (fileInfo is FileInfo) { obj.Size = (ulong)(fileInfo as FileInfo).Length; obj.IsDirectory = false; if (INCLUDE_CONTENT_HASH) { obj.ContentHash = FileSystemUtils.GetFileHash(fileInfo); } // Set IsExecutable and Signature Status if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { if (WindowsFileSystemUtils.IsLocal(obj.Path) || downloadCloud) { try { if (WindowsFileSystemUtils.NeedsSignature(obj.Path)) { obj.SignatureStatus = WindowsFileSystemUtils.GetSignatureStatus(fileInfo.FullName); obj.Characteristics = WindowsFileSystemUtils.GetDllCharacteristics(fileInfo.FullName); obj.IsExecutable = FileSystemUtils.IsExecutable(obj.Path); } } catch (System.UnauthorizedAccessException ex) { Log.Verbose(ex, "Couldn't access {0} to check if signature is needed.", fileInfo.FullName); } } } else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux) || RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) { obj.IsExecutable = FileSystemUtils.IsExecutable(obj.Path); } } } catch (System.UnauthorizedAccessException e) { Log.Verbose(e, "Access Denied {0}", fileInfo?.FullName); } catch (System.IO.IOException e) { Log.Verbose(e, "Couldn't parse {0}", fileInfo?.FullName); } catch (Exception e) { Log.Warning(e, "Error collecting file system information: {0}", e.Message); } return(obj); }
public override void Execute() { if (!CanRunOnPlatform()) { return; } Start(); //Ensure the transaction is started to prevent collisions on the multithreaded code ahead _ = DatabaseManager.Transaction; if (roots == null || !roots.Any()) { if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { foreach (var driveInfo in DriveInfo.GetDrives()) { if (driveInfo.IsReady && driveInfo.DriveType == DriveType.Fixed) { roots.Add(driveInfo.Name); } } } else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) { roots.Add("/"); // @TODO Improve this } else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) { roots.Add("/"); // @TODO Improve this } } foreach (var root in roots) { Log.Information("{0} root {1}",Strings.Get("Scanning"),root.ToString()); try { var fileInfoEnumerable = DirectoryWalker.WalkDirectory(root, Helpers.GetPlatformString()); Parallel.ForEach(fileInfoEnumerable, (fileInfo => { try { FileSystemObject obj = null; if (fileInfo is DirectoryInfo) { obj = new FileSystemObject() { Path = fileInfo.FullName, Permissions = FileSystemUtils.GetFilePermissions(fileInfo), IsDirectory = true }; } else { obj = new FileSystemObject() { Path = fileInfo.FullName, Permissions = FileSystemUtils.GetFilePermissions(fileInfo), Size = (ulong)(fileInfo as FileInfo).Length, IsDirectory = false }; if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { if (WindowsFileSystemUtils.IsLocal(obj.Path) || downloadCloud) { if (WindowsFileSystemUtils.NeedsSignature(obj.Path)) { obj.SignatureStatus = WindowsFileSystemUtils.GetSignatureStatus(fileInfo.FullName); obj.Characteristics = WindowsFileSystemUtils.GetDllCharacteristics(fileInfo.FullName); } else { obj.SignatureStatus = "Cloud"; } } } if (INCLUDE_CONTENT_HASH) { obj.ContentHash = FileSystemUtils.GetFileHash(fileInfo); } if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux) || RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) { if (obj.Permissions.Contains("Execute")) { obj.IsExecutable = true; } } else { // TODO: Improve this to detect executables more intelligently if (WindowsFileSystemUtils.NeedsSignature(obj.Path)) { obj.IsExecutable = true; } } if () } if (obj != null) { DatabaseManager.Write(obj,runId); } } catch (Exception ex) { Log.Warning(ex, "Error processing {0}", fileInfo?.FullName); } })); } catch (Exception ex) { Log.Warning(ex, "Error collecting file system information: {0}", ex.Message); } } Stop(); DatabaseManager.Commit(); }