internal static void InstallPowershellArtifacts(PackageJson package, string fastPath, PackageSourceListRequest request) { var provider1 = PackageSourceListRequest.FindProvider(request, package.Type, request, true); if (provider1 == null) return; // As the PowerShellGet may access the -source via $request.Options or PackageSources, // so we need to fill in both options and sources parameters var installRequest = PackageSourceListRequest.ExtendRequest(new Dictionary<string, string[]> { {"Source", new[] {package.Source ?? ""}} }, new[] { package.Source ?? "" }, package.IsTrustedSource, request); var psid = PackageSourceListRequest.CreateCanonicalId(package, Constants.ProviderNames.PowerShellGet); var pkgs = request.PackageManagementService.FindPackageByCanonicalId(psid, installRequest) .Where(each => new SemanticVersion(each.Version) == new SemanticVersion(package.Version)).ToArray(); switch (pkgs.Length) { case 0: request.Warning(Resources.Messages.CannotFindPackage, Constants.ProviderName, psid); break; case 1: InstallPackageViaPowerShellGet(package, request, pkgs); break; default: request.Warning(Resources.Messages.FoundMorePackages, Constants.ProviderName, pkgs.Length, psid); break; } return; }
private static void InstallPackageViaPowerShellGet(PackageJson packageJson, PackageSourceListRequest request, SoftwareIdentity[] packages) { var provider = PackageSourceListRequest.FindProvider(request, packageJson.Type, request, true); if (provider == null) return; IHostApi installRequest = request; if (provider.Name.EqualsIgnoreCase(Constants.ProviderNames.PowerShellGet) && !request.ProviderServices.IsElevated) { // if we're not elevated, we want powershellget to install to the user scope installRequest = PackageSourceListRequest.ExtendRequest( new Dictionary<string, string[]> { {"Scope", new[] {"CurrentUser"}} }, null, packageJson.IsTrustedSource, request); } else { installRequest = PackageSourceListRequest.ExtendRequest( new Dictionary<string, string[]> { {"Destination", new[] {packageJson.Destination ?? ""}} }, null, packageJson.IsTrustedSource, request); } request.Debug("Calling '{0}' provider to install the package '{1}.{2}'", provider.Name, packageJson.Name, packageJson.Version); var installing = provider.InstallPackage(packages[0], installRequest); if (installing == null || !installing.Any()) { request.Verbose(Resources.Messages.NumberOfPackagesRecevied, 0, provider.Name, "InstallPackage"); request.Warning(Resources.Messages.FailToInstallPackage, Constants.ProviderName, packages[0].Name); return; } int packagesRecevied = 0; foreach (var i in installing) { request.YieldSoftwareIdentity(i.FastPackageReference, i.Name, i.Version, i.VersionScheme, i.Summary, i.Source, i.SearchKey, i.FullPath, i.PackageFilename); if (request.IsCanceled) { installing.Cancel(); } else { request.Verbose(Resources.Messages.SuccessfullyInstalled, "{0}.{1}".format(packageJson.Name, packageJson.Version)); //load provider if (packageJson.IsPackageProvider) { //Per provider development guidance: provider name and module name should be the same otherwise we can not import it. request.PackageManagementService.ImportPackageProvider(request, packageJson.Name, null, null, null, isRooted: false, force: false); } } packagesRecevied++; } request.Verbose(Resources.Messages.NumberOfPackagesRecevied, packagesRecevied, provider.Name, "install-package"); }
internal static void GetInstalledZipPackage(PackageJson package, PackageSourceListRequest request) { string path = Path.Combine(package.Destination, package.Name, package.Version); if (Directory.Exists(path)) { if (Directory.EnumerateFiles(path, "*", SearchOption.AllDirectories).Any()) { var fp = PackageSourceListRequest.MakeFastPathComplex(package.Source, package.Name, (package.DisplayName ?? ""), package.Version, path); //the directory exists and contain files, we think the package has been installed. request.YieldSoftwareIdentity(fp, package.Name, package.Version, package.VersionScheme, package.Summary, path, package.Name, path, path); } } }
/// <summary> /// Uninstalls a package /// </summary> /// <param name="package">package defined in the PackageSourceList</param> /// <param name="fastPackageReference"></param> /// <param name="request">An object passed in from the PackageManagement that contains functions that can be used to interact with its Provider</param> /// <param name="fastPackReftable"></param> internal static void UninstallNuGetPackage(PackageJson package, string fastPackageReference, PackageSourceListRequest request, Dictionary<string, SoftwareIdentity> fastPackReftable) { if (request == null) { throw new ArgumentNullException("request"); } request.Debug(Resources.Messages.DebugInfoCallMethod, Constants.ProviderName, string.Format(CultureInfo.InvariantCulture, "UninstallNuGetPackage' - fastReference='{0}'", fastPackageReference)); var unInstallRequest = PackageSourceListRequest.ExtendRequest( new Dictionary<string, string[]> { {"Destination", new[] {package.Destination ?? ""}} }, null, package.IsTrustedSource, request); var provider = PackageSourceListRequest.FindProvider(request, package.Type, request, true); if (provider != null) { request.Debug("{0}: Using the provider '{1} to uninstall the package '{2}'", Constants.ProviderName, provider.Name, package.Name); if (!fastPackReftable.ContainsKey(fastPackageReference)) { request.WriteError(ErrorCategory.InvalidData, fastPackageReference, Resources.Messages.FailedToGetPackageObject, Constants.ProviderName, fastPackageReference); return; } var p = fastPackReftable[fastPackageReference]; //calling NuGet for uninstall var installing = provider.UninstallPackage(p, unInstallRequest); foreach (var i in installing) { request.YieldSoftwareIdentity(i.FastPackageReference, i.Name, i.Version, i.VersionScheme, i.Summary, i.Source, i.SearchKey, i.FullPath, i.PackageFilename); if (request.IsCanceled) { installing.Cancel(); } } } }
internal static void GeInstalledNuGetPackages(PackageJson package, string requiredVersion, string minimumVersion, string maximumVersion, Dictionary<string, SoftwareIdentity> fastPackReftable, PackageSourceListRequest request) { if (request == null) { throw new ArgumentNullException("request"); } request.Debug(Resources.Messages.DebugInfoCallMethod, Constants.ProviderName, string.Format(CultureInfo.InvariantCulture, "GeInstalledNuGetPackages' - name='{0}', requiredVersion='{1}',minimumVersion='{2}', maximumVersion='{3}'", package.Name, requiredVersion, minimumVersion, maximumVersion)); //clone the request //nuget provider may not know the location of the package gets installed. //we need to pass around the destination path to nuget provider var installedRequest = PackageSourceListRequest.ExtendRequest( new Dictionary<string, string[]> { {"Destination", new[] { package.Destination ?? ""}} }, null, package.IsTrustedSource, request); var provider = PackageSourceListRequest.FindProvider(request, package.Type, request); if (provider != null) { //calling NuGet provider var packagesInstalled = provider.GetInstalledPackages(package.Name, requiredVersion, minimumVersion, maximumVersion, installedRequest); if (packagesInstalled != null) { foreach (var i in packagesInstalled) { request.Debug("Found an installed package '{0}.{1} from {2}' ", i.Name, i.Version, i.Source); var info = PackageSourceListRequest.MakeFastPathComplex(i.Source, i.Name, "", i.Version, ""); fastPackReftable.AddOrSet(info, i); // make it semver because in find-package we use semver var version = i.Version.CompareVersion(package.Version) ? package.Version : i.Version; request.YieldSoftwareIdentity(info, i.Name, version, i.VersionScheme, i.Summary, i.Source, i.SearchKey, i.FullPath, i.PackageFilename); } } } }
internal static void InstallProviderFromInstaller(PackageJson package, string fastPath, PackageSourceListRequest request) { request.Debug(Resources.Messages.DebugInfoCallMethod, Constants.ProviderName, string.Format(CultureInfo.InvariantCulture, "InstallProviderFromInstaller' - name='{0}', fastPath='{1}'", package.Name, fastPath)); //install any dependency packages InstallDependencies(package, request); switch (package.Type.ToLowerInvariant()) { case Constants.MediaType.MsiPackage: case Constants.MediaType.MsuPackage: InstallPackageFile(package, fastPath, request); break; case Constants.MediaType.AppxPackage: //TODO for future whenever needed to support appx packages break; case Constants.MediaType.NuGetPackage: NupkgInstaller.InstallNuGetPackage(package, fastPath, request); break; case Constants.MediaType.ZipPackage: ZipPackageInstaller.InstallZipPackage(package, fastPath, request); break; case Constants.MediaType.ExePackage: ExePackageInstaller.InstallExePackage(package, fastPath, request); break; case Constants.MediaType.PsArtifacts: PowerShellArtifactInstaller.InstallPowershellArtifacts(package, fastPath, request); break; default: request.WriteError(ErrorCategory.InvalidData, fastPath, Resources.Messages.UnknownMediaType, package.Name, package.Source, package.Type); break; } return; }
internal static void InstallNuGetPackage(PackageJson package, string fastPath, PackageSourceListRequest request) { request.Debug(Resources.Messages.DebugInfoCallMethod, Constants.ProviderName, string.Format(CultureInfo.InvariantCulture, "InstallNuGetPackage' - name='{0}', fastPath='{1}'", package.Name, fastPath)); var canonicalId = PackageSourceListRequest.CreateCanonicalId(package, Constants.ProviderNames.NuGet); // "nuget:jquery/2.1.0#http://nuget.org/api/v2"; var pkgs = request.PackageManagementService.FindPackageByCanonicalId(canonicalId, request.As<IHostApi>()) .Where(each => string.IsNullOrWhiteSpace(package.Version) || (new SemanticVersion(each.Version) == new SemanticVersion(package.Version))).ToArray(); switch (pkgs.Length) { case 0: request.Warning(Resources.Messages.CannotFindPackage, Constants.ProviderName, canonicalId); return; case 1: InstallPackageReference(package, request, pkgs); return; default: request.Warning(Resources.Messages.FoundMorePackages, Constants.ProviderName, pkgs.Length, canonicalId); return; } }
private static void InstallPackageReference(PackageJson package, PackageSourceListRequest request, SoftwareIdentity[] packages) { var installRequest = PackageSourceListRequest.ExtendRequest( new Dictionary<string, string[]> { {"Destination", new[] {package.Destination ?? ""}} }, new[] { package.Source ?? "" }, package.IsTrustedSource, request); var provider = PackageSourceListRequest.FindProvider(request, package.Type, installRequest, true); if (provider == null) { return; } var installing = provider.InstallPackage(packages[0], installRequest); foreach (var i in installing) { request.YieldSoftwareIdentity(i.FastPackageReference, i.Name, i.Version, i.VersionScheme, i.Summary, i.Source, i.SearchKey, i.FullPath, i.PackageFilename); if (request.IsCanceled) { installing.Cancel(); } } }
internal static bool InstallExePackage(PackageJson package, string fastPath, PackageSourceListRequest request) { ProgressTracker tracker = new ProgressTracker(request.StartProgress(0, Resources.Messages.Installing)); var exePackage = Path.ChangeExtension(Path.GetTempFileName(), "exe"); WebDownloader.DownloadFile(package.Source, exePackage, request, tracker); if (File.Exists(exePackage)) { request.Verbose("Package: '{0}'", exePackage); // validate the file if (!WebDownloader.VerifyHash(exePackage,package, request)) { return false; } if (!package.IsTrustedSource) { if (!request.ShouldContinueWithUntrustedPackageSource(package.Name, package.Source)) { request.Warning(Constants.Messages.UserDeclinedUntrustedPackageInstall, package.Name); return false; } } // Prepare the process to run var processArguments = string.IsNullOrWhiteSpace(package.InstallArguments) ? "/VERYSILENT /CLOSEAPPLICATIONS /NORESTART /NOCANCEL /SP /qn" : package.InstallArguments; var start = new ProcessStartInfo { FileName = exePackage, Arguments = processArguments, UseShellExecute = false, RedirectStandardInput = true, RedirectStandardOutput = true, RedirectStandardError = true, CreateNoWindow = true, //LoadUserProfile = true, }; double percent = tracker.StartPercent; Timer timer = null; object timerLock = new object(); bool cleanUp = false; Action cleanUpAction = () => { lock (timerLock) { // check whether clean up is already done before or not if (!cleanUp) { try { if (timer != null) { // stop timer timer.Change(Timeout.Infinite, Timeout.Infinite); // dispose it timer.Dispose(); } } catch { } cleanUp = true; } } }; // Run the external process & wait for it to finish using (var proc = Process.Start(start)) { var timer1 = timer; timer = new Timer(_ => { percent += 0.025; // percent between startProgress and endProgress var progressPercent = tracker.ConvertPercentToProgress(percent); if (progressPercent < 90) { request.Progress(tracker.ProgressID, (int)progressPercent, Resources.Messages.InstallingPackage, package.Source); } if (request.IsCanceled) { cleanUpAction(); } }, null, 100, 3000); proc.WaitForExit(); // Retrieve the app's exit code var exitCode = proc.ExitCode; if (exitCode != 0) { request.WriteError(ErrorCategory.InvalidOperation, fastPath, Resources.Messages.InstallFailed, package.Name, proc.StandardError.ReadToEnd()); request.CompleteProgress(tracker.ProgressID, false); return false; } else { request.CompleteProgress(tracker.ProgressID, true); request.YieldFromSwidtag(package, fastPath); request.Verbose(Resources.Messages.SuccessfullyInstalled, package.Name); } cleanUpAction(); } return true; } else { request.Error(ErrorCategory.InvalidOperation, Resources.Messages.FailedToDownload, Constants.ProviderName, package.Source, exePackage); } return false; }
internal static bool VerifyHash(string fileFullPath,PackageJson package, PackageSourceListRequest request) { //skip in case the skip switch is specified if (request.SkipHashValidation.Value) { request.Verbose(Resources.Messages.SkipHashValidation); return true; } PackageHash packageHash = package.Hash; if (packageHash==null || string.IsNullOrWhiteSpace(packageHash.algorithm) || string.IsNullOrWhiteSpace(packageHash.hashCode)) { request.WriteError(ErrorCategory.InvalidArgument, Constants.ProviderName, Resources.Messages.HashNotSpecified, package.Name); return false; } try { HashAlgorithm hashAlgorithm = null; switch (packageHash.algorithm.ToLowerInvariant()) { case "sha256": hashAlgorithm = SHA256.Create(); break; case "md5": hashAlgorithm = MD5.Create(); break; case "sha512": hashAlgorithm = SHA512.Create(); break; default: request.WriteError(ErrorCategory.InvalidArgument, Constants.ProviderName, Resources.Messages.InvalidHashAlgorithm, packageHash.algorithm); return false; } using (FileStream stream = File.OpenRead(fileFullPath)) { // compute the hash byte[] computedHash = hashAlgorithm.ComputeHash(stream); // convert the original hash we got from json byte[] hashFromJSON = Convert.FromBase64String(package.Hash.hashCode); if (!Enumerable.SequenceEqual(computedHash, hashFromJSON)) { request.WriteError(ErrorCategory.InvalidOperation, Constants.ProviderName, Resources.Messages.HashVerificationFailed, package.Name, package.Source); return false; } else { request.Verbose(Resources.Messages.HashValidationSuccessful); } } } catch { request.WriteError(ErrorCategory.InvalidOperation, Constants.ProviderName, Resources.Messages.HashVerificationFailed, package.Name, package.Source); return false; } return true; }
internal static void GetInstalledExePackages(PackageJson package, string requiredVersion, string minimumVersion, string maximumVersion, Request request) { if (request == null) { throw new ArgumentNullException("request"); } request.Debug("Calling '{0}::GetInstalledPackages' '{1}','{2}','{3}','{4}'", Constants.ProviderName, package.Name, requiredVersion, minimumVersion, maximumVersion); #if !CORECLR if (Environment.Is64BitOperatingSystem) { using (var hklm64 = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry64).OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall", RegistryKeyPermissionCheck.ReadSubTree, RegistryRights.ReadKey)) { #else if (System.Runtime.InteropServices.RuntimeInformation.OSArchitecture == System.Runtime.InteropServices.Architecture.X64) { using (var hklm64 = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry64).OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall")) { #endif if (!YieldPackages("hklm64", hklm64, package.Name, package.DisplayName, requiredVersion, minimumVersion, maximumVersion, package, request)) { return; } } using (var hkcu64 = RegistryKey.OpenBaseKey(RegistryHive.CurrentUser, RegistryView.Registry64).OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall", false)) { if (!YieldPackages("hkcu64", hkcu64, package.Name, package.DisplayName, requiredVersion, minimumVersion, maximumVersion, package, request)) { return; } } } using (var hklm32 = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry32).OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall", false)) { if (!YieldPackages("hklm32", hklm32, package.Name, package.DisplayName, requiredVersion, minimumVersion, maximumVersion, package, request)) { return; } } using (var hkcu32 = RegistryKey.OpenBaseKey(RegistryHive.CurrentUser, RegistryView.Registry32).OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall", false)) { if (!YieldPackages("hkcu32", hkcu32, package.Name, package.DisplayName, requiredVersion, minimumVersion, maximumVersion, package, request)) { } } }
private static bool YieldPackages(string hive, RegistryKey regkey, string name, string displayname, string requiredVersion, string minimumVersion, string maximumVersion, PackageJson package, Request request) { //TODO make it wildcard match, follow the fastfrence format, get-package git no results, get-package git* if (regkey != null) { var includeSystemComponent = request.GetOptionValue("IncludeSystemComponent").IsTrue(); foreach (var key in regkey.GetSubKeyNames()) { var subkey = regkey.OpenSubKey(key); if (subkey != null) { var properties = subkey.GetValueNames().ToDictionaryNicely(each => each.ToString(), each => (subkey.GetValue(each) ?? string.Empty).ToString(), StringComparer.OrdinalIgnoreCase); //if (!includeWindowsInstaller && properties.ContainsKey("WindowsInstaller") && properties["WindowsInstaller"] == "1") //{ // continue; //} if (!includeSystemComponent && properties.ContainsKey("SystemComponent") && properties["SystemComponent"] == "1") { continue; } var productName = ""; if (!properties.TryGetValue("DisplayName", out productName)) { // no product name? continue; } if (IsMatch(name, productName) || IsMatch(displayname, productName)) { var productVersion = properties.Get("DisplayVersion") ?? ""; var publisher = properties.Get("Publisher") ?? ""; var uninstallString = properties.Get("QuietUninstallString") ?? properties.Get("UninstallString") ?? ""; var comments = properties.Get("Comments") ?? ""; var fp = hive + @"\" + subkey; if (!string.IsNullOrEmpty(requiredVersion)) { if (new SemanticVersion(requiredVersion) != new SemanticVersion(productVersion)) { continue; } } else { if (!string.IsNullOrEmpty(minimumVersion) && new SemanticVersion(minimumVersion) > new SemanticVersion(productVersion)) { continue; } if (!string.IsNullOrEmpty(maximumVersion) && new SemanticVersion(maximumVersion) < new SemanticVersion(productVersion)) { continue; } } fp = PackageSourceListRequest.MakeFastPathComplex(package.Destination ?? "", package.Name, package.DisplayName, productVersion, fp); var source = properties.Get("InstallLocation") ?? ""; //we use name here because find-package uses name (not displayname) in the PSL.json, if (request.YieldSoftwareIdentity(fp, name, productVersion, "unknown", comments, source, name, "", "") != null) { if (properties.Keys.Where(each => !string.IsNullOrWhiteSpace(each)).Any(k => request.AddMetadata(fp, k.MakeSafeFileName(), properties[k]) == null)) { return false; } } } } } } return true; }
internal static bool InstallExePackage(PackageJson package, string fastPath, PackageSourceListRequest request) { ProgressTracker tracker = new ProgressTracker(request.StartProgress(0, Resources.Messages.Installing)); var exePackage = Path.ChangeExtension(Path.GetTempFileName(), "exe"); WebDownloader.DownloadFile(package.Source, exePackage, request, tracker); if (File.Exists(exePackage)) { request.Verbose("Package: '{0}'", exePackage); // validate the file if (!WebDownloader.VerifyHash(exePackage, package, request)) { return(false); } if (!package.IsTrustedSource) { if (!request.ShouldContinueWithUntrustedPackageSource(package.Name, package.Source)) { request.Warning(Constants.Messages.UserDeclinedUntrustedPackageInstall, package.Name); return(false); } } // Prepare the process to run var processArguments = string.IsNullOrWhiteSpace(package.InstallArguments) ? "/VERYSILENT /CLOSEAPPLICATIONS /NORESTART /NOCANCEL /SP /qn" : package.InstallArguments; var start = new ProcessStartInfo { FileName = exePackage, Arguments = processArguments, UseShellExecute = false, RedirectStandardInput = true, RedirectStandardOutput = true, RedirectStandardError = true, CreateNoWindow = true, //LoadUserProfile = true, }; double percent = tracker.StartPercent; Timer timer = null; object timerLock = new object(); bool cleanUp = false; Action cleanUpAction = () => { lock (timerLock) { // check whether clean up is already done before or not if (!cleanUp) { try { if (timer != null) { // stop timer timer.Change(Timeout.Infinite, Timeout.Infinite); // dispose it timer.Dispose(); } } catch { } cleanUp = true; } } }; // Run the external process & wait for it to finish using (var proc = Process.Start(start)) { var timer1 = timer; timer = new Timer(_ => { percent += 0.025; // percent between startProgress and endProgress var progressPercent = tracker.ConvertPercentToProgress(percent); if (progressPercent < 90) { request.Progress(tracker.ProgressID, (int)progressPercent, Resources.Messages.InstallingPackage, package.Source); } if (request.IsCanceled) { cleanUpAction(); } }, null, 100, 3000); proc.WaitForExit(); // Retrieve the app's exit code var exitCode = proc.ExitCode; if (exitCode != 0) { request.WriteError(ErrorCategory.InvalidOperation, fastPath, Resources.Messages.InstallFailed, package.Name, proc.StandardError.ReadToEnd()); request.CompleteProgress(tracker.ProgressID, false); return(false); } else { request.CompleteProgress(tracker.ProgressID, true); request.YieldFromSwidtag(package, fastPath); request.Verbose(Resources.Messages.SuccessfullyInstalled, package.Name); } cleanUpAction(); } return(true); } else { request.Error(ErrorCategory.InvalidOperation, Resources.Messages.FailedToDownload, Constants.ProviderName, package.Source, exePackage); } return(false); }
private static IEnumerable<PackageJson> GetDependencies(PackageJson packageJson, PackageSourceListRequest request) { if (packageJson.DependencyObjects == null) { yield break; } bool force = request.GetOptionValue("Force") != null; foreach (var dep in packageJson.DependencyObjects.Where(dep => (dep != null) && !dep.IsCommonDefinition)) { if (!force) { var provider = PackageSourceListRequest.FindProvider(request, dep.Type, request, true); if(provider == null) { //FindProvider logged an error already break; } //Check whether the dependency package is installed var installedPackages = provider.GetInstalledPackages(dep.Name, requiredVersion: null, minimumVersion: dep.Version, maximumVersion: null, requestObject: request); if (installedPackages == null || !installedPackages.Any()) { request.Verbose(Resources.Messages.DependencyNotInstalled, dep.Name); yield return dep; } else { request.Verbose(Resources.Messages.DependencyInstalled, dep.Name); } } else { yield return dep; } } }
internal static bool InstallZipPackage(PackageJson package, string fastPath, PackageSourceListRequest request) { // download the exe package var file = Path.ChangeExtension(Path.GetTempFileName(), "exe"); WebDownloader.DownloadFile(package.Source, file, request, null); if (!File.Exists(file)) { return false; } // validate the file if (!WebDownloader.VerifyHash(file, package,request)) { return false; } if (!package.IsTrustedSource) { if (!request.ShouldContinueWithUntrustedPackageSource(package.Name, package.Source)) { request.Warning(Constants.Messages.UserDeclinedUntrustedPackageInstall, package.Name); return false; } } Timer timer = null; object timerLock = new object(); bool cleanUp = false; ProgressTracker tracker = new ProgressTracker(request.StartProgress(0, "Installing Zip Package............")); double percent = tracker.StartPercent; Action cleanUpAction = () => { lock (timerLock) { // check whether clean up is already done before or not if (!cleanUp) { try { if (timer != null) { // stop timer timer.Change(Timeout.Infinite, Timeout.Infinite); timer.Dispose(); timer = null; } } catch { } cleanUp = true; } } }; // extracted folder string extractedFolder = string.Concat(file.GenerateTemporaryFilename()); try { timer = new Timer(_ => { percent += 0.025; var progressPercent = tracker.ConvertPercentToProgress(percent); if (progressPercent < 90) { request.Progress(tracker.ProgressID, (int)progressPercent, string.Format(CultureInfo.CurrentCulture, "Copying files ...")); } if (request.IsCanceled) { cleanUpAction(); } }, null, 0, 1000); //unzip the file ZipFile.ExtractToDirectory(file, extractedFolder); if (Directory.Exists(extractedFolder)) { var versionFolder = Path.Combine(package.Destination, package.Name, package.Version); // create the directory version folder if not exist if (!Directory.Exists(versionFolder)) { Directory.CreateDirectory(versionFolder); } try { FileUtility.CopyDirectory(extractedFolder, versionFolder, true); request.YieldFromSwidtag(package, fastPath); } catch (Exception e) { request.CompleteProgress(tracker.ProgressID, false); request.Debug(e.StackTrace); if (!(e is UnauthorizedAccessException || e is IOException)) { // something wrong, delete the version folder versionFolder.TryHardToDelete(); return false; } } return true; } else { request.Warning("Failed to download a Zip package {0} from {1}", package.Name, package.Source); } } finally { cleanUpAction(); file.TryHardToDelete(); extractedFolder.TryHardToDelete(); request.CompleteProgress(tracker.ProgressID, true); } return false; }
private static void InstallPackageViaPowerShellGet(PackageJson packageJson, PackageSourceListRequest request, SoftwareIdentity[] packages) { var provider = PackageSourceListRequest.FindProvider(request, packageJson.Type, request, true); if (provider == null) { return; } IHostApi installRequest = request; if (provider.Name.EqualsIgnoreCase(Constants.ProviderNames.PowerShellGet) && !request.ProviderServices.IsElevated) { // if we're not elevated, we want powershellget to install to the user scope installRequest = PackageSourceListRequest.ExtendRequest( new Dictionary <string, string[]> { { "Scope", new[] { "CurrentUser" } } }, null, packageJson.IsTrustedSource, request); } else { installRequest = PackageSourceListRequest.ExtendRequest( new Dictionary <string, string[]> { { "Destination", new[] { packageJson.Destination ?? "" } } }, null, packageJson.IsTrustedSource, request); } request.Debug("Calling '{0}' provider to install the package '{1}.{2}'", provider.Name, packageJson.Name, packageJson.Version); var installing = provider.InstallPackage(packages[0], installRequest); if (installing == null || !installing.Any()) { request.Verbose(Resources.Messages.NumberOfPackagesReceived, 0, provider.Name, "InstallPackage"); request.Warning(Resources.Messages.FailToInstallPackage, Constants.ProviderName, packages[0].Name); return; } int packagesReceived = 0; foreach (var i in installing) { request.YieldSoftwareIdentity(i.FastPackageReference, i.Name, i.Version, i.VersionScheme, i.Summary, i.Source, i.SearchKey, i.FullPath, i.PackageFilename); if (request.IsCanceled) { installing.Cancel(); } else { request.Verbose(Resources.Messages.SuccessfullyInstalled, "{0}.{1}".format(packageJson.Name, packageJson.Version)); //load provider if (packageJson.IsPackageProvider) { //Per provider development guidance: provider name and module name should be the same otherwise we can not import it. request.PackageManagementService.ImportPackageProvider(request, packageJson.Name, null, null, null, isRooted: false, force: false); } } packagesReceived++; } request.Verbose(Resources.Messages.NumberOfPackagesReceived, packagesReceived, provider.Name, "install-package"); }
private void UnInstallMsiPackage(PackageSourceListRequest request, string fastPath, PackageJson package) { request.Debug(Resources.Messages.DebugInfoCallMethod, PackageProviderName, string.Format(CultureInfo.InvariantCulture, "UnInstallMsiPackage' - name='{0}', fastPath='{1}'", package.Name, fastPath)); string sourceLocation; string id; string displayName; string version; string fastPackageReference; if (!request.TryParseFastPathComplex(fastPath: fastPath, regex: PackageSourceListRequest.RegexFastPathComplex, location: out sourceLocation, id: out id, displayname: out displayName, version: out version, fastpath: out fastPackageReference)) { //we don't need to error out even if fastpath is not correct because msi provider is expected to handle the uninstall-package. request.Verbose(Resources.Messages.UnsupportMSIUninstall, Constants.ProviderName, package.Name); return; } // Normally uninstall-package will be handled by MSI provider. Here we added a special case for handling uninstall-package nodejs // which msi provider unable to deal with (node.js only for msi) if (id != null && id.EqualsIgnoreCase("nodejs")) { var provider = PackageSourceListRequest.FindProvider(request, Constants.ProviderNames.Msi, request); if (provider != null) { if (!_fastPackReftable.ContainsKey(fastPackageReference)) { request.WriteError(ErrorCategory.InvalidData, fastPackageReference, Resources.Messages.FailedToGetPackageObject, Constants.ProviderName, fastPackageReference); return; } request.Verbose(Resources.Messages.UninstallingPackage, Constants.ProviderName, package.Name); var p = _fastPackReftable[fastPackageReference]; var installing = provider.UninstallPackage(p, request); foreach (var i in installing) { request.YieldSoftwareIdentity(i.FastPackageReference, i.Name, i.Version, i.VersionScheme, i.Summary, package.Source, i.SearchKey, i.FullPath, i.PackageFilename); if (request.IsCanceled) { installing.Cancel(); } return; } } } else { //no-op for uninstalling the msi packages. only install-package nodejs is supported because msi can not handle it request.Verbose(Resources.Messages.UnsupportMSIUninstall, Constants.ProviderName, package.Name); return; } }
private void GetMsiInstalledPackage(string name, PackageJson package, string requiredVersion, string minimumVersion, string maximumVersion, PackageSourceListRequest request) { request.Debug(Resources.Messages.DebugInfoCallMethod, PackageProviderName, string.Format(CultureInfo.InvariantCulture, "GetMsiInstalledPackage' - name='{0}', requiredVersion='{1}',minimumVersion='{2}', maximumVersion='{3}'", name, requiredVersion, minimumVersion, maximumVersion)); var provider = PackageSourceListRequest.FindProvider(request, package.Type, request); if (provider != null) { var packagesInstalled = provider.GetInstalledPackages(package.Name, requiredVersion, minimumVersion, maximumVersion, request); if (!packagesInstalled.Any()) { packagesInstalled = provider.GetInstalledPackages(package.DisplayName, requiredVersion, minimumVersion, maximumVersion, request); } foreach (var i in packagesInstalled) { request.Debug("found a package '{0}.{1}' installed from '{2}'", i.Name, i.Version, i.Source); var info = PackageSourceListRequest.MakeFastPathComplex(i.Source, name, (package.DisplayName?? ""), i.Version, i.FastPackageReference); _fastPackReftable.AddOrSet(i.FastPackageReference, i); // check if the installed version matches with the one specified in the PSL.json. // If so, we choose PSL.json. var version = i.Version.CompareVersion(package.Version) ? package.Version : i.Version; //we use displayname here because msi provider uses the displayname. request.YieldSoftwareIdentity(info, package.DisplayName, version, i.VersionScheme, i.Summary, package.Source, i.SearchKey, i.FullPath, i.PackageFilename); return; } } }
internal bool YieldFromSwidtag(PackageJson package, string searchKey) { if (package == null) { return !IsCanceled; } var targetFilename = package.FilePath; var summary = package.Summary; var fastPath = MakeFastPath(package); // As 'nodejs' become 'node.js' after the install, GetInstalledPackage() will return node.js. To skip installing node.js // if already installed, we need to return the node.js i.e., use display name for msi provider. if (package.Type.EqualsIgnoreCase(Constants.MediaType.MsiPackage)) { if (!string.IsNullOrWhiteSpace(package.DisplayName)) { package.Name = package.DisplayName; } } if (YieldSoftwareIdentity(fastPath, package.Name, package.SemVer.ToString(), package.VersionScheme, summary, package.Source, searchKey, null, targetFilename) != null) { //this is a trusted source if (AddMetadata(fastPath, "FromTrustedSource", "true") == null) { return !IsCanceled; } if (AddMetadata(fastPath, "Source", package.Source) == null) { return !IsCanceled; } if (AddMetadata(fastPath, "Type", package.Type) == null) { return !IsCanceled; } if (package.Dependencies != null) { //iterate thru the dependencies and add them to the software identity. foreach (var dependency in package.Dependencies) { // foreach (var pkg in dependency) { AddDependency("PSL", dependency.Name, dependency.Version, null, null); } } } } return !IsCanceled; }
internal string MakeFastPath(PackageJson package) { return string.Format(CultureInfo.InvariantCulture, @"${0}\{1}", package.Name.ToBase64(), package.Version.ToBase64()); }
internal static string CreateCanonicalId(PackageJson package, string providerName) { // example: "nuget:jquery/2.1.0#http://nuget.org/api/v2" if (package == null || string.IsNullOrEmpty(package.Name) || string.IsNullOrEmpty(providerName)) { return null; } if (string.IsNullOrWhiteSpace(package.Version) && string.IsNullOrWhiteSpace(package.Source)) { return "{0}:{1}".format(CultureInfo.CurrentCulture.TextInfo.ToLower(providerName), package.Name); } if (string.IsNullOrWhiteSpace(package.Source)) { return "{0}:{1}/{2}".format(CultureInfo.CurrentCulture.TextInfo.ToLower(providerName), package.Name, package.Version); } Uri pkgId; var source = package.Source; if (Uri.TryCreate(package.Source, UriKind.Absolute, out pkgId)) { source = pkgId.AbsoluteUri; } if (string.IsNullOrWhiteSpace(package.Version)) { "{0}:{1}#{2}".format(CultureInfo.CurrentCulture.TextInfo.ToLower(providerName), package.Name, source); } return "{0}:{1}/{2}#{3}".format(CultureInfo.CurrentCulture.TextInfo.ToLower(providerName), package.Name, package.Version, source); }
internal static void GeInstalledPowershellArtifacts(PackageJson package, string requiredVersion, string minimumVersion, string maximumVersion, Dictionary<string, SoftwareIdentity> fastPackReftable, PackageSourceListRequest request) { if (request == null) { throw new ArgumentNullException("request"); } request.Debug(Resources.Messages.DebugInfoCallMethod, Constants.ProviderName, string.Format(CultureInfo.InvariantCulture, "GeInstalledPowershellArtifacts' - name='{0}', requiredVersion='{1}',minimumVersion='{2}', maximumVersion='{3}'", package.Name, requiredVersion, minimumVersion, maximumVersion)); var provider = PackageSourceListRequest.FindProvider(request, package.Type, request); if (provider == null) return; //calling the PowerShellGet provider request.Debug("Calling '{0}' provider to get installed packages '{1}.{2}'", provider.Name, package.Name, package.Version); var packagesInstalled = provider.GetInstalledPackages(package.Name, requiredVersion, minimumVersion, maximumVersion, request).ToArray(); if (packagesInstalled == null || !packagesInstalled.Any()) { request.Verbose(Resources.Messages.NumberOfPackagesRecevied, 0, provider.Name, "GetInstalledPackages"); return; } foreach (var i in packagesInstalled) { request.Debug("Found an installed package '{0}.{1} from {2}' ", i.Name, i.Version, i.Source); var info = PackageSourceListRequest.MakeFastPathComplex(i.Source, i.Name, "", i.Version, ""); fastPackReftable.AddOrSet(info, i); // check if the installed version matches with the one specified in the PSL.json. // If so, we choose PSL.json. var version = i.Version.CompareVersion(package.Version) ? package.Version : i.Version; request.YieldSoftwareIdentity(info, i.Name, version, i.VersionScheme, i.Summary, i.Source, i.SearchKey, i.FullPath, i.PackageFilename); } }
private static void InstallPackageFile(PackageJson package, string fastPath, PackageSourceListRequest request) { request.Debug(Resources.Messages.DebugInfoCallMethod, Constants.ProviderName, string.Format(CultureInfo.InvariantCulture, "InstallPackageFile' - name='{0}', fastPath='{1}'", package.Name, fastPath)); // get a temp file name, msi or msu var providerType = package.Type.ToLowerInvariant(); var destination = Path.ChangeExtension(Path.GetTempFileName(), providerType); //download the msi package to the temp file WebDownloader.DownloadFile(package.Source, destination, request, null); if (!File.Exists(destination)) { return; } // validate the file if (!WebDownloader.VerifyHash(destination,package, request)) { return; } if (!package.IsTrustedSource) { if (!request.ShouldContinueWithUntrustedPackageSource(package.Name, package.Source)) { request.Warning(Constants.Messages.UserDeclinedUntrustedPackageInstall, package.Name); return; } } var installRequest = PackageSourceListRequest.ExtendRequest(new Dictionary<string, string[]> { {"Source", new[] {package.Source ?? ""}} }, new[] { package.Source ?? "" }, package.IsTrustedSource, request); request.Verbose(Resources.Messages.CallMsiForInstall, package.Name); if (request.ProviderServices.Install(destination, "", installRequest)) { // it installed ok!exit request.YieldFromSwidtag(package, fastPath); return; } else { request.WriteError(ErrorCategory.InvalidOperation, Constants.ProviderName, Resources.Messages.PackageFailedInstall, package.Name); } }
internal static void InstallDependencies(PackageJson packageJson, PackageSourceListRequest request) { //TODO dependency chain check //let's install dependency first in case it is needed for installing the actual package if (packageJson.DependencyObjects != null) { var dependencies = GetDependencies(packageJson, request); if (dependencies != null) { foreach (var dep in dependencies.Where(dep => (dep != null) && !dep.IsCommonDefinition)) { //dependency source trusty follows its parent dep.IsTrustedSource |= packageJson.IsTrustedSource; var id = PackageSourceListRequest.CreateCanonicalId(dep, dep.Name); InstallProviderFromInstaller(dep, id, request); } } } }
private static bool YieldPackages(string hive, RegistryKey regkey, string name, string displayname, string requiredVersion, string minimumVersion, string maximumVersion, PackageJson package, Request request) { //TODO make it wildcard match, follow the fastfrence format, get-package git no reults, get-package git* if (regkey != null) { var includeSystemComponent = request.GetOptionValue("IncludeSystemComponent").IsTrue(); foreach (var key in regkey.GetSubKeyNames()) { var subkey = regkey.OpenSubKey(key); if (subkey != null) { var properties = subkey.GetValueNames().ToDictionaryNicely(each => each.ToString(), each => (subkey.GetValue(each) ?? string.Empty).ToString(), StringComparer.OrdinalIgnoreCase); //if (!includeWindowsInstaller && properties.ContainsKey("WindowsInstaller") && properties["WindowsInstaller"] == "1") //{ // continue; //} if (!includeSystemComponent && properties.ContainsKey("SystemComponent") && properties["SystemComponent"] == "1") { continue; } var productName = ""; if (!properties.TryGetValue("DisplayName", out productName)) { // no product name? continue; } if (IsMatch(name, productName) || IsMatch(displayname, productName)) { var productVersion = properties.Get("DisplayVersion") ?? ""; var publisher = properties.Get("Publisher") ?? ""; var uninstallString = properties.Get("QuietUninstallString") ?? properties.Get("UninstallString") ?? ""; var comments = properties.Get("Comments") ?? ""; var fp = hive + @"\" + subkey; if (!string.IsNullOrEmpty(requiredVersion)) { if (new SemanticVersion(requiredVersion) != new SemanticVersion(productVersion)) { continue; } } else { if (!string.IsNullOrEmpty(minimumVersion) && new SemanticVersion(minimumVersion) > new SemanticVersion(productVersion)) { continue; } if (!string.IsNullOrEmpty(maximumVersion) && new SemanticVersion(maximumVersion) < new SemanticVersion(productVersion)) { continue; } } fp = PackageSourceListRequest.MakeFastPathComplex(package.Destination ?? "", package.Name, package.DisplayName, productVersion, fp); var source = properties.Get("InstallLocation") ?? ""; //we use name here because find-package uses name (not displayname) in the PSL.json, if (request.YieldSoftwareIdentity(fp, name, productVersion, "unknown", comments, source, name, "", "") != null) { if (properties.Keys.Where(each => !string.IsNullOrWhiteSpace(each)).Any(k => request.AddMetadata(fp, k.MakeSafeFileName(), properties[k]) == null)) { return(false); } } } } } } return(true); }