public void InitializeInternal(XElement configuration) { if (configuration.Attribute("frameworkVersion") == null) { throw new InvalidOperationException("A frameworkVersion attribute value is required"); } if (configuration.Attribute("packageGuid") == null) { throw new InvalidOperationException("A packageGuid attribute value is required"); } frameworkVersion = new Version(configuration.Attribute("frameworkVersion").Value); packageGuid = new Guid(configuration.Attribute("packageGuid").Value); // Load the Visual Studio package versions foreach (var package in configuration.Elements("package")) { var vsix = new VisualStudioInstallerPackage { PackageName = package.Attribute("name").Value }; vsixPackages.Add(vsix); var supportedVersions = package.Attribute("supportedVersions").Value.Split(new[] { ',', ' ' }, StringSplitOptions.RemoveEmptyEntries); var versionsFound = VisualStudioInstance.AllInstances.Where(i => supportedVersions.Any(v => i.Version.StartsWith(v, StringComparison.Ordinal))).OrderBy(i => i.Version).ToList(); // Use the latest VSIX installer found if (versionsFound.Any()) { vsix.VsixInstallerPath = versionsFound.Last().VSIXInstallerPath; } foreach (var vs in versionsFound) { vsix.InstalledVersionDescriptions.Add(vs.DisplayName); // Version 2015.7.25.0 and earlier were installed for the current user only string basePackagePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), @"Microsoft\VisualStudio"); if (Directory.Exists(basePackagePath)) { string version = vs.Version.Substring(0, 2) + ".0"; // VS2017 and later can install side by side and use a random name for the extensions // folder starting with the version number. Exclude the experimental instances. foreach (string packagePath in Directory.EnumerateDirectories(basePackagePath).Where(p => Path.GetFileName(p).StartsWith(version, StringComparison.Ordinal) && !p.EndsWith("Exp", StringComparison.OrdinalIgnoreCase))) { // This is used to suppress prompting if the package appears to be installed and the // user clicks Next to continue. VS2012 and later VSIX installers puts the package in // a randomly named folder so we'll have to search for it. string shfbPackage = Directory.EnumerateFiles(packagePath, "SandcastleBuilder.Utils.dll", SearchOption.AllDirectories).FirstOrDefault(); if (shfbPackage != null) { vsix.InstalledLocations.Add(Path.GetDirectoryName(shfbPackage)); } } } // Versions after 2015.7.25.0 are installed for all users if (Directory.Exists(vs.AllUsersExtensionsPath)) { string shfbPackage = Directory.EnumerateFiles(vs.AllUsersExtensionsPath, "SandcastleBuilder.Utils.dll", SearchOption.AllDirectories).FirstOrDefault(); if (shfbPackage != null) { vsix.InstalledLocations.Add(Path.GetDirectoryName(shfbPackage)); } } } } if (vsixPackages.Count == 0) { throw new InvalidOperationException("At least one package element must be defined"); } base.Initialize(configuration); }
public void InitializeInternal(XElement configuration) { if (configuration.Attribute("frameworkVersion") == null) { throw new InvalidOperationException("A frameworkVersion attribute value is required"); } if (configuration.Attribute("packageGuid") == null) { throw new InvalidOperationException("A packageGuid attribute value is required"); } frameworkVersion = new Version(configuration.Attribute("frameworkVersion").Value); packageGuid = new Guid(configuration.Attribute("packageGuid").Value); // Load the Visual Studio package versions foreach (var package in configuration.Elements("package")) { var vsix = new VisualStudioInstallerPackage { PackageName = package.Attribute("name").Value, Description = package.Attribute("description").Value }; vsixPackages.Add(vsix); foreach (var vs in package.Elements("visualStudio")) { string versionNumber = vs.Attribute("version").Value, basePath = vs.Attribute("basePath").Value, editionPaths = (string)vs.Attribute("editionPaths"); // VS2015 and earlier don't install side-by-side if (editionPaths == null) { string vsixPath = Path.Combine(Environment.ExpandEnvironmentVariables(basePath), "VSIXInstaller.exe"); // Use the latest one found if (File.Exists(vsixPath)) { vsix.VsixInstallerPath = vsixPath; } // Version 2015.7.25.0 and earlier were installed for the current user only string appDataPath = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), packagePath = Path.Combine(appDataPath, @"Microsoft\VisualStudio\" + versionNumber + @"\Extensions"); if (Directory.Exists(packagePath)) { // This is used to suppress prompting if the package appears to be installed and the // user clicks Next to continue. VS2012 and later VSIX installers puts the package in // a randomly named folder so we'll have to search for it. packagePath = Directory.EnumerateFiles(packagePath, "SandcastleBuilder.Utils.dll", SearchOption.AllDirectories).FirstOrDefault(); if (packagePath != null) { vsix.InstalledLocations.Add(Path.GetDirectoryName(packagePath)); } } // Versions after 2015.7.25.0 are installed for all users appDataPath = Environment.GetFolderPath(Environment.Is64BitProcess ? Environment.SpecialFolder.ProgramFilesX86 : Environment.SpecialFolder.ProgramFiles); packagePath = Path.Combine(appDataPath, "Microsoft Visual Studio " + versionNumber, @"Common7\IDE\Extensions"); if (Directory.Exists(packagePath)) { packagePath = Directory.EnumerateFiles(packagePath, "SandcastleBuilder.Utils.dll", SearchOption.AllDirectories).FirstOrDefault(); if (packagePath != null) { vsix.InstalledLocations.Add(Path.GetDirectoryName(packagePath)); } } } else { foreach (string edition in editionPaths.Split(new[] { ',', ' ' }, StringSplitOptions.RemoveEmptyEntries)) { // VS2017 and later can be installed side-by-side so find the first one available string vsixPath = String.Format(CultureInfo.InvariantCulture, Path.Combine(Environment.ExpandEnvironmentVariables(basePath), "VSIXInstaller.exe"), edition); // Use the latest one found. Within an edition it doesn't matter but we still need // to know about each installed edition. if (File.Exists(vsixPath)) { vsix.VsixInstallerPath = vsixPath; } // Version 2015.7.25.0 and earlier were installed for the current user only string appDataPath = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), packagePath = Path.Combine(appDataPath, @"Microsoft\VisualStudio\" + versionNumber + @"\Extensions"); if (Directory.Exists(packagePath)) { // This is used to suppress prompting if the package appears to be installed and the // user clicks Next to continue. VS2012 and later VSIX installers puts the package in // a randomly named folder so we'll have to search for it. packagePath = Directory.EnumerateFiles(packagePath, "SandcastleBuilder.Utils.dll", SearchOption.AllDirectories).FirstOrDefault(); if (packagePath != null) { vsix.InstalledLocations.Add(Path.GetDirectoryName(packagePath)); } } // Versions after 2015.7.25.0 are installed for all users packagePath = Path.Combine(Path.GetDirectoryName(vsixPath), "Extensions"); if (Directory.Exists(packagePath)) { packagePath = Directory.EnumerateFiles(packagePath, "SandcastleBuilder.Utils.dll", SearchOption.AllDirectories).FirstOrDefault(); if (packagePath != null) { vsix.InstalledLocations.Add(Path.GetDirectoryName(packagePath)); } } } } } } if (vsixPackages.Count == 0) { throw new InvalidOperationException("At least one package element must be defined"); } base.Initialize(configuration); }