예제 #1
0
파일: DocFX.cs 프로젝트: alexfordc/Au
    static void Upload(string docDir)
    {
        if (!ARegistry.GetString(out var user, "kas", @"\Help") ||
            !ARegistry.GetString(out var pass, "kaip", @"\Help") ||
            !ARegistry.GetString(out var pass2, "kaip2", @"\Help")
            )
        {
            throw new FileNotFoundException("user or password not found in registry");
        }

        //upload
        pass = Encoding.UTF8.GetString(Convert.FromBase64String(pass));
        var name = @"\_site.tar.bz2";
        var path = docDir + name;

        using (var client = new WebClient()) {
            client.Credentials = new NetworkCredential(user, pass);
            client.UploadFile("ftp://ftp.quickmacros.com/public_html/au" + name, WebRequestMethods.Ftp.UploadFile, path);
        }
        AFile.Delete(path);
        AOutput.Write("Uploaded");

        //extract
        using (var client = new WebClient()) {
            string r1 = client.DownloadString($"https://www.quickmacros.com/au/extract_help.php?kaip={pass2}");
            if (r1 != "done")
            {
                AOutput.Write(r1); return;
            }
        }
        AOutput.Write("<>Extracted to <link>https://www.quickmacros.com/au/help/</link>");
    }
예제 #2
0
        /// <summary>
        /// 执行宏删除指令
        /// </summary>
        /// <exception cref="MacroFormatException"></exception>
        /// <exception cref="AFile.StartupItemNotFoundException"></exception>
        /// <exception cref="UnauthorizedAccessException"></exception>
        private void ExecuteMacroDel()
        {
            // MacroDeleteType - Const Instruction
            if ((Instruction.IndexOf("(") < Instruction.IndexOf(")")) && Instruction.IndexOf(")") != -1 && Instruction.IndexOf(")") == Instruction.Length - 1)
            {
                try { AConstInstruction.Delete(AInstruction_Const.GetConstInstructionFromMacroInstruction(Instruction)); return; }
                catch (Exception exception) { throw exception; }
            }

            List <string> macroInstructionParametersRaw = GetMacroInstructionParametersList();

            if (macroInstructionParametersRaw.Count < 1)
            {
                throw new MacroFormatException();
            }
            foreach (string delItemString in macroInstructionParametersRaw)
            {
                switch (GetMacroDelType(delItemString))
                {
                case MacroDelType.STARTUP: AFile.Delete(delItemString); break;

                case MacroDelType.CONST_QUOTE: ExecuteMacroDelConstQuote(delItemString); break;
                }
            }
        }
예제 #3
0
파일: JSettings.cs 프로젝트: alexfordc/Au
        static JSettings _Load(string file, Type type, bool useDefault)
        {
            JSettings R = null;

            if (AFile.ExistsAsAny(file))
            {
                try {
                    if (useDefault)
                    {
                        AFile.Delete(file);
                    }
                    else
                    {
                        var b   = AFile.LoadBytes(file);
                        var opt = new JsonSerializerOptions {
                            IgnoreNullValues = true, AllowTrailingCommas = true
                        };
                        R = JsonSerializer.Deserialize(b, type, opt) as JSettings;
                    }
                }
                catch (Exception ex) {
                    string es = ex.ToStringWithoutStack();
                    if (useDefault)
                    {
                        AOutput.Write($"Failed to delete settings file '{file}'. {es}");
                    }
                    else
                    {
                        string backup = file + ".backup";
                        try { AFile.Move(file, backup, IfExists.Delete); } catch { backup = "failed"; }
                        AOutput.Write(
                            $@"Failed to load settings from {file}. Will use default settings.
	{es}
	Backup: {backup}"    );
                    }
                }
            }
            R ??= Activator.CreateInstance(type) as JSettings;
            R._file   = file;
            R._loaded = true;

            //autosave
            if (Interlocked.Exchange(ref s_loadedOnce, 1) == 0)
            {
                AThread.Start(() => {
                    for (; ;)
                    {
                        Thread.Sleep(2000);
                        _SaveAllIfNeed();
                    }
                }, sta: false);

                AProcess.Exit += (unu, sed) => _SaveAllIfNeed();                 //info: Core does not call finalizers when process exits
            }
            lock (s_list) s_list.Add(R);

            return(R);
        }
예제 #4
0
    /// <summary>
    /// Creates SQLite database containing Windows API declarations.
    /// </summary>
    public static void CreateWinapi(string csDir = @"Q:\app\Au\Other\Api", string dataDir = @"Q:\app\Au\Other\Data")
    {
        Cursor.Current = Cursors.WaitCursor;
        string dbFile = dataDir + @"\winapi.db";

        AFile.Delete(dbFile);

        string s = File.ReadAllText(csDir + @"\Api.cs");

        using var d     = new ASqlite(dbFile);
        using var trans = d.Transaction();
        d.Execute("CREATE TABLE api (name TEXT, def TEXT)");         //note: no PRIMARY KEY. Don't need index.
        using var statInsert = d.Statement("INSERT INTO api VALUES (?, ?)");

        string rxType     = @"(?ms)^(?:\[[^\r\n]+\r\n)*internal (?:struct|enum|interface|class) (\w+)[^\r\n\{]+\{(?:\}$|.+?^\})";
        string rxFunc     = @"(?m)^(?:\[[^\r\n]+\r\n)*internal (?:static extern|delegate) \w+\** (\w+)\(.+;$";
        string rxVarConst = @"(?m)^internal (?:const|readonly|static) \w+ (\w+) =.+;$";

        foreach (var m in s.RegexFindAll(rxType))
        {
            _Add(m);
        }
        foreach (var m in s.RegexFindAll(rxFunc))
        {
            _Add(m);
        }
        foreach (var m in s.RegexFindAll(rxVarConst))
        {
            _Add(m);
        }

        void _Add(RXMatch m)
        {
            statInsert.Bind(1, m[1].Value);
            statInsert.Bind(2, m.Value);
            statInsert.Step();
            statInsert.Reset();
        }

        trans.Commit();
        d.Execute("VACUUM");

        Program.Settings.db_copy_winapi = dbFile;

        AOutput.Write("CreateWinapi done.");
        Cursor.Current = Cursors.Arrow;
    }
예제 #5
0
    static void _CreateRef(string dbFile, string dir1, string dir2)
    {
        AFile.Delete(dbFile);
        using var d     = new ASqlite(dbFile);
        using var trans = d.Transaction();
        d.Execute("CREATE TABLE ref (name TEXT PRIMARY KEY, data BLOB)");
        using var statInsert = d.Statement("INSERT OR REPLACE INTO ref VALUES (?, ?)");

        _AddDir(dir1, "WindowsBase", "System.Drawing");
        _AddDir(dir2);

        trans.Commit();
        d.Execute("VACUUM");

        AOutput.Write("Created " + dbFile);

        void _AddDir(string dir, params string[] skip)
        {
            foreach (var f in AFile.EnumDirectory(dir))
            {
                if (f.IsDirectory)
                {
                    continue;
                }
                if (!f.Name.Ends(".dll", true))
                {
                    continue;
                }
                var asmName = f.Name.RemoveSuffix(4);
                if (skip.Contains(asmName))
                {
                    continue;
                }
                _AddFile(asmName, f.FullPath);
                //break;
            }
        }

        void _AddFile(string asmName, string asmFile)
        {
            //AOutput.Write(asmName);
            statInsert.Bind(1, asmName);
            statInsert.Bind(2, File.ReadAllBytes(asmFile));
            statInsert.Step();
            statInsert.Reset();
        }
    }
예제 #6
0
        void _SaveLayout()
        {
            try {
                if (ZResetLayoutAfterRestart)
                {
                    AFile.Delete(_xmlFile);
                    return;
                }
                AFile.CreateDirectoryFor(_xmlFile);
                var sett = new XmlWriterSettings()
                {
                    OmitXmlDeclaration = true,
                    Indent             = true,
                    IndentChars        = "\t"
                };
                AFile.Save(_xmlFile, temp => {
                    using (var x = XmlWriter.Create(temp, sett)) {
                        x.WriteStartDocument();
                        x.WriteStartElement("panels");
                        x.WriteAttributeString("version", _asmVersion);
                        _firstSplit.Save(x);
                        x.WriteEndDocument();
                    }
                });
            }
            catch (Exception ex) {
#if DEBUG
                AOutput.QM2.Write(ex);                 //cannot Write or show dialog in ctor
#else
                _ = ex;
#endif
                //AOutput.Write(ex);
                //these don't work, maybe because now is closing app. Never mind, unlikely to fail, and not very important.
                //ADialog.ShowError("Failed to save panel/toolbar layout", _xmlFile, DFlags.Wider, expandedText: e.ToString());
                //MessageBox.Show("aaaa");
            }
        }
예제 #7
0
 void _ApplyTemplates()
 {
     for (int i = 0; i < _templCustomText.Length; i++)
     {
         string text = _templCustomText[i]; if (text == null)
         {
             continue;
         }
         var tt   = (FileNode.ETempl)(1 << i);
         var file = FileNode.Templates.FilePathRaw(tt, true);
         try {
             if (text == FileNode.Templates.Load(tt, false))
             {
                 AFile.Delete(file);
             }
             else
             {
                 AFile.SaveText(file, text);
             }
         }
         catch (Exception ex) { AOutput.Write(ex.ToStringWithoutStack()); }
     }
     Program.Settings.templ_use = _templUseCustom;
 }
예제 #8
0
파일: DocFX.cs 프로젝트: alexfordc/Au
    static void Compress(string docDir)
    {
        var sevenZip = @"C:\Program Files\7-Zip\7z.exe";

        AFile.Delete(docDir + @"\_site.tar");
        AFile.Delete(docDir + @"\_site.tar.bz2");

        int r1 = AExec.RunConsole(out var s, sevenZip, $@"a _site.tar .\_site\*", docDir);

        if (r1 != 0)
        {
            AOutput.Write(s); return;
        }
        int r2 = AExec.RunConsole(out s, sevenZip, $@"a _site.tar.bz2 _site.tar", docDir);

        if (r2 != 0)
        {
            AOutput.Write(s); return;
        }

        AFile.Delete(docDir + @"\_site.tar");

        AOutput.Write("Compressed");
    }
예제 #9
0
        static bool _Compile(bool forRun, FileNode f, out CompResults r, FileNode projFolder)
        {
            var p1 = APerf.Create();

            r = new CompResults();

            var m = new MetaComments();

            if (!m.Parse(f, projFolder, EMPFlags.PrintErrors))
            {
                return(false);
            }
            var err = m.Errors;

            p1.Next('m');

            bool needOutputFiles = m.Role != ERole.classFile;

            //if for run, don't compile if f role is classFile
            if (forRun && !needOutputFiles)
            {
                r.role = ERole.classFile;
                return(false);
            }

            XCompiled cache = XCompiled.OfCollection(f.Model);
            string    outPath = null, outFile = null, fileName = null;

            if (needOutputFiles)
            {
                if (m.OutputPath != null)
                {
                    outPath  = m.OutputPath;
                    fileName = m.Name + ".dll";
                }
                else
                {
                    outPath  = cache.CacheDirectory;
                    fileName = f.IdString;
                }
                outFile = outPath + "\\" + fileName;
                AFile.CreateDirectory(outPath);
            }

            if (m.PreBuild.f != null && !_RunPrePostBuildScript(false, m, outFile))
            {
                return(false);
            }

            var po    = m.CreateParseOptions();
            var trees = new CSharpSyntaxTree[m.CodeFiles.Count];

            for (int i = 0; i < trees.Length; i++)
            {
                var f1 = m.CodeFiles[i];
                trees[i] = CSharpSyntaxTree.ParseText(f1.code, po, f1.f.FilePath, Encoding.UTF8) as CSharpSyntaxTree;
                //info: file path is used later in several places: in compilation error messages, run time stack traces (from PDB), Visual Studio debugger, etc.
                //	Our AOutputServer.SetNotifications callback will convert file/line info to links. It supports compilation errors and run time stack traces.
            }
            //p1.Next('t');

            string asmName = m.Name;

            if (m.Role == ERole.editorExtension)
            {
                asmName = asmName + "|" + (++c_versionCounter).ToString();                                             //AssemblyLoadContext.Default cannot load multiple assemblies with same name
            }
            var compilation = CSharpCompilation.Create(asmName, trees, m.References.Refs, m.CreateCompilationOptions());

            //p1.Next('c');

#if PDB
            string pdbFile = null;
#endif
            MemoryStream          pdbStream = null;
            string                xdFile    = null;
            Stream                xdStream  = null;
            Stream                resNat    = null;
            ResourceDescription[] resMan    = null;
            EmitOptions           eOpt      = null;

            if (needOutputFiles)
            {
                _AddAttributes(ref compilation, needVersionEtc: m.Role == ERole.miniProgram || m.Role == ERole.exeProgram);

                //create debug info always. It is used for run-time error links.
#if PDB
                pdbStream = new MemoryStream();
                if (m.OutputPath != null)
                {
                    pdbFile = Path.ChangeExtension(outFile, "pdb");
                    eOpt    = new EmitOptions(debugInformationFormat: DebugInformationFormat.Pdb, pdbFilePath: pdbFile);
                    //eOpt = new EmitOptions(debugInformationFormat: DebugInformationFormat.PortablePdb, pdbFilePath: pdbFile); //smaller, but not all tools support it
                }
                else
                {
                    //eOpt = new EmitOptions(debugInformationFormat: DebugInformationFormat.Embedded); //no, it is difficult to extract, because we load assembly from byte[] to avoid locking. We instead append portable PDB stream to the assembly stream.
                    eOpt = new EmitOptions(debugInformationFormat: DebugInformationFormat.PortablePdb);
                    //adds < 1 KB; almost the same compiling speed. Separate pdb file is 14 KB; 2 times slower compiling, slower loading.
                }
#else
                if (m.OutputPath != null)
                {
                    //we don't use classic pdb file becouse of this error after switching to .NET Core:
                    //	Unexpected error writing debug information -- 'The version of Windows PDB writer is older than required: 'diasymreader.dll''
                    eOpt = new EmitOptions(debugInformationFormat: DebugInformationFormat.Embedded);
                }
                else
                {
                    pdbStream = new MemoryStream();
                    //eOpt = new EmitOptions(debugInformationFormat: DebugInformationFormat.Embedded); //no, it is difficult to extract, because we load assembly from byte[] to avoid locking. We instead append portable PDB stream to the assembly stream.
                    eOpt = new EmitOptions(debugInformationFormat: DebugInformationFormat.PortablePdb);
                    //adds < 1 KB; almost the same compiling speed. Separate pdb file is 14 KB; 2 times slower compiling, slower loading.
                }
#endif

                if (m.XmlDocFile != null)
                {
                    xdStream = AFile.WaitIfLocked(() => File.Create(xdFile = APath.Normalize(m.XmlDocFile, outPath)));
                }

                resMan = _CreateManagedResources(m);
                if (err.ErrorCount != 0)
                {
                    err.PrintAll(); return(false);
                }

                if (m.Role == ERole.exeProgram || m.Role == ERole.classLibrary)
                {
                    resNat = _CreateNativeResources(m, compilation);
                }
                if (err.ErrorCount != 0)
                {
                    err.PrintAll(); return(false);
                }

                //EmbeddedText.FromX //it seems we can embed source code in PDB. Not tested.
            }

            //p1.Next();
            var asmStream  = new MemoryStream(8000);
            var emitResult = compilation.Emit(asmStream, pdbStream, xdStream, resNat, resMan, eOpt);

            if (needOutputFiles)
            {
                xdStream?.Dispose();
                resNat?.Dispose();                 //info: compiler disposes resMan
            }
            //p1.Next('e');

            var diag = emitResult.Diagnostics;
            if (!diag.IsEmpty)
            {
                foreach (var d in diag)
                {
                    if (d.Severity == DiagnosticSeverity.Hidden)
                    {
                        continue;
                    }
                    err.AddErrorOrWarning(d, f);
                    if (d.Severity == DiagnosticSeverity.Error && d.Id == "CS0009")
                    {
                        MetaReferences.RemoveBadReference(d.GetMessage());
                    }
                }
                err.PrintAll();
            }
            if (!emitResult.Success)
            {
                if (needOutputFiles)
                {
                    AFile.Delete(outFile);
#if PDB
                    if (pdbFile != null)
                    {
                        AFile.Delete(pdbFile);
                    }
#endif
                    if (xdFile != null)
                    {
                        AFile.Delete(xdFile);
                    }
                }
                return(false);
            }

            if (needOutputFiles)
            {
                //If there is no [STAThread], will need MTA thread.
                if (m.Role == ERole.miniProgram || m.Role == ERole.exeProgram)
                {
                    bool hasSTAThread = compilation.GetEntryPoint(default)?.GetAttributes().Any(o => o.ToString() == "System.STAThreadAttribute") ?? false;
예제 #10
0
파일: DocFX.cs 프로젝트: alexfordc/Au
    static void _Main()
    {
        bool isConsole = AOutput.IsConsoleProcess;

        if (!isConsole)
        {
            AOutput.QM2.UseQM2 = true;
            AOutput.Clear();
        }

        var docfx   = @"Q:\Programs\DocFx\docfx.exe";
        var objDir  = @"Q:\Temp\Au\DocFX\obj";
        var docDir  = @"Q:\app\Au\Other\DocFX\_doc";
        var siteDir = docDir + @"\_site";
        var apiDir  = docDir + @"\api";

        //ProcessYamlFile(apiDir + @"\Au.AaaDocFX.yml", true); return;
        //ProcessHtmlFiles(siteDir, true); return;
        //ProcessToc(siteDir); return;

        //Compress(docDir); return;
        //Upload(docDir); return;
        //CompressAndUpload(docDir); return;

        foreach (var v in Process.GetProcessesByName("docfx"))
        {
            v.Kill();
        }
        if (isConsole)
        {
            int k = 0;
            foreach (var v in AWnd.FindAll(@"C:\WINDOWS\system32\cmd.exe", "ConsoleWindowClass"))
            {
                if (k++ > 0)
                {
                    v.Close();
                }
            }
        }

        AFile.Delete(siteDir);
        Directory.SetCurrentDirectory(docDir);

        var t1 = ATime.PerfMilliseconds;

        using (var fw = new FileSystemWatcher(apiDir, "*.yml")) {
            fw.Changed += (sen, e) => {
                //AOutput.Write(e.Name);
                if (e.Name.Starts("Au.", true))
                {
                    ProcessYamlFile(e.FullPath, false);
                }
            };
            fw.EnableRaisingEvents = true;
            fw.NotifyFilter        = NotifyFilters.LastWrite;

            bool serving = false;
            try {
                AExec.RunConsole(o => {
                    AOutput.Write(o);
                    if (o.Starts("Serving"))
                    {
                        throw new OperationCanceledException();
                    }
                }, docfx, $@"docfx.json --intermediateFolder ""{objDir}"" --serve");
                // --force
            }
            catch (OperationCanceledException) {
                serving = true;
            }
            //if(!serving) { ADialog.Show("error?"); return; } //need if this process is not hosted
            if (!serving)
            {
                return;
            }
        }

        var t2 = ATime.PerfMilliseconds;

        ProcessHtmlFiles(siteDir, false);

        var t3 = ATime.PerfMilliseconds; AOutput.Write("speed (s):", (t2 - t1) / 1000, (t3 - t2) / 1000);

        //AWnd.Find("* Chrome").Activate();
        //AKeys.Key("F5");

        1.s();
        if (1 == ADialog.Show("Upload?", null, "1 Yes|2 No" /*, secondsTimeout: 5*/))
        {
            CompressAndUpload(docDir);
        }

        //Delete obj folder if big. Each time it grows by 10 MB, and after a day or two can be > 1 GB. After deleting builds slower by ~50%.
        if (AFile.More.CalculateDirectorySize(objDir) / 1024 / 1024 > 500)
        {
            AOutput.Write("Deleting obj folder."); AFile.Delete(objDir);
        }
        //info: if DocFX starts throwing stack overflow exception, delete the obj folder manually. It is likely to happen after many refactorings in the project.
    }
예제 #11
0
        /// <summary>
        /// Deletes the specified file.
        /// </summary>
        /// <param name="file">The file.</param>
        /// <returns>Whether the file was deleted or not.</returns>
        public static bool Delete(AFile file)
        {
            Exceptions.NotNullException<AFile>(file, nameof(file));

            return file.Delete();
        }
예제 #12
0
            /// <summary>
            /// Creates documentation provider for assembly <i>asmPath</i>.
            /// Returns null if its xml file does not exist.
            /// Returns _DocumentationProvider if xml file is big and found or successfully created and successfully loaded database for it.
            /// Else returns XmlDocumentationProvider.
            /// </summary>
            public static DocumentationProvider Create(string asmPath)
            {
                if (s_d.TryGetValue(asmPath, out var dp))
                {
                    return(dp);
                }

                var xmlPath = Path.ChangeExtension(asmPath, "xml");

                if (!AFile.GetProperties(xmlPath, out var px))
                {
                    return(null);
                }

                if (px.Size >= 10_000)
                {
                    var md5    = new Au.Util.AHash.MD5(); md5.Add(xmlPath.Lower());
                    var dbPath = AFolders.ThisAppTemp + md5.Hash.ToString() + ".db";
                    try {
                        if (!AFile.GetProperties(dbPath, out var pd) || pd.LastWriteTimeUtc != px.LastWriteTimeUtc)
                        {
                            //ADebug.Print($"creating db: {asmPath}  ->  {dbPath}");
                            AFile.Delete(dbPath);
                            using (var d = new ASqlite(dbPath)) {
                                using var trans = d.Transaction();
                                d.Execute("CREATE TABLE doc (name TEXT PRIMARY KEY, xml TEXT)");
                                using var statInsert = d.Statement("INSERT INTO doc VALUES (?, ?)");

                                var xr = AExtXml.LoadElem(xmlPath);
                                foreach (var e in xr.Descendants("member"))
                                {
                                    var name = e.Attr("name");

                                    //remove <remarks> and <example>.
                                    foreach (var v in e.Descendants("remarks").ToArray())
                                    {
                                        v.Remove();
                                    }
                                    foreach (var v in e.Descendants("example").ToArray())
                                    {
                                        v.Remove();
                                    }

                                    using var reader = e.CreateReader();
                                    reader.MoveToContent();
                                    var xml = reader.ReadInnerXml();
                                    //AOutput.Write(name, xml);

                                    statInsert.BindAll(name, xml).Step();
                                    statInsert.Reset();
                                }
                                trans.Commit();
                                d.Execute("VACUUM");
                            }
                            File.SetLastWriteTimeUtc(dbPath, px.LastWriteTimeUtc);
                        }
                        var db = new ASqlite(dbPath, SLFlags.SQLITE_OPEN_READONLY);                         //never mind: we don't dispose it on process exit
                        s_d[asmPath] = dp = new _DocumentationProvider {
                            _db = db
                        };
                        return(dp);
                    }
                    catch (Exception ex) { ADebug.Print(ex.ToStringWithoutStack()); }
                }
                return(XmlDocumentationProvider.CreateFromFile(xmlPath));
            }
예제 #13
0
    static void _CreateDoc(string dbFile, string dir1, string dir2)
    {
        AFile.Delete(dbFile);
        using var d     = new ASqlite(dbFile, sql: "PRAGMA page_size = 8192;");     //8192 makes file smaller by 2-3 MB.
        using var trans = d.Transaction();
        d.Execute("CREATE TABLE doc (name TEXT PRIMARY KEY, xml TEXT)");
        using var statInsert = d.Statement("INSERT INTO doc VALUES (?, ?)");
        using var statDupl   = d.Statement("SELECT xml FROM doc WHERE name=?");
        var haveRefs = new List <string>();
        var uniq     = new Dictionary <string, string>();    //name -> asmName

        //using var textFile = File.CreateText(Path.ChangeExtension(dbFile, "txt")); //test. Compresses almost 2 times better than db.

        _AddDir(dir1, "WindowsBase");
        _AddDir(dir2);

        statInsert.BindAll(".", string.Join("\n", haveRefs)).Step();

        trans.Commit();
        d.Execute("VACUUM");

        AOutput.Write("Created " + dbFile);

        void _AddDir(string dir, params string[] skip)
        {
            foreach (var f in AFile.EnumDirectory(dir))
            {
                if (f.IsDirectory)
                {
                    continue;
                }
                if (!f.Name.Ends(".xml", true))
                {
                    continue;
                }
                var asmName = f.Name.RemoveSuffix(4);
                if (skip.Contains(asmName))
                {
                    continue;
                }
                if (!AFile.ExistsAsFile(dir + asmName + ".dll"))
                {
                    AOutput.Write("<><c 0x808080>" + f.Name + "</c>");
                    continue;
                }
                _AddFile(asmName, f.FullPath);
                //break;
            }
        }

        void _AddFile(string asmName, string xmlFile)
        {
            //AOutput.Write(asmName);
            haveRefs.Add(asmName);
            var xr = AExtXml.LoadElem(xmlFile);

            foreach (var e in xr.Descendants("member"))
            {
                var name = e.Attr("name");

                //remove <remarks> and <example>. Does not save much space, because .NET xmls don't have it.
                foreach (var v in e.Descendants("remarks").ToArray())
                {
                    v.Remove();
                }
                foreach (var v in e.Descendants("example").ToArray())
                {
                    v.Remove();
                }

                using var reader = e.CreateReader();
                reader.MoveToContent();
                var xml = reader.ReadInnerXml();
                //AOutput.Write(name, xml);

                //textFile.WriteLine(name); textFile.WriteLine(xml); textFile.WriteLine("\f");

                if (uniq.TryGetValue(name, out var prevRef))
                {
                    if (!statDupl.Bind(1, name).Step())
                    {
                        throw new AuException();
                    }
                    var prev = statDupl.GetText(0);
                    if (xml != prev && asmName != "System.Linq")
                    {
                        AOutput.Write($"<>\t{name} already defined in {prevRef}\r\n<c 0xc000>{prev}</c>\r\n<c 0xff0000>{xml}</c>");
                    }
                    statDupl.Reset();
                }
                else
                {
                    statInsert.BindAll(name, xml).Step();
                    uniq.Add(name, asmName);
                }
                statInsert.Reset();
            }
        }
    }