From ca47896204482bf4a6979e3838bf7f09f61cebeb Mon Sep 17 00:00:00 2001 From: giy <giy@omp-system.ru> Date: Fri, 02 Sep 2022 14:16:56 +0300 Subject: [PATCH] Обновление до версии 2.9.0 --- QtVsTools.Core/HelperFunctions.cs | 629 ++++++++++++++------------------------------------------ 1 files changed, 162 insertions(+), 467 deletions(-) diff --git a/QtVsTools.Core/HelperFunctions.cs b/QtVsTools.Core/HelperFunctions.cs index b6fe0ff..a07fa89 100644 --- a/QtVsTools.Core/HelperFunctions.cs +++ b/QtVsTools.Core/HelperFunctions.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,10 +26,6 @@ ** ****************************************************************************/ -using EnvDTE; -using Microsoft.VisualStudio.VCProjectEngine; -using Microsoft.Win32; -using QtVsTools.Core.QtMsBuild; using System; using System.Collections.Generic; using System.Diagnostics; @@ -40,105 +36,31 @@ using System.Text; using System.Text.RegularExpressions; using System.Windows.Forms; +using Microsoft.VisualStudio.Shell; +using Microsoft.VisualStudio.VCProjectEngine; +#if VS2017 +using Microsoft.Win32; +#endif +using EnvDTE; using Process = System.Diagnostics.Process; namespace QtVsTools.Core { + using QtMsBuild; + public static class HelperFunctions { - public static string FindQtDirWithTools(Project project) - { - var versionManager = QtVersionManager.The(); - string projectQtVersion = null; - if (IsQtProject(project)) - projectQtVersion = versionManager.GetProjectQtVersion(project); - return FindQtDirWithTools(projectQtVersion); - } - - public static string FindQtDirWithTools(string projectQtVersion) - { - string tool = null; - return FindQtDirWithTools(tool, projectQtVersion); - } - - public static string FindQtDirWithTools(string tool, string projectQtVersion) - { - if (!string.IsNullOrEmpty(tool)) { - if (!tool.StartsWith("\\bin\\", StringComparison.OrdinalIgnoreCase)) - tool = "\\bin\\" + tool; - if (!tool.EndsWith(".exe", StringComparison.OrdinalIgnoreCase)) - tool += ".exe"; - } - - var versionManager = QtVersionManager.The(); - string qtDir = null; - if (projectQtVersion != null) - qtDir = versionManager.GetInstallPath(projectQtVersion); - - if (qtDir == null) - qtDir = Environment.GetEnvironmentVariable("QTDIR"); - - var found = false; - if (tool == null) { - found = File.Exists(qtDir + "\\bin\\designer.exe") - && File.Exists(qtDir + "\\bin\\linguist.exe"); - } else { - found = File.Exists(qtDir + tool); - } - if (!found) { - VersionInformation exactlyMatchingVersion = null; - VersionInformation matchingVersion = null; - VersionInformation somehowMatchingVersion = null; - var viProjectQtVersion = versionManager.GetVersionInfo(projectQtVersion); - foreach (var qtVersion in versionManager.GetVersions()) { - var vi = versionManager.GetVersionInfo(qtVersion); - if (tool == null) { - found = File.Exists(vi.qtDir + "\\bin\\designer.exe") - && File.Exists(vi.qtDir + "\\bin\\linguist.exe"); - } else { - found = File.Exists(vi.qtDir + tool); - } - if (!found) - continue; - - if (viProjectQtVersion != null - && vi.qtMajor == viProjectQtVersion.qtMajor - && vi.qtMinor == viProjectQtVersion.qtMinor) { - exactlyMatchingVersion = vi; - break; - } - if (matchingVersion == null - && viProjectQtVersion != null - && vi.qtMajor == viProjectQtVersion.qtMajor) { - matchingVersion = vi; - } - if (somehowMatchingVersion == null) - somehowMatchingVersion = vi; - } - - if (exactlyMatchingVersion != null) - qtDir = exactlyMatchingVersion.qtDir; - else if (matchingVersion != null) - qtDir = matchingVersion.qtDir; - else if (somehowMatchingVersion != null) - qtDir = somehowMatchingVersion.qtDir; - else - qtDir = null; - } - return qtDir; - } - static readonly HashSet<string> _sources = new HashSet<string>(new[] { ".c", ".cpp", ".cxx" }, StringComparer.OrdinalIgnoreCase); - static public bool IsSourceFile(string fileName) + public static bool IsSourceFile(string fileName) { return _sources.Contains(Path.GetExtension(fileName)); } static readonly HashSet<string> _headers = new HashSet<string>(new[] { ".h", ".hpp", ".hxx" }, StringComparer.OrdinalIgnoreCase); - static public bool IsHeaderFile(string fileName) + public static bool IsHeaderFile(string fileName) { return _headers.Contains(Path.GetExtension(fileName)); } @@ -173,23 +95,28 @@ return ".qml".Equals(Path.GetExtension(fileName), StringComparison.OrdinalIgnoreCase); } - static public void SetDebuggingEnvironment(Project prj) + public static void SetDebuggingEnvironment(Project prj) { + ThreadHelper.ThrowIfNotOnUIThread(); SetDebuggingEnvironment(prj, string.Empty); } - static public void SetDebuggingEnvironment(Project prj, string solutionConfig) + public static void SetDebuggingEnvironment(Project prj, string solutionConfig) { + ThreadHelper.ThrowIfNotOnUIThread(); SetDebuggingEnvironment(prj, "PATH=$(QTDIR)\\bin;$(PATH)", false, solutionConfig); } - static public void SetDebuggingEnvironment(Project prj, string envpath, bool overwrite) + public static void SetDebuggingEnvironment(Project prj, string envpath, bool overwrite) { + ThreadHelper.ThrowIfNotOnUIThread(); SetDebuggingEnvironment(prj, envpath, overwrite, string.Empty); } - static public void SetDebuggingEnvironment(Project prj, string envpath, bool overwrite, string solutionConfig) + public static void SetDebuggingEnvironment(Project prj, string envpath, bool overwrite, string solutionConfig) { + ThreadHelper.ThrowIfNotOnUIThread(); + if (QtProject.GetFormatVersion(prj) >= Resources.qtMinFormatVersion_Settings) return; @@ -252,28 +179,29 @@ } } - public static bool IsProjectInSolution(DTE dteObject, string fullName) + public static Project ProjectFromSolution(DTE dteObject, string fullName) { - var fi = new FileInfo(fullName); + ThreadHelper.ThrowIfNotOnUIThread(); + fullName = new FileInfo(fullName).FullName; foreach (var p in ProjectsInSolution(dteObject)) { - if (p.FullName.ToLower() == fi.FullName.ToLower()) - return true; + if (p.FullName.Equals(fullName, StringComparison.OrdinalIgnoreCase)) + return p; } - return false; + return null; } /// <summary> /// Returns the normalized file path of a given file. /// </summary> /// <param name="name">file name</param> - static public string NormalizeFilePath(string name) + public static string NormalizeFilePath(string name) { var fi = new FileInfo(name); return fi.FullName; } - static public string NormalizeRelativeFilePath(string path) + public static string NormalizeRelativeFilePath(string path) { if (path == null) return ".\\"; @@ -299,7 +227,7 @@ return path; } - static public bool IsAbsoluteFilePath(string path) + public static bool IsAbsoluteFilePath(string path) { path = path.Trim(); if (path.Length >= 2 && path[1] == ':') @@ -316,7 +244,7 @@ /// </summary> /// <param name="streamReader"></param> /// <returns>the composite string</returns> - static private string ReadProFileLine(StreamReader streamReader) + private static string ReadProFileLine(StreamReader streamReader) { var line = streamReader.ReadLine(); if (line == null) @@ -337,7 +265,7 @@ /// </summary> /// <param name="profile">full name of .pro file to read</param> /// <returns>true if this is a subdirs file</returns> - static public bool IsSubDirsFile(string profile) + public static bool IsSubDirsFile(string profile) { StreamReader sr = null; try { @@ -407,55 +335,6 @@ } /// <summary> - /// Replaces a string in the commandLine, description, outputs and additional dependencies - /// in all Custom build tools of the project - /// </summary> - /// <param name="project">Project</param> - /// <param name="oldString">String, which is going to be replaced</param> - /// <param name="oldString">String, which is going to replace the other one</param> - /// <returns></returns> - public static void ReplaceInCustomBuildTools(Project project, string oldString, string replaceString) - { - var vcPro = (VCProject)project.Object; - if (vcPro == null) - return; - - var qtMsBuild = new QtMsBuildContainer(new VCPropertyStorageProvider()); - qtMsBuild.BeginSetItemProperties(); - foreach (VCFile vcfile in (IVCCollection)vcPro.Files) { - foreach (VCFileConfiguration config in (IVCCollection)vcfile.FileConfigurations) { - try { - if (vcfile.ItemType == "CustomBuild") { - var tool = GetCustomBuildTool(config); - if (tool == null) - continue; - - tool.CommandLine = tool.CommandLine - .Replace(oldString, replaceString, - StringComparison.OrdinalIgnoreCase); - tool.Description = tool.Description - .Replace(oldString, replaceString, - StringComparison.OrdinalIgnoreCase); - tool.Outputs = tool.Outputs - .Replace(oldString, replaceString, - StringComparison.OrdinalIgnoreCase); - tool.AdditionalDependencies = tool.AdditionalDependencies - .Replace(oldString, replaceString, - StringComparison.OrdinalIgnoreCase); - } else { - var tool = new QtCustomBuildTool(config, qtMsBuild); - tool.CommandLine = tool.CommandLine - .Replace(oldString, replaceString, - StringComparison.OrdinalIgnoreCase); - } - } catch (Exception) { - } - } - } - qtMsBuild.EndSetItemProperties(); - } - - /// <summary> /// Since VS2010 it is possible to have VCCustomBuildTools without commandlines /// for certain filetypes. We are not interested in them and thus try to read the /// tool's commandline. If this causes an exception, we ignore it. @@ -463,23 +342,19 @@ /// </summary> /// <param name="config">File configuration</param> /// <returns></returns> - static public VCCustomBuildTool GetCustomBuildTool(VCFileConfiguration config) + public static VCCustomBuildTool GetCustomBuildTool(VCFileConfiguration config) { - var file = config.File as VCFile; - if (file == null || file.ItemType != "CustomBuild") - return null; - - var tool = config.Tool as VCCustomBuildTool; - if (tool == null) - return null; - - try { - // TODO: The return value is not used at all? - var cmdLine = tool.CommandLine; - } catch { - return null; + if (config.File is VCFile file + && file.ItemType == "CustomBuild" + && config.Tool is VCCustomBuildTool tool) { + try { + _ = tool.CommandLine; + } catch { + return null; + } + return tool; } - return tool; + return null; } /// <summary> @@ -488,8 +363,10 @@ /// has to be "CustomBuild" /// </summary> /// <param name="projectItem">Project Item which needs to have custom build tool</param> - static public void EnsureCustomBuildToolAvailable(ProjectItem projectItem) + public static void EnsureCustomBuildToolAvailable(ProjectItem projectItem) { + ThreadHelper.ThrowIfNotOnUIThread(); + foreach (Property prop in projectItem.Properties) { if (prop.Name == "ItemType") { if ((string)prop.Value != "CustomBuild") @@ -499,169 +376,10 @@ } } - /// <summary> - /// As Qmake -tp vc Adds the full path to the additional dependencies - /// we need to do the same when toggling project kind to qmake generated. - /// </summary> - /// <returns></returns> - private static string AddFullPathToAdditionalDependencies(string qtDir, string additionalDependencies) - { - var returnString = additionalDependencies; - returnString = - Regex.Replace(returnString, "Qt(\\S+5?)\\.lib", qtDir + "\\lib\\Qt${1}.lib"); - returnString = - Regex.Replace(returnString, "(qtmaind?5?)\\.lib", qtDir + "\\lib\\${1}.lib"); - returnString = - Regex.Replace(returnString, "(enginiod?5?)\\.lib", qtDir + "\\lib\\${1}.lib"); - return returnString; - } - - /// <summary> - /// Toggles the kind of a project. If the project is a QMake generated project (qmake -tp vc) - /// it is transformed to an Qt VS Tools project and vice versa. - /// </summary> - /// <param name="project">Project</param> - /// <returns></returns> - public static void ToggleProjectKind(Project project) - { - if (QtProject.GetFormatVersion(project) >= Resources.qtMinFormatVersion_Settings) - return; - - string qtDir = null; - var vcPro = (VCProject)project.Object; - if (!IsQMakeProject(project)) - return; - if (IsQtProject(project)) { - // TODO: qtPro is never used. - var qtPro = QtProject.Create(project); - var vm = QtVersionManager.The(); - qtDir = vm.GetInstallPath(project); - - foreach (var global in (string[])project.Globals.VariableNames) { - if (global.StartsWith("Qt5Version", StringComparison.Ordinal)) - project.Globals.set_VariablePersists(global, false); - } - - foreach (VCConfiguration config in (IVCCollection)vcPro.Configurations) { - var compiler = CompilerToolWrapper.Create(config); - var linker = (VCLinkerTool)((IVCCollection)config.Tools).Item("VCLinkerTool"); - var librarian = (VCLibrarianTool)((IVCCollection)config.Tools).Item("VCLibrarianTool"); - if (compiler != null) { - var additionalIncludes = compiler.GetAdditionalIncludeDirectories(); - additionalIncludes = additionalIncludes.Replace("$(QTDIR)", qtDir, - StringComparison.OrdinalIgnoreCase); - compiler.SetAdditionalIncludeDirectories(additionalIncludes); - } - if (linker != null) { - linker.AdditionalLibraryDirectories = linker.AdditionalLibraryDirectories. - Replace("$(QTDIR)", qtDir, StringComparison.OrdinalIgnoreCase); - linker.AdditionalDependencies = AddFullPathToAdditionalDependencies(qtDir, linker.AdditionalDependencies); - } else { - librarian.AdditionalLibraryDirectories = librarian.AdditionalLibraryDirectories - .Replace("$(QTDIR)", qtDir, StringComparison.OrdinalIgnoreCase); - librarian.AdditionalDependencies = AddFullPathToAdditionalDependencies(qtDir, librarian.AdditionalDependencies); - } - } - - ReplaceInCustomBuildTools(project, "$(QTDIR)", qtDir); - } else { - qtDir = GetQtDirFromQMakeProject(project); - - var vm = QtVersionManager.The(); - var qtVersion = vm.GetQtVersionFromInstallDir(qtDir); - if (qtVersion == null) - qtVersion = vm.GetDefaultVersion(); - if (qtDir == null) - qtDir = vm.GetInstallPath(qtVersion); - var vi = vm.GetVersionInfo(qtVersion); - var platformName = vi.GetVSPlatformName(); - vm.SaveProjectQtVersion(project, qtVersion, platformName); - var qtPro = QtProject.Create(project); - if (!qtPro.SelectSolutionPlatform(platformName) || !qtPro.HasPlatform(platformName)) { - var newProject = false; - qtPro.CreatePlatform("Win32", platformName, null, vi, ref newProject); - if (!qtPro.SelectSolutionPlatform(platformName)) - Messages.Print("Can't select the platform " + platformName + "."); - } - - var activeConfig = project.ConfigurationManager.ActiveConfiguration.ConfigurationName; - var activeVCConfig = (VCConfiguration)((IVCCollection)qtPro.VCProject.Configurations).Item(activeConfig); - if (activeVCConfig.ConfigurationType == ConfigurationTypes.typeDynamicLibrary) { - var compiler = CompilerToolWrapper.Create(activeVCConfig); - var linker = (VCLinkerTool)((IVCCollection)activeVCConfig.Tools).Item("VCLinkerTool"); - var ppdefs = compiler.GetPreprocessorDefinitions(); - if (ppdefs != null - && ppdefs.IndexOf("QT_PLUGIN", StringComparison.Ordinal) > -1 - && ppdefs.IndexOf("QDESIGNER_EXPORT_WIDGETS", StringComparison.Ordinal) > -1 - && ppdefs.IndexOf("QtDesigner", StringComparison.Ordinal) > -1 - && linker.AdditionalDependencies != null - && linker.AdditionalDependencies.IndexOf("QtDesigner", StringComparison.Ordinal) > -1) { - qtPro.MarkAsDesignerPluginProject(); - } - } - - CleanupQMakeDependencies(project); - - foreach (VCConfiguration config in (IVCCollection)vcPro.Configurations) { - var compiler = CompilerToolWrapper.Create(config); - var linker = (VCLinkerTool)((IVCCollection)config.Tools).Item("VCLinkerTool"); - - if (compiler != null) { - var additionalIncludes = compiler.AdditionalIncludeDirectories; - if (additionalIncludes != null) { - ReplaceDirectory(ref additionalIncludes, qtDir, "$(QTDIR)", project); - compiler.AdditionalIncludeDirectories = additionalIncludes; - } - } - if (linker != null) { - var linkerToolWrapper = new LinkerToolWrapper(linker); - var paths = linkerToolWrapper.AdditionalLibraryDirectories; - if (paths != null) { - ReplaceDirectory(ref paths, qtDir, "$(QTDIR)", project); - linkerToolWrapper.AdditionalLibraryDirectories = paths; - } - } - } - - ReplaceInCustomBuildTools(project, qtDir, "$(QTDIR)"); - qtPro.TranslateFilterNames(); - } - project.Save(project.FullName); - } - - /// <summary> - /// Replaces every occurrence of oldDirectory with replacement in the array of strings. - /// Parameter oldDirectory must be an absolute path. - /// This function converts relative directories to absolute paths internally - /// and replaces them, if necessary. If no replacement is done, the path isn't altered. - /// </summary> - /// <param name="project">The project is needed to convert relative paths to absolute paths.</param> - private static void ReplaceDirectory(ref List<string> paths, string oldDirectory, string replacement, Project project) - { - for (var i = 0; i < paths.Count; ++i) { - var dirName = paths[i]; - if (dirName.StartsWith("\"", StringComparison.Ordinal) && dirName.EndsWith("\"", StringComparison.Ordinal)) { - dirName = dirName.Substring(1, dirName.Length - 2); - } - if (!Path.IsPathRooted(dirName)) { - // convert to absolute path - dirName = Path.Combine(Path.GetDirectoryName(project.FullName), dirName); - dirName = Path.GetFullPath(dirName); - var alteredDirName = dirName.Replace(oldDirectory, replacement, StringComparison - .OrdinalIgnoreCase); - if (alteredDirName == dirName) - continue; - dirName = alteredDirName; - } else { - dirName = dirName.Replace(oldDirectory, replacement, StringComparison - .OrdinalIgnoreCase); - } - paths[i] = dirName; - } - } - public static string GetQtDirFromQMakeProject(Project project) { + ThreadHelper.ThrowIfNotOnUIThread(); + var vcProject = project.Object as VCProject; if (vcProject == null) return null; @@ -742,13 +460,25 @@ } /// <summary> - /// Return true if the project is a Qt project, otherwise false. + /// Return true if the project is a VS tools project; false otherwise. /// </summary> /// <param name="proj">project</param> - /// <returns></returns> - public static bool IsQtProject(VCProject proj) + public static bool IsVsToolsProject(Project proj) { - if (!IsQMakeProject(proj)) + ThreadHelper.ThrowIfNotOnUIThread(); // C++ Project Type GUID + if (proj == null || proj.Kind != "{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") + return false; + return IsVsToolsProject(proj.Object as VCProject); + } + + /// <summary> + /// Return true if the project is a VS tools project; false otherwise. + /// </summary> + /// <param name="proj">project</param> + public static bool IsVsToolsProject(VCProject proj) + { + ThreadHelper.ThrowIfNotOnUIThread(); + if (!IsQtProject(proj)) return false; if (QtProject.GetFormatVersion(proj) >= Resources.qtMinFormatVersion_Settings) @@ -759,95 +489,39 @@ return false; foreach (var global in envPro.Globals.VariableNames as string[]) { - if (global.StartsWith("Qt5Version", StringComparison.Ordinal) && envPro.Globals.get_VariablePersists(global)) + if (global.StartsWith("Qt5Version", StringComparison.Ordinal) + && envPro.Globals.get_VariablePersists(global)) { return true; + } } return false; } /// <summary> - /// Returns true if the specified project is a Qt Project. + /// Return true if the project is a Qt project; false otherwise. /// </summary> /// <param name="proj">project</param> public static bool IsQtProject(Project proj) { - try { - if (proj != null && proj.Kind == "{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") - return IsQtProject(proj.Object as VCProject); - } catch { } - return false; + ThreadHelper.ThrowIfNotOnUIThread(); //C++ Project Type GUID + if (proj == null || proj.Kind != "{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") + return false; + return IsQtProject(proj.Object as VCProject); } /// <summary> - /// Return true if the project is a QMake -tp vc project, otherwise false. + /// Return true if the project is a Qt project; false otherwise. /// </summary> /// <param name="proj">project</param> - /// <returns></returns> - public static bool IsQMakeProject(VCProject proj) + public static bool IsQtProject(VCProject proj) { if (proj == null) return false; var keyword = proj.keyword; - if (keyword == null || - (!keyword.StartsWith(Resources.qtProjectV2Keyword, StringComparison.Ordinal) - && !keyword.StartsWith(Resources.qtProjectKeyword, StringComparison.Ordinal))) { + if (string.IsNullOrEmpty(keyword)) return false; - } - - return true; - } - - /// <summary> - /// Returns true if the specified project is a QMake -tp vc Project. - /// </summary> - /// <param name="proj">project</param> - public static bool IsQMakeProject(Project proj) - { - try { - if (proj != null && proj.Kind == "{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") - return IsQMakeProject(proj.Object as VCProject); - } catch { } - return false; - } - - public static void CleanupQMakeDependencies(Project project) - { - var vcPro = (VCProject)project.Object; - // clean up qmake mess - var rxp1 = new Regex("\\bQt\\w+d?5?\\.lib\\b"); - var rxp2 = new Regex("\\bQAx\\w+\\.lib\\b"); - var rxp3 = new Regex("\\bqtmaind?.lib\\b"); - var rxp4 = new Regex("\\benginiod?.lib\\b"); - foreach (VCConfiguration cfg in (IVCCollection)vcPro.Configurations) { - var linker = (VCLinkerTool)((IVCCollection)cfg.Tools).Item("VCLinkerTool"); - if (linker == null || linker.AdditionalDependencies == null) - continue; - var linkerWrapper = new LinkerToolWrapper(linker); - var deps = linkerWrapper.AdditionalDependencies; - var newDeps = new List<string>(); - foreach (var lib in deps) { - var m1 = rxp1.Match(lib); - var m2 = rxp2.Match(lib); - var m3 = rxp3.Match(lib); - var m4 = rxp4.Match(lib); - if (m1.Success) - newDeps.Add(m1.ToString()); - else if (m2.Success) - newDeps.Add(m2.ToString()); - else if (m3.Success) - newDeps.Add(m3.ToString()); - else if (m4.Success) - newDeps.Add(m4.ToString()); - else - newDeps.Add(lib); - } - // Remove Duplicates - var uniques = new Dictionary<string, int>(); - foreach (var dep in newDeps) - uniques[dep] = 1; - var uniqueList = new List<string>(uniques.Keys); - linkerWrapper.AdditionalDependencies = uniqueList; - } + return keyword.StartsWith(Resources.qtProjectKeyword, StringComparison.Ordinal) + || keyword.StartsWith(Resources.qtProjectV2Keyword, StringComparison.Ordinal); } /// <summary> @@ -951,6 +625,30 @@ } } + /// <summary> + /// Converts all directory separators of the path to the alternate character + /// directory separator. For instance, FromNativeSeparators("c:\\winnt\\system32") + /// returns "c:/winnt/system32". + /// </summary> + /// <param name="path">The path to convert.</param> + /// <returns>Returns path using '/' as file separator.</returns> + public static string FromNativeSeparators(string path) + { + return path.Replace(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar); + } + + /// <summary> + /// Converts all alternate directory separators characters of the path to the native + /// directory separator. For instance, ToNativeSeparators("c:/winnt/system32") + /// returns "c:\\winnt\\system32". + /// </summary> + /// <param name="path">The path to convert.</param> + /// <returns>Returns path using '\' as file separator.</returns> + public static string ToNativeSeparator(string path) + { + return path.Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar); + } + public static string ChangePathFormat(string path) { return path.Replace('\\', '/'); @@ -981,6 +679,8 @@ public static void CollapseFilter(UIHierarchyItem item, UIHierarchy hierarchy, string nodeToCollapseFilter) { + ThreadHelper.ThrowIfNotOnUIThread(); + if (string.IsNullOrEmpty(nodeToCollapseFilter)) return; @@ -994,6 +694,8 @@ public static void CollapseFilter(UIHierarchyItem item, UIHierarchy hierarchy) { + ThreadHelper.ThrowIfNotOnUIThread(); + var subItems = item.UIHierarchyItems; if (subItems != null) { foreach (UIHierarchyItem innerItem in subItems) { @@ -1042,7 +744,7 @@ public static List<string> GetProjectFiles(Project pro, FilesToList filter) { - var fileList = new List<string>(); + ThreadHelper.ThrowIfNotOnUIThread(); VCProject vcpro; try { @@ -1052,6 +754,7 @@ return null; } + var fileList = new List<string>(); var configurationName = pro.ConfigurationManager.ActiveConfiguration.ConfigurationName; foreach (VCFile vcfile in (IVCCollection)vcpro.Files) { @@ -1120,21 +823,24 @@ /// <param name="fileName"></param> public static void RemoveFileInProject(VCProject vcpro, string fileName) { - var qtProj = QtProject.Create(vcpro); - var fi = new FileInfo(fileName); + ThreadHelper.ThrowIfNotOnUIThread(); + fileName = new FileInfo(fileName).FullName; foreach (VCFile vcfile in (IVCCollection)vcpro.Files) { - if (vcfile.FullPath.ToLower() == fi.FullName.ToLower()) { + if (vcfile.FullPath.Equals(fileName, StringComparison.OrdinalIgnoreCase)) { vcpro.RemoveFile(vcfile); - qtProj.MoveFileToDeletedFolder(vcfile); + QtProject.Create(vcpro)?.MoveFileToDeletedFolder(vcfile); } } } public static Project GetSelectedProject(DTE dteObject) { + ThreadHelper.ThrowIfNotOnUIThread(); + if (dteObject == null) return null; + Array prjs = null; try { prjs = (Array)dteObject.ActiveSolutionProjects; @@ -1146,30 +852,23 @@ return null; // don't handle multiple selection... use the first one - if (prjs.GetValue(0) is Project) - return (Project)prjs.GetValue(0); + if (prjs.GetValue(0) is Project project) + return project; return null; } public static Project GetActiveDocumentProject(DTE dteObject) { - if (dteObject == null) - return null; - var doc = dteObject.ActiveDocument; - if (doc == null) - return null; - - if (doc.ProjectItem == null) - return null; - - return doc.ProjectItem.ContainingProject; + ThreadHelper.ThrowIfNotOnUIThread(); + return dteObject?.ActiveDocument?.ProjectItem?.ContainingProject; } public static Project GetSingleProjectInSolution(DTE dteObject) { + ThreadHelper.ThrowIfNotOnUIThread(); + var projectList = ProjectsInSolution(dteObject); - if (dteObject == null || dteObject.Solution == null || - projectList.Count != 1) + if (projectList.Count != 1) return null; // no way to know which one to select return projectList[0]; @@ -1182,22 +881,24 @@ /// </summary> public static Project GetSelectedQtProject(DTE dteObject) { + ThreadHelper.ThrowIfNotOnUIThread(); + // can happen sometimes shortly after starting VS - if (dteObject == null || dteObject.Solution == null - || ProjectsInSolution(dteObject).Count == 0) + if (ProjectsInSolution(dteObject).Count == 0) return null; - Project pro; - - if ((pro = GetSelectedProject(dteObject)) == null) { + var pro = GetSelectedProject(dteObject); + if (pro == null) { if ((pro = GetSingleProjectInSolution(dteObject)) == null) pro = GetActiveDocumentProject(dteObject); } - return IsQtProject(pro) ? pro : null; + return IsVsToolsProject(pro) ? pro : null; } public static VCFile[] GetSelectedFiles(DTE dteObject) { + ThreadHelper.ThrowIfNotOnUIThread(); + if (GetSelectedQtProject(dteObject) == null) return null; @@ -1239,6 +940,8 @@ public static RccOptions ParseRccOptions(string cmdLine, VCFile qrcFile) { + ThreadHelper.ThrowIfNotOnUIThread(); + var pro = VCProjectToProject((VCProject)qrcFile.project); var rccOpts = new RccOptions(pro, qrcFile); @@ -1261,11 +964,17 @@ public static Project VCProjectToProject(VCProject vcproj) { + ThreadHelper.ThrowIfNotOnUIThread(); return (Project)vcproj.Object; } public static List<Project> ProjectsInSolution(DTE dteObject) { + ThreadHelper.ThrowIfNotOnUIThread(); + + if (dteObject == null) + return new List<Project>(); + var projects = new List<Project>(); var solution = dteObject.Solution; if (solution != null) { @@ -1287,6 +996,8 @@ private static void addSubProjects(Project prj, ref List<Project> projects) { + ThreadHelper.ThrowIfNotOnUIThread(); + // If the actual object of the project is null then the project was probably unloaded. if (prj.Object == null) return; @@ -1303,6 +1014,8 @@ private static void addSubProjects(ProjectItems subItems, ref List<Project> projects) { + ThreadHelper.ThrowIfNotOnUIThread(); + if (subItems == null) return; @@ -1393,21 +1106,6 @@ return true; } - public static string FindFileInPATH(string fileName) - { - var envPATH = Environment.ExpandEnvironmentVariables("%PATH%"); - var directories = envPATH.Split(';'); - foreach (var directory in directories) { - var fullFilePath = directory; - if (!fullFilePath.EndsWith("\\", StringComparison.Ordinal)) - fullFilePath += '\\'; - fullFilePath += fileName; - if (File.Exists(fullFilePath)) - return fullFilePath; - } - return null; - } - /// <summary> /// This method copies the specified directory and all its child directories and files to /// the specified destination. The destination directory is created if it does not exist. @@ -1453,13 +1151,14 @@ string platformName, string filePath = null) { + ThreadHelper.ThrowIfNotOnUIThread(); + if (project == null || string.IsNullOrEmpty(configName) || string.IsNullOrEmpty(platformName)) return false; var vcProject = project.Object as VCProject; - if (filePath == null) { var vcConfig = (from VCConfiguration _config in (IVCCollection)vcProject.Configurations @@ -1503,12 +1202,10 @@ VCProject vcProj = null; VCFile vcFile = null; string configName = "", platformName = ""; - var vcConfig = config as VCConfiguration; - if (vcConfig != null) { + if (config is VCConfiguration vcConfig) { vcProj = vcConfig.project as VCProject; configName = vcConfig.ConfigurationName; - var vcPlatform = vcConfig.Platform as VCPlatform; - if (vcPlatform != null) + if (vcConfig.Platform is VCPlatform vcPlatform) platformName = vcPlatform.Name; try { expanded = vcConfig.Evaluate(expanded); @@ -1520,11 +1217,9 @@ vcFile = vcFileConfig.File as VCFile; if (vcFile != null) vcProj = vcFile.project as VCProject; - var vcProjConfig = vcFileConfig.ProjectConfiguration as VCConfiguration; - if (vcProjConfig != null) { + if (vcFileConfig.ProjectConfiguration is VCConfiguration vcProjConfig) { configName = vcProjConfig.ConfigurationName; - var vcPlatform = vcProjConfig.Platform as VCPlatform; - if (vcPlatform != null) + if (vcProjConfig.Platform is VCPlatform vcPlatform) platformName = vcPlatform.Name; } try { @@ -1637,6 +1332,7 @@ return true; } +#if VS2017 private static string GetRegistrySoftwareString(string subKeyName, string valueName) { var keyName = new StringBuilder(); @@ -1644,28 +1340,25 @@ if (System.Environment.Is64BitOperatingSystem && IntPtr.Size == 4) keyName.Append(@"WOW6432Node\"); keyName.Append(subKeyName); - try { using (var key = Registry.LocalMachine.OpenSubKey(keyName.ToString(), false)) { if (key == null) return ""; //key not found - RegistryValueKind valueKind = key.GetValueKind(valueName); if (valueKind != RegistryValueKind.String && valueKind != RegistryValueKind.ExpandString) { return ""; //wrong value kind } - Object objValue = key.GetValue(valueName); if (objValue == null) return ""; //error getting value - return objValue.ToString(); } } catch { return ""; } } +#endif public static string GetWindows10SDKVersion() { @@ -1713,11 +1406,6 @@ string vcPath = Path.Combine(vsPath, "VC"); #endif return vcPath; - } - - public static bool SetVCVars(ProcessStartInfo startInfo) - { - return SetVCVars(null, startInfo); } public static bool SetVCVars(VersionInformation VersionInfo, ProcessStartInfo startInfo) @@ -1820,8 +1508,21 @@ } } } + + // Get PATH string envPath = startInfo.EnvironmentVariables["PATH"]; - string clPath = envPath.Split(';') + + // Remove invalid chars + envPath = string.Join("", envPath.Split(Path.GetInvalidPathChars())); + + // Split into list of paths + var paths = envPath + .Split(';') + .Where(x => !string.IsNullOrEmpty(x)) + .Select(x => x.Trim()); + + // Check if cl.exe is in PATH + string clPath = paths .Select(path => Path.Combine(path, "cl.exe")) .Where(pathToCl => File.Exists(pathToCl)) .FirstOrDefault(); @@ -1872,12 +1573,6 @@ } else { return canonicalPath; } - } - - public static bool PathEquals(string path1, string path2) - { - return (CanonicalPath(path1).Equals(CanonicalPath(path2), - StringComparison.InvariantCultureIgnoreCase)); } public static bool PathIsRelativeTo(string path, string subPath) -- Gitblit v1.9.1