internal static IHostApi SuppressErrorsAndWarnings(this IHostApi parent, bool isProcessing) { return(new object[] { new { Error = new Func <string, string, string, string, bool>((id, cat, targetobjectvalue, messageText) => { #if DEBUG parent.Verbose("Suppressed Error {0}".format(messageText)); #endif return false; }), Warning = new Func <string, bool>((messageText) => { #if DEBUG parent.Verbose("Suppressed Warning {0}".format(messageText)); #endif return true; }), Verbose = new Func <string, bool>((messageText) => { if (isProcessing) { parent.Verbose(messageText); } #if DEBUG else { parent.Verbose("Suppressed Verbose {0}".format(messageText)); } #endif return true; }), }, parent, }.As <IHostApi>()); }
public bool Verbose(string messageText) { if (CanCallHost) { return(_hostApi.Verbose(GetMessageString(messageText, null) ?? messageText)); } return(true); }
public bool Verbose(string messageText) { if (CanCallHost) { return(_hostApi.Verbose(messageText)); } return(true); }
public bool Verbose(string messageText) { return(_hostApi.Verbose(messageText)); }
private IEnumerable<PackageProvider> ImportPackageProviderViaPath(IHostApi request, string providerName) { var extension = Path.GetExtension(providerName); if (extension != null && extension.Equals(".dll")) { //TODO need to check if the assembly is from the known designated folder // List<string> knownAssemblyFolders = new List<string>(); //todo: get the current ps module folder instead of program files //todo build a internal asemlby table for Get-packageprovider to display. //todo: PackageProviderItem: providername, version, path, loaded, type (PS or dll), providerobject sorted by loaded var exist = AutoloadedAssemblyLocations.Where(each => each.Equals(Path.GetDirectoryName(providerName))).Any(); //if (knownAssemblyFolders.Contains(Path.GetDirectoryName(providerName))) { if (exist) { //If so, load it. var loaded = LoadProviderAssembly(request, providerName); if (loaded) { request.Verbose("loaded successfully"); //TODO not need to be so sily, reference to the key of master list is enough yield return _packageProviders[Path.GetFileNameWithoutExtension(providerName)]; //return SelectProviders(Path.GetFileNameWithoutExtension(providerName), request); } request.Warning(string.Format("cannot load assembly '{0}'. you need to add your assembly here...", providerName)); yield return null; } else { request.Warning(string.Format("The specified provider '{0}' was not loaded because no valid provider file was found", providerName)); } } //deal with modules with full path var powerShellMetaProvider = GetMetaProviderObject(request); if (powerShellMetaProvider == null) { yield return null; } //load the proviver //TODO firstordefault yield return ImportProvider(request, providerName, powerShellMetaProvider); }
//TODO Name, Version,.... public IEnumerable<PackageProvider> ImportPackageProvider(IHostApi request, string providerName, bool isPathRooted) { if (providerName.IsNullOrEmpty()) { return Enumerable.Empty<PackageProvider>(); } //foreach (var name in providerNames) { //check if it;s loaded. var results = _packageProviders.Values.Where(each => each.ProviderName.IsWildcardMatch(providerName)).ReEnumerable(); if (results.Any()) { //the provider is already loaded and tracked in the loaded master list: _packageProviders request.Verbose(string.Format("The provider '{0}' has already been imported.", providerName)); return Enumerable.Empty<PackageProvider>(); } if (isPathRooted) { if (File.Exists(providerName)) { // looks like we have something that could definitely be a // a module path. //yield return new KeyValuePair<string, string>(fullPath, (moduleVersion ?? new Version(0, 0)).ToString()); return ImportPackageProviderViaPath(request, providerName); } else { //error out request.Warning(String.Format("{0} is not found", providerName)); } } else { return ImportPackageProviderViaName(request, providerName); } // return providerNames.SelectMany(each => ImportPackageProvider(request, each)); // } return Enumerable.Empty<PackageProvider>(); }
//Scan through the well-known providerAssemblies folder to find the providers that met the condition. internal IEnumerable<string> ScanAllProvidersFromProviderAssembliesLocation( IHostApi request, string providerName, Version requiredVersion, Version minimumVersion, Version maximumVersion, ProviderOption providerOption = ProviderOption.LatestVersion) { //if provider is installed in providername\version format var providerFolder = ProviderAssembliesLocation.Distinct(new PathEqualityComparer(PathCompareOption.Full)).SelectMany(Directory.EnumerateDirectories); foreach (var providerNameFolder in providerFolder) { var name = Path.GetFileName(providerNameFolder); //check the providername folder if (!string.IsNullOrWhiteSpace(providerName)) { if (string.IsNullOrWhiteSpace(providerNameFolder)) { continue; } if (string.IsNullOrWhiteSpace(name) || !name.IsWildcardMatch(providerName)) { continue; } } var selectedVersions = Directory.EnumerateDirectories(providerNameFolder).Select(versionFolder => { //check if the version is in a valid format. Ver will be 0 if TryParse fails and it won't be selected Version ver; if (System.Version.TryParse(Path.GetFileName(versionFolder), out ver)) { return new { folder = versionFolder, version = (FourPartVersion)ver }; } return null; }).Where(each => each != null && each.version > 0L); selectedVersions = selectedVersions.Where(eachVersion => { if ((requiredVersion == null) || eachVersion.version == (FourPartVersion)requiredVersion) { if ((minimumVersion == null) || eachVersion.version >= (FourPartVersion)minimumVersion) { if ((maximumVersion == null) || eachVersion.version <= (FourPartVersion)maximumVersion) { return true; } } } return false; }); //Get the version folders var versionFolders = (providerOption == ProviderOption.AllProvider) ? selectedVersions.Select(each => each.folder).Where(Directory.Exists) : new[] {selectedVersions.OrderByDescending(each => each.version).Select(each => each.folder).FirstOrDefault(Directory.Exists)}; foreach (var assemblyFolder in versionFolders.WhereNotNull()) { //we reached the provider assembly file path now var files = Directory.EnumerateFiles(assemblyFolder) .Where(file => (file != null) && (Path.GetExtension(file).EqualsIgnoreCase(".dll") || Path.GetExtension(file).EqualsIgnoreCase(".exe"))).ToArray(); //if found more than one dll is installed under a version folder, this is not allowed. warning here as enumerating for providers should continue if (files.Any() && files.Count() > 1) { request.Warning(string.Format(CultureInfo.CurrentCulture, Resources.Messages.SingleAssemblyAllowed, files.JoinWithComma())); continue; } // find modules that have the provider manifests var filelist = files.Where(each => Manifest.LoadFrom(each).Any(manifest => Swidtag.IsSwidtag(manifest) && new Swidtag(manifest).IsApplicable(new Hashtable()))); if (!filelist.Any()) { continue; } var version = Path.GetFileName(assemblyFolder); var defaultPkgProvider = new DefaultPackageProvider(name, version); var providerPath = files.FirstOrDefault(); var pkgProvider = new PackageProvider(defaultPkgProvider) { ProviderPath = providerPath, Version = version, IsLoaded = false }; AddToProviderCacheTable(name, pkgProvider); yield return providerPath; } } //check if assembly is installed at the top leverl folder. var providerFiles = ProviderAssembliesLocation.Distinct(new PathEqualityComparer(PathCompareOption.Full)).SelectMany(Directory.EnumerateFiles) .Where(each => each.FileExists() && (Path.GetExtension(each).EqualsIgnoreCase(".dll") || Path.GetExtension(each).EqualsIgnoreCase(".exe"))).ReEnumerable(); // found the assemblies at the top level folder. // if a user is looking for a specific version & provider name, we are not be able to know the provider name or version without loading it. // Thus, for the top level providers, we just need to load them for the backward compatibility. if (providerFiles.Any()) { request.Verbose(string.Format(CultureInfo.CurrentCulture, Resources.Messages.ProviderNameAndVersionNotAvailableFromFilePath, providerFiles.JoinWithComma())); foreach (var provider in providerFiles) { //the provider is installed at the top level. // find modules that have the provider manifests if (Manifest.LoadFrom(provider).Any(manifest => Swidtag.IsSwidtag(manifest) && new Swidtag(manifest).IsApplicable(new Hashtable()))) { yield return provider; } } } }
private IMetaProvider GetMetaProviderObject(IHostApi request) { //retrieve the powershell metaprovider object if (_metaProviders.ContainsKey("PowerShell")) { var powerShellMetaProvider = _metaProviders["PowerShell"]; if (powerShellMetaProvider != null) { return powerShellMetaProvider; } } request.Verbose(string.Format(CultureInfo.CurrentCulture, Resources.Messages.FailedPowerShellMetaProvider)); return null; }
private IEnumerable<PackageProvider> FindMatchedProvidersFromInternalCacheTable( IHostApi request, string providerName, Version requiredVersion, Version minimumVersion, Version maximumVersion, bool force) { //Search from the internal table to see if we can the matched provider //check if the provider name matches var providersTable = _providerCacheTable.Where(each => each.Key.IsWildcardMatch(providerName)) .Select(each => each.Value).ToArray(); //check if version matches var providers = providersTable.Select(list => list.Where(each => { bool foundMatch = true; if (requiredVersion != null) { return each.Version.Equals(requiredVersion); } if (minimumVersion != null) { foundMatch = each.Version >= (FourPartVersion)minimumVersion; } if (maximumVersion != null) { foundMatch |= each.Version <= (FourPartVersion)maximumVersion; } return foundMatch; }).Select(each => each)).ToArray(); var selectedProviders = providers.Select(each => each.OrderByDescending(p => p.Version).FirstOrDefault()).WhereNotNull(); foreach (var instance in selectedProviders) { if (instance.IsLoaded) { //Initialize the provider instance.Initialize(request); //Add it to the provider list that all imported and in use _packageProviders.AddOrSet(instance.ProviderName, instance); request.Verbose(string.Format(Resources.Messages.ImportPackageProvider, instance.ProviderName)); yield return instance; } else { if (Path.GetExtension(instance.ProviderPath).EqualsIgnoreCase(".psm1")) { //it's a powershell provider var psProviders = ImportPowerShellProvider(request, instance.ProviderPath, instance.Version, shouldRefreshCache: force); foreach (var p in psProviders) { yield return p; } } else { LoadProviderAssembly(request, instance.ProviderPath, shouldRefreshCache: force); var foo = _packageProviders.Where(each => each.Key.IsWildcardMatch(providerName)); foreach (var p in foo) { yield return p.Value; } } } } }
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> /// 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; }
/// <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; }
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>(); }