Exemplo n.º 1
0
        //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 PORTABLE
            return Enumerable.Empty<string>();
#else
            //We don't need to scan provider assemblies on corepowershell.

            //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"))
                                        // we only check for dll that has manifest attached to it. (In case there are supporting assemblies in this folder)
                                        && Manifest.LoadFrom(file).Any(manifest => Swidtag.IsSwidtag(manifest) && new Swidtag(manifest).IsApplicable(new Hashtable())))
                        .ToArray();

                    //if found more than one dll with manifest 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
                    };

                    pkgProvider.SetSwidTag(providerPath);

                    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;
                    }
                }
            }
#endif
        }