public void UpdateDeletedAddins(IProgressStatus monitor, AddinScanFolderInfo folderInfo, AddinScanResult scanResult) { ArrayList missing = folderInfo.GetMissingAddins(); if (missing.Count > 0) { if (Directory.Exists(folderInfo.Folder)) { scanResult.ModifiedFolderInfos.Add(folderInfo); } scanResult.ChangesFound = true; if (scanResult.CheckOnly) { return; } foreach (AddinFileInfo info in missing) { if (info.IsRoot) { database.UninstallRootAddin(monitor, info.AddinId, info.File, scanResult); } else { database.UninstallAddin(monitor, info.AddinId, scanResult); } } } }
public void RegisterModifiedFolderInfo(AddinScanFolderInfo folderInfo) { if (!ModifiedFolderInfos.Contains(folderInfo)) { ModifiedFolderInfos.Add(folderInfo); } }
public void AddFileToScan(string file, AddinScanFolderInfo folderInfo) { FileToScan di = new FileToScan(); di.File = file; di.AddinScanFolderInfo = folderInfo; FilesToScan.Add(di); RegisterModifiedFolderInfo(folderInfo); }
public static AddinScanFolderInfo Read(FileDatabase filedb, string file) { AddinScanFolderInfo finfo = (AddinScanFolderInfo)filedb.ReadSharedObject(file, typeMap); if (finfo != null) { finfo.fileName = file; } return(finfo); }
public static AddinScanFolderInfo Read(FileDatabase filedb, string basePath, string folderPath) { string fileName; AddinScanFolderInfo finfo = (AddinScanFolderInfo)filedb.ReadSharedObject(basePath, GetDomain(folderPath), ".data", Path.GetFullPath(folderPath), typeMap, out fileName); if (finfo != null) { finfo.fileName = fileName; } return(finfo); }
public void AddFileToScan(string file, AddinScanFolderInfo folderInfo) { FileToScan di = new FileToScan(); di.File = file; di.AddinScanFolderInfo = folderInfo; FilesToScan.Add(di); if (!ModifiedFolderInfos.Contains(folderInfo)) { ModifiedFolderInfos.Add(folderInfo); } }
void RegisterFileToScan(IProgressStatus monitor, string file, AddinScanFolderInfo folderInfo, AddinScanData scanData) { AddinFileInfo finfo = folderInfo.GetAddinFileInfo(file); bool added = false; if (finfo != null && (!finfo.IsAddin || finfo.Domain == folderInfo.GetDomain(finfo.IsRoot)) && !finfo.HasChanged(FileSystem, scanData?.MD5) && !scanResult.RegenerateAllData) { if (finfo.ScanError) { // Always schedule the file for scan if there was an error in a previous scan. // However, don't set ChangesFound=true, in this way if there isn't any other // change in the registry, the file won't be scanned again. scanResult.AddFileToScan(file, folderInfo, scanData); added = true; } if (!finfo.IsAddin) { return; } if (database.AddinDescriptionExists(finfo.Domain, finfo.AddinId)) { // It is an add-in and it has not changed. Paths in the ignore list // are still valid, so they can be used. if (finfo.IgnorePaths != null) { scanResult.ScanContext.AddPathsToIgnore(finfo.IgnorePaths); } return; } } scanResult.ChangesFound = true; if (!scanResult.CheckOnly && !added) { scanResult.AddFileToScan(file, folderInfo, scanData); } }
public void UpdateDeletedAddins(IProgressStatus monitor, AddinScanFolderInfo folderInfo) { var missing = folderInfo.GetMissingAddins(FileSystem); if (missing.Count > 0) { if (FileSystem.DirectoryExists(folderInfo.Folder)) { scanResult.RegisterModifiedFolderInfo(folderInfo); } scanResult.ChangesFound = true; if (scanResult.CheckOnly) { return; } foreach (AddinFileInfo info in missing) { database.UninstallAddin(monitor, info.Domain, info.AddinId, info.File, scanResult); } } }
void RegisterFileToScan(IProgressStatus monitor, string file, AddinScanResult scanResult, AddinScanFolderInfo folderInfo) { if (scanResult.LocateAssembliesOnly) return; AddinFileInfo finfo = folderInfo.GetAddinFileInfo (file); bool added = false; if (finfo != null && (!finfo.IsAddin || finfo.Domain == folderInfo.GetDomain (finfo.IsRoot)) && fs.GetLastWriteTime (file) == finfo.LastScan && !scanResult.RegenerateAllData) { if (finfo.ScanError) { // Always schedule the file for scan if there was an error in a previous scan. // However, don't set ChangesFound=true, in this way if there isn't any other // change in the registry, the file won't be scanned again. scanResult.AddFileToScan (file, folderInfo); added = true; } if (!finfo.IsAddin) return; if (database.AddinDescriptionExists (finfo.Domain, finfo.AddinId)) { // It is an add-in and it has not changed. Paths in the ignore list // are still valid, so they can be used. if (finfo.IgnorePaths != null) scanResult.AddPathsToIgnore (finfo.IgnorePaths); return; } } scanResult.ChangesFound = true; if (!scanResult.CheckOnly && !added) scanResult.AddFileToScan (file, folderInfo); }
public void UpdateDeletedAddins(IProgressStatus monitor, AddinScanFolderInfo folderInfo, AddinScanResult scanResult) { ArrayList missing = folderInfo.GetMissingAddins (fs); if (missing.Count > 0) { if (fs.DirectoryExists (folderInfo.Folder)) scanResult.RegisterModifiedFolderInfo (folderInfo); scanResult.ChangesFound = true; if (scanResult.CheckOnly) return; foreach (AddinFileInfo info in missing) { database.UninstallAddin (monitor, info.Domain, info.AddinId, info.File, scanResult); } } }
public void ScanFolder(IProgressStatus monitor, string path, string domain, AddinScanResult scanResult) { path = Path.GetFullPath (path); // Avoid folders including each other if (!scanResult.VisitFolder (path)) return; AddinScanFolderInfo folderInfo; if (!database.GetFolderInfoForPath (monitor, path, out folderInfo)) { // folderInfo file was corrupt. // Just in case, we are going to regenerate all relation data. if (!fs.DirectoryExists (path)) scanResult.RegenerateRelationData = true; } else { // Directory is included but it doesn't exist. Ignore it. if (folderInfo == null && !fs.DirectoryExists (path)) return; } // if domain is null it means that a new domain has to be created. bool sharedFolder = domain == AddinDatabase.GlobalDomain; bool isNewFolder = folderInfo == null; if (isNewFolder) { // No folder info. It is the first time this folder is scanned. // There is no need to store this object if the folder does not // contain add-ins. folderInfo = new AddinScanFolderInfo (path); } if (!sharedFolder && (folderInfo.SharedFolder || folderInfo.Domain != domain)) { // If the folder already has a domain, reuse it if (domain == null && folderInfo.RootsDomain != null && folderInfo.RootsDomain != AddinDatabase.GlobalDomain) domain = folderInfo.RootsDomain; else if (domain == null) { folderInfo.Domain = domain = database.GetUniqueDomainId (); scanResult.RegenerateRelationData = true; } else { folderInfo.Domain = domain; if (!isNewFolder) { // Domain has changed. Update the folder info and regenerate everything. scanResult.RegenerateRelationData = true; scanResult.RegisterModifiedFolderInfo (folderInfo); } } } else if (!folderInfo.SharedFolder && sharedFolder) { scanResult.RegenerateRelationData = true; } folderInfo.SharedFolder = sharedFolder; // If there is no domain assigned to the host, get one now if (scanResult.Domain == AddinDatabase.UnknownDomain) scanResult.Domain = domain; // Discard folders not belonging to the required domain if (scanResult.Domain != null && domain != scanResult.Domain && domain != AddinDatabase.GlobalDomain) { return; } if (monitor.LogLevel > 1 && !scanResult.LocateAssembliesOnly) monitor.Log ("Checking: " + path); if (fs.DirectoryExists (path)) { IEnumerable<string> files = fs.GetFiles (path); // First of all, look for .addin files. Addin files must be processed before // assemblies, because they may add files to the ignore list (i.e., assemblies // included in .addin files won't be scanned twice). foreach (string file in files) { if (file.EndsWith (".addin.xml") || file.EndsWith (".addin")) { RegisterFileToScan (monitor, file, scanResult, folderInfo); } } // Now scan assemblies. They can also add files to the ignore list. foreach (string file in files) { string ext = Path.GetExtension (file).ToLower (); if (ext == ".dll" || ext == ".exe") { RegisterFileToScan (monitor, file, scanResult, folderInfo); scanResult.AddAssemblyLocation (file); } } // Finally scan .addins files foreach (string file in files) { if (Path.GetExtension (file).EndsWith (".addins")) { ScanAddinsFile (monitor, file, domain, scanResult); } } } else if (!scanResult.LocateAssembliesOnly) { // The folder has been deleted. All add-ins defined in that folder should also be deleted. scanResult.RegenerateRelationData = true; scanResult.ChangesFound = true; if (scanResult.CheckOnly) return; database.DeleteFolderInfo (monitor, folderInfo); } if (scanResult.LocateAssembliesOnly) return; // Look for deleted add-ins. UpdateDeletedAddins (monitor, folderInfo, scanResult); }
public void ScanFile(IProgressStatus monitor, string file, AddinScanFolderInfo folderInfo, AddinScanResult scanResult) { if (scanResult.IgnorePath (file)) { // The file must be ignored. Maybe it caused a crash in a previous scan, or it // might be included by a .addin file (in which case it will be scanned when processing // the .addin file). folderInfo.SetLastScanTime (file, null, false, fs.GetLastWriteTime (file), true); return; } if (monitor.LogLevel > 1) monitor.Log ("Scanning file: " + file); // Log the file to be scanned, so in case of a process crash the main process // will know what crashed monitor.Log ("plog:scan:" + file); string scannedAddinId = null; bool scannedIsRoot = false; bool scanSuccessful = false; AddinDescription config = null; try { string ext = Path.GetExtension (file).ToLower (); if (ext == ".dll" || ext == ".exe") scanSuccessful = ScanAssembly (monitor, file, scanResult, out config); else scanSuccessful = ScanConfigAssemblies (monitor, file, scanResult, out config); if (config != null) { AddinFileInfo fi = folderInfo.GetAddinFileInfo (file); // If version is not specified, make up one if (config.Version.Length == 0) { config.Version = "0.0.0.0"; } if (config.LocalId.Length == 0) { // Generate an internal id for this add-in config.LocalId = database.GetUniqueAddinId (file, (fi != null ? fi.AddinId : null), config.Namespace, config.Version); config.HasUserId = false; } // Check errors in the description StringCollection errors = config.Verify (fs); if (database.IsGlobalRegistry && config.AddinId.IndexOf ('.') == -1) { errors.Add ("Add-ins registered in the global registry must have a namespace."); } if (errors.Count > 0) { scanSuccessful = false; monitor.ReportError ("Errors found in add-in '" + file + ":", null); foreach (string err in errors) monitor.ReportError (err, null); } // Make sure all extensions sets are initialized with the correct add-in id config.SetExtensionsAddinId (config.AddinId); scanResult.ChangesFound = true; // If the add-in already existed, try to reuse the relation data it had. // Also, the dependencies of the old add-in need to be re-analized AddinDescription existingDescription = null; bool res = database.GetAddinDescription (monitor, folderInfo.Domain, config.AddinId, config.AddinFile, out existingDescription); // If we can't get information about the old assembly, just regenerate all relation data if (!res) scanResult.RegenerateRelationData = true; string replaceFileName = null; if (existingDescription != null) { // Reuse old relation data config.MergeExternalData (existingDescription); Util.AddDependencies (existingDescription, scanResult); replaceFileName = existingDescription.FileName; } // If the scanned file results in an add-in version different from the one obtained from // previous scans, the old add-in needs to be uninstalled. if (fi != null && fi.IsAddin && fi.AddinId != config.AddinId) { database.UninstallAddin (monitor, folderInfo.Domain, fi.AddinId, fi.File, scanResult); // If the add-in version has changed, regenerate everything again since old data can't be reused if (Addin.GetIdName (fi.AddinId) == Addin.GetIdName (config.AddinId)) scanResult.RegenerateRelationData = true; } // If a description could be generated, save it now (if the scan was successful) if (scanSuccessful) { // Assign the domain if (config.IsRoot) { if (folderInfo.RootsDomain == null) { if (scanResult.Domain != null && scanResult.Domain != AddinDatabase.UnknownDomain && scanResult.Domain != AddinDatabase.GlobalDomain) folderInfo.RootsDomain = scanResult.Domain; else folderInfo.RootsDomain = database.GetUniqueDomainId (); } config.Domain = folderInfo.RootsDomain; } else config.Domain = folderInfo.Domain; if (config.IsRoot && scanResult.HostIndex != null) { // If the add-in is a root, register its assemblies foreach (string f in config.MainModule.Assemblies) { string asmFile = Path.Combine (config.BasePath, f); scanResult.HostIndex.RegisterAssembly (asmFile, config.AddinId, config.AddinFile, config.Domain); } } // Finally save if (database.SaveDescription (monitor, config, replaceFileName)) { // The new dependencies also have to be updated Util.AddDependencies (config, scanResult); scanResult.AddAddinToUpdate (config.AddinId); scannedAddinId = config.AddinId; scannedIsRoot = config.IsRoot; return; } } } } catch (Exception ex) { monitor.ReportError ("Unexpected error while scanning file: " + file, ex); } finally { AddinFileInfo ainfo = folderInfo.SetLastScanTime (file, scannedAddinId, scannedIsRoot, fs.GetLastWriteTime (file), !scanSuccessful); if (scanSuccessful && config != null) { // Update the ignore list in the folder info object. To be used in the next scan foreach (string df in config.AllIgnorePaths) { string path = Path.Combine (config.BasePath, df); ainfo.AddPathToIgnore (Path.GetFullPath (path)); } } monitor.Log ("plog:endscan"); } }
public void ScanFolder (IProgressStatus monitor, string path, AddinScanResult scanResult) { path = Util.GetFullPath (path); // Avoid folders including each other if (!scanResult.VisitFolder (path)) return; if (monitor.VerboseLog && !scanResult.LocateAssembliesOnly) monitor.Log ("Checking: " + path); AddinScanFolderInfo folderInfo; if (!database.GetFolderInfoForPath (monitor, path, out folderInfo)) { // folderInfo file was corrupt. // Just in case, we are going to regenerate all relation data. if (!Directory.Exists (path)) scanResult.RegenerateRelationData = true; } else { if (folderInfo == null && !Directory.Exists (path)) return; } if (folderInfo == null) folderInfo = new AddinScanFolderInfo (path); if (Directory.Exists (path)) { foreach (string file in Directory.GetFiles (path)) { if (file.EndsWith (".addin.xml")) { RegisterFileToScan (monitor, file, scanResult, folderInfo); continue; } switch (Path.GetExtension (file)) { case ".dll": case ".exe": RegisterFileToScan (monitor, file, scanResult, folderInfo); scanResult.AddAssemblyLocation (file); break; case ".addin": RegisterFileToScan (monitor, file, scanResult, folderInfo); break; case ".addins": ScanAddinsFile (monitor, file, scanResult); break; } } } else if (!scanResult.LocateAssembliesOnly) { // The folder has been deleted. All add-ins defined in that folder should also be deleted. scanResult.RegenerateRelationData = true; scanResult.ChangesFound = true; if (scanResult.CheckOnly) return; database.DeleteFolderInfo (monitor, folderInfo); } if (scanResult.LocateAssembliesOnly) return; // Look for deleted add-ins. UpdateDeletedAddins (monitor, folderInfo, scanResult); }
public void ScanFolder (IProgressStatus monitor, string path, string domain, AddinScanResult scanResult) { path = Util.GetFullPath (path); // Avoid folders including each other if (!scanResult.VisitFolder (path)) return; if (monitor.LogLevel > 1 && !scanResult.LocateAssembliesOnly) monitor.Log ("Checking: " + path); AddinScanFolderInfo folderInfo; if (!database.GetFolderInfoForPath (monitor, path, out folderInfo)) { // folderInfo file was corrupt. // Just in case, we are going to regenerate all relation data. if (!Directory.Exists (path)) scanResult.RegenerateRelationData = true; } else { if (folderInfo == null && !Directory.Exists (path)) return; } // if domain is null it means that a new domain has to be created. bool sharedFolder = domain == AddinDatabase.GlobalDomain; if (folderInfo == null) folderInfo = new AddinScanFolderInfo (path); if (!sharedFolder && (folderInfo.SharedFolder || folderInfo.Domain != domain)) { // If the folder already has a domain, reuse it if (domain == null && folderInfo.RootsDomain != null && folderInfo.RootsDomain != AddinDatabase.GlobalDomain) domain = folderInfo.RootsDomain; else if (domain == null) { folderInfo.Domain = domain = database.GetUniqueDomainId (); scanResult.RegenerateRelationData = true; } else { folderInfo.Domain = domain; scanResult.RegenerateRelationData = true; } } else if (!folderInfo.SharedFolder && sharedFolder) { scanResult.RegenerateRelationData = true; } folderInfo.SharedFolder = sharedFolder; if (Directory.Exists (path)) { string[] files = Directory.GetFiles (path); // First of all, look for .addin files. Addin files must be processed before // assemblies, because they may add files to the ignore list (i.e., assemblies // included in .addin files won't be scanned twice). foreach (string file in files) { if (file.EndsWith (".addin.xml") || file.EndsWith (".addin")) { RegisterFileToScan (monitor, file, scanResult, folderInfo); } } foreach (string file in files) { switch (Path.GetExtension (file)) { case ".dll": case ".exe": RegisterFileToScan (monitor, file, scanResult, folderInfo); scanResult.AddAssemblyLocation (file); break; case ".addins": ScanAddinsFile (monitor, file, domain, scanResult); break; } } } else if (!scanResult.LocateAssembliesOnly) { // The folder has been deleted. All add-ins defined in that folder should also be deleted. scanResult.RegenerateRelationData = true; scanResult.ChangesFound = true; if (scanResult.CheckOnly) return; database.DeleteFolderInfo (monitor, folderInfo); } if (scanResult.LocateAssembliesOnly) return; // Look for deleted add-ins. UpdateDeletedAddins (monitor, folderInfo, scanResult); }
public bool SaveFolderInfo (IProgressStatus monitor, AddinScanFolderInfo folderInfo) { try { folderInfo.Write (fileDatabase, AddinFolderCachePath); return true; } catch (Exception ex) { monitor.ReportError ("Could not write folder info file", ex); return false; } }
public void UpdateDeletedAddins (IProgressStatus monitor, AddinScanFolderInfo folderInfo, AddinScanResult scanResult) { ArrayList missing = folderInfo.GetMissingAddins (); if (missing.Count > 0) { if (Directory.Exists (folderInfo.Folder)) scanResult.ModifiedFolderInfos.Add (folderInfo); scanResult.ChangesFound = true; if (scanResult.CheckOnly) return; foreach (AddinFileInfo info in missing) { if (info.IsRoot) database.UninstallRootAddin (monitor, info.AddinId, info.File, scanResult); else database.UninstallAddin (monitor, info.AddinId, scanResult); } } }
void RegisterFileToScan (IProgressStatus monitor, string file, AddinScanResult scanResult, AddinScanFolderInfo folderInfo) { if (scanResult.LocateAssembliesOnly) return; AddinFileInfo finfo = folderInfo.GetAddinFileInfo (file); bool added = false; if (finfo != null && File.GetLastWriteTime (file) == finfo.LastScan && !scanResult.RegenerateAllData) { if (finfo.ScanError) { // Always schedule the file for scan if there was an error in a previous scan. // However, don't set ChangesFound=true, in this way if there isn't any other // change in the registry, the file won't be scanned again. scanResult.AddFileToScan (file, folderInfo); added = true; } if (finfo.AddinId == null || finfo.AddinId.Length == 0) return; if (!finfo.IsRoot) { if (database.AddinDescriptionExists (finfo.AddinId)) return; } else { if (database.HostDescriptionExists (finfo.AddinId, file)) return; } } scanResult.ChangesFound = true; if (!scanResult.CheckOnly && !added) scanResult.AddFileToScan (file, folderInfo); }
public void RegisterModifiedFolderInfo(AddinScanFolderInfo folderInfo) { if (!ModifiedFolderInfos.Contains (folderInfo)) ModifiedFolderInfos.Add (folderInfo); }
public void AddFileToScan(string file, AddinScanFolderInfo folderInfo) { FileToScan di = new FileToScan (); di.File = file; di.AddinScanFolderInfo = folderInfo; FilesToScan.Add (di); RegisterModifiedFolderInfo (folderInfo); }
public void ScanFolder(IProgressStatus monitor, string path, string domain, AddinScanResult scanResult) { path = Util.GetFullPath(path); // Avoid folders including each other if (!scanResult.VisitFolder(path)) { return; } AddinScanFolderInfo folderInfo; if (!database.GetFolderInfoForPath(monitor, path, out folderInfo)) { // folderInfo file was corrupt. // Just in case, we are going to regenerate all relation data. if (!Directory.Exists(path)) { scanResult.RegenerateRelationData = true; } } else { // Directory is included but it doesn't exist. Ignore it. if (folderInfo == null && !Directory.Exists(path)) { return; } } // if domain is null it means that a new domain has to be created. bool sharedFolder = domain == AddinDatabase.GlobalDomain; bool isNewFolder = folderInfo == null; if (isNewFolder) { // No folder info. It is the first time this folder is scanned. // There is no need to store this object if the folder does not // contain add-ins. folderInfo = new AddinScanFolderInfo(path); } if (!sharedFolder && (folderInfo.SharedFolder || folderInfo.Domain != domain)) { // If the folder already has a domain, reuse it if (domain == null && folderInfo.RootsDomain != null && folderInfo.RootsDomain != AddinDatabase.GlobalDomain) { domain = folderInfo.RootsDomain; } else if (domain == null) { folderInfo.Domain = domain = database.GetUniqueDomainId(); scanResult.RegenerateRelationData = true; } else { folderInfo.Domain = domain; if (!isNewFolder) { // Domain has changed. Update the folder info and regenerate everything. scanResult.RegenerateRelationData = true; scanResult.RegisterModifiedFolderInfo(folderInfo); } } } else if (!folderInfo.SharedFolder && sharedFolder) { scanResult.RegenerateRelationData = true; } folderInfo.SharedFolder = sharedFolder; // If there is no domain assigned to the host, get one now if (scanResult.Domain == AddinDatabase.UnknownDomain) { scanResult.Domain = domain; } // Discard folders not belonging to the required domain if (scanResult.Domain != null && domain != scanResult.Domain && domain != AddinDatabase.GlobalDomain) { return; } if (monitor.LogLevel > 1 && !scanResult.LocateAssembliesOnly) { monitor.Log("Checking: " + path); } if (Directory.Exists(path)) { string[] files = Directory.GetFiles(path); // First of all, look for .addin files. Addin files must be processed before // assemblies, because they may add files to the ignore list (i.e., assemblies // included in .addin files won't be scanned twice). foreach (string file in files) { if (file.EndsWith(".addin.xml") || file.EndsWith(".addin")) { RegisterFileToScan(monitor, file, scanResult, folderInfo); } } // Now scan assemblies. They can also add files to the ignore list. foreach (string file in files) { string ext = Path.GetExtension(file).ToLower(); if (ext == ".dll" || ext == ".exe") { RegisterFileToScan(monitor, file, scanResult, folderInfo); scanResult.AddAssemblyLocation(file); } } // Finally scan .addins files foreach (string file in files) { if (Path.GetExtension(file).EndsWith(".addins")) { ScanAddinsFile(monitor, file, domain, scanResult); } } } else if (!scanResult.LocateAssembliesOnly) { // The folder has been deleted. All add-ins defined in that folder should also be deleted. scanResult.RegenerateRelationData = true; scanResult.ChangesFound = true; if (scanResult.CheckOnly) { return; } database.DeleteFolderInfo(monitor, folderInfo); } if (scanResult.LocateAssembliesOnly) { return; } // Look for deleted add-ins. UpdateDeletedAddins(monitor, folderInfo, scanResult); }
public void ScanFile(IProgressStatus monitor, string file, AddinScanFolderInfo folderInfo, AddinScanResult scanResult) { if (scanResult.IgnorePath(file)) { // The file must be ignored. Maybe it caused a crash in a previous scan, or it // might be included by a .addin file (in which case it will be scanned when processing // the .addin file). folderInfo.SetLastScanTime(file, null, false, File.GetLastWriteTime(file), true); return; } if (monitor.LogLevel > 1) { monitor.Log("Scanning file: " + file); } // Log the file to be scanned, so in case of a process crash the main process // will know what crashed monitor.Log("plog:scan:" + file); string scannedAddinId = null; bool scannedIsRoot = false; bool scanSuccessful = false; AddinDescription config = null; try { string ext = Path.GetExtension(file); if (ext == ".dll" || ext == ".exe") { scanSuccessful = ScanAssembly(monitor, file, scanResult, out config); } else { scanSuccessful = ScanConfigAssemblies(monitor, file, scanResult, out config); } if (config != null) { AddinFileInfo fi = folderInfo.GetAddinFileInfo(file); // If version is not specified, make up one if (config.Version.Length == 0) { config.Version = "0.0.0.0"; } if (config.LocalId.Length == 0) { // Generate an internal id for this add-in config.LocalId = database.GetUniqueAddinId(file, (fi != null ? fi.AddinId : null), config.Namespace, config.Version); config.HasUserId = false; } // Check errors in the description StringCollection errors = config.Verify(); if (database.IsGlobalRegistry && config.AddinId.IndexOf('.') == -1) { errors.Add("Add-ins registered in the global registry must have a namespace."); } if (errors.Count > 0) { scanSuccessful = false; monitor.ReportError("Errors found in add-in '" + file + ":", null); foreach (string err in errors) { monitor.ReportError(err, null); } } // Make sure all extensions sets are initialized with the correct add-in id config.SetExtensionsAddinId(config.AddinId); scanResult.ChangesFound = true; // If the add-in already existed, try to reuse the relation data it had. // Also, the dependencies of the old add-in need to be re-analized AddinDescription existingDescription = null; bool res = database.GetAddinDescription(monitor, folderInfo.Domain, config.AddinId, out existingDescription); // If we can't get information about the old assembly, just regenerate all relation data if (!res) { scanResult.RegenerateRelationData = true; } string replaceFileName = null; if (existingDescription != null) { // Reuse old relation data config.MergeExternalData(existingDescription); Util.AddDependencies(existingDescription, scanResult); replaceFileName = existingDescription.FileName; } // If the scanned file results in an add-in version different from the one obtained from // previous scans, the old add-in needs to be uninstalled. if (fi != null && fi.IsAddin && fi.AddinId != config.AddinId) { database.UninstallAddin(monitor, folderInfo.Domain, fi.AddinId, scanResult); // If the add-in version has changed, regenerate everything again since old data can't be reused if (Addin.GetIdName(fi.AddinId) == Addin.GetIdName(config.AddinId)) { scanResult.RegenerateRelationData = true; } } // If a description could be generated, save it now (if the scan was successful) if (scanSuccessful) { // Assign the domain if (config.IsRoot) { if (folderInfo.RootsDomain == null) { if (scanResult.Domain != null && scanResult.Domain != AddinDatabase.UnknownDomain && scanResult.Domain != AddinDatabase.GlobalDomain) { folderInfo.RootsDomain = scanResult.Domain; } else { folderInfo.RootsDomain = database.GetUniqueDomainId(); } } config.Domain = folderInfo.RootsDomain; } else { config.Domain = folderInfo.Domain; } if (config.IsRoot && scanResult.HostIndex != null) { // If the add-in is a root, register its assemblies foreach (string f in config.MainModule.Assemblies) { string asmFile = Path.Combine(config.BasePath, f); scanResult.HostIndex.RegisterAssembly(asmFile, config.AddinId, config.AddinFile, config.Domain); } } // Finally save if (database.SaveDescription(monitor, config, replaceFileName)) { // The new dependencies also have to be updated Util.AddDependencies(config, scanResult); scanResult.AddAddinToUpdateRelations(config.AddinId); scannedAddinId = config.AddinId; scannedIsRoot = config.IsRoot; return; } } } } catch (Exception ex) { monitor.ReportError("Unexpected error while scanning file: " + file, ex); } finally { AddinFileInfo ainfo = folderInfo.SetLastScanTime(file, scannedAddinId, scannedIsRoot, File.GetLastWriteTime(file), !scanSuccessful); if (scanSuccessful && config != null) { // Update the ignore list in the folder info object. To be used in the next scan foreach (string df in config.AllIgnorePaths) { string path = Path.Combine(config.BasePath, df); ainfo.AddPathToIgnore(Util.GetFullPath(path)); } } monitor.Log("plog:endscan"); } }
public void AddFileToScan (string file, AddinScanFolderInfo folderInfo) { FileToScan di = new FileToScan (); di.File = file; di.AddinScanFolderInfo = folderInfo; FilesToScan.Add (di); if (!ModifiedFolderInfos.Contains (folderInfo)) ModifiedFolderInfos.Add (folderInfo); }
public bool ReadFolderInfo (IProgressStatus monitor, string file, out AddinScanFolderInfo folderInfo) { try { folderInfo = AddinScanFolderInfo.Read (fileDatabase, file); return true; } catch (Exception ex) { folderInfo = null; monitor.ReportError ("Could not read folder info file", ex); return false; } }
public bool GetFolderInfoForPath (IProgressStatus monitor, string path, out AddinScanFolderInfo folderInfo) { try { folderInfo = AddinScanFolderInfo.Read (fileDatabase, AddinFolderCachePath, path); return true; } catch (Exception ex) { folderInfo = null; monitor.ReportError ("Could not read folder info file", ex); return false; } }
protected override void OnVisitFolder(IProgressStatus monitor, string path, string domain, bool recursive) { AddinScanFolderInfo folderInfo; if (!database.GetFolderInfoForPath(monitor, path, out folderInfo)) { // folderInfo file was corrupt. // Just in case, we are going to regenerate all relation data. if (!FileSystem.DirectoryExists(path)) { scanResult.RegenerateRelationData = true; } } else { // Directory is included but it doesn't exist. Ignore it. if (folderInfo == null && !FileSystem.DirectoryExists(path)) { return; } } // if domain is null it means that a new domain has to be created. // Look for an add-in scan data index file. If it is present, it means the folder has been pre-scanned var dirScanDataIndex = AddinScanDataIndex.LoadFromFolder(monitor, path); if (dirScanDataIndex != null && scanResult.CleanGeneratedAddinScanDataFiles) { // Remove any existing dir.addindata if data is being generated dirScanDataIndex.Delete(); dirScanDataIndex = null; } bool sharedFolder = domain == AddinDatabase.GlobalDomain; bool isNewFolder = folderInfo == null; bool folderHasIndex = dirScanDataIndex != null; if (isNewFolder) { // No folder info. It is the first time this folder is scanned. // There is no need to store this object if the folder does not // contain add-ins. folderInfo = new AddinScanFolderInfo(path); folderInfo.FolderHasScanDataIndex = folderHasIndex; } else if (folderInfo.FolderHasScanDataIndex != folderHasIndex) { // A scan data index appeared or disappeared. The information in folderInfo is not reliable. // Update the folder info and regenerate everything. scanResult.RegenerateRelationData = true; folderInfo.Reset(); scanResult.RegisterModifiedFolderInfo(folderInfo); folderInfo.FolderHasScanDataIndex = folderHasIndex; } if (!sharedFolder && (folderInfo.SharedFolder || folderInfo.Domain != domain)) { // If the folder already has a domain, reuse it if (domain == null && folderInfo.RootsDomain != null && folderInfo.RootsDomain != AddinDatabase.GlobalDomain) { domain = folderInfo.RootsDomain; } else if (domain == null) { folderInfo.Domain = domain = database.GetUniqueDomainId(); scanResult.RegenerateRelationData = true; } else { folderInfo.Domain = domain; if (!isNewFolder) { // Domain has changed. Update the folder info and regenerate everything. scanResult.RegenerateRelationData = true; scanResult.RegisterModifiedFolderInfo(folderInfo); } } } else if (!folderInfo.SharedFolder && sharedFolder) { scanResult.RegenerateRelationData = true; } folderInfo.SharedFolder = sharedFolder; // If there is no domain assigned to the host, get one now if (scanResult.Domain == AddinDatabase.UnknownDomain) { scanResult.Domain = domain; } // Discard folders not belonging to the required domain if (scanResult.Domain != null && domain != scanResult.Domain && domain != AddinDatabase.GlobalDomain) { return; } if (monitor.LogLevel > 1) { monitor.Log("Checking: " + path); } if (dirScanDataIndex != null) { // Instead of scanning the folder, just register the files in the index foreach (var file in dirScanDataIndex.Files) { RegisterFileToScan(monitor, file.FileName, folderInfo, file); } foreach (var file in dirScanDataIndex.Assemblies) { scanResult.AssemblyIndex.AddAssemblyLocation(file); } } else { currentFolderInfo = folderInfo; base.OnVisitFolder(monitor, path, domain, recursive); if (!FileSystem.DirectoryExists(path)) { // The folder has been deleted. All add-ins defined in that folder should also be deleted. scanResult.RegenerateRelationData = true; scanResult.ChangesFound = true; if (scanResult.CheckOnly) { return; } database.DeleteFolderInfo(monitor, folderInfo); } } // Look for deleted add-ins. UpdateDeletedAddins(monitor, folderInfo); }
public bool DeleteFolderInfo (IProgressStatus monitor, AddinScanFolderInfo folderInfo) { return SafeDelete (monitor, folderInfo.FileName); }
public void ScanFile(IProgressStatus monitor, string file, AddinScanFolderInfo folderInfo, AddinScanResult scanResult) { if (monitor.VerboseLog) { monitor.Log("Scanning file: " + file); } string scannedAddinId = null; bool scannedIsRoot = false; bool scanSuccessful = false; try { string ext = Path.GetExtension(file); AddinDescription config = null; if (ext == ".dll" || ext == ".exe") { scanSuccessful = ScanAssembly(monitor, file, scanResult, out config); } else { scanSuccessful = ScanConfigAssemblies(monitor, file, scanResult, out config); } if (config != null) { AddinFileInfo fi = folderInfo.GetAddinFileInfo(file); // If version is not specified, make up one if (config.Version.Length == 0) { config.Version = "0.0.0.0"; } if (config.LocalId.Length == 0) { // Generate an internal id for this add-in config.LocalId = database.GetUniqueAddinId(file, (fi != null ? fi.AddinId : null), config.Namespace, config.Version); config.HasUserId = false; } // Check errors in the description StringCollection errors = config.Verify(); if (database.IsGlobalRegistry && config.AddinId.IndexOf('.') == -1) { errors.Add("Add-ins registered in the global registry must have a namespace."); } if (errors.Count > 0) { scanSuccessful = false; monitor.ReportError("Errors found in add-in '" + file + ":", null); foreach (string err in errors) { monitor.ReportError(err, null); } } // Make sure all extensions sets are initialized with the correct add-in id config.SetExtensionsAddinId(config.AddinId); scanResult.ChangesFound = true; // If the add-in already existed, try to reuse the relation data it had. // Also, the dependencies of the old add-in need to be re-analized AddinDescription existingDescription = null; bool res; if (config.IsRoot) { res = database.GetHostDescription(monitor, config.AddinId, config.AddinFile, out existingDescription); } else { res = database.GetAddinDescription(monitor, config.AddinId, out existingDescription); } // If we can't get information about the old assembly, just regenerate all relation data if (!res) { scanResult.RegenerateRelationData = true; } string replaceFileName = null; if (existingDescription != null) { // Reuse old relation data config.MergeExternalData(existingDescription); Util.AddDependencies(existingDescription, scanResult); replaceFileName = existingDescription.FileName; } // If the scanned file results in an add-in version different from the one obtained from // previous scans, the old add-in needs to be uninstalled. if (fi != null && fi.AddinId != null && fi.AddinId != config.AddinId) { if (fi.IsRoot) { database.UninstallRootAddin(monitor, fi.AddinId, file, scanResult); } else { database.UninstallAddin(monitor, fi.AddinId, scanResult); } // If the add-in version has changed, regenerate everything again since old data can't be reused if (Addin.GetIdName(fi.AddinId) == Addin.GetIdName(config.AddinId)) { scanResult.RegenerateRelationData = true; } } // If a description could be generated, save it now (if the scan was successful) if (scanSuccessful) { if (database.SaveDescription(monitor, config, replaceFileName)) { // The new dependencies also have to be updated Util.AddDependencies(config, scanResult); scanResult.AddAddinToUpdateRelations(config.AddinId); scannedAddinId = config.AddinId; scannedIsRoot = config.IsRoot; return; } } } } catch (Exception ex) { monitor.ReportError("Unexpected error while scanning file: " + file, ex); } finally { folderInfo.SetLastScanTime(file, scannedAddinId, scannedIsRoot, File.GetLastWriteTime(file), !scanSuccessful); } }
public void ScanFolder(IProgressStatus monitor, string path, AddinScanResult scanResult) { path = Util.GetFullPath(path); // Avoid folders including each other if (!scanResult.VisitFolder(path)) { return; } if (monitor.VerboseLog && !scanResult.LocateAssembliesOnly) { monitor.Log("Checking: " + path); } AddinScanFolderInfo folderInfo; if (!database.GetFolderInfoForPath(monitor, path, out folderInfo)) { // folderInfo file was corrupt. // Just in case, we are going to regenerate all relation data. if (!Directory.Exists(path)) { scanResult.RegenerateRelationData = true; } } else { if (folderInfo == null && !Directory.Exists(path)) { return; } } if (folderInfo == null) { folderInfo = new AddinScanFolderInfo(path); } if (Directory.Exists(path)) { foreach (string file in Directory.GetFiles(path)) { if (file.EndsWith(".addin.xml")) { RegisterFileToScan(monitor, file, scanResult, folderInfo); continue; } switch (Path.GetExtension(file)) { case ".dll": case ".exe": RegisterFileToScan(monitor, file, scanResult, folderInfo); scanResult.AddAssemblyLocation(file); break; case ".addin": RegisterFileToScan(monitor, file, scanResult, folderInfo); break; case ".addins": ScanAddinsFile(monitor, file, scanResult); break; } } } else if (!scanResult.LocateAssembliesOnly) { // The folder has been deleted. All add-ins defined in that folder should also be deleted. scanResult.RegenerateRelationData = true; scanResult.ChangesFound = true; if (scanResult.CheckOnly) { return; } database.DeleteFolderInfo(monitor, folderInfo); } if (scanResult.LocateAssembliesOnly) { return; } // Look for deleted add-ins. UpdateDeletedAddins(monitor, folderInfo, scanResult); }
public void ScanFile (IProgressStatus monitor, string file, AddinScanFolderInfo folderInfo, AddinScanResult scanResult) { if (monitor.VerboseLog) monitor.Log ("Scanning file: " + file); string scannedAddinId = null; bool scannedIsRoot = false; bool scanSuccessful = false; try { string ext = Path.GetExtension (file); AddinDescription config = null; if (ext == ".dll" || ext == ".exe") scanSuccessful = ScanAssembly (monitor, file, scanResult, out config); else scanSuccessful = ScanConfigAssemblies (monitor, file, scanResult, out config); if (config != null) { AddinFileInfo fi = folderInfo.GetAddinFileInfo (file); // If version is not specified, make up one if (config.Version.Length == 0) { config.Version = "0.0.0.0"; } if (config.LocalId.Length == 0) { // Generate an internal id for this add-in config.LocalId = database.GetUniqueAddinId (file, (fi != null ? fi.AddinId : null), config.Namespace, config.Version); config.HasUserId = false; } // Check errors in the description StringCollection errors = config.Verify (); if (database.IsGlobalRegistry && config.AddinId.IndexOf ('.') == -1) { errors.Add ("Add-ins registered in the global registry must have a namespace."); } if (errors.Count > 0) { scanSuccessful = false; monitor.ReportError ("Errors found in add-in '" + file + ":", null); foreach (string err in errors) monitor.ReportError (err, null); } // Make sure all extensions sets are initialized with the correct add-in id config.SetExtensionsAddinId (config.AddinId); scanResult.ChangesFound = true; // If the add-in already existed, try to reuse the relation data it had. // Also, the dependencies of the old add-in need to be re-analized AddinDescription existingDescription = null; bool res; if (config.IsRoot) res = database.GetHostDescription (monitor, config.AddinId, config.AddinFile, out existingDescription); else res = database.GetAddinDescription (monitor, config.AddinId, out existingDescription); // If we can't get information about the old assembly, just regenerate all relation data if (!res) scanResult.RegenerateRelationData = true; string replaceFileName = null; if (existingDescription != null) { // Reuse old relation data config.MergeExternalData (existingDescription); Util.AddDependencies (existingDescription, scanResult); replaceFileName = existingDescription.FileName; } // If the scanned file results in an add-in version different from the one obtained from // previous scans, the old add-in needs to be uninstalled. if (fi != null && fi.AddinId != null && fi.AddinId != config.AddinId) { if (fi.IsRoot) database.UninstallRootAddin (monitor, fi.AddinId, file, scanResult); else database.UninstallAddin (monitor, fi.AddinId, scanResult); // If the add-in version has changed, regenerate everything again since old data can't be reused if (Addin.GetIdName (fi.AddinId) == Addin.GetIdName (config.AddinId)) scanResult.RegenerateRelationData = true; } // If a description could be generated, save it now (if the scan was successful) if (scanSuccessful) { if (database.SaveDescription (monitor, config, replaceFileName)) { // The new dependencies also have to be updated Util.AddDependencies (config, scanResult); scanResult.AddAddinToUpdateRelations (config.AddinId); scannedAddinId = config.AddinId; scannedIsRoot = config.IsRoot; return; } } } } catch (Exception ex) { monitor.ReportError ("Unexpected error while scanning file: " + file, ex); } finally { folderInfo.SetLastScanTime (file, scannedAddinId, scannedIsRoot, File.GetLastWriteTime (file), !scanSuccessful); } }
public void ScanFolder(IProgressStatus monitor, string path, string domain, AddinScanResult scanResult) { path = Util.GetFullPath(path); // Avoid folders including each other if (!scanResult.VisitFolder(path)) { return; } if (monitor.LogLevel > 1 && !scanResult.LocateAssembliesOnly) { monitor.Log("Checking: " + path); } AddinScanFolderInfo folderInfo; if (!database.GetFolderInfoForPath(monitor, path, out folderInfo)) { // folderInfo file was corrupt. // Just in case, we are going to regenerate all relation data. if (!Directory.Exists(path)) { scanResult.RegenerateRelationData = true; } } else { if (folderInfo == null && !Directory.Exists(path)) { return; } } // if domain is null it means that a new domain has to be created. bool sharedFolder = domain == AddinDatabase.GlobalDomain; if (folderInfo == null) { folderInfo = new AddinScanFolderInfo(path); } if (!sharedFolder && (folderInfo.SharedFolder || folderInfo.Domain != domain)) { // If the folder already has a domain, reuse it if (domain == null && folderInfo.RootsDomain != null && folderInfo.RootsDomain != AddinDatabase.GlobalDomain) { domain = folderInfo.RootsDomain; } else if (domain == null) { folderInfo.Domain = domain = database.GetUniqueDomainId(); scanResult.RegenerateRelationData = true; } else { folderInfo.Domain = domain; scanResult.RegenerateRelationData = true; } } else if (!folderInfo.SharedFolder && sharedFolder) { scanResult.RegenerateRelationData = true; } folderInfo.SharedFolder = sharedFolder; if (Directory.Exists(path)) { string[] files = Directory.GetFiles(path); // First of all, look for .addin files. Addin files must be processed before // assemblies, because they may add files to the ignore list (i.e., assemblies // included in .addin files won't be scanned twice). foreach (string file in files) { if (file.EndsWith(".addin.xml") || file.EndsWith(".addin")) { RegisterFileToScan(monitor, file, scanResult, folderInfo); } } foreach (string file in files) { switch (Path.GetExtension(file)) { case ".dll": case ".exe": RegisterFileToScan(monitor, file, scanResult, folderInfo); scanResult.AddAssemblyLocation(file); break; case ".addins": ScanAddinsFile(monitor, file, domain, scanResult); break; } } } else if (!scanResult.LocateAssembliesOnly) { // The folder has been deleted. All add-ins defined in that folder should also be deleted. scanResult.RegenerateRelationData = true; scanResult.ChangesFound = true; if (scanResult.CheckOnly) { return; } database.DeleteFolderInfo(monitor, folderInfo); } if (scanResult.LocateAssembliesOnly) { return; } // Look for deleted add-ins. UpdateDeletedAddins(monitor, folderInfo, scanResult); }
void RegisterFileToScan(IProgressStatus monitor, string file, AddinScanResult scanResult, AddinScanFolderInfo folderInfo) { if (scanResult.LocateAssembliesOnly) { return; } AddinFileInfo finfo = folderInfo.GetAddinFileInfo(file); bool added = false; if (finfo != null && File.GetLastWriteTime(file) == finfo.LastScan && !scanResult.RegenerateAllData) { if (finfo.ScanError) { // Always schedule the file for scan if there was an error in a previous scan. // However, don't set ChangesFound=true, in this way if there isn't any other // change in the registry, the file won't be scanned again. scanResult.AddFileToScan(file, folderInfo); added = true; } if (finfo.AddinId == null || finfo.AddinId.Length == 0) { return; } if (!finfo.IsRoot) { if (database.AddinDescriptionExists(finfo.AddinId)) { return; } } else { if (database.HostDescriptionExists(finfo.AddinId, file)) { return; } } } scanResult.ChangesFound = true; if (!scanResult.CheckOnly && !added) { scanResult.AddFileToScan(file, folderInfo); } }