// search directory for *.dll,
        // return loaded, failed, new dlls not in the allowed/disallowed list, disabled
        // alloweddisallowed list is +allowed,-disallowed..
        // all Csharp assembly DLLs are loaded - only ones implementing *EDDClass class causes it to be added to the DLL list
        // only normal DLLs implementing EDDInitialise are kept loaded

        public Tuple <string, string, string, string> Load(string[] dlldirectories, bool[] disallowautomatically, string ourversion, string[] inoptions,
                                                           EDDDLLInterfaces.EDDDLLIF.EDDCallBacks callbacks, ref string alloweddisallowed,
                                                           Func <string, string> getconfig, Action <string, string> setconfig
                                                           )
        {
            string loaded   = "";
            string failed   = "";
            string disabled = "";
            string newdlls  = "";

            for (int i = 0; i < dlldirectories.Length; i++)
            {
                var dlldirectory = dlldirectories[i];

                if (dlldirectory != null)
                {
                    if (!Directory.Exists(dlldirectory))
                    {
                        failed = failed.AppendPrePad("DLL Folder " + dlldirectory + " does not exist", ",");
                    }
                    else
                    {
                        FileInfo[] allFiles = Directory.EnumerateFiles(dlldirectory, "*.dll", SearchOption.TopDirectoryOnly).Select(f => new FileInfo(f)).OrderBy(p => p.LastWriteTime).ToArray();

                        string[] allowedfiles = alloweddisallowed.Split(',');

                        foreach (FileInfo f in allFiles)
                        {
                            EDDDLLCaller caller = new EDDDLLCaller();

                            System.Diagnostics.Debug.WriteLine("Try to load " + f.FullName);

                            string filename = System.IO.Path.GetFileNameWithoutExtension(f.FullName);

                            bool isallowed = alloweddisallowed.Equals("All", StringComparison.InvariantCultureIgnoreCase) ||
                                             allowedfiles.Contains("+" + f.FullName, StringComparer.InvariantCultureIgnoreCase) ||    // full name is now used
                                             allowedfiles.Contains("+" + filename, StringComparer.InvariantCultureIgnoreCase);        // filename previously used

                            bool isdisallowed = allowedfiles.Contains("-" + f.FullName, StringComparer.InvariantCultureIgnoreCase) || // full name is now used
                                                allowedfiles.Contains("-" + filename, StringComparer.InvariantCultureIgnoreCase);     // filename previously used

                            if (isdisallowed)                                                                                         // disallowed
                            {
                                disabled = disabled.AppendPrePad(f.FullName, ",");
                            }
                            else if (isallowed)                                                      // if allowed..
                            {
                                if (caller.Load(f.FullName))                                         // if loaded okay
                                {
                                    if (caller.Init(ourversion, inoptions, dlldirectory, callbacks)) // must init
                                    {
                                        if (caller.HasConfig())
                                        {
                                            string cfg = getconfig(caller.Name);
                                            string res = caller.Config(cfg, false);  // pass in config, save config, don't edit
                                            setconfig(caller.Name, res);
                                        }

                                        DLLs.Add(caller);
                                        loaded = loaded.AppendPrePad(filename, ",");        // just use short name for reporting
                                    }
                                    else
                                    {
                                        string errstr = caller.Version.HasChars() ? (": " + caller.Version.Substring(1)) : "";
                                        failed = failed.AppendPrePad(f.FullName + errstr, ","); // long name for failure
                                    }
                                }
                            }
                            else
                            {
                                bool innewdlls = newdlls.Contains(f.FullName);

                                if (disallowautomatically[i])
                                {
                                    if (!innewdlls)     // Ealhstan special - if we are scanning the same folder multiple times, it may have already been added to newdlls
                                    {
                                        alloweddisallowed = alloweddisallowed.AppendPrePad("-" + f.FullName, ",");
                                        disabled          = disabled.AppendPrePad(f.FullName, ",");
                                    }
                                }
                                else
                                {
                                    if (!innewdlls)      // Eahlstan special - don't add twice to the newdlls in case we are scanning the same folder twice
                                    {
                                        newdlls = newdlls.AppendPrePad(f.FullName, ",");
                                    }
                                }
                            }
                        }
                    }
                }
            }

            return(new Tuple <string, string, string, string>(loaded, failed, newdlls, disabled));
        }