Наша сборка Qt VS Tools
giy
2022-09-02 ca47896204482bf4a6979e3838bf7f09f61cebeb
QtVsTools.Core/QtVersionManager.cs
@@ -1,6 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Copyright (C) 2022 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt VS Tools.
@@ -26,16 +26,14 @@
**
****************************************************************************/
using Microsoft.VisualStudio.VCProjectEngine;
using Microsoft.Win32;
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading;
using QtVsTools.VisualStudio;
using EnvDTE;
using Microsoft.VisualStudio.Shell;
using Microsoft.VisualStudio.VCProjectEngine;
using Microsoft.Win32;
namespace QtVsTools.Core
{
@@ -45,37 +43,20 @@
    public class QtVersionManager
    {
        private static QtVersionManager instance;
        private string regVersionPath;
        private string strVersionKey;
        private readonly string regVersionPath;
        private readonly string strVersionKey;
        private Hashtable versionCache;
        protected QtVersionManager()
        {
            strVersionKey = "Versions";
            regVersionPath = Resources.registryVersionPath;
            RefreshVersionNames();
        }
        void RefreshVersionNames()
        {
            var rootKeyPath = "SOFTWARE\\" + Resources.registryRootPath;
            try {
                using (var rootKey = Registry.CurrentUser.OpenSubKey(rootKeyPath, true))
                using (var versionsKey = rootKey.OpenSubKey(strVersionKey, true)) {
                    versionsKey.SetValue("VersionNames", string.Join(";", GetVersions()));
                }
        private static readonly EventWaitHandle packageInit = new EventWaitHandle(false, EventResetMode.ManualReset);
        private static EventWaitHandle packageInitDone = null;
            } catch (Exception e) {
                Messages.Print(
                    e.Message + "\r\n\r\nStacktrace:\r\n" + e.StackTrace);
            }
        }
        static EventWaitHandle
            packageInit = new EventWaitHandle(false, EventResetMode.ManualReset),
            packageInitDone = null;
        static public QtVersionManager The(EventWaitHandle initDone = null)
        public static QtVersionManager The(EventWaitHandle initDone = null)
        {
            if (initDone == null) {
                packageInit.WaitOne();
@@ -92,10 +73,10 @@
        public VersionInformation GetVersionInfo(string name)
        {
            if (name == "$(DefaultQtVersion)")
                name = GetDefaultVersion();
            if (name == null)
                return null;
            if (name == "$(DefaultQtVersion)")
                name = GetDefaultVersion();
            if (versionCache == null)
                versionCache = new Hashtable();
@@ -111,13 +92,8 @@
        public VersionInformation GetVersionInfo(EnvDTE.Project project)
        {
            ThreadHelper.ThrowIfNotOnUIThread();
            return GetVersionInfo(GetProjectQtVersion(project));
        }
        public void ClearVersionCache()
        {
            if (versionCache != null)
                versionCache.Clear();
        }
        public string[] GetVersions()
@@ -130,13 +106,12 @@
            if (qtDir == null)
                return null;
            qtDir = qtDir.ToLower();
            var versions = GetVersions();
            foreach (var version in versions) {
                var installPath = GetInstallPath(version);
                if (installPath == null)
                    continue;
                if (installPath.ToLower() == qtDir)
                if (installPath.Equals(qtDir, StringComparison.OrdinalIgnoreCase))
                    return version;
            }
@@ -157,84 +132,61 @@
        /// <summary>
        /// Check if all Qt versions are valid and readable.
        /// </summary>
        /// Also sets the default Qt version to the newest version, if needed.
        /// <param name="errorMessage"></param>
        /// <returns>true, if we found an invalid version</returns>
        public bool HasInvalidVersions(out string errorMessage)
        /// <returns>true, if there are one or more invalid Qt version</returns>
        public bool HasInvalidVersions(out string errorMessage, out bool defaultVersionInvalid)
        {
            var validVersions = new Dictionary<string, QtConfig>();
            var invalidVersions = new List<string>();
            var defaultVersion = GetDefaultVersionString();
            defaultVersionInvalid = string.IsNullOrEmpty(defaultVersion);
            foreach (var v in GetVersions()) {
                if (v == "$(DefaultQtVersion)")
                    continue;
                var vPath = GetInstallPath(v);
                if (string.IsNullOrEmpty(vPath)) {
                    invalidVersions.Add(v);
                    continue;
                }
                if (vPath.StartsWith("SSH:") || vPath.StartsWith("WSL:"))
                    continue;
                var qmakePath = Path.Combine(vPath, "bin", "qmake.exe");
                if (!File.Exists(qmakePath))
                    qmakePath = Path.Combine(vPath, "qmake.exe");
                if (!File.Exists(qmakePath)) {
                    invalidVersions.Add(v);
                    continue;
                }
                validVersions[v] = new QtConfig(vPath);
            }
            if (invalidVersions.Count > 0) {
                errorMessage = "These Qt version are inaccessible:\n";
                foreach (var invalidVersion in invalidVersions)
                    errorMessage += invalidVersion + " in " + GetInstallPath(invalidVersion) + "\n";
                errorMessage += "Make sure that you have read access to all files in your Qt directories.";
                // Is the default Qt version invalid?
                var isDefaultQtVersionInvalid = false;
                var defaultQtVersionName = GetDefaultVersion();
                if (string.IsNullOrEmpty(defaultQtVersionName)) {
                    isDefaultQtVersionInvalid = true;
                } else {
                    foreach (var name in invalidVersions) {
                        if (name == defaultQtVersionName) {
                            isDefaultQtVersionInvalid = true;
                            break;
                        }
                    }
                }
                // find the newest valid Qt version that can be used as default version
                if (isDefaultQtVersionInvalid && validVersions.Count > 0) {
                    QtConfig defaultQtVersionConfig = null;
                    foreach (var vNameConfig in validVersions) {
                        var vName = vNameConfig.Key;
                        var v = vNameConfig.Value;
                        if (defaultQtVersionConfig == null) {
                            defaultQtVersionConfig = v;
                            defaultQtVersionName = vName;
                            continue;
                        }
                        if (defaultQtVersionConfig.VersionMajor < v.VersionMajor ||
                               (defaultQtVersionConfig.VersionMajor == v.VersionMajor && (defaultQtVersionConfig.VersionMinor < v.VersionMinor ||
                                   (defaultQtVersionConfig.VersionMinor == v.VersionMinor && defaultQtVersionConfig.VersionPatch < v.VersionPatch)))) {
                            defaultQtVersionConfig = v;
                            defaultQtVersionName = vName;
                        }
                    }
                    if (defaultQtVersionConfig != null)
                        SaveDefaultVersion(defaultQtVersionName);
                }
                return true;
            }
            errorMessage = null;
            return false;
            foreach (var version in GetVersions()) {
                if (version == "$(DefaultQtVersion)")
                    continue;
                var path = GetInstallPath(version);
                if (path != null && (path.StartsWith("SSH:") || path.StartsWith("WSL:")))
                    continue;
                if (string.IsNullOrEmpty(path) || !QMake.Exists(path)) {
                    errorMessage += version + " in " + path + "\n";
                    defaultVersionInvalid |= version == defaultVersion;
                }
                if (!string.IsNullOrEmpty(errorMessage)) {
                    errorMessage = "These Qt version are inaccessible:\n"
                        + errorMessage
                        + "Make sure that you have read access to all files in your Qt directories.";
                }
            }
            return errorMessage != null;
        }
        public void SetLatestQtVersionAsDefault()
        {
            var validVersions = new Dictionary<string, Version>();
            foreach (var version in GetVersions()) {
                if (version == "$(DefaultQtVersion)")
                    continue;
                var path = GetInstallPath(version);
                if (!string.IsNullOrEmpty(path) && QMake.Exists(path))
                    validVersions[version] = new Version(new QtConfig(path).VersionString);
            }
            if (validVersions.Count <= 0)
                return;
            var defaultName = "";
            Version defaultVersion = null;
            foreach (var tmp in validVersions) {
                var version = tmp.Value;
                if (defaultVersion == null || defaultVersion < version) {
                    defaultName = tmp.Key;
                    defaultVersion = version;
                }
            }
            SaveDefaultVersion(defaultName);
        }
        public string GetInstallPath(string version)
@@ -252,16 +204,14 @@
                return Environment.GetEnvironmentVariable("QTDIR");
            var key = root.OpenSubKey("SOFTWARE\\" + Resources.registryRootPath, false);
            if (key == null)
                return null;
            var versionKey = key.OpenSubKey(strVersionKey + "\\" + version, false);
            if (versionKey == null)
                return null;
            return (string)versionKey.GetValue("InstallDir");
            var versionKey = key?.OpenSubKey(strVersionKey + "\\" + version, false);
            return versionKey?.GetValue("InstallDir") as string;
        }
        public string GetInstallPath(EnvDTE.Project project)
        {
            ThreadHelper.ThrowIfNotOnUIThread();
            var version = GetProjectQtVersion(project);
            if (version == "$(DefaultQtVersion)")
                version = GetDefaultVersion();
@@ -309,7 +259,6 @@
                    versionKey.SetValue("InstallDir", dir);
                }
            }
            RefreshVersionNames();
            return true;
        }
@@ -320,10 +269,9 @@
                return;
            key.DeleteSubKey(versionName);
            key.Close();
            RefreshVersionNames();
        }
        private bool IsVersionAvailable(string version)
        internal bool IsVersionAvailable(string version)
        {
            var versionAvailable = false;
            var versions = GetVersions();
@@ -338,13 +286,17 @@
        public bool SaveProjectQtVersion(EnvDTE.Project project, string version)
        {
            ThreadHelper.ThrowIfNotOnUIThread();
            return SaveProjectQtVersion(project, version, project.ConfigurationManager.ActiveConfiguration.PlatformName);
        }
        public bool SaveProjectQtVersion(EnvDTE.Project project, string version, string platform)
        {
            ThreadHelper.ThrowIfNotOnUIThread();
            if (!IsVersionAvailable(version) && version != "$(DefaultQtVersion)")
                return false;
            if (QtProject.GetFormatVersion(project) >= Resources.qtMinFormatVersion_Settings) {
                var vcPro = project.Object as VCProject;
                if (vcPro == null)
@@ -365,6 +317,8 @@
        public string GetProjectQtVersion(EnvDTE.Project project)
        {
            ThreadHelper.ThrowIfNotOnUIThread();
            EnvDTE.Configuration config = null;
            try {
                config = project.ConfigurationManager.ActiveConfiguration;
@@ -382,13 +336,15 @@
            }
            if (version == null)
                version = GetSolutionQtVersion(project.DTE.Solution);
                version = Legacy.QtVersionManager.GetSolutionQtVersion(project.DTE.Solution);
            return version;
        }
        public string GetProjectQtVersion(EnvDTE.Project project, EnvDTE.Configuration config)
        {
            ThreadHelper.ThrowIfNotOnUIThread();
            if (QtProject.GetFormatVersion(project) >= Resources.qtMinFormatVersion_Settings)
                return QtProject.GetPropertyValue(project, config, "QtInstall");
@@ -402,6 +358,8 @@
        public string GetProjectQtVersion(EnvDTE.Project project, string platform)
        {
            ThreadHelper.ThrowIfNotOnUIThread();
            if (QtProject.GetFormatVersion(project) >= Resources.qtMinFormatVersion_Settings)
                return GetProjectQtVersion(project);
@@ -426,29 +384,6 @@
                    version = Environment.GetEnvironmentVariable(env);
                }
            }
        }
        public bool SaveSolutionQtVersion(EnvDTE.Solution solution, string version)
        {
            if (!IsVersionAvailable(version) && version != "$(DefaultQtVersion)")
                return false;
            solution.Globals["Qt5Version"] = version;
            if (!solution.Globals.get_VariablePersists("Qt5Version"))
                solution.Globals.set_VariablePersists("Qt5Version", true);
            return true;
        }
        public string GetSolutionQtVersion(EnvDTE.Solution solution)
        {
            if (solution == null)
                return null;
            if (solution.Globals.get_VariableExists("Qt5Version")) {
                var version = (string)solution.Globals["Qt5Version"];
                return VerifyIfQtVersionExists(version) ? version : null;
            }
            return null;
        }
        public string GetDefaultVersion()
@@ -489,6 +424,25 @@
                }
            }
            return VerifyIfQtVersionExists(defaultVersion) ? defaultVersion : null;
        }
        public string GetDefaultVersionString()
        {
            string defaultVersion = null;
            try {
                var key = Registry.CurrentUser.OpenSubKey("SOFTWARE\\" + regVersionPath, false);
                if (key != null)
                    defaultVersion = key.GetValue("DefaultQtVersion") as string;
            } catch {
                Messages.Print("Cannot read the default Qt version from registry.");
            }
            if (defaultVersion == null) {
                var qtDir = Environment.GetEnvironmentVariable("QTDIR");
                if (string.IsNullOrEmpty(qtDir))
                    return defaultVersion;
            }
            return defaultVersion;
        }
        public bool SaveDefaultVersion(string version)
@@ -540,7 +494,7 @@
            }
        }
        private bool VerifyIfQtVersionExists(string version)
        internal bool VerifyIfQtVersionExists(string version)
        {
            if (version == "$(DefaultQtVersion)")
                version = GetDefaultVersion();