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>());
        }
Beispiel #2
0
 public bool Verbose(string messageText)
 {
     if (CanCallHost)
     {
         return(_hostApi.Verbose(GetMessageString(messageText, null) ?? messageText));
     }
     return(true);
 }
Beispiel #3
0
 public bool Verbose(string messageText)
 {
     if (CanCallHost)
     {
         return(_hostApi.Verbose(messageText));
     }
     return(true);
 }
Beispiel #4
0
 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>();
        }