/// <summary> /// Ensures the appropriate version of the specified packages are installed. If an existing version of the package /// already exists the following will happen: /// If a semantically compatible version already exists, no change is made to the package. /// If an older major version exists, a warning is logged and the package is upgraded. /// If an older minor/build version exists, an information message is logged and the package is upgraded. /// If a newer major version exists, a warning is logged and no change is made to the package. /// </summary> public static async Task InstallPackagesAsync( Project targetProject, Dictionary <string, string> packages, Func <string, string, Task> installPackage, ConnectedServiceLogger logger, IVsPackageInstallerServices packageInstallerServices) { IEnumerable <IVsPackageMetadata> installedPackages; try { installedPackages = packageInstallerServices.GetInstalledPackages(targetProject); } catch (ArgumentException) { // This happens for C++ projects installedPackages = new List <IVsPackageMetadata>(); } foreach (KeyValuePair <string, string> requiredPackage in packages) { IVsPackageMetadata installedPackage = installedPackages.FirstOrDefault(p => p.Id == requiredPackage.Key); if (installedPackage == null) { // The package does not exist - notify and install the package. await logger.WriteMessageAsync( LoggerMessageCategory.Information, Resource.LogMessage_AddingNuGetPackage, requiredPackage.Key, requiredPackage.Value); } else { Version installedVersion = NuGetUtilities.GetVersion(installedPackage.VersionString); Version requiredVersion = NuGetUtilities.GetVersion(requiredPackage.Value); if (installedVersion == null || requiredVersion == null) { // Unable to parse the version - continue. continue; } else if (installedVersion.Major < requiredVersion.Major) { // An older potentially non-compatible version of the package already exists - warn and upgrade the package. await logger.WriteMessageAsync( LoggerMessageCategory.Warning, Resource.LogMessage_OlderMajorVersionNuGetPackageExists, requiredPackage.Key, installedPackage.VersionString, requiredPackage.Value); } else if (installedVersion.Major > requiredVersion.Major) { // A newer potentially non-compatible version of the package already exists - warn and continue. await logger.WriteMessageAsync( LoggerMessageCategory.Warning, Resource.LogMessage_NewerMajorVersionNuGetPackageExists, requiredPackage.Key, requiredPackage.Value, installedPackage.VersionString); continue; } else if (installedVersion >= requiredVersion) { // A semantically compatible version of the package already exists - continue. continue; } else { // An older semantically compatible version of the package exists - notify and upgrade the package. await logger.WriteMessageAsync( LoggerMessageCategory.Information, Resource.LogMessage_UpgradingNuGetPackage, requiredPackage.Key, installedPackage.VersionString, requiredPackage.Value); } } await installPackage(requiredPackage.Key, requiredPackage.Value); } }