bool ScanDescription(IProgressStatus monitor, IAssemblyReflector reflector, AddinDescription config, object rootAssembly, AddinScanResult scanResult)
        {
            // First of all scan the main module

            ArrayList assemblies = new ArrayList ();

            try {
                string rootAsmFile = null;

                if (rootAssembly != null) {
                    ScanAssemblyAddinHeaders (reflector, config, rootAssembly, scanResult);
                    ScanAssemblyImports (reflector, config.MainModule, rootAssembly);
                    assemblies.Add (rootAssembly);
                    rootAsmFile = Path.GetFileName (config.AddinFile);
                }

                // The assembly list may be modified while scanning the headears, so
                // we use a for loop instead of a foreach
                for (int n=0; n<config.MainModule.Assemblies.Count; n++) {
                    string s = config.MainModule.Assemblies [n];
                    string asmFile = Path.GetFullPath (Path.Combine (config.BasePath, s));
                    scanResult.AddPathToIgnore (asmFile);
                    if (s == rootAsmFile || config.MainModule.IgnorePaths.Contains (s))
                        continue;
                    object asm = reflector.LoadAssembly (asmFile);
                    assemblies.Add (asm);
                    ScanAssemblyAddinHeaders (reflector, config, asm, scanResult);
                    ScanAssemblyImports (reflector, config.MainModule, asm);
                }

                // Add all data files to the ignore file list. It avoids scanning assemblies
                // which are included as 'data' in an add-in.
                foreach (string df in config.MainModule.DataFiles) {
                    string file = Path.Combine (config.BasePath, df);
                    scanResult.AddPathToIgnore (Path.GetFullPath (file));
                }
                foreach (string df in config.MainModule.IgnorePaths) {
                    string path = Path.Combine (config.BasePath, df);
                    scanResult.AddPathToIgnore (Path.GetFullPath (path));
                }

                // The add-in id and version must be already assigned at this point

                // Clean host data from the index. New data will be added.
                if (scanResult.HostIndex != null)
                    scanResult.HostIndex.RemoveHostData (config.AddinId, config.AddinFile);

                foreach (object asm in assemblies)
                    ScanAssemblyContents (reflector, config, config.MainModule, asm, scanResult);

            } catch (Exception ex) {
                ReportReflectionException (monitor, ex, config, scanResult);
                return false;
            }

            // Extension node types may have child nodes declared as attributes. Find them.

            Hashtable internalNodeSets = new Hashtable ();

            ArrayList setsCopy = new ArrayList ();
            setsCopy.AddRange (config.ExtensionNodeSets);
            foreach (ExtensionNodeSet eset in setsCopy)
                ScanNodeSet (reflector, config, eset, assemblies, internalNodeSets);

            foreach (ExtensionPoint ep in config.ExtensionPoints) {
                ScanNodeSet (reflector, config, ep.NodeSet, assemblies, internalNodeSets);
            }

            // Now scan all modules

            if (!config.IsRoot) {
                foreach (ModuleDescription mod in config.OptionalModules) {
                    try {
                        assemblies.Clear ();
                        for (int n=0; n<mod.Assemblies.Count; n++) {
                            string s = mod.Assemblies [n];
                            if (mod.IgnorePaths.Contains (s))
                                continue;
                            string asmFile = Path.Combine (config.BasePath, s);
                            object asm = reflector.LoadAssembly (asmFile);
                            assemblies.Add (asm);
                            scanResult.AddPathToIgnore (Path.GetFullPath (asmFile));
                            ScanAssemblyImports (reflector, mod, asm);
                        }
                        // Add all data files to the ignore file list. It avoids scanning assemblies
                        // which are included as 'data' in an add-in.
                        foreach (string df in mod.DataFiles) {
                            string file = Path.Combine (config.BasePath, df);
                            scanResult.AddPathToIgnore (Path.GetFullPath (file));
                        }
                        foreach (string df in mod.IgnorePaths) {
                            string path = Path.Combine (config.BasePath, df);
                            scanResult.AddPathToIgnore (Path.GetFullPath (path));
                        }

                        foreach (object asm in assemblies)
                            ScanAssemblyContents (reflector, config, mod, asm, scanResult);

                    } catch (Exception ex) {
                        ReportReflectionException (monitor, ex, config, scanResult);
                    }
                }
            }

            config.StoreFileInfo ();
            return true;
        }
        bool ScanDescription(IProgressStatus monitor, AddinDescription config, Assembly rootAssembly, AddinScanResult scanResult)
        {
            // First of all scan the main module

            ArrayList assemblies           = new ArrayList();
            ArrayList asmFiles             = new ArrayList();
            ArrayList hostExtensionClasses = new ArrayList();

            try {
                // Add all data files to the ignore file list. It avoids scanning assemblies
                // which are included as 'data' in an add-in.
                foreach (string df in config.AllFiles)
                {
                    string file = Path.Combine(config.BasePath, df);
                    scanResult.AddPathToIgnore(Util.GetFullPath(file));
                }
                foreach (string df in config.AllIgnorePaths)
                {
                    string path = Path.Combine(config.BasePath, df);
                    scanResult.AddPathToIgnore(Util.GetFullPath(path));
                }

                foreach (string s in config.MainModule.Assemblies)
                {
                    string asmFile = Path.Combine(config.BasePath, s);
                    asmFiles.Add(asmFile);
                    object asm = reflector.LoadAssembly(asmFile);
                    assemblies.Add(asm);
                    scanResult.AddPathToIgnore(Util.GetFullPath(asmFile));
                }

                foreach (object asm in assemblies)
                {
                    ScanAssemblyAddinHeaders(config, asm, scanResult);
                }

                // The add-in id and version must be already assigned at this point

                // Clean host data from the index. New data will be added.
                if (scanResult.HostIndex != null)
                {
                    scanResult.HostIndex.RemoveHostData(config.AddinId, config.AddinFile);
                }

                foreach (object asm in assemblies)
                {
                    ScanAssemblyContents(config, asm, hostExtensionClasses, scanResult);
                }
            } catch (Exception ex) {
                ReportReflectionException(monitor, ex, config, scanResult);
                return(false);
            }

            foreach (object t in hostExtensionClasses)
            {
                RegisterHostTypeNode(config, t, assemblies);
            }

            // Extension node types may have child nodes declared as attributes. Find them.

            Hashtable internalNodeSets = new Hashtable();

            ArrayList setsCopy = new ArrayList();

            setsCopy.AddRange(config.ExtensionNodeSets);
            foreach (ExtensionNodeSet eset in setsCopy)
            {
                ScanNodeSet(config, eset, assemblies, internalNodeSets);
            }

            foreach (ExtensionPoint ep in config.ExtensionPoints)
            {
                ScanNodeSet(config, ep.NodeSet, assemblies, internalNodeSets);
            }

            // Now scan all modules

            if (!config.IsRoot)
            {
                foreach (ModuleDescription mod in config.OptionalModules)
                {
                    try {
                        assemblies.Clear();
                        asmFiles.Clear();
                        foreach (string s in mod.Assemblies)
                        {
                            string asmFile = Path.Combine(config.BasePath, s);
                            asmFiles.Add(asmFile);
                            object asm = reflector.LoadAssembly(asmFile);
                            assemblies.Add(asm);
                            scanResult.AddPathToIgnore(Util.GetFullPath(asmFile));
                        }
                        foreach (object asm in assemblies)
                        {
                            ScanAssemblyContents(config, asm, null, scanResult);
                        }
                    } catch (Exception ex) {
                        ReportReflectionException(monitor, ex, config, scanResult);
                    }
                }
            }

            config.StoreFileInfo();
            return(true);
        }
        public void ScanAddinsFile(IProgressStatus monitor, string file, string domain, AddinScanResult scanResult)
        {
            XmlTextReader r = null;
            ArrayList directories = new ArrayList ();
            ArrayList directoriesWithSubdirs = new ArrayList ();
            string basePath = Path.GetDirectoryName (file);

            try {
                r = new XmlTextReader (fs.OpenTextFile (file));
                r.MoveToContent ();
                if (r.IsEmptyElement)
                    return;
                r.ReadStartElement ();
                r.MoveToContent ();
                while (r.NodeType != XmlNodeType.EndElement) {
                    if (r.NodeType == XmlNodeType.Element && r.LocalName == "Directory") {
                        string subs = r.GetAttribute ("include-subdirs");
                        string sdom;
                        string share = r.GetAttribute ("shared");
                        if (share == "true")
                            sdom = AddinDatabase.GlobalDomain;
                        else if (share == "false")
                            sdom = null;
                        else
                            sdom = domain; // Inherit the domain

                        string path = r.ReadElementString ().Trim ();
                        if (path.Length > 0) {
                            path = Util.NormalizePath (path);
                            if (subs == "true")
                                directoriesWithSubdirs.Add (new string[] {path, sdom});
                            else
                                directories.Add (new string[] {path, sdom});
                        }
                    }
                    else if (r.NodeType == XmlNodeType.Element && r.LocalName == "GacAssembly") {
                        string aname = r.ReadElementString ().Trim ();
                        if (aname.Length > 0) {
                            aname = Util.NormalizePath (aname);
                            aname = Util.GetGacPath (aname);
                            if (aname != null) {
                                // Gac assemblies always use the global domain
                                directories.Add (new string[] {aname, AddinDatabase.GlobalDomain});
                            }
                        }
                    }
                    else if (r.NodeType == XmlNodeType.Element && r.LocalName == "Exclude") {
                        string path = r.ReadElementString ().Trim ();
                        if (path.Length > 0) {
                            path = Util.NormalizePath (path);
                            if (!Path.IsPathRooted (path))
                                path = Path.Combine (basePath, path);
                            scanResult.AddPathToIgnore (Path.GetFullPath (path));
                        }
                    }
                    else
                        r.Skip ();
                    r.MoveToContent ();
                }
            } catch (Exception ex) {
                monitor.ReportError ("Could not process addins file: " + file, ex);
                return;
            } finally {
                if (r != null)
                    r.Close ();
            }

            foreach (string[] d in directories) {
                string dir = d[0];
                if (!Path.IsPathRooted (dir))
                    dir = Path.Combine (basePath, dir);
                ScanFolder (monitor, dir, d[1], scanResult);
            }
            foreach (string[] d in directoriesWithSubdirs) {
                string dir = d[0];
                if (!Path.IsPathRooted (dir))
                    dir = Path.Combine (basePath, dir);
                ScanFolderRec (monitor, dir, d[1], scanResult);
            }
        }
        public void ScanAddinsFile(IProgressStatus monitor, string file, string domain, AddinScanResult scanResult)
        {
            XmlTextReader r                      = null;
            ArrayList     directories            = new ArrayList();
            ArrayList     directoriesWithSubdirs = new ArrayList();
            string        basePath               = Path.GetDirectoryName(file);

            try {
                r = new XmlTextReader(new StreamReader(file));
                r.MoveToContent();
                if (r.IsEmptyElement)
                {
                    return;
                }
                r.ReadStartElement();
                r.MoveToContent();
                while (r.NodeType != XmlNodeType.EndElement)
                {
                    if (r.NodeType == XmlNodeType.Element && r.LocalName == "Directory")
                    {
                        string subs = r.GetAttribute("include-subdirs");
                        string sdom;
                        string share = r.GetAttribute("shared");
                        if (share == "true")
                        {
                            sdom = AddinDatabase.GlobalDomain;
                        }
                        else if (share == "false")
                        {
                            sdom = null;
                        }
                        else
                        {
                            sdom = domain;                             // Inherit the domain
                        }
                        string path = r.ReadElementString().Trim();
                        if (path.Length > 0)
                        {
                            path = Util.NormalizePath(path);
                            if (subs == "true")
                            {
                                directoriesWithSubdirs.Add(new string[] { path, sdom });
                            }
                            else
                            {
                                directories.Add(new string[] { path, sdom });
                            }
                        }
                    }
                    else if (r.NodeType == XmlNodeType.Element && r.LocalName == "GacAssembly")
                    {
                        string aname = r.ReadElementString().Trim();
                        if (aname.Length > 0)
                        {
                            aname = Util.NormalizePath(aname);
                            aname = Util.GetGacPath(aname);
                            if (aname != null)
                            {
                                // Gac assemblies always use the global domain
                                directories.Add(new string[] { aname, AddinDatabase.GlobalDomain });
                            }
                        }
                    }
                    else if (r.NodeType == XmlNodeType.Element && r.LocalName == "Exclude")
                    {
                        string path = r.ReadElementString().Trim();
                        if (path.Length > 0)
                        {
                            path = Util.NormalizePath(path);
                            if (!Path.IsPathRooted(path))
                            {
                                path = Path.Combine(basePath, path);
                            }
                            scanResult.AddPathToIgnore(Util.GetFullPath(path));
                        }
                    }
                    else
                    {
                        r.Skip();
                    }
                    r.MoveToContent();
                }
            } catch (Exception ex) {
                monitor.ReportError("Could not process addins file: " + file, ex);
                return;
            } finally {
                if (r != null)
                {
                    r.Close();
                }
            }

            foreach (string[] d in directories)
            {
                string dir = d[0];
                if (!Path.IsPathRooted(dir))
                {
                    dir = Path.Combine(basePath, dir);
                }
                ScanFolder(monitor, dir, d[1], scanResult);
            }
            foreach (string[] d in directoriesWithSubdirs)
            {
                string dir = d[0];
                if (!Path.IsPathRooted(dir))
                {
                    dir = Path.Combine(basePath, dir);
                }
                ScanFolderRec(monitor, dir, d[1], scanResult);
            }
        }