private Downloader RegisterDownloader(IDownloader provider, FourPartVersion asmVersion, IHostApi request) { string name = null; try { FourPartVersion ver = provider.GetProviderVersion(); var version = ver == 0 ? asmVersion : ver; name = provider.GetDownloaderName(); if (string.IsNullOrWhiteSpace(name)) { return(null); } // Initialize the provider before locking the collection // that way we're not blocking others on non-deterministic actions. request.Debug("Initializing provider '{0}'".format(name)); provider.InitializeProvider(request.As <IRequest>()); request.Debug("Provider '{0}' Initialized".format(name)); lock (Downloaders) { if (Downloaders.ContainsKey(name)) { if (version > Downloaders[name].Version) { // remove the old provider first. // todo: this won't remove the plugin domain and unload the code yet // we'll have to do that later. Downloaders.Remove(name); } else { return(null); } } request.Debug("Using Downloader Provider {0}".format(name)); var downloader = new Downloader(provider) { Version = version }; downloader.Initialize(request); Downloaders.AddOrSet(name, downloader); return(downloader); } } catch (Exception e) { request.Debug("Provider '{0}' Failed".format(name)); e.Dump(); } return(null); }
internal bool TryLoadProviderViaMetaProvider(string metaproviderName, string providerNameOrPath, IHostApi request) { if (_metaProviders.ContainsKey(metaproviderName)) { var metaProvider = _metaProviders[metaproviderName]; request.Debug("Using MetaProvider '{0}' to attempt to load provider from '{1}'".format(metaproviderName, providerNameOrPath)); return(LoadViaMetaProvider(_metaProviders[metaproviderName], providerNameOrPath, metaProvider.GetProviderVersion(), request)); } request.Debug("MetaProvider '{0}' is not recognized".format(metaproviderName)); return(false); }
public bool Debug(string messageText) { if (CanCallHost) { return(_hostApi.Debug(messageText)); } return(true); }
public IAsyncEnumerable <SoftwareIdentity> FindPackage(string name, string requiredVersion, string minimumVersion, string maximumVersion, IHostApi requestObject) { if (requestObject != null) { requestObject.Debug(String.Format(System.Globalization.CultureInfo.CurrentCulture, "PackageProvider::FindPackage with name {0}", name)); } return(new SoftwareIdentityRequestObject(this, requestObject ?? new object().As <IHostApi>(), request => Provider.FindPackage(name, requiredVersion, minimumVersion, maximumVersion, 0, request), Constants.PackageStatus.Available)); }
public bool Debug(string messageText) { if (CanCallHost) { return(_hostApi.Debug(GetMessageString(messageText, null) ?? messageText)); } return(true); }
/// <summary> /// Searches for the assembly, interrogates it for it's providers and then proceeds to load /// </summary> /// <param name="request"></param> /// <param name="providerAssemblyName"></param> /// <returns></returns> internal bool TryToLoadProviderAssembly(string providerAssemblyName, IHostApi request) { request.Debug(request.FormatMessageString("Trying provider assembly: {0}", providerAssemblyName)); var assemblyPath = FindAssembly(providerAssemblyName); if (assemblyPath != null) { try { byte[] hash = null; using (var stream = File.Open(assemblyPath, FileMode.Open, FileAccess.Read, FileShare.Read)) { hash = System.Security.Cryptography.MD5.Create().ComputeHash(stream); } lock (_providerFiles) { if (_providerFiles.ContainsKey(assemblyPath)) { // have we tried this file before? if (_providerFiles[assemblyPath].SequenceEqual(hash)) { // and it's the exact same file? request.Debug(request.FormatMessageString("Skipping previously processed assembly: {0}", assemblyPath)); return(false); } request.Debug(request.FormatMessageString("New assembly in location: {0}", assemblyPath)); // it's a different file in the same path? // we're gonna let it try the new file. _providerFiles.Remove(assemblyPath); } else { request.Debug(request.FormatMessageString("Attempting loading of assembly: {0}", assemblyPath)); } // record that this file is being loaded. _providerFiles.Add(assemblyPath, hash); } if (AcquireProviders(assemblyPath, request)) { request.Debug(request.FormatMessageString("SUCCESS provider assembly: {0}", providerAssemblyName)); return(true); } } catch (Exception e) { e.Dump(); lock (_providerFiles) { // can't create hash from file? // we're not going to try and load this. // all we can do is record the name. if (!_providerFiles.ContainsKey(assemblyPath)) { _providerFiles.Add(assemblyPath, new byte[0]); } } } } request.Debug(request.FormatMessageString("FAILED provider assembly: {0}", providerAssemblyName)); return(false); }
private bool RegisterDownloader(IDownloader provider, FourPartVersion asmVersion, IHostApi request) { try { FourPartVersion ver = provider.GetProviderVersion(); var version = ver == 0 ? asmVersion : ver; var name = provider.GetDownloaderName(); lock (Downloaders) { if (Downloaders.ContainsKey(name)) { if (version > Downloaders[name].Version) { // remove the old provider first. // todo: this won't remove the plugin domain and unload the code yet // we'll have to do that later. Downloaders.Remove(name); } else { return(false); } } request.Debug("Loading Downloader {0}".format(name, provider.GetDownloaderName())); provider.InitializeProvider(request.As <IRequest>()); Downloaders.AddOrSet(name, new Downloader(provider) { Version = version }).Initialize(request); } return(true); } catch (Exception e) { e.Dump(); } return(false); }
private IEnumerable<PackageProvider> ImportPowerShellProvider(IHostApi request, string modulePath, Version requiredVersion, bool shouldRefreshCache) { request.Debug(string.Format(CultureInfo.CurrentCulture, "Calling ImportPowerShellProvider. providerName = '{0}', requiredVersion='{1}'", modulePath, requiredVersion)); var powerShellMetaProvider = GetMetaProviderObject(request); if (powerShellMetaProvider == null) { yield break; } //providerName can be a file path or name. var instances = powerShellMetaProvider.LoadAvailableProvider(request.As<IRequest>(), modulePath, requiredVersion, shouldRefreshCache).ReEnumerable(); if (!instances.Any()) { //A provider is not found request.Error(Constants.Messages.UnknownProvider, ErrorCategory.InvalidOperation.ToString(), modulePath, string.Format(Resources.Messages.UnknownProvider, modulePath)); yield break; } foreach (var instance in instances) { //Register the provider var provider = instance.As<PackageProvider>(); if (provider != null) { //initialize the actual powershell package provider if (provider.Provider == null) { continue; } provider.Provider.InitializeProvider(request.As<IRequest>()); AddToProviderCacheTable(provider.ProviderName, provider); //initialize the warpper package provider provider.Initialize(request); // addOrSet locks the collection anyway. _packageProviders.AddOrSet(provider.ProviderName, provider); yield return provider; } } }
private IEnumerable<PackageProvider> ImportPackageProviderViaName(IHostApi request, string providerName, Version requiredVersion, Version minimumVersion, Version maximumVersion, bool force) { request.Debug(string.Format(CultureInfo.CurrentCulture, "Calling ImportPackageProviderViaName. providerName = '{0}', requiredVersion='{1}', minimumVersion = '{2}', maximumVersion='{3}'", providerName, requiredVersion, minimumVersion, maximumVersion)); //Check if the module or assembly is already loaded //key = path, value = version HashSet<KeyValuePair<string, string>> refreshingProvidersPaths = new HashSet<KeyValuePair<string, string>>(); foreach (var provider in _packageProviders) { if (provider.Key.IsWildcardMatch(providerName)) { //found the provider with the same name is already loaded if (force) { if (IsVersionMatch(provider.Value, requiredVersion, minimumVersion, maximumVersion)) { //if -force is specified and the version is the same, we will re-import directly from the path refreshingProvidersPaths.Add(new KeyValuePair<string, string>(_packageProviders[provider.Key].ProviderPath, _packageProviders[provider.Key].Version)); } request.Verbose(string.Format(CultureInfo.CurrentCulture, Resources.Messages.ReImportProvider, provider.Key)); } else { request.Verbose(string.Format(CultureInfo.CurrentCulture, Resources.Messages.ProviderImportedAlready, provider.Key)); return Enumerable.Empty<PackageProvider>(); } } } //reload the assembly foreach (var providerPath in refreshingProvidersPaths) { var providers = ImportPackageProviderViaPath(request, providerPath.Key, requiredVersion, minimumVersion, maximumVersion, force); return providers; } //check if the provider is in the cache table var results = FindMatchedProvidersFromInternalCacheTable(request, providerName, requiredVersion, minimumVersion, maximumVersion, force).ToArray(); if (results.Any()) { return results; } //If the provider is not in the cache list, rescan for providers ScanForAvailableProviders(request, providerName, requiredVersion, minimumVersion, maximumVersion, true); results = FindMatchedProvidersFromInternalCacheTable(request, providerName, requiredVersion, minimumVersion, maximumVersion, force).ToArray(); if (!results.Any()) { request.Error(Constants.Messages.NoMatchFoundForCriteria, ErrorCategory.InvalidData.ToString(), providerName, string.Format(CultureInfo.CurrentCulture, Resources.Messages.NoMatchFoundForCriteria, providerName)); } else { return results; } return Enumerable.Empty<PackageProvider>(); }
private IEnumerable<PackageProvider> ImportPackageProviderViaPath(IHostApi request, string providerPath, Version requiredVersion, Version minimumVersion, Version maximumVersion, bool force) { request.Debug(string.Format(CultureInfo.CurrentCulture, "Calling ImportPackageProviderViaPath. providerName = '{0}', requiredVersion='{1}', minimumVersion = '{2}', maximumVersion='{3}'", providerPath, requiredVersion, minimumVersion, maximumVersion)); var extension = Path.GetExtension(providerPath); if (extension != null && extension.EqualsIgnoreCase(".psm1")) { //loading the PowerShell provider request.Verbose(string.Format(CultureInfo.CurrentCulture, Resources.Messages.LoadingPowerShellModule, providerPath)); return ImportPowerShellProvider(request, providerPath, requiredVersion, force); } //loading non-PowerShell providers request.Verbose(string.Format(CultureInfo.CurrentCulture, Resources.Messages.LoadingAssembly, providerPath)); var loaded = LoadProviderAssembly(request, providerPath, force); if (loaded) { return _packageProviders.Where(p => p.Value.ProviderPath.EqualsIgnoreCase(providerPath)).Select(each => each.Value); } return Enumerable.Empty<PackageProvider>(); }
/// <summary> /// Import a package provider. /// </summary> /// <param name="request"></param> /// <param name="providerName">Provider name or file path</param> /// <param name="requiredVersion">The provider version to be loaded</param> /// <param name="minimumVersion">The minimum version of the provider to be loaded</param> /// <param name="maximumVersion">The maximum version of the provider to be loaded</param> /// <param name="isPathRooted">Whether the 'providerName' is path or name</param> /// <param name="force">Whether -force is specified</param> /// <returns></returns> public IEnumerable<PackageProvider> ImportPackageProvider(IHostApi request, string providerName, Version requiredVersion, Version minimumVersion, Version maximumVersion, bool isPathRooted, bool force) { request.Debug(string.Format(CultureInfo.CurrentCulture, "Calling ImportPackageProvider. providerName = '{0}', requiredVersion='{1}', minimumVersion = '{2}', maximumVersion='{3}'", providerName, requiredVersion, minimumVersion, maximumVersion)); if (string.IsNullOrWhiteSpace(providerName)) { return Enumerable.Empty<PackageProvider>(); } if (providerName.ContainsWildcards()) { request.Error(Constants.Messages.InvalidParameter, ErrorCategory.InvalidData.ToString(), providerName, string.Format(CultureInfo.CurrentCulture, Resources.Messages.InvalidParameter, "Import-PackageProvider")); return Enumerable.Empty<PackageProvider>(); } if (isPathRooted) { if (!File.Exists(providerName)) { request.Error(Constants.Messages.InvalidFilename, ErrorCategory.InvalidData.ToString(), providerName, string.Format(CultureInfo.CurrentCulture, Resources.Messages.FileNotFound, providerName)); return Enumerable.Empty<PackageProvider>(); } //Check if the file type is supported: .dll, .exe, or .psm1 if (!Constants.SupportedAssemblyTypes.Any(each => each.EqualsIgnoreCase(Path.GetExtension(providerName)))) { var fileTypes = Constants.SupportedAssemblyTypes.Aggregate(string.Empty, (current, each) => current + " " + each); request.Error(Constants.Messages.InvalidFilename, ErrorCategory.InvalidData.ToString(), providerName, string.Format(CultureInfo.CurrentCulture, Resources.Messages.InvalidFileType, providerName, fileTypes)); return Enumerable.Empty<PackageProvider>(); } } var providers = isPathRooted ? ImportPackageProviderViaPath(request, providerName, requiredVersion, minimumVersion, maximumVersion, force) : ImportPackageProviderViaName(request, providerName, requiredVersion, minimumVersion, maximumVersion, force); return providers; }
/// <summary> /// Searches for the assembly, interrogates it for it's providers and then proceeds to load /// </summary> /// <param name="request"></param> /// <param name="providerAssemblyName"></param> /// <returns></returns> public bool LoadProviderAssembly(IHostApi request, string providerAssemblyName) { request.Debug(request.FormatMessageString("Trying provider assembly: {0}", providerAssemblyName)); var assemblyPath = FindAssembly(providerAssemblyName); if (assemblyPath != null) { try { byte[] hash = null; using (var stream = File.Open(assemblyPath, FileMode.Open, FileAccess.Read, FileShare.Read)) { hash = MD5.Create().ComputeHash(stream); } lock (_providerFiles) { if (_providerFiles.ContainsKey(assemblyPath)) { // have we tried this file before? if (_providerFiles[assemblyPath].SequenceEqual(hash)) { // and it's the exact same file? request.Debug(request.FormatMessageString("Skipping previously processed assembly: {0}", assemblyPath)); return false; } request.Debug(request.FormatMessageString("New assembly in location: {0}", assemblyPath)); // it's a different file in the same path? // we're gonna let it try the new file. _providerFiles.Remove(assemblyPath); } else { request.Debug(request.FormatMessageString("Attempting loading of assembly: {0}", assemblyPath)); } // record that this file is being loaded. _providerFiles.Add(assemblyPath, hash); } if (AcquireProviders(assemblyPath, request)) { request.Debug(request.FormatMessageString("SUCCESS provider assembly: {0}", providerAssemblyName)); return true; } } catch (Exception e) { e.Dump(); lock (_providerFiles) { // can't create hash from file? // we're not going to try and load this. // all we can do is record the name. if (!_providerFiles.ContainsKey(assemblyPath)) { _providerFiles.Add(assemblyPath, new byte[0]); } } } } request.Debug(request.FormatMessageString("FAILED provider assembly: {0}", providerAssemblyName)); return false; }
public bool RequirePackageProvider(string requestor, string packageProviderName, string minimumVersion, IHostApi hostApi) { // check if the package provider is already installed if (_packageProviders.ContainsKey(packageProviderName)) { var current = _packageProviders[packageProviderName].Version; if (current >= minimumVersion) { return true; } } var currentCallCount = hostApi.CallCount; if (_lastCallCount >= currentCallCount) { // we've already been here this call. // are they asking for the same provider again? if (_providersTriedThisCall.Contains(packageProviderName)) { hostApi.Debug("Skipping RequirePackageProvider -- tried once this call previously."); return false; } // remember this in case we come back again. _providersTriedThisCall.Add(packageProviderName); } else { _lastCallCount = currentCallCount; _providersTriedThisCall = new HashSet<string> { packageProviderName }; } if (!hostApi.IsInteractive) { hostApi.Debug("Skipping RequirePackageProvider due to not interactive"); // interactive indicates that the host can respond to queries -- this doesn't happen // in powershell during tab-completion. return false; } // no? // ask the bootstrap provider if there is a package provider with that name available. if (!_packageProviders.ContainsKey(packageProviderName)){ return false; } var bootstrap = _packageProviders["Bootstrap"]; if (bootstrap == null) { hostApi.Debug("Skipping RequirePackageProvider due to missing bootstrap provider"); return false; } var pkg = bootstrap.FindPackage(packageProviderName, null, minimumVersion, null, hostApi).OrderByDescending(p => p, SoftwareIdentityVersionComparer.Instance).GroupBy(package => package.Name).ToArray(); if (pkg.Length == 1) { // Yeah? Install it. var package = pkg[0].FirstOrDefault(); var metaWithProviderType = package.Meta.FirstOrDefault(each => each.ContainsKey("providerType")); var providerType = metaWithProviderType == null ? "unknown" : metaWithProviderType.GetAttribute("providerType"); var destination = providerType == "assembly" ? (AdminPrivilege.IsElevated ? SystemAssemblyLocation : UserAssemblyLocation) : String.Empty; var link = package.Links.FirstOrDefault(each => each.Relationship == "installationmedia"); var location = String.Empty; if (link != null) { location = link.HRef.ToString(); } // what can't find an installationmedia link? // todo: what should we say here? if (hostApi.ShouldBootstrapProvider(requestor, package.Name, package.Version, providerType, location, destination)) { var newRequest = hostApi.Extend<IHostApi>(new { GetOptionValues = new Func<string, IEnumerable<string>>(key => { if (key == "DestinationPath") { return new[] { destination }; } return new string[0]; }) }); var packagesInstalled = bootstrap.InstallPackage(package, newRequest).LastOrDefault(); if (packagesInstalled == null) { // that's sad. hostApi.Error(Constants.Messages.FailedProviderBootstrap, ErrorCategory.InvalidOperation.ToString(), package.Name, hostApi.FormatMessageString(Constants.Messages.FailedProviderBootstrap, package.Name)); return false; } // so it installed something // we must tell the plugin loader to reload the plugins again. LoadProviders(hostApi); return true; } } return false; }
private Downloader RegisterDownloader(IDownloader provider, FourPartVersion asmVersion, IHostApi request) { string name = null; try { FourPartVersion ver = provider.GetProviderVersion(); var version = ver == 0 ? asmVersion : ver; name = provider.GetDownloaderName(); if (String.IsNullOrWhiteSpace(name)) { return null; } // Initialize the provider before locking the collection // that way we're not blocking others on non-deterministic actions. request.Debug("Initializing provider '{0}'".format(name)); provider.InitializeProvider(request.As<IRequest>()); request.Debug("Provider '{0}' Initialized".format(name)); lock (Downloaders) { if (Downloaders.ContainsKey(name)) { if (version > Downloaders[name].Version) { // remove the old provider first. // todo: this won't remove the plugin domain and unload the code yet // we'll have to do that later. Downloaders.Remove(name); } else { return null; } } request.Debug("Using Downloader Provider {0}".format(name)); var downloader = new Downloader(provider) { Version = version, IsLoaded = true }; downloader.Initialize(request); Downloaders.AddOrSet(name, downloader); return downloader; } } catch (Exception e) { request.Debug("Provider '{0}' Failed".format(name)); e.Dump(); } return null; }
//Return all providers under the providerAssemblies folder internal IEnumerable<string> AllProvidersFromProviderAssembliesLocation(IHostApi request) { try { return ScanAllProvidersFromProviderAssembliesLocation(request, null, null, null, null, ProviderOption.AllProvider).WhereNotNull().ToArray(); } catch (Exception ex) { request.Debug(ex.Message); } return Enumerable.Empty<string>(); }
private IEnumerable<PackageProvider> ImportPackageProviderViaName(IHostApi request, string providerName, Version requiredVersion, Version minimumVersion, Version maximumVersion, bool force, bool throwErrorWhenImportWithName) { request.Debug(string.Format(CultureInfo.CurrentCulture, "Calling ImportPackageProviderViaName. providerName = '{0}', requiredVersion='{1}', minimumVersion = '{2}', maximumVersion='{3}'", providerName, requiredVersion, minimumVersion, maximumVersion)); //Check if the module or assembly is already loaded //key = path, value = version HashSet<KeyValuePair<string, FourPartVersion>> refreshingProvidersPaths = new HashSet<KeyValuePair<string, FourPartVersion>>(); foreach (var provider in _packageProviders) { if (provider.Key.IsWildcardMatch(providerName)) { //found the provider with the same name is already loaded if (force) { // if -force is present and required version is specified, we will enforce that the loaded provider version must match the required version if ((requiredVersion != null && provider.Value.Version == (FourPartVersion)requiredVersion) // if -force is specified and no version information is provided, we will re-import directly from the path of the loaded provider ||(requiredVersion == null && maximumVersion == null && minimumVersion == null)) { refreshingProvidersPaths.Add(new KeyValuePair<string, FourPartVersion>(_packageProviders[provider.Key].ProviderPath, _packageProviders[provider.Key].Version)); } request.Verbose(string.Format(CultureInfo.CurrentCulture, Resources.Messages.ReImportProvider, provider.Key)); } else { request.Verbose(string.Format(CultureInfo.CurrentCulture, Resources.Messages.ProviderImportedAlready, provider.Key)); return Enumerable.Empty<PackageProvider>(); } } } //reload the assembly foreach (var providerPath in refreshingProvidersPaths) { var providers = ImportPackageProviderViaPath(request, providerPath.Key, providerPath.Value, minimumVersion, maximumVersion, force); return providers; } IEnumerable<PackageProvider> results = null; // if user doesn't have all the available providers in the cache, // then there is a chance that we will miss the latest version of the provider // so we will only try to search from the cache table without refreshing it // if the user does not provide -force and either maximum or minimum version. if (!force || (maximumVersion == null && minimumVersion == null)) { //check if the provider is in the cache table results = FindMatchedProvidersFromInternalCacheTable(request, providerName, requiredVersion, minimumVersion, maximumVersion, force).ToArray(); if (results.Any()) { return results; } } //If the provider is not in the cache list, rescan for providers ScanForAvailableProviders(request, providerName, requiredVersion, minimumVersion, maximumVersion, true, false); results = FindMatchedProvidersFromInternalCacheTable(request, providerName, requiredVersion, minimumVersion, maximumVersion, force).ToArray(); if (!results.Any()) { if (throwErrorWhenImportWithName) { request.Error(Constants.Messages.NoMatchFoundForCriteria, ErrorCategory.InvalidData.ToString(), providerName, string.Format(CultureInfo.CurrentCulture, Resources.Messages.NoMatchFoundForCriteria, providerName)); } else { request.Verbose(string.Format(CultureInfo.CurrentCulture, Resources.Messages.NoMatchFoundForCriteria, providerName)); } } else { return results; } return Enumerable.Empty<PackageProvider>(); }
//Return all providers under the providerAssemblies folder internal IEnumerable<string> AllProvidersFromProviderAssembliesLocation(IHostApi request) { #if !PORTABLE // don't need this for core powershell try { return ScanAllProvidersFromProviderAssembliesLocation(request, null, null, null, null, ProviderOption.AllProvider).WhereNotNull().ToArray(); } catch (Exception ex) { request.Debug(ex.Message); } #endif return Enumerable.Empty<string>(); }
/// <summary> /// This initializes the provider registry with the list of package providers. /// (currently a hardcoded list, soon, registry driven) /// </summary> /// <param name="request"></param> internal void LoadProviders(IHostApi request) { if (request == null) { throw new ArgumentNullException("request"); } var providerAssemblies = (_initialized ? Enumerable.Empty <string>() : _defaultProviders) .Concat(GetProvidersFromRegistry(Registry.LocalMachine, "SOFTWARE\\MICROSOFT\\PACKAGEMANAGEMENT")) .Concat(GetProvidersFromRegistry(Registry.CurrentUser, "SOFTWARE\\MICROSOFT\\PACKAGEMANAGEMENT")) .Concat(AutoloadedAssemblyLocations.SelectMany(location => { if (Directory.Exists(location)) { return(Directory.EnumerateFiles(location).Where(each => (each.EndsWith(".exe", StringComparison.OrdinalIgnoreCase) || each.EndsWith(".dll", StringComparison.OrdinalIgnoreCase)))); } return(Enumerable.Empty <string>()); })); #if DEEP_DEBUG providerAssemblies = providerAssemblies.ToArray(); foreach (var each in providerAssemblies) { request.Debug("possible assembly: {0}".format(each)); } #endif // find modules that have manifests // todo: expand this out to validate the assembly is ok for this instance of PackageManagement. providerAssemblies = providerAssemblies.Where(each => Manifest.LoadFrom(each).Any(manifest => Swidtag.IsSwidtag(manifest) && new Swidtag(manifest).IsApplicable(new Hashtable()))); // add inbox assemblies (don't require manifests, because they are versioned with the core) #if !COMMUNITY_BUILD // todo: these should just be strong-named references. for now, just load them from the same directory. providerAssemblies = providerAssemblies.Concat(new[] { Path.Combine(BaseDir, "Microsoft.PackageManagement.MetaProvider.PowerShell.dll"), Path.Combine(BaseDir, "Microsoft.PackageManagement.ArchiverProviders.dll"), Path.Combine(BaseDir, "Microsoft.PackageManagement.CoreProviders.dll"), Path.Combine(BaseDir, "Microsoft.PackageManagement.MsuProvider.dll"), #if !CORE_CLR // can't load these providers here. Path.Combine(BaseDir, "Microsoft.PackageManagement.MsiProvider.dll"), #endif }); #endif #if DEEP_DEBUG providerAssemblies = providerAssemblies.ToArray(); foreach (var each in providerAssemblies) { request.Debug("possible assembly with manifest: {0}".format(each)); } #endif providerAssemblies = providerAssemblies.OrderByDescending(each => { try { // try to get a version from the file first return((ulong)(FourPartVersion)FileVersionInfo.GetVersionInfo(each)); } catch { // otherwise we can't make a distinction. return((ulong)0); } }); providerAssemblies = providerAssemblies.Distinct(new PathEqualityComparer(PathCompareOption.FileWithoutExtension)); // there is no trouble with loading providers concurrently. #if DEEP_DEBUG providerAssemblies.SerialForEach(providerAssemblyName => { #else providerAssemblies.ParallelForEach(providerAssemblyName => { #endif TryToLoadProviderAssembly(providerAssemblyName, request); }); #if DEEP_DEBUG WaitForDebugger(); #endif }
public bool RequirePackageProvider(string requestor, string packageProviderName, string minimumVersion, IHostApi hostApi) { // check if the package provider is already installed if (_packageProviders.ContainsKey(packageProviderName)) { var current = _packageProviders[packageProviderName].Version; if (current >= minimumVersion) { return(true); } } var currentCallCount = hostApi.CallCount; if (_lastCallCount >= currentCallCount) { // we've already been here this call. // are they asking for the same provider again? if (_providersTriedThisCall.Contains(packageProviderName)) { hostApi.Debug("Skipping RequirePackageProvider -- tried once this call previously."); return(false); } // remember this in case we come back again. _providersTriedThisCall.Add(packageProviderName); } else { _lastCallCount = currentCallCount; _providersTriedThisCall = new HashSet <string> { packageProviderName }; } if (!hostApi.IsInteractive) { hostApi.Debug("Skipping RequirePackageProvider due to not interactive"); // interactive indicates that the host can respond to queries -- this doesn't happen // in powershell during tab-completion. return(false); } // no? // ask the bootstrap provider if there is a package provider with that name available. var bootstrap = _packageProviders["Bootstrap"]; if (bootstrap == null) { hostApi.Debug("Skipping RequirePackageProvider due to missing bootstrap provider"); return(false); } var pkg = bootstrap.FindPackage(packageProviderName, null, minimumVersion, null, hostApi).OrderByDescending(p => p, SoftwareIdentityVersionComparer.Instance).GroupBy(package => package.Name).ToArray(); if (pkg.Length == 1) { // Yeah? Install it. var package = pkg[0].FirstOrDefault(); var metaWithProviderType = package.Meta.FirstOrDefault(each => each.ContainsKey("providerType")); var providerType = metaWithProviderType == null ? "unknown" : metaWithProviderType.GetAttribute("providerType"); var destination = providerType == "assembly" ? (AdminPrivilege.IsElevated ? SystemAssemblyLocation : UserAssemblyLocation) : string.Empty; var link = package.Links.FirstOrDefault(each => each.Relationship == "installationmedia"); var location = string.Empty; if (link != null) { location = link.HRef.ToString(); } // what can't find an installationmedia link? // todo: what should we say here? if (hostApi.ShouldBootstrapProvider(requestor, package.Name, package.Version, providerType, location, destination)) { var newRequest = hostApi.Extend <IHostApi>(new { GetOptionValues = new Func <string, IEnumerable <string> >(key => { if (key == "DestinationPath") { return(new[] { destination }); } return(new string[0]); }) }); var packagesInstalled = bootstrap.InstallPackage(package, newRequest).LastOrDefault(); if (packagesInstalled == null) { // that's sad. hostApi.Error(Constants.Messages.FailedProviderBootstrap, ErrorCategory.InvalidOperation.ToString(), package.Name, hostApi.FormatMessageString(Constants.Messages.FailedProviderBootstrap, package.Name)); return(false); } // so it installed something // we must tell the plugin loader to reload the plugins again. LoadProviders(hostApi); return(true); } } return(false); }
//return the providers with latest version under the providerAssemblies folder private IEnumerable<string> ProvidersWithLatestVersionFromProviderAssembliesLocation(IHostApi request) { try { var providerPaths = ScanAllProvidersFromProviderAssembliesLocation(request, null, null, null, null, ProviderOption.LatestVersion).WhereNotNull().ToArray(); var notRootAssemblies = providerPaths.Where(each => !ProviderAssembliesLocation.ContainsIgnoreCase(Path.GetDirectoryName(each))).ToArray(); var rootAssemblies = providerPaths.Where(each => ProviderAssembliesLocation.ContainsIgnoreCase(Path.GetDirectoryName(each))).ToArray(); var equalityComparer = new PathEqualityComparer(PathCompareOption.File); //return the assemblies that are installed not directly under ProviderAssemblies root folder. //For the assemblies under the root directory, we need to check further if the provider that has the later version //installed under providername\version folder //Convention: the providers are installed under providerassemblies\providername\version folder has the later version //than those at the top root folder. var assembliesUnderRootFolder = rootAssemblies.Where(rootPath => !notRootAssemblies.Any(element => equalityComparer.Equals(element, rootPath))); //for these assemblies not under the providerassemblies root folders but they have the same provider names, we return the latest version var assembliesUnderVersionFolder = notRootAssemblies.GroupBy(Path.GetFileName).Select( each => each.OrderByDescending(file => { var versionFolder = Path.GetDirectoryName(file); Version ver; return !System.Version.TryParse(Path.GetFileName(versionFolder), out ver) ? new Version("0.0") : ver; }).FirstOrDefault()).WhereNotNull(); return assembliesUnderVersionFolder.Concat(assembliesUnderRootFolder); } catch (Exception ex) { request.Debug(ex.Message); } return Enumerable.Empty<string>(); }
/// <summary> /// Searches for the assembly, interrogates it for it's providers and then proceeds to load /// </summary> /// <param name="request"></param> /// <param name="providerAssemblyName"></param> /// <param name="shouldRefreshCache"></param> /// <returns></returns> internal bool LoadProviderAssembly(IHostApi request, string providerAssemblyName, bool shouldRefreshCache) { request.Debug(request.FormatMessageString("Trying provider assembly: {0}", providerAssemblyName)); var assemblyPath = FindAssembly(providerAssemblyName); if (assemblyPath != null) { try { byte[] hash = null; using (var stream = File.Open(assemblyPath, FileMode.Open, FileAccess.Read, FileShare.Read)) { hash = System.Security.Cryptography.MD5.Create().ComputeHash(stream); } lock (_providerFiles) { if (_providerFiles.ContainsKey(assemblyPath)) { // have we tried this file before? //if the exactly same provider is loaded already, skip the processed assembly. if (_providerFiles[assemblyPath].SequenceEqual(hash) && !shouldRefreshCache) { // and it's the exact same file? request.Verbose(string.Format(CultureInfo.CurrentCulture, Resources.Messages.SkippingProcessedAssembly, assemblyPath)); return false; } // it's a different file in the same path? -force exists? // we're gonna let it try the new file. _providerFiles.Remove(assemblyPath); } request.Debug(request.FormatMessageString("Attempting loading of assembly: {0}", assemblyPath)); // record that this file is being loaded. _providerFiles.Add(assemblyPath, hash); } if (AcquireProviders(assemblyPath, request, shouldRefreshCache)) { request.Debug(request.FormatMessageString("SUCCESS provider assembly: {0}", providerAssemblyName)); return true; } } catch (Exception e) { e.Dump(); lock (_providerFiles) { // can't create hash from file? // we're not going to try and load this. // all we can do is record the name. if (!_providerFiles.ContainsKey(assemblyPath)) { _providerFiles.Add(assemblyPath, new byte[0]); } } } } request.Debug(request.FormatMessageString("FAILED provider assembly: {0}", providerAssemblyName)); return false; }
internal bool TryLoadProviderViaMetaProvider(string metaproviderName, string providerNameOrPath, IHostApi request ) { if (_metaProviders.ContainsKey(metaproviderName)) { var metaProvider = _metaProviders[metaproviderName]; request.Debug("Using MetaProvider '{0}' to attempt to load provider from '{1}'".format(metaproviderName, providerNameOrPath)); return LoadViaMetaProvider( _metaProviders[metaproviderName], providerNameOrPath, metaProvider.GetProviderVersion(),request); } request.Debug("MetaProvider '{0}' is not recognized".format(metaproviderName)); return false; }
internal bool AcquireProviders(string assemblyPath, IHostApi request, bool shouldRefreshCache) { var found = false; try { Assembly assembly = null; #if !CORECLR assembly = Assembly.LoadFrom(assemblyPath); #else assembly = Microsoft.PowerShell.CoreCLR.AssemblyExtensions.LoadFrom(assemblyPath); #endif if (assembly == null) { return false; } var asmVersion = GetAssemblyVersion(assembly); request.Debug("Acquiring providers for assembly" + assemblyPath); assembly.FindCompatibleTypes<IMetaProvider>().AsyncForEach(metaProviderClass => { request.Debug("Registering providers via metaproviders for assembly " + metaProviderClass); found |= RegisterProvidersViaMetaProvider(metaProviderClass.Create<IMetaProvider>(), asmVersion, request); }) .Concat(assembly.FindCompatibleTypes<IPackageProvider>().AsyncForEach(packageProviderClass => { try { //Handling C# based providers var packageProvider = RegisterPackageProvider(packageProviderClass.Create<IPackageProvider>(), asmVersion, request, shouldRefreshCache); if (packageProvider != null) { found = true; packageProvider.ProviderPath = assemblyPath; } } catch (Exception ex) { request.Debug(ex.Message); } })) .Concat(assembly.FindCompatibleTypes<IArchiver>().AsyncForEach(serviceProviderClass => { var archiver = RegisterArchiver(serviceProviderClass.Create<IArchiver>(), asmVersion, request); if (archiver != null) { found = true; archiver.ProviderPath = assemblyPath; } })) .Concat(assembly.FindCompatibleTypes<IDownloader>().AsyncForEach(serviceProviderClass => { var downloader = RegisterDownloader(serviceProviderClass.Create<IDownloader>(), asmVersion, request); if (downloader != null) { found = true; downloader.ProviderPath = assemblyPath; } })).WaitAll(); } catch (Exception e) { request.Debug(e.Message); request.Debug(e.StackTrace); } return found; }
/// <summary> /// This initializes the provider registry with the list of package providers. /// (currently a hardcoded list, soon, registry driven) /// </summary> /// <param name="request"></param> internal void LoadProviders(IHostApi request) { if (request == null) { throw new ArgumentNullException("request"); } var providerAssemblies = (_initialized ? Enumerable.Empty<string>() : _defaultProviders) .Concat(GetProvidersFromRegistry(Registry.LocalMachine, "SOFTWARE\\MICROSOFT\\PACKAGEMANAGEMENT")) .Concat(GetProvidersFromRegistry(Registry.CurrentUser, "SOFTWARE\\MICROSOFT\\PACKAGEMANAGEMENT")) .Concat(AutoloadedAssemblyLocations.SelectMany(location => { if (Directory.Exists(location)) { return Directory.EnumerateFiles(location).Where(each => (each.EndsWith(".exe", StringComparison.OrdinalIgnoreCase) || each.EndsWith(".dll", StringComparison.OrdinalIgnoreCase))); } return Enumerable.Empty<string>(); })); #if DEEP_DEBUG providerAssemblies = providerAssemblies.ToArray(); foreach (var each in providerAssemblies) { request.Debug("possible assembly: {0}".format(each)); } #endif // find modules that have manifests // todo: expand this out to validate the assembly is ok for this instance of PackageManagement. providerAssemblies = providerAssemblies.Where(each => Manifest.LoadFrom(each).Any(manifest => Swidtag.IsSwidtag(manifest) && new Swidtag(manifest).IsApplicable(new Hashtable()))); // add inbox assemblies (don't require manifests, because they are versioned with the core) #if !COMMUNITY_BUILD // todo: these should just be strong-named references. for now, just load them from the same directory. providerAssemblies = providerAssemblies.Concat(new[] { Path.Combine(BaseDir, "Microsoft.PackageManagement.MetaProvider.PowerShell.dll"), Path.Combine(BaseDir, "Microsoft.PackageManagement.ArchiverProviders.dll"), Path.Combine(BaseDir, "Microsoft.PackageManagement.CoreProviders.dll"), Path.Combine(BaseDir, "Microsoft.PackageManagement.MsuProvider.dll"), Path.Combine(BaseDir, "Microsoft.PackageManagement.MsiProvider.dll") }); #endif #if DEEP_DEBUG providerAssemblies = providerAssemblies.ToArray(); foreach (var each in providerAssemblies) { request.Debug("possible assembly with manifest: {0}".format(each)); } #endif providerAssemblies = providerAssemblies.OrderByDescending(each => { try { // try to get a version from the file first return (ulong)(FourPartVersion)FileVersionInfo.GetVersionInfo(each); } catch { // otherwise we can't make a distinction. return (ulong)0; } }); providerAssemblies = providerAssemblies.Distinct(new PathEqualityComparer(PathCompareOption.FileWithoutExtension)); // there is no trouble with loading providers concurrently. #if DEEP_DEBUG providerAssemblies.SerialForEach(providerAssemblyName => { #else providerAssemblies.ParallelForEach(providerAssemblyName => { #endif LoadProviderAssembly(request, providerAssemblyName); }); #if DEEP_DEBUG WaitForDebugger(); #endif }
/// <summary> /// Register the package provider /// </summary> /// <param name="provider">Package provider object</param> /// <param name="asmVersion">assembly version info</param> /// <param name="request"></param> /// <param name="shouldRefreshCache">should refresh the internal provider list</param> /// <returns></returns> private PackageProvider RegisterPackageProvider(IPackageProvider provider, FourPartVersion asmVersion, IHostApi request, bool shouldRefreshCache) { string name = null; try { if (provider == null) { return null; } FourPartVersion ver = provider.GetProviderVersion(); var version = ver == 0 ? asmVersion : ver; name = provider.GetPackageProviderName(); if (string.IsNullOrWhiteSpace(name)) { return null; } // Initialize the provider before locking the collection // that way we're not blocking others on non-deterministic actions. request.Debug("Initializing provider '{0}'".format(name)); provider.InitializeProvider(request.As<IRequest>()); request.Debug("Provider '{0}' Initialized".format(name)); lock (_packageProviders) { //Check if the provider is loaded already. if (_packageProviders.ContainsKey(name)) { //if no -force, do nothing if (!shouldRefreshCache) { request.Verbose(string.Format(CultureInfo.CurrentCulture, Resources.Messages.SkipPreviousProcessedProvider, name)); //add the provider to the list var pkgprovider = new PackageProvider(provider) { Version = version, IsLoaded = true }; AddToProviderCacheTable(name, pkgprovider); return pkgprovider; } else { //looks like -force is used, we need to remove the old provider first. // this won't remove the plugin domain and unload the code yet _packageProviders.Remove(name); } } } request.Debug("Using Package Provider {0}".format(name)); var packageProvider = new PackageProvider(provider) { Version = version }; //initialize the package provider packageProvider.Initialize(request); // addOrSet locks the collection anyway. _packageProviders.AddOrSet(name, packageProvider); packageProvider.IsLoaded = true; request.Debug("The provider '{0}' is imported".format(name)); //add the provider to the list AddToProviderCacheTable(name, packageProvider); return packageProvider; } catch (Exception e) { request.Debug("Provider '{0}' Failed to import".format(name)); e.Dump(); } return null; }
private PackageProvider RegisterPackageProvider(IPackageProvider provider, string name, FourPartVersion asmVersion, IHostApi request) { // string name = null; try { FourPartVersion ver = provider.GetProviderVersion(); var version = ver == 0 ? asmVersion : ver; //TODO: Need to write a blog file name is the provider name. Provider is no longer required to impl ProvierName property //name = provider.GetPackageProviderName(); //if (String.IsNullOrWhiteSpace(name)) { // return null; //} // Initialize the provider before locking the collection // that way we're not blocking others on non-deterministic actions. request.Debug("Initializing provider '{0}'".format(name)); provider.InitializeProvider(request.As<IRequest>()); request.Debug("Provider '{0}' Initialized".format(name)); lock (_packageProviders) { if (_packageProviders.ContainsKey(name)) { if (version > _packageProviders[name].Version) { // remove the old provider first. // todo: this won't remove the plugin domain and unload the code yet // we'll have to do that later. _packageProviders.Remove(name); } else { return null; } } } request.Debug("Using Package Provider {0}".format(name)); var packageProvider = new PackageProvider(provider) { Version = version, IsLoaded = true }; packageProvider.Initialize(request); // addOrSet locks the collection anyway. _packageProviders.AddOrSet(name, packageProvider); return packageProvider; } catch (Exception e) { request.Debug("Provider '{0}' Failed".format(name)); e.Dump(); } return null; }
internal bool RegisterProvidersViaMetaProvider(IMetaProvider provider, FourPartVersion asmVersion, IHostApi request) { request.Debug("Trying to register metaprovider"); var found = false; var metaProviderName = provider.GetMetaProviderName(); lock (_metaProviders) { if (!_metaProviders.ContainsKey(metaProviderName)) { // Meta Providers can't be replaced at this point _metaProviders.AddOrSet(metaProviderName, provider); } } try { provider.InitializeProvider(request.As<IRequest>()); provider.GetProviderNames().ParallelForEach(name => { found = LoadViaMetaProvider(provider, name, asmVersion, request); }); } catch (Exception e) { e.Dump(); } return found; }
public bool Debug(string messageText) { return(_hostApi.Debug(messageText)); }
/// <summary> /// This initializes the provider registry with the list of package providers. /// (currently a hardcoded list, soon, registry driven) /// </summary> /// <param name="request"></param> internal void LoadProviders(IHostApi request) { if (request == null) { throw new ArgumentNullException("request"); } var baseDir = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); var providerAssemblies = (_initialized ? Enumerable.Empty <string>() : _defaultProviders) .Concat(GetProvidersFromRegistry(Registry.LocalMachine, "SOFTWARE\\MICROSOFT\\ONEGET")) .Concat(GetProvidersFromRegistry(Registry.CurrentUser, "SOFTWARE\\MICROSOFT\\ONEGET")) .Concat(AutoloadedAssemblyLocations.SelectMany(location => { if (Directory.Exists(location)) { return(Directory.EnumerateFiles(location).Where(each => !IsExcluded(each) && (each.EndsWith(".exe", StringComparison.CurrentCultureIgnoreCase) || each.EndsWith(".dll", StringComparison.CurrentCultureIgnoreCase)))); } return(Enumerable.Empty <string>()); })); #if DEEP_DEBUG providerAssemblies = providerAssemblies.ToArray(); foreach (var each in providerAssemblies) { request.Debug("possible assembly: {0}".format(each)); } #endif // find modules that have manifests // todo: expand this out to validate the assembly is ok for this instance of OneGet. providerAssemblies = providerAssemblies.Where(each => Manifest.LoadFrom(each).Any(manifest => Swidtag.IsSwidtag(manifest) && new Swidtag(manifest).IsApplicable(new Hashtable()))); // add inbox assemblies (don't require manifests, because they are versioned with the core) #if !COMMUNITY_BUILD // todo: these should just be strong-named references. for now, just load them from the same directory. providerAssemblies = providerAssemblies.Concat(new[] { Path.Combine(baseDir, "Microsoft.OneGet.MetaProvider.PowerShell.dll"), Path.Combine(baseDir, "Microsoft.OneGet.ArchiverProviders.dll"), Path.Combine(baseDir, "Microsoft.OneGet.CoreProviders.dll"), Path.Combine(baseDir, "Microsoft.OneGet.MsuProvider.dll"), #if !CORE_CLR // can't load these providers here. Path.Combine(baseDir, "Microsoft.OneGet.MsiProvider.dll"), #endif }); #endif #if DEEP_DEBUG providerAssemblies = providerAssemblies.ToArray(); foreach (var each in providerAssemblies) { request.Debug("possible assembly with manifest: {0}".format(each)); } #endif providerAssemblies = providerAssemblies.OrderByDescending(each => { try { // try to get a version from the file first return((ulong)(FourPartVersion)FileVersionInfo.GetVersionInfo(each)); } catch { // otherwise we can't make a distinction. return((ulong)0); } }); providerAssemblies = providerAssemblies.Distinct(new PathEqualityComparer(PathCompareOption.FileWithoutExtension)); #if BEFORE_WE_HAD_MANIFESTS // hack to make sure we don't load the old version of the nuget provider // when we have the ability to examine a plugin without dragging it into the // primary appdomain, this won't be needed. FourPartVersion minimumnugetversion = "2.8.3.6"; providerAssemblies = providerAssemblies.Where(assemblyFile => { try { if ("nuget-anycpu".EqualsIgnoreCase(Path.GetFileNameWithoutExtension(assemblyFile)) && ((FourPartVersion)FileVersionInfo.GetVersionInfo(assemblyFile)) < minimumnugetversion) { return(false); } } catch { } return(true); }); #endif // there is no trouble with loading providers concurrently. #if DEBUG providerAssemblies.SerialForEach(providerAssemblyName => { #else providerAssemblies.ParallelForEach(providerAssemblyName => { #endif try { request.Debug(request.FormatMessageString("Trying provider assembly: {0}", providerAssemblyName)); if (TryToLoadProviderAssembly(providerAssemblyName, request)) { request.Debug(request.FormatMessageString("SUCCESS provider assembly: {0}", providerAssemblyName)); } else { request.Debug(request.FormatMessageString("FAILED provider assembly: {0}", providerAssemblyName)); } } catch { request.Error(Constants.Messages.ProviderPluginLoadFailure, ErrorCategory.InvalidOperation.ToString(), providerAssemblyName, request.FormatMessageString(Constants.Messages.ProviderPluginLoadFailure, providerAssemblyName)); } }); }