private void DoManualGetChildItems(CmdletProvider providerInstance, string path, bool recurse, CmdletProviderContext context, bool skipIsItemContainerCheck = false) { Collection<WildcardPattern> patterns = SessionStateUtilities.CreateWildcardsFromStrings(context.Include, WildcardOptions.IgnoreCase); Collection<WildcardPattern> collection2 = SessionStateUtilities.CreateWildcardsFromStrings(context.Exclude, WildcardOptions.IgnoreCase); if (skipIsItemContainerCheck || this.IsItemContainer(providerInstance, path, context)) { CmdletProviderContext context2 = new CmdletProviderContext(context); Collection<PSObject> accumulatedObjects = null; Dictionary<string, bool> dictionary = null; try { this.GetChildNames(providerInstance, path, recurse ? ReturnContainers.ReturnAllContainers : ReturnContainers.ReturnMatchingContainers, context2); context2.WriteErrorsToContext(context); accumulatedObjects = context2.GetAccumulatedObjects(); if (recurse && providerInstance.IsFilterSet()) { context2.RemoveStopReferral(); context2 = new CmdletProviderContext(context); Collection<PSObject> collection4 = new Collection<PSObject>(); dictionary = new Dictionary<string, bool>(); this.GetChildNames(providerInstance, path, ReturnContainers.ReturnMatchingContainers, context2); foreach (PSObject obj2 in context2.GetAccumulatedObjects()) { string baseObject = obj2.BaseObject as string; if (baseObject != null) { dictionary[baseObject] = true; } } } } finally { context2.RemoveStopReferral(); } for (int i = 0; i < accumulatedObjects.Count; i++) { if (context.Stopping) { return; } string child = accumulatedObjects[i].BaseObject as string; if (child != null) { string str3 = this.MakePath(providerInstance, path, child, context); if (str3 != null) { if (SessionStateUtilities.MatchesAnyWildcardPattern(child, patterns, true) && !SessionStateUtilities.MatchesAnyWildcardPattern(child, collection2, false)) { bool flag2 = true; if (dictionary != null) { bool flag3 = false; flag2 = dictionary.TryGetValue(child, out flag3); } if (flag2) { this.GetItemPrivate(providerInstance, str3, context); } } if (this.IsItemContainer(providerInstance, str3, context) && recurse) { if (context.Stopping) { return; } this.DoManualGetChildItems(providerInstance, str3, recurse, context, true); } } } } } else { string text = path; text = this.GetChildName(providerInstance, path, context, true); if (SessionStateUtilities.MatchesAnyWildcardPattern(text, patterns, true) && !SessionStateUtilities.MatchesAnyWildcardPattern(text, collection2, false)) { this.GetItemPrivate(providerInstance, path, context); } } }
} // GetChildItems /// <summary> /// Since we can't do include and exclude filtering on items we have to /// do the recursion ourselves. We get each child name and see if it matches /// the include and exclude filters. If the child is a container we recurse /// into that container. /// </summary> /// /// <param name="providerInstance"> /// The instance of the provider to use. /// </param> /// /// <param name="path"> /// The path to the item to get the children from. /// </param> /// /// <param name="recurse"> /// Recurse into sub-containers when getting children. /// </param> /// /// <param name="context"> /// The context under which the command is running. /// </param> /// /// <param name="childrenNotMatchingFilterCriteria"> /// The count of items that do not match any include/exclude criteria. /// </param> /// /// <param name="processMode">Indicates if this is a Enumerate/Remove operation</param> /// /// <param name="skipIsItemContainerCheck">a hint used to skip IsItemContainer checks</param> /// /// <exception cref="ProviderNotFoundException"> /// If the <paramref name="path"/> refers to a provider that could not be found. /// </exception> /// /// <exception cref="DriveNotFoundException"> /// If the <paramref name="path"/> refers to a drive that could not be found. /// </exception> /// /// <exception cref="NotSupportedException"> /// If the provider that the <paramref name="path"/> refers to does /// not support this operation. /// </exception> /// /// <exception cref="ProviderInvocationException"> /// If the provider threw an exception. /// </exception> /// private void ProcessPathItems( CmdletProvider providerInstance, string path, bool recurse, CmdletProviderContext context, out int childrenNotMatchingFilterCriteria, ProcessMode processMode = ProcessMode.Enumerate, bool skipIsItemContainerCheck = false) { ContainerCmdletProvider containerCmdletProvider = GetContainerProviderInstance(providerInstance); childrenNotMatchingFilterCriteria = 0; Dbg.Diagnostics.Assert( providerInstance != null, "The caller should have verified the providerInstance"); Dbg.Diagnostics.Assert( path != null, "The caller should have verified the path"); Dbg.Diagnostics.Assert( context != null, "The caller should have verified the context"); // Construct the include filter Collection<WildcardPattern> includeMatcher = SessionStateUtilities.CreateWildcardsFromStrings( context.Include, WildcardOptions.IgnoreCase); // Construct the exclude filter Collection<WildcardPattern> excludeMatcher = SessionStateUtilities.CreateWildcardsFromStrings( context.Exclude, WildcardOptions.IgnoreCase); // If the item is a container we have to filter its children // Use a hint + lazy evaluation to skip a container check if (skipIsItemContainerCheck || IsItemContainer(providerInstance, path, context)) { CmdletProviderContext newContext = new CmdletProviderContext(context); Collection<PSObject> childNameObjects = null; System.Collections.Generic.Dictionary<string, bool> filteredChildNameDictionary = null; try { // Get all the child names GetChildNames( providerInstance, path, (recurse) ? ReturnContainers.ReturnAllContainers : ReturnContainers.ReturnMatchingContainers, newContext); newContext.WriteErrorsToContext(context); childNameObjects = newContext.GetAccumulatedObjects(); // The code above initially retrieves all of the containers so that it doesn't limit the recursion, // but then emits the non-matching container further down. The public API doesn't support a way to // differentiate the two, so we need to do a diff. // So if there was a filter, do it again to get the fully filtered items. if (recurse && (providerInstance.IsFilterSet())) { newContext.RemoveStopReferral(); newContext = new CmdletProviderContext(context); filteredChildNameDictionary = new System.Collections.Generic.Dictionary<string, bool>(); GetChildNames( providerInstance, path, ReturnContainers.ReturnMatchingContainers, newContext); var filteredChildNameObjects = newContext.GetAccumulatedObjects(); foreach (PSObject filteredChildName in filteredChildNameObjects) { string filteredName = filteredChildName.BaseObject as string; if (filteredName != null) { filteredChildNameDictionary[filteredName] = true; } } } } finally { newContext.RemoveStopReferral(); } // Now loop through all the child objects matching the filters and recursing // into containers for (int index = 0; index < childNameObjects.Count; ++index) { // Making sure to obey the StopProcessing. if (context.Stopping) { return; } string childName = childNameObjects[index].BaseObject as string; if (childName == null) { continue; } // Generate the provider path for the child string qualifiedPath = MakePath(providerInstance, path, childName, context); if (qualifiedPath == null) { continue; } bool isIncludeMatch = !context.SuppressWildcardExpansion && SessionStateUtilities.MatchesAnyWildcardPattern( childName, includeMatcher, true); if (isIncludeMatch) { if (!SessionStateUtilities.MatchesAnyWildcardPattern( childName, excludeMatcher, false)) { bool emitItem = true; if (filteredChildNameDictionary != null) { bool isChildNameInDictionary = false; emitItem = filteredChildNameDictionary.TryGetValue(childName, out isChildNameInDictionary); } if (emitItem) { if (processMode == ProcessMode.Delete) { containerCmdletProvider.RemoveItem(qualifiedPath, false, context); } else if (processMode != ProcessMode.Delete) { // The object is a match so get it and write it out. GetItemPrivate(providerInstance, qualifiedPath, context); } } } else { childrenNotMatchingFilterCriteria++; } } else { childrenNotMatchingFilterCriteria++; } // Now recurse if it is a container if (recurse && IsItemContainer(providerInstance, qualifiedPath, context)) { // Making sure to obey the StopProcessing. if (context.Stopping) { return; } // The item is a container so recurse into it. ProcessPathItems(providerInstance, qualifiedPath, recurse, context, out childrenNotMatchingFilterCriteria, processMode, skipIsItemContainerCheck: true); } } // for each childName } else { // The path is not a container so write it out if its name // matches the filter string childName = path; childName = GetChildName(providerInstance, path, context, true); // Write out the object if it is a match bool isIncludeMatch = SessionStateUtilities.MatchesAnyWildcardPattern( childName, includeMatcher, true); if (isIncludeMatch) { if (!SessionStateUtilities.MatchesAnyWildcardPattern( childName, excludeMatcher, false)) { if (processMode != ProcessMode.Delete) { // The object is a match so get it and write it out. GetItemPrivate(providerInstance, path, context); } else { // The object is a match so, remove it. containerCmdletProvider.RemoveItem(path, recurse, context); } } } } } // ProcessPathItems