Esempio n. 1
0
    /// <summary>
    /// Creates SQLite databases containing design-time assemblies and XML documentation files of a .NET Core runtime. The SDK must be installed.
    /// </summary>
    /// <remarks>
    /// Shows a list dialog.
    ///		If selected All, creates for all runtime versions starting from 3.1, with names ref.version.db (eg ref.3.1.0.db) and doc.version.db, in AFolders.ThisAppBS.
    ///		Else creates only for the selected runtime version, with names ref.db and doc.db, in dataDir, and sets to copy to AFolders.ThisAppBS when opening next time after process restarts.
    /// We ship and at run time load databases of single version, named ref.db and doc.db. In the future should allow to download and use multiple versions.
    /// Also this function allows users to create databases from SDKs installed on their PC, but currently this feature is not exposed. Would need to add UI and exception handling.
    /// ref.db contains dlls from 'dotnet\packs' folder. They contain only metadata of public API, not all code like dlls in the 'dotnet\shared' folder.
    ///		Why need it when we can load PortableExecutableReference from 'dotnet\shared' folder? Because:
    ///			1. They are big and may add 100 MB of process memory. We need to load all, because cannot know which are actually used in various stages of compilation.
    ///			2. When loading from dll files, Windows Defender makes it as slow as 2.5 s or more, unless the files already are in OS file buffers.
    ///			3. Better compatibility. See https://github.com/dotnet/standard/blob/master/docs/history/evolution-of-design-time-assemblies.md
    ///	doc.db contains XML documentation files of .NET Core assemblies. From the same 'dotnet\packs' folder.
    ///		Why need it:
    ///			1. Else users would have to download whole .NET Core SDK. Now need only runtimes.
    ///			2. Parsed XML files can use eg 200 MB of process memory. Now we get doc of a single type/method/etc from database only when need; all other data is not in memory.
    ///
    /// Need to run this after changing Core version of C# projects (<TargetFramework>netcoreapp3.1</TargetFramework>). Also update COREVER2 etc in AppHost.cpp.
    /// </remarks>
    public static void CreateRefAndDoc(string dataDir = @"Q:\app\Au\Other\Data")
    {
        Cursor.Current = Cursors.WaitCursor;
        if (0 == AFolders.NetRuntimeBS.RegexReplace(@"(?i)\\shared\\(Microsoft\.NETCore\.App)\\.+", @"\packs\$1.Ref", out var refDir, 1))
        {
            throw new AuException();
        }
        //AOutput.Write(refDir);
        var a = new List <string>();

        foreach (var f in AFile.EnumDirectory(refDir, FEFlags.UseRawPath))          //for each version
        {
            if (!f.IsDirectory)
            {
                continue;
            }
            var s = f.Name;
            int v1 = s.ToInt(0, out int ne), v2 = s.ToInt(ne + 1); if (v1 < 3 || v2 < 1)
            {
                continue;                                                                                     //must be 3.1 or later
            }
            a.Add(s);
        }
        a.Add("All");
        int i = ADialog.ShowList(a, "Create database", "For runtime") - 1;

        if (i < 0)
        {
            return;
        }
        int n = a.Count - 1;

        if (i < n)
        {
            _CreateRefAndDoc(refDir, a[i], false, dataDir);
        }
        else
        {
            for (i = 0; i < n; i++)
            {
                _CreateRefAndDoc(refDir, a[i], true, dataDir);
            }
        }
        AOutput.Write("CreateRefAndDoc done.");
        Cursor.Current = Cursors.Arrow;
    }
Esempio n. 2
0
    async void _ConvertTypeLibrary(object tlDef, object button)
    {
        string comDll = null;

        switch (tlDef)
        {
        case string path:
            comDll = path;
            break;

        case _RegTypelib r:
            //can be several locales
            var aloc  = new List <string>();           //registry keys like "0" or "409"
            var aloc2 = new List <string>();           //locale names for display in the list dialog
            using (var verKey = Registry.ClassesRoot.OpenSubKey($@"TypeLib\{r.guid}\{r.version}")) {
                foreach (var s1 in verKey.GetSubKeyNames())
                {
                    int lcid = s1.ToInt(0, out int iEnd, STIFlags.IsHexWithout0x);
                    if (iEnd != s1.Length)
                    {
                        continue;                                       //"FLAGS" etc; must be hex number without 0x
                    }
                    aloc.Add(s1);
                    var s2 = "Neutral";
                    if (lcid > 0)
                    {
                        try { s2 = new CultureInfo(lcid).DisplayName; } catch { s2 = s1; }
                    }
                    aloc2.Add(s2);
                }
            }
            string locale;
            if (aloc.Count == 1)
            {
                locale = aloc[0];
            }
            else
            {
                int i = ADialog.ShowList(aloc2, "Locale", owner: this);
                if (i == 0)
                {
                    return;
                }
                locale = aloc[i - 1];
            }
            comDll = r.GetPath(locale);
            if (comDll == null || !AFile.ExistsAsFile(comDll))
            {
                ADialog.ShowError(comDll == null ? "Failed to get file path." : "File does not exist.", owner: this);
                return;
            }
            break;
        }

        await Task.Run(() => {
            this.Enabled = false;
            AOutput.Write($"Converting COM type library to .NET assembly.");
            try {
                if (_convertedDir == null)
                {
                    _convertedDir = AFolders.Workspace + @".interop\";
                    AFile.CreateDirectory(_convertedDir);
                }
                List <string> converted  = new List <string>();
                Action <string> callback = s => {
                    AOutput.Write(s);
                    if (s.Starts("Converted: "))
                    {
                        s.RegexMatch(@"""(.+?)"".$", 1, out s);
                        converted.Add(s);
                    }
                };
                int rr = AExec.RunConsole(callback, AFolders.ThisAppBS + "Au.Net45.exe", $"/typelib \"{_convertedDir}|{comDll}\"", encoding: Encoding.UTF8);
                if (rr == 0)
                {
                    foreach (var v in converted)
                    {
                        if (!_meta.com.Contains(v))
                        {
                            _meta.com.Add(v);
                        }
                    }
                    AOutput.Write(@"<>Converted and saved in <link>%AFolders.Workspace%\.interop<>.");
                    _Added(button, _meta.com);
                }
            }
            catch (Exception ex) { ADialog.ShowError("Failed to convert type library", ex.ToStringWithoutStack(), owner: this); }
            this.Enabled = true;
        });
    }