Files
PowerShell-PowerShell/src/System.Management.Automation/engine/SessionStateContainer.cs
T

4937 lines
190 KiB
C#

// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
using System.Collections;
using System.Collections.ObjectModel;
using System.IO;
using System.Management.Automation.Internal;
using System.Management.Automation.Provider;
using System.Management.Automation.Runspaces;
using System.Reflection;
using Dbg = System.Management.Automation;
#pragma warning disable 1634, 1691 // Stops compiler from warning about unknown warnings
#pragma warning disable 56500
namespace System.Management.Automation
{
/// <summary>
/// Holds the state of a Monad Shell session.
/// </summary>
internal sealed partial class SessionStateInternal
{
#region ContainerCmdletProvider accessors
#region ItemExists
/// <summary>
/// Determines if the monad virtual namespace path exists.
/// </summary>
/// <param name="path">
/// The path to the object to determine if it exists.
/// </param>
/// <param name="force">
/// Passed on to providers to force operations.
/// </param>
/// <param name="literalPath">
/// If true, globbing is not done on paths.
/// </param>
/// <returns>
/// true if the object specified by path exists, false otherwise.
/// </returns>
/// <exception cref="ArgumentNullException">
/// If <paramref name="path"/> is null.
/// </exception>
/// <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>
internal bool ItemExists(string path, bool force, bool literalPath)
{
if (path == null)
{
throw PSTraceSource.NewArgumentNullException(nameof(path));
}
CmdletProviderContext context = new CmdletProviderContext(this.ExecutionContext);
context.Force = force;
context.SuppressWildcardExpansion = literalPath;
bool result = ItemExists(path, context);
context.ThrowFirstErrorOrDoNothing();
return result;
}
/// <summary>
/// Determines if the monad virtual namespace path exists.
/// </summary>
/// <param name="path">
/// The path to the object to determine if it exists.
/// </param>
/// <param name="context">
/// The context which the core command is running.
/// </param>
/// <returns>
/// true if the object specified by path exists, false otherwise.
/// </returns>
/// <exception cref="ArgumentNullException">
/// If <paramref name="path"/> is null.
/// </exception>
/// <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>
internal bool ItemExists(
string path,
CmdletProviderContext context)
{
if (path == null)
{
throw PSTraceSource.NewArgumentNullException(nameof(path));
}
ProviderInfo provider = null;
CmdletProvider providerInstance = null;
bool result = false;
try
{
Collection<string> providerPaths =
Globber.GetGlobbedProviderPathsFromMonadPath(
path,
true,
context,
out provider,
out providerInstance);
foreach (string providerPath in providerPaths)
{
result = ItemExists(providerInstance, providerPath, context);
if (result)
{
break;
}
}
}
catch (ItemNotFoundException)
{
result = false;
}
return result;
}
/// <summary>
/// Determines if the item at the specified path exists.
/// </summary>
/// <param name="providerInstance">
/// The provider instance to use.
/// </param>
/// <param name="path">
/// The path to the item if it was specified on the command line.
/// </param>
/// <param name="context">
/// The context which the core command is running.
/// </param>
/// <exception cref="NotSupportedException">
/// If the <paramref name="providerInstance"/> does not support this operation.
/// </exception>
/// <exception cref="PipelineStoppedException">
/// If the pipeline is being stopped while executing the command.
/// </exception>
/// <exception cref="ProviderInvocationException">
/// If the provider threw an exception.
/// </exception>
internal bool ItemExists(
CmdletProvider providerInstance,
string path,
CmdletProviderContext context)
{
// All parameters should have been validated by caller
Dbg.Diagnostics.Assert(
providerInstance != null,
"Caller should validate providerId before calling this method");
Dbg.Diagnostics.Assert(
path != null,
"Caller should validate path before calling this method");
Dbg.Diagnostics.Assert(
context != null,
"Caller should validate context before calling this method");
ItemCmdletProvider itemCmdletProvider =
GetItemProviderInstance(providerInstance);
bool result = false;
try
{
result = itemCmdletProvider.ItemExists(path, context);
}
catch (LoopFlowException)
{
throw;
}
catch (PipelineStoppedException)
{
throw;
}
catch (ActionPreferenceStopException)
{
throw;
}
catch (Exception e) // Catch-all OK, 3rd party callout.
{
throw NewProviderInvocationException(
"ItemExistsProviderException",
SessionStateStrings.ItemExistsProviderException,
itemCmdletProvider.ProviderInfo,
path,
e);
}
return result;
}
/// <summary>
/// Gets the dynamic parameters for the test-path cmdlet.
/// </summary>
/// <param name="path">
/// The path to the item if it was specified on the command line.
/// </param>
/// <param name="context">
/// The context which the core command is running.
/// </param>
/// <returns>
/// An object that has properties and fields decorated with
/// parsing attributes similar to a cmdlet class.
/// </returns>
/// <exception cref="ArgumentNullException">
/// If <paramref name="path"/> is null.
/// </exception>
/// <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>
/// <exception cref="ItemNotFoundException">
/// If <paramref name="path"/> does not contain glob characters and
/// could not be found.
/// </exception>
internal object ItemExistsDynamicParameters(string path, CmdletProviderContext context)
{
if (path == null)
{
throw PSTraceSource.NewArgumentNullException(nameof(path));
}
ProviderInfo provider = null;
CmdletProvider providerInstance = null;
CmdletProviderContext newContext =
new CmdletProviderContext(context);
newContext.SetFilters(
new Collection<string>(),
new Collection<string>(),
null);
Collection<string> providerPaths =
Globber.GetGlobbedProviderPathsFromMonadPath(
path,
true,
newContext,
out provider,
out providerInstance);
if (providerPaths.Count > 0)
{
// Get the dynamic parameters for the first resolved path
return ItemExistsDynamicParameters(providerInstance, providerPaths[0], newContext);
}
return null;
}
/// <summary>
/// Gets the dynamic parameters for the test-path cmdlet.
/// </summary>
/// <param name="path">
/// The path to the item if it was specified on the command line.
/// </param>
/// <param name="providerInstance">
/// The instance of the provider to use.
/// </param>
/// <param name="context">
/// The context which the core command is running.
/// </param>
/// <returns>
/// An object that has properties and fields decorated with
/// parsing attributes similar to a cmdlet class.
/// </returns>
/// <exception cref="NotSupportedException">
/// If the <paramref name="providerInstance"/> does not support this operation.
/// </exception>
/// <exception cref="PipelineStoppedException">
/// If the pipeline is being stopped while executing the command.
/// </exception>
/// <exception cref="ProviderInvocationException">
/// If the provider threw an exception.
/// </exception>
private object ItemExistsDynamicParameters(
CmdletProvider providerInstance,
string path,
CmdletProviderContext context)
{
// All parameters should have been validated by caller
Dbg.Diagnostics.Assert(
providerInstance != null,
"Caller should validate providerInstance before calling this method");
Dbg.Diagnostics.Assert(
path != null,
"Caller should validate path before calling this method");
Dbg.Diagnostics.Assert(
context != null,
"Caller should validate context before calling this method");
ContainerCmdletProvider containerCmdletProvider =
GetContainerProviderInstance(providerInstance);
object result = null;
try
{
result = containerCmdletProvider.ItemExistsDynamicParameters(path, context);
}
catch (LoopFlowException)
{
throw;
}
catch (PipelineStoppedException)
{
throw;
}
catch (ActionPreferenceStopException)
{
throw;
}
catch (Exception e) // Catch-all OK, 3rd party callout.
{
throw NewProviderInvocationException(
"ItemExistsDynamicParametersProviderException",
SessionStateStrings.ItemExistsDynamicParametersProviderException,
containerCmdletProvider.ProviderInfo,
path,
e);
}
return result;
}
#endregion Exists
#region IsValidPath
/// <summary>
/// Determines if the MSH path is a syntactically and semantically valid path for the provider.
/// </summary>
/// <param name="path">
/// The path to validate.
/// </param>
/// <returns>
/// true if the object specified by path is syntactically and semantically valid, false otherwise.
/// </returns>
/// <exception cref="ArgumentNullException">
/// If <paramref name="path"/> is null.
/// </exception>
/// <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>
internal bool IsValidPath(string path)
{
if (path == null)
{
throw PSTraceSource.NewArgumentNullException(nameof(path));
}
CmdletProviderContext context = new CmdletProviderContext(this.ExecutionContext);
bool result = IsValidPath(path, context);
context.ThrowFirstErrorOrDoNothing();
return result;
}
/// <summary>
/// Determines if the MSH path is a syntactically and semantically valid path for the provider.
/// </summary>
/// <param name="path">
/// The path to validate.
/// </param>
/// <param name="context">
/// The context which the core command is running.
/// </param>
/// <returns>
/// true if the object specified by path is syntactically and semantically valid, false otherwise.
/// </returns>
/// <exception cref="ArgumentNullException">
/// If <paramref name="path"/> is null.
/// </exception>
/// <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>
internal bool IsValidPath(
string path,
CmdletProviderContext context)
{
if (path == null)
{
throw PSTraceSource.NewArgumentNullException(nameof(path));
}
ProviderInfo provider = null;
PSDriveInfo driveInfo = null;
string providerPath =
Globber.GetProviderPath(
path,
context,
out provider,
out driveInfo);
ItemCmdletProvider providerInstance = GetItemProviderInstance(provider);
return IsValidPath(providerInstance, providerPath, context);
}
/// <summary>
/// Determines if the specified path is valid.
/// </summary>
/// <param name="providerInstance">
/// The provider instance to use.
/// </param>
/// <param name="path">
/// The path to the item if it was specified on the command line.
/// </param>
/// <param name="context">
/// The context which the core command is running.
/// </param>
/// <exception cref="NotSupportedException">
/// If the <paramref name="providerInstance"/> does not support this operation.
/// </exception>
/// <exception cref="PipelineStoppedException">
/// If the pipeline is being stopped while executing the command.
/// </exception>
/// <exception cref="ProviderInvocationException">
/// If the provider threw an exception.
/// </exception>
private bool IsValidPath(
CmdletProvider providerInstance,
string path,
CmdletProviderContext context)
{
// All parameters should have been validated by caller
Dbg.Diagnostics.Assert(
providerInstance != null,
"Caller should validate providerInstance before calling this method");
Dbg.Diagnostics.Assert(
path != null,
"Caller should validate path before calling this method");
Dbg.Diagnostics.Assert(
context != null,
"Caller should validate context before calling this method");
ItemCmdletProvider itemCmdletProvider =
GetItemProviderInstance(providerInstance);
bool result = false;
try
{
result = itemCmdletProvider.IsValidPath(path, context);
}
catch (LoopFlowException)
{
throw;
}
catch (PipelineStoppedException)
{
throw;
}
catch (ActionPreferenceStopException)
{
throw;
}
catch (Exception e) // Catch-all OK, 3rd party callout.
{
throw NewProviderInvocationException(
"IsValidPathProviderException",
SessionStateStrings.IsValidPathProviderException,
itemCmdletProvider.ProviderInfo,
path,
e);
}
return result;
}
#endregion IsValidPath
#region IsItemContainer
/// <summary>
/// Determines if the monad virtual namespace path is a container.
/// </summary>
/// <param name="path">
/// The path to the object to determine if it is a container.
/// </param>
/// <returns>
/// true if the object specified by path is a container, false otherwise.
/// </returns>
/// <exception cref="ArgumentNullException">
/// If <paramref name="path"/> is null.
/// </exception>
/// <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>
internal bool IsItemContainer(string path)
{
if (path == null)
{
throw PSTraceSource.NewArgumentNullException(nameof(path));
}
CmdletProviderContext context = new CmdletProviderContext(this.ExecutionContext);
bool result = IsItemContainer(path, context);
context.ThrowFirstErrorOrDoNothing();
return result;
}
/// <summary>
/// Determines if the monad virtual namespace path is a container.
/// </summary>
/// <param name="path">
/// The path to the object to determine if it is a container.
/// </param>
/// <param name="context">
/// The context which the core command is running.
/// </param>
/// <returns>
/// true if the object specified by path is a container, false otherwise.
/// </returns>
/// <exception cref="ArgumentNullException">
/// If <paramref name="path"/> is null.
/// </exception>
/// <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>
internal bool IsItemContainer(
string path,
CmdletProviderContext context)
{
if (path == null)
{
throw PSTraceSource.NewArgumentNullException(nameof(path));
}
ProviderInfo provider = null;
CmdletProvider providerInstance = null;
bool result = false;
try
{
Collection<string> providerPaths =
Globber.GetGlobbedProviderPathsFromMonadPath(
path,
true,
context,
out provider,
out providerInstance);
foreach (string providerPath in providerPaths)
{
result = IsItemContainer(providerInstance, providerPath, context);
if (!result)
{
break;
}
}
}
catch (ItemNotFoundException)
{
result = false;
}
return result;
}
/// <summary>
/// Determines if the item at the specified path is a container.
/// </summary>
/// <param name="providerInstance">
/// The provider instance to use.
/// </param>
/// <param name="path">
/// The path to the item if it was specified on the command line.
/// </param>
/// <param name="context">
/// The context which the core command is running.
/// </param>
/// <exception cref="NotSupportedException">
/// If the <paramref name="providerInstance"/> does not support this operation.
/// </exception>
/// <exception cref="PipelineStoppedException">
/// If the pipeline is being stopped while executing the command.
/// </exception>
/// <exception cref="ProviderInvocationException">
/// If the provider threw an exception.
/// </exception>
private bool IsItemContainer(
CmdletProvider providerInstance,
string path,
CmdletProviderContext context)
{
// All parameters should have been validated by caller
Dbg.Diagnostics.Assert(
providerInstance != null,
"Caller should validate providerInstance before calling this method");
Dbg.Diagnostics.Assert(
path != null,
"Caller should validate path before calling this method");
Dbg.Diagnostics.Assert(
context != null,
"Caller should validate context before calling this method");
bool result = false;
NavigationCmdletProvider navigationCmdletProvider = null;
try
{
// If it is a NavigationProvider instance then we
// can ask the provider if the path is to a container.
navigationCmdletProvider =
GetNavigationProviderInstance(providerInstance, false);
try
{
result = navigationCmdletProvider.IsItemContainer(path, context);
}
catch (LoopFlowException)
{
throw;
}
catch (PipelineStoppedException)
{
throw;
}
catch (ActionPreferenceStopException)
{
throw;
}
catch (Exception e) // Catch-all OK, 3rd party callout.
{
throw NewProviderInvocationException(
"IsItemContainerProviderException",
SessionStateStrings.IsItemContainerProviderException,
navigationCmdletProvider.ProviderInfo,
path,
e);
}
}
catch (NotSupportedException)
{
try
{
// If it is a ContainerProvider instance then the
// root (empty path) is considered a container
// but everything else is not.
GetContainerProviderInstance(providerInstance);
if (path.Length == 0)
{
result = true;
}
else
{
result = false;
}
}
catch (NotSupportedException)
{
// If the provider is neither a NavigationProvider nor a
// ContainerProvider then the path cannot be a container
result = false;
}
}
return result;
}
#endregion IsItemContainer
#region RemoveItem
/// <summary>
/// Deletes the specified object.
/// </summary>
/// <param name="paths">
/// A relative or absolute path to the object to be deleted.
/// </param>
/// <param name="recurse">
/// The delete should occur in all sub-containers of the specified path.
/// </param>
/// <param name="force">
/// Passed on to providers to force operations.
/// </param>
/// <param name="literalPath">
/// If true, globbing is not done on paths.
/// </param>
/// <exception cref="ArgumentNullException">
/// If <paramref name="path"/> is null.
/// </exception>
/// <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>
internal void RemoveItem(string[] paths, bool recurse, bool force, bool literalPath)
{
if (paths == null)
{
throw PSTraceSource.NewArgumentNullException(nameof(paths));
}
CmdletProviderContext context = new CmdletProviderContext(this.ExecutionContext);
context.Force = force;
context.SuppressWildcardExpansion = literalPath;
RemoveItem(paths, recurse, context);
context.ThrowFirstErrorOrDoNothing();
}
/// <summary>
/// Deletes the specified object.
/// </summary>
/// <param name="paths">
/// A relative or absolute path to the object to be deleted.
/// </param>
/// <param name="recurse">
/// The delete should occur in all sub-containers of the specified path.
/// </param>
/// <param name="context">
/// The context which the core command is running.
/// </param>
/// <exception cref="ArgumentNullException">
/// If <paramref name="path"/> is null.
/// </exception>
/// <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>
/// <exception cref="ItemNotFoundException">
/// If <paramref name="path"/> does not contain glob characters and
/// could not be found.
/// </exception>
internal void RemoveItem(
string[] paths,
bool recurse,
CmdletProviderContext context)
{
if (paths == null)
{
throw PSTraceSource.NewArgumentNullException(nameof(paths));
}
foreach (string path in paths)
{
if (path == null)
{
throw PSTraceSource.NewArgumentNullException(nameof(paths));
}
ProviderInfo provider = null;
CmdletProvider providerInstance = null;
Collection<string> providerPaths =
Globber.GetGlobbedProviderPathsFromMonadPath(
path,
false,
context,
out provider,
out providerInstance);
foreach (string providerPath in providerPaths)
{
RemoveItem(providerInstance, providerPath, recurse, context);
}
}
}
/// <summary>
/// Internal remove item method that just calls the provider directly without globbing.
/// </summary>
/// <param name="providerId">
/// The name of the provider to use.
/// </param>
/// <param name="path">
/// The path of the item to remove.
/// </param>
/// <param name="recurse">
/// True if all items should be removed recursively.
/// </param>
/// <param name="context">
/// The context under which the command is running.
/// </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>
internal void RemoveItem(
string providerId,
string path,
bool recurse,
CmdletProviderContext context)
{
// All parameters should have been validated by caller
Dbg.Diagnostics.Assert(
providerId != null,
"Caller should validate providerId before calling this method");
Dbg.Diagnostics.Assert(
path != null,
"Caller should validate path before calling this method");
Dbg.Diagnostics.Assert(
context != null,
"Caller should validate context before calling this method");
CmdletProvider providerInstance = GetProviderInstance(providerId);
RemoveItem(providerInstance, path, recurse, context);
}
/// <summary>
/// Internal remove item method that just calls the provider directly without globbing.
/// </summary>
/// <param name="providerInstance">
/// The instance of the provider to use.
/// </param>
/// <param name="path">
/// The path of the item to remove.
/// </param>
/// <param name="recurse">
/// True if all items should be removed recursively.
/// </param>
/// <param name="context">
/// The context under which the command is running.
/// </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>
internal void RemoveItem(
CmdletProvider providerInstance,
string path,
bool recurse,
CmdletProviderContext context)
{
// All parameters should have been validated by caller
Dbg.Diagnostics.Assert(
providerInstance != null,
"Caller should validate providerInstance before calling this method");
Dbg.Diagnostics.Assert(
path != null,
"Caller should validate path before calling this method");
Dbg.Diagnostics.Assert(
context != null,
"Caller should validate context before calling this method");
ContainerCmdletProvider containerCmdletProvider =
GetContainerProviderInstance(providerInstance);
try
{
if (context.HasIncludeOrExclude)
{
int childrenNotMatchingFilterCriteria = 0;
// Use the new code path only if either Include or Exclude is specified
// This will take care of all the child items.
// This will also take care of the case where "path" is not a container.
ProcessPathItems(providerInstance, path, recurse, context, out childrenNotMatchingFilterCriteria, ProcessMode.Delete, skipIsItemContainerCheck: false);
// Now delete the container if it matches the filter(s)
// and the container does not have any children.
if (IsItemContainer(providerInstance, path, context))
{
string item = GetChildName(path, context, false);
bool isIncludeMatch =
SessionStateUtilities.MatchesAnyWildcardPattern(
item,
SessionStateUtilities.CreateWildcardsFromStrings(
context.Include, WildcardOptions.IgnoreCase),
true);
if (isIncludeMatch)
{
if (!SessionStateUtilities.MatchesAnyWildcardPattern(
item,
SessionStateUtilities.CreateWildcardsFromStrings(
context.Exclude, WildcardOptions.IgnoreCase),
false))
{
// Earlier, we used to check if "path" has any child items remaining. If not, we remove "path".
// This does not work for some providers (for e.g. IIS provider) which do not support removing the child items
// So, instead of checking for any child items remaining (which are applicable to only those providers which support them - like File, Registry),
// we check if there are any items that were never intended to be deleted. If there are no such items, then, we can remove "path".
// WinBlue: 289907
if (childrenNotMatchingFilterCriteria == 0)
{
containerCmdletProvider.RemoveItem(path, false, context);
}
}
}
}
}
else
{
containerCmdletProvider.RemoveItem(path, recurse, context);
}
}
catch (LoopFlowException)
{
throw;
}
catch (PipelineStoppedException)
{
throw;
}
catch (ActionPreferenceStopException)
{
throw;
}
catch (Exception e) // Catch-all OK, 3rd party callout.
{
throw NewProviderInvocationException(
"RemoveItemProviderException",
SessionStateStrings.RemoveItemProviderException,
containerCmdletProvider.ProviderInfo,
path,
e);
}
}
/// <summary>
/// Gets the dynamic parameters for the remove-item cmdlet.
/// </summary>
/// <param name="path">
/// The path to the item if it was specified on the command line.
/// </param>
/// <param name="recurse">
/// The delete should occur in all sub-containers of the specified path.
/// </param>
/// <param name="context">
/// The context which the core command is running.
/// </param>
/// <returns>
/// An object that has properties and fields decorated with
/// parsing attributes similar to a cmdlet class.
/// </returns>
/// <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>
/// <exception cref="ItemNotFoundException">
/// If <paramref name="path"/> does not contain glob characters and
/// could not be found.
/// </exception>
internal object RemoveItemDynamicParameters(
string path,
bool recurse,
CmdletProviderContext context)
{
if (path == null)
{
return null;
}
ProviderInfo provider = null;
CmdletProvider providerInstance = null;
CmdletProviderContext newContext =
new CmdletProviderContext(context);
newContext.SetFilters(
new Collection<string>(),
new Collection<string>(),
null);
Collection<string> providerPaths =
Globber.GetGlobbedProviderPathsFromMonadPath(
path,
true,
newContext,
out provider,
out providerInstance);
if (providerPaths.Count > 0)
{
// Get the dynamic parameters for the first resolved path
return RemoveItemDynamicParameters(providerInstance, providerPaths[0], recurse, newContext);
}
return null;
}
/// <summary>
/// Gets the dynamic parameters for the remove-item cmdlet.
/// </summary>
/// <param name="path">
/// The path to the item if it was specified on the command line.
/// </param>
/// <param name="recurse">
/// If true, all items in the subtree should be removed.
/// </param>
/// <param name="providerInstance">
/// The instance of the provider to use.
/// </param>
/// <param name="context">
/// The context which the core command is running.
/// </param>
/// <returns>
/// An object that has properties and fields decorated with
/// parsing attributes similar to a cmdlet class.
/// </returns>
/// <exception cref="NotSupportedException">
/// If the <paramref name="providerInstance"/> does not support this operation.
/// </exception>
/// <exception cref="PipelineStoppedException">
/// If the pipeline is being stopped while executing the command.
/// </exception>
/// <exception cref="ProviderInvocationException">
/// If the provider threw an exception.
/// </exception>
private object RemoveItemDynamicParameters(
CmdletProvider providerInstance,
string path,
bool recurse,
CmdletProviderContext context)
{
// All parameters should have been validated by caller
Dbg.Diagnostics.Assert(
providerInstance != null,
"Caller should validate providerInstance before calling this method");
Dbg.Diagnostics.Assert(
path != null,
"Caller should validate path before calling this method");
Dbg.Diagnostics.Assert(
context != null,
"Caller should validate context before calling this method");
ContainerCmdletProvider containerCmdletProvider =
GetContainerProviderInstance(providerInstance);
object result = null;
try
{
result = containerCmdletProvider.RemoveItemDynamicParameters(path, recurse, context);
}
catch (LoopFlowException)
{
throw;
}
catch (PipelineStoppedException)
{
throw;
}
catch (ActionPreferenceStopException)
{
throw;
}
catch (Exception e) // Catch-all OK, 3rd party callout.
{
throw NewProviderInvocationException(
"RemoveItemProviderException",
SessionStateStrings.RemoveItemProviderException,
containerCmdletProvider.ProviderInfo,
path,
e);
}
return result;
}
#endregion RemoveItem
#region GetChildItems
/// <summary>
/// Gets the children of the specified item.
/// </summary>
/// <param name="paths">
/// An array of relative or absolute paths to the object to get the children of.
/// </param>
/// <param name="recurse">
/// If true, gets all the children in all the sub-containers of the specified
/// container. If false, only gets the immediate children of the specified
/// container.
/// </param>
/// <param name="depth">
/// Limits the depth of recursion; uint.MaxValue performs full recursion.
/// </param>
/// <param name="force">
/// Passed on to providers to force operations.
/// </param>
/// <param name="literalPath">
/// If true, globbing is not done on paths.
/// </param>
/// <remarks>
/// This method does not provider streaming of the results. If you want streaming
/// then you must call the overload that takes a CmdletProviderContext.
/// </remarks>
/// <exception cref="ArgumentNullException">
/// If <paramref name="path"/> or <paramref name="context"/> is null.
/// </exception>
/// <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>
internal Collection<PSObject> GetChildItems(string[] paths, bool recurse, uint depth, bool force, bool literalPath)
{
if (paths == null)
{
throw PSTraceSource.NewArgumentNullException(nameof(paths));
}
CmdletProviderContext context = new CmdletProviderContext(this.ExecutionContext);
context.Force = force;
context.SuppressWildcardExpansion = literalPath;
foreach (string path in paths)
{
if (path == null)
{
throw PSTraceSource.NewArgumentNullException(nameof(paths));
}
GetChildItems(path, recurse, depth, context);
}
context.ThrowFirstErrorOrDoNothing();
return context.GetAccumulatedObjects();
}
/// <summary>
/// Gets the children of the specified item.
/// </summary>
/// <param name="path">
/// A relative or absolute path to the object to get the children of.
/// </param>
/// <param name="recurse">
/// If true, gets all the children in all the sub-containers of the specified
/// container. If false, only gets the immediate children of the specified
/// container.
/// </param>
/// <param name="depth">
/// Limits the depth of recursion; uint.MaxValue performs full recursion.
/// </param>
/// <param name="context">
/// The context which the core command is running.
/// </param>
/// <exception cref="ArgumentNullException">
/// If <paramref name="path"/> or <paramref name="context"/> is null.
/// </exception>
/// <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>
/// <exception cref="ItemNotFoundException">
/// If <paramref name="path"/> does not contain glob characters and
/// could not be found.
/// </exception>
internal void GetChildItems(
string path,
bool recurse,
uint depth,
CmdletProviderContext context)
{
if (path == null)
{
throw PSTraceSource.NewArgumentNullException(nameof(path));
}
if (context == null)
{
throw PSTraceSource.NewArgumentNullException(nameof(context));
}
ProviderInfo provider = null;
if ((recurse && !context.SuppressWildcardExpansion) || LocationGlobber.ShouldPerformGlobbing(path, context))
{
bool modifiedInclude = false;
try
{
// If we're recursing, do some path fixups to match user
// expectations:
if (recurse)
{
string childName = GetChildName(path, context);
// If -File or -Directory is specified and path is ended with '*', we should include the parent path as search path
bool isFileOrDirectoryPresent = false;
if (context.DynamicParameters is Microsoft.PowerShell.Commands.GetChildDynamicParameters dynParam)
{
isFileOrDirectoryPresent = dynParam.File.IsPresent || dynParam.Directory.IsPresent;
}
if (string.Equals(childName, "*", StringComparison.OrdinalIgnoreCase) && isFileOrDirectoryPresent)
{
string parentName = path.Substring(0, path.Length - childName.Length);
path = parentName;
}
// dir c:\tem* -include *.ps1 -rec => No change
if ((context.Include == null) || (context.Include.Count == 0))
{
// dir c:\tem* -rec => dir c:\ -include tem* -rec
// dir tem* -rec => dir -include tem* -rec
// dir temp -rec
// Should glob paths and files that match tem*, but then
// recurse into all subdirectories and do the same for
// those directories.
if (!string.IsNullOrEmpty(path) && !IsItemContainer(path))
{
if (!string.Equals(childName, "*", StringComparison.OrdinalIgnoreCase))
{
if (context.Include != null)
{
context.Include.Add(childName);
modifiedInclude = true;
}
}
string parentName = path.Substring(0, path.Length - childName.Length);
path = parentName;
}
}
}
// Save the include and exclude filters so that we can ignore
// them when doing recursion
Collection<string> include = context.Include;
Collection<string> exclude = context.Exclude;
string filter = context.Filter;
if (recurse)
{
context.SetFilters(
new Collection<string>(),
new Collection<string>(),
null);
}
CmdletProvider providerInstance = null;
Collection<string> providerPaths = null;
try
{
providerPaths = Globber.GetGlobbedProviderPathsFromMonadPath(
path,
false,
context,
out provider,
out providerInstance);
}
finally
{
// Reset the include and exclude filters
context.SetFilters(
include,
exclude,
filter);
}
// Ensure this is a container provider before recursing.
// GetContainerProviderInstance throws otherwise (as was done in V2.)
if (recurse)
{
ContainerCmdletProvider unused = GetContainerProviderInstance(provider);
}
bool getChildrenBecauseNoGlob = !LocationGlobber.StringContainsGlobCharacters(path);
// If we are doing recursion and we have include or exclude
// filters the recursion must be done manually.
// Win8: 279933 Perf degradation: recursive get-childitem is 100% slower than win7
// To fix this Perf regression, using getChildrenBecauseNoGlob (+recurse) variables
// to decide when to use ManualGetChildItems and when not to.
if (
(recurse && !getChildrenBecauseNoGlob && (include != null) && (include.Count == 0)) ||
(include != null && include.Count > 0) ||
(exclude != null && exclude.Count > 0))
{
// Do the recursion manually so that we can apply the
// include and exclude filters
foreach (string providerPath in providerPaths)
{
// Making sure to obey the StopProcessing.
if (context.Stopping)
{
return;
}
int unUsedChildrenNotMatchingFilterCriteria = 0;
ProcessPathItems(providerInstance, providerPath, recurse, depth, context, out unUsedChildrenNotMatchingFilterCriteria, ProcessMode.Enumerate);
}
}
else
{
// If the path wasn't globbed or we are recursing then we want to get the
// children of the path. If we were globbing and we are not recursing
// then we just want to get the item for the resolved paths.
foreach (string providerPath in providerPaths)
{
// Making sure to obey the StopProcessing.
if (context.Stopping)
{
return;
}
if ((getChildrenBecauseNoGlob || recurse) && IsItemContainer(providerInstance, providerPath, context))
{
GetChildItems(providerInstance, providerPath, recurse, depth, context);
}
else
{
GetItemPrivate(providerInstance, providerPath, context);
}
}
}
}
finally
{
if (modifiedInclude)
{
context.Include.Clear();
}
}
}
else
{
PSDriveInfo drive = null;
string originalPath = path;
path =
Globber.GetProviderPath(
context.SuppressWildcardExpansion ? path : WildcardPattern.Unescape(path),
context,
out provider,
out drive);
if (drive != null)
{
context.Drive = drive;
}
ContainerCmdletProvider providerInstance = GetContainerProviderInstance(provider);
if (
(context.Include != null && context.Include.Count > 0) ||
(context.Exclude != null && context.Exclude.Count > 0))
{
// Do the recursion manually so that we can apply the
// include and exclude filters
int unUsedChildrenNotMatchingFilterCriteria = 0;
try
{
// Temeporary set literal path as false to apply filter
context.SuppressWildcardExpansion = false;
ProcessPathItems(providerInstance, path, recurse, depth, context, out unUsedChildrenNotMatchingFilterCriteria, ProcessMode.Enumerate);
}
finally
{
context.SuppressWildcardExpansion = true;
}
}
else if (path != null && this.ItemExists(providerInstance, path, context))
{
if (IsItemContainer(providerInstance, path, context))
{
GetChildItems(providerInstance, path, recurse, depth, context);
}
else
{
GetItemPrivate(providerInstance, path, context);
}
}
else
{
ItemNotFoundException pathNotFound =
new ItemNotFoundException(
path,
"PathNotFound",
SessionStateStrings.PathNotFound);
throw pathNotFound;
}
}
}
/// <summary>
/// Gets the child items of the item at the specified path.
/// </summary>
/// <param name="providerInstance">
/// The provider instance to use.
/// </param>
/// <param name="path">
/// The path to the item if it was specified on the command line.
/// </param>
/// <param name="recurse">
/// If true, all the child items in the subtree are returned.
/// </param>
/// <param name="depth">
/// Limits the depth of recursion; uint.MaxValue performs full recursion.
/// </param>
/// <param name="context">
/// The context which the core command is running.
/// </param>
/// <exception cref="NotSupportedException">
/// If the <paramref name="providerInstance"/> does not support this operation.
/// </exception>
/// <exception cref="PipelineStoppedException">
/// If the pipeline is being stopped while executing the command.
/// </exception>
/// <exception cref="ProviderInvocationException">
/// If the provider threw an exception.
/// </exception>
private void GetChildItems(
CmdletProvider providerInstance,
string path,
bool recurse,
uint depth,
CmdletProviderContext context)
{
// All parameters should have been validated by caller
Dbg.Diagnostics.Assert(
providerInstance != null,
"Caller should validate providerInstance before calling this method");
Dbg.Diagnostics.Assert(
path != null,
"Caller should validate path before calling this method");
Dbg.Diagnostics.Assert(
context != null,
"Caller should validate context before calling this method");
ContainerCmdletProvider containerCmdletProvider =
GetContainerProviderInstance(providerInstance);
try
{
containerCmdletProvider.GetChildItems(path, recurse, depth, context);
}
catch (LoopFlowException)
{
throw;
}
catch (PipelineStoppedException)
{
throw;
}
catch (ActionPreferenceStopException)
{
throw;
}
catch (Exception e) // Catch-all OK, 3rd party callout.
{
throw NewProviderInvocationException(
"GetChildrenProviderException",
SessionStateStrings.GetChildrenProviderException,
containerCmdletProvider.ProviderInfo,
path,
e);
}
}
/// <summary>
/// Determines if the item at the specified path is a container.
/// </summary>
/// <param name="providerInstance">
/// The provider instance to use.
/// </param>
/// <param name="path">
/// The path to the item if it was specified on the command line.
/// </param>
/// <param name="context">
/// The context which the core command is running.
/// </param>
private bool IsPathContainer(
CmdletProvider providerInstance,
string path,
CmdletProviderContext context)
{
bool itemContainer = false;
try
{
itemContainer = IsItemContainer(providerInstance, path, context);
}
catch (UnauthorizedAccessException accessException)
{
context.WriteError(new ErrorRecord(accessException, "GetItemUnauthorizedAccessError", ErrorCategory.PermissionDenied, path));
}
catch (ProviderInvocationException accessException)
{
// if providerinvocationexception is wrapping access denied error, it is ok to not terminate the pipeline
if (accessException.InnerException != null &&
accessException.InnerException.GetType().Equals(typeof(System.UnauthorizedAccessException)))
{
context.WriteError(new ErrorRecord(accessException, "GetItemUnauthorizedAccessError", ErrorCategory.PermissionDenied, path));
}
else
{
throw;
}
}
return itemContainer;
}
/// <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)
{
// Call ProcessPathItems with 'depth' set to maximum value for infinite recursion when needed.
ProcessPathItems(providerInstance, path, recurse, uint.MaxValue, context, out childrenNotMatchingFilterCriteria, processMode, skipIsItemContainerCheck);
}
/// <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="depth">
/// Limits the depth of recursion; uint.MaxValue performs full recursion.
/// </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,
uint depth,
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 || IsPathContainer(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;
}
if (!(childNameObjects[index].BaseObject is string childName))
{
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 && IsPathContainer(providerInstance, qualifiedPath, context) && depth > 0)
{
// Making sure to obey the StopProcessing.
if (context.Stopping)
{
return;
}
// The item is a container so recurse into it.
ProcessPathItems(providerInstance, qualifiedPath, recurse, depth - 1, context, out childrenNotMatchingFilterCriteria, processMode, skipIsItemContainerCheck: true);
}
}
}
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);
}
}
}
}
}
/// <summary>
/// Gets the dynamic parameters for the get-childitem cmdlet.
/// </summary>
/// <param name="path">
/// The path to the item if it was specified on the command line.
/// </param>
/// <param name="recurse">
/// The delete should occur in all sub-containers of the specified path.
/// </param>
/// <param name="context">
/// The context which the core command is running.
/// </param>
/// <returns>
/// An object that has properties and fields decorated with
/// parsing attributes similar to a cmdlet class.
/// </returns>
/// <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>
/// <exception cref="ItemNotFoundException">
/// If <paramref name="path"/> does not contain glob characters and
/// could not be found.
/// </exception>
internal object GetChildItemsDynamicParameters(
string path,
bool recurse,
CmdletProviderContext context)
{
if (path == null)
{
return null;
}
ProviderInfo provider = null;
CmdletProvider providerInstance = null;
// Get the provider that will handle this path
Globber.GetProviderPath(path, out provider);
// See if it supports dynamic parameters. If not, we don't need to
// glob the path.
if (!HasGetChildItemDynamicParameters(provider))
{
return null;
}
CmdletProviderContext newContext =
new CmdletProviderContext(context);
newContext.SetFilters(
new Collection<string>(),
new Collection<string>(),
null);
Collection<string> providerPaths = null;
try
{
providerPaths =
Globber.GetGlobbedProviderPathsFromMonadPath(
path,
true,
newContext,
out provider,
out providerInstance);
}
catch (ItemNotFoundException)
{
// If the provided path is like c:\fakepath\aa*, since we cannot resolve c:\fakepath, an
// ItemNotFoundException will be thrown out. In this case, we catch the exception
// and check if the "providerInstance" is identified. If providerInstance is not null,
// we can carry on with the get-dynamic-parameters method.
if (providerInstance == null)
{
throw;
}
}
if (providerPaths != null && providerPaths.Count > 0)
{
// Get the dynamic parameters for the first resolved path
return GetChildItemsDynamicParameters(providerInstance, providerPaths[0], recurse, newContext);
}
else
{
if (providerInstance != null)
{
PSDriveInfo drive = null;
// If we get here, the GetProviderPath should always succeed. This method was already invoked
// in the call to GetGlobbedProviderPathsFromMonadPath, and since "providerInstance" is not null,
// the invocation in method GetGlobbedProviderPathsFromMonadPath should succeed.
string providerPath = Globber.GetProviderPath(path, context, out provider, out drive);
if (providerPath != null)
{
return GetChildItemsDynamicParameters(providerInstance, providerPath, recurse, newContext);
}
}
}
return null;
}
// Detect if the GetChildItemDynamicParameters has been overridden.
private static bool HasGetChildItemDynamicParameters(ProviderInfo providerInfo)
{
Type providerType = providerInfo.ImplementingType;
MethodInfo mi = null;
do
{
mi = providerType.GetMethod("GetChildItemsDynamicParameters",
BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.DeclaredOnly);
providerType = providerType.BaseType;
} while (
(mi == null) &&
(providerType != null) &&
(providerType != typeof(ContainerCmdletProvider))
);
return (mi != null);
}
/// <summary>
/// Gets the dynamic parameters for the get-childitem cmdlet.
/// </summary>
/// <param name="path">
/// The path to the item if it was specified on the command line.
/// </param>
/// <param name="recurse">
/// If true, all child items in the subtree should be returned.
/// </param>
/// <param name="providerInstance">
/// The instance of the provider to use.
/// </param>
/// <param name="context">
/// The context which the core command is running.
/// </param>
/// <returns>
/// An object that has properties and fields decorated with
/// parsing attributes similar to a cmdlet class.
/// </returns>
/// <exception cref="NotSupportedException">
/// If the <paramref name="providerInstance"/> does not support this operation.
/// </exception>
/// <exception cref="PipelineStoppedException">
/// If the pipeline is being stopped while executing the command.
/// </exception>
/// <exception cref="ProviderInvocationException">
/// If the provider threw an exception.
/// </exception>
private object GetChildItemsDynamicParameters(
CmdletProvider providerInstance,
string path,
bool recurse,
CmdletProviderContext context)
{
// All parameters should have been validated by caller
Dbg.Diagnostics.Assert(
providerInstance != null,
"Caller should validate providerInstance before calling this method");
Dbg.Diagnostics.Assert(
path != null,
"Caller should validate path before calling this method");
Dbg.Diagnostics.Assert(
context != null,
"Caller should validate context before calling this method");
ContainerCmdletProvider containerCmdletProvider =
GetContainerProviderInstance(providerInstance);
object result = null;
try
{
result = containerCmdletProvider.GetChildItemsDynamicParameters(path, recurse, context);
}
catch (LoopFlowException)
{
throw;
}
catch (PipelineStoppedException)
{
throw;
}
catch (ActionPreferenceStopException)
{
throw;
}
catch (Exception e) // Catch-all OK, 3rd party callout.
{
throw NewProviderInvocationException(
"GetChildrenDynamicParametersProviderException",
SessionStateStrings.GetChildrenDynamicParametersProviderException,
containerCmdletProvider.ProviderInfo,
path,
e);
}
return result;
}
#endregion GetChildItems
#region GetChildNames
/// <summary>
/// Gets names of the children of the specified path.
/// </summary>
/// <param name="paths">
/// The paths to the items from which to retrieve the child names.
/// </param>
/// <param name="returnContainers">
/// Determines if all containers should be returned or only those containers that match the
/// filter(s).
/// </param>
/// <param name="recurse">
/// If true, gets all the relative paths of all the children
/// in all the sub-containers of the specified
/// container. If false, only gets the immediate child names of the specified
/// container.
/// </param>
/// <param name="depth">
/// Limits the depth of recursion; uint.MaxValue performs full recursion.
/// </param>
/// <param name="force">
/// Passed on to providers to force operations.
/// </param>
/// <param name="literalPath">
/// If true, globbing is not done on paths.
/// </param>
/// <returns>
/// An array of strings that contains the names of the children of the specified
/// container.
/// </returns>
/// <remarks>
/// The child names are the leaf portion of the path. Example, for the file system
/// the name for the path c:\windows\system32\foo.dll would be foo.dll or for
/// the directory c:\windows\system32 would be system32. For Active Directory the
/// child names would be RDN values of the child objects of the container.
/// </remarks>
/// <exception cref="ArgumentNullException">
/// If <paramref name="path"/> or <paramref name="propertyToClear"/> is null.
/// </exception>
/// <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>
internal Collection<string> GetChildNames(
string[] paths,
ReturnContainers returnContainers,
bool recurse,
uint depth,
bool force,
bool literalPath)
{
if (paths == null)
{
throw PSTraceSource.NewArgumentNullException(nameof(paths));
}
CmdletProviderContext context = new CmdletProviderContext(this.ExecutionContext);
context.Force = force;
context.SuppressWildcardExpansion = literalPath;
foreach (string path in paths)
{
if (path == null)
{
throw PSTraceSource.NewArgumentNullException(nameof(paths));
}
GetChildNames(path, returnContainers, recurse, depth, context);
}
context.ThrowFirstErrorOrDoNothing();
Collection<PSObject> objectResults = context.GetAccumulatedObjects();
Collection<string> results = new Collection<string>();
foreach (PSObject resultObject in objectResults)
{
results.Add(resultObject.BaseObject as string);
}
return results;
}
/// <summary>
/// Gets names of the children of the specified path.
/// </summary>
/// <param name="path">
/// The path to the item from which to retrieve the child names.
/// </param>
/// <param name="returnContainers">
/// Determines if all containers should be returned or only those containers that match the
/// filter(s).
/// </param>
/// <param name="recurse">
/// If true, gets all the relative paths of all the children
/// in all the sub-containers of the specified
/// container. If false, only gets the immediate child names of the specified
/// container.
/// </param>
/// <param name="depth">
/// Limits the depth of recursion; uint.MaxValue performs full recursion.
/// </param>
/// <param name="context">
/// The context which the core command is running.
/// </param>
/// <returns>
/// Nothing is returned, but all names should be written to the context object.
/// </returns>
/// <remarks>
/// The child names are the leaf portion of the path. Example, for the file system
/// the name for the path c:\windows\system32\foo.dll would be foo.dll or for
/// the directory c:\windows\system32 would be system32. For Active Directory the
/// child names would be RDN values of the child objects of the container.
/// </remarks>
/// <exception cref="ArgumentNullException">
/// If <paramref name="path"/> or <paramref name="propertyToClear"/> is null.
/// </exception>
/// <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>
/// <exception cref="ItemNotFoundException">
/// If <paramref name="path"/> does not contain glob characters and
/// could not be found.
/// </exception>
internal void GetChildNames(
string path,
ReturnContainers returnContainers,
bool recurse,
uint depth,
CmdletProviderContext context)
{
if (path == null)
{
throw PSTraceSource.NewArgumentNullException(nameof(path));
}
// 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 (LocationGlobber.ShouldPerformGlobbing(path, context))
{
ProviderInfo provider = null;
CmdletProvider providerInstance = null;
// We don't want to process include/exclude filters
// when globbing the targets of the operation, so
// copy the context without the filters.
CmdletProviderContext resolvePathContext =
new CmdletProviderContext(context);
resolvePathContext.SetFilters(
new Collection<string>(),
new Collection<string>(),
null);
// Resolve the path
Collection<string> providerPaths =
Globber.GetGlobbedProviderPathsFromMonadPath(
path,
false,
resolvePathContext,
out provider,
out providerInstance);
if (resolvePathContext.Drive != null)
{
context.Drive = resolvePathContext.Drive;
}
bool pathContainsGlobCharacters = LocationGlobber.StringContainsGlobCharacters(path);
foreach (string providerPath in providerPaths)
{
// Making sure to obey the StopProcessing.
if (context.Stopping)
{
return;
}
if ((!pathContainsGlobCharacters || recurse) && IsItemContainer(providerInstance, providerPath, context))
{
// Since the path contained glob characters or we are recursing and the
// path is a container, do the name enumeration manually
DoGetChildNamesManually(
providerInstance,
providerPath,
string.Empty,
returnContainers,
includeMatcher,
excludeMatcher,
context,
recurse,
depth);
}
else
{
// Since the original path did not contain glob characters,
// if the provider is a NavigationCmdletProvider, write
// out the child name, else write out the name as it
// was resolved.
if (providerInstance is NavigationCmdletProvider)
{
string childName =
GetChildName(
providerInstance,
providerPath,
context, false);
bool isIncludeMatch =
SessionStateUtilities.MatchesAnyWildcardPattern(
childName,
includeMatcher,
true);
bool isExcludeMatch =
SessionStateUtilities.MatchesAnyWildcardPattern(
childName,
excludeMatcher,
false);
if (isIncludeMatch && !isExcludeMatch)
{
context.WriteObject(childName);
}
}
else
{
context.WriteObject(providerPath);
}
}
}
}
else
{
// Figure out which provider to use
ProviderInfo provider = null;
PSDriveInfo drive = null;
string providerPath =
Globber.GetProviderPath(
context.SuppressWildcardExpansion ? path : WildcardPattern.Unescape(path),
context,
out provider,
out drive);
ContainerCmdletProvider providerInstance = GetContainerProviderInstance(provider);
if (drive != null)
{
context.Drive = drive;
}
if (!providerInstance.ItemExists(providerPath, context))
{
ItemNotFoundException pathNotFound =
new ItemNotFoundException(
providerPath,
"PathNotFound",
SessionStateStrings.PathNotFound);
throw pathNotFound;
}
if (recurse)
{
// The path did not contain glob characters but recurse was specified
// so do the enumeration manually
DoGetChildNamesManually(
providerInstance,
providerPath,
string.Empty,
returnContainers,
includeMatcher,
excludeMatcher,
context,
recurse,
depth);
}
else
{
// Since the path did not contain glob characters and recurse wasn't
// specified, we can have the provider write out the child names directly
GetChildNames(
providerInstance,
providerPath,
returnContainers,
context);
}
}
}
/// <summary>
/// Gets the child names of the item at the specified path by
/// manually recursing through all the containers instead of
/// allowing the provider to do the recursion.
/// </summary>
/// <param name="providerInstance">
/// The provider instance to use.
/// </param>
/// <param name="providerPath">
/// The path to the item if it was specified on the command line.
/// </param>
/// <param name="relativePath">
/// The path the name is relative to.
/// </param>
/// <param name="recurse">
/// If true all names in the subtree should be returned.
/// </param>
/// <param name="depth">
/// Current depth of recursion; special case uint.MaxValue performs full recursion.
/// </param>
/// <param name="returnContainers">
/// Determines if all containers should be returned or only those containers that match the
/// filter(s).
/// </param>
/// <param name="includeMatcher">
/// A set of filters that the names must match to be returned.
/// </param>
/// <param name="excludeMatcher">
/// A set of filters that the names cannot match to be returned.
/// </param>
/// <param name="context">
/// The context which the core command is running.
/// </param>
/// <exception cref="NotSupportedException">
/// If the <paramref name="providerInstance"/> does not support this operation.
/// </exception>
/// <exception cref="PipelineStoppedException">
/// If the pipeline is being stopped while executing the command.
/// </exception>
/// <exception cref="ProviderInvocationException">
/// If the provider threw an exception.
/// </exception>
private void DoGetChildNamesManually(
CmdletProvider providerInstance,
string providerPath,
string relativePath,
ReturnContainers returnContainers,
Collection<WildcardPattern> includeMatcher,
Collection<WildcardPattern> excludeMatcher,
CmdletProviderContext context,
bool recurse,
uint depth)
{
Dbg.Diagnostics.Assert(
providerInstance != null,
"The providerInstance should have been verified by the caller");
Dbg.Diagnostics.Assert(
providerPath != null,
"The paths should have been verified by the caller");
Dbg.Diagnostics.Assert(
context != null,
"The context should have been verified by the caller");
string newProviderPath =
MakePath(
providerInstance,
providerPath,
relativePath,
context);
CmdletProviderContext childNamesContext =
new CmdletProviderContext(context);
try
{
// First get all children that match the filters and write them out
GetChildNames(
providerInstance,
newProviderPath,
ReturnContainers.ReturnMatchingContainers,
childNamesContext);
Collection<PSObject> results = childNamesContext.GetAccumulatedObjects();
foreach (PSObject result in results)
{
// Making sure to obey the StopProcessing.
if (context.Stopping)
{
return;
}
if (!(result.BaseObject is string name))
{
continue;
}
bool isIncludeMatch =
SessionStateUtilities.MatchesAnyWildcardPattern(
name,
includeMatcher,
true);
if (isIncludeMatch)
{
if (!SessionStateUtilities.MatchesAnyWildcardPattern(
name,
excludeMatcher,
false))
{
string resultPath = MakePath(providerInstance, relativePath, name, context);
context.WriteObject(resultPath);
}
}
}
if (recurse)
{
// Now get all the children that are containers and recurse into them
// Limiter for recursion
if (depth > 0) // this includes special case 'depth == uint.MaxValue' for unlimited recursion
{
GetChildNames(
providerInstance,
newProviderPath,
ReturnContainers.ReturnAllContainers,
childNamesContext);
results = childNamesContext.GetAccumulatedObjects();
foreach (PSObject result in results)
{
// Making sure to obey the StopProcessing.
if (context.Stopping)
{
return;
}
if (!(result.BaseObject is string name))
{
continue;
}
// Generate the relative path from the provider path
string resultRelativePath =
MakePath(
providerInstance,
relativePath,
name,
context);
// Generate the provider path for the child item to see
// if it is a container
string resultProviderPath =
MakePath(
providerInstance,
providerPath,
resultRelativePath,
context);
// If the item is a container recurse into it and output its
// child names
if (IsItemContainer(providerInstance, resultProviderPath, context))
{
DoGetChildNamesManually(
providerInstance,
providerPath,
resultRelativePath,
returnContainers,
includeMatcher,
excludeMatcher,
context,
true,
depth - 1);
}
}
}
}
}
finally
{
childNamesContext.RemoveStopReferral();
}
}
/// <summary>
/// Gets the names of the children of the item at the specified path.
/// </summary>
/// <param name="providerInstance">
/// The provider instance to use.
/// </param>
/// <param name="path">
/// The path to the item if it was specified on the command line.
/// </param>
/// <param name="returnContainers">
/// Determines if all containers should be returned or only those containers that match the
/// filter(s).
/// </param>
/// <param name="context">
/// The context which the core command is running.
/// </param>
/// <exception cref="NotSupportedException">
/// If the <paramref name="providerInstance"/> does not support this operation.
/// </exception>
/// <exception cref="PipelineStoppedException">
/// If the pipeline is being stopped while executing the command.
/// </exception>
/// <exception cref="ProviderInvocationException">
/// If the provider threw an exception.
/// </exception>
private void GetChildNames(
CmdletProvider providerInstance,
string path,
ReturnContainers returnContainers,
CmdletProviderContext context)
{
// All parameters should have been validated by caller
Dbg.Diagnostics.Assert(
providerInstance != null,
"Caller should validate providerInstance before calling this method");
Dbg.Diagnostics.Assert(
path != null,
"Caller should validate path before calling this method");
Dbg.Diagnostics.Assert(
context != null,
"Caller should validate context before calling this method");
ContainerCmdletProvider containerCmdletProvider =
GetContainerProviderInstance(providerInstance);
try
{
containerCmdletProvider.GetChildNames(path, returnContainers, context);
}
catch (LoopFlowException)
{
throw;
}
catch (PipelineStoppedException)
{
throw;
}
catch (ActionPreferenceStopException)
{
throw;
}
catch (Exception e) // Catch-all OK, 3rd party callout.
{
throw NewProviderInvocationException(
"GetChildNamesProviderException",
SessionStateStrings.GetChildNamesProviderException,
containerCmdletProvider.ProviderInfo,
path,
e);
}
}
/// <summary>
/// Gets the dynamic parameters for the get-childitem -name cmdlet.
/// </summary>
/// <param name="path">
/// The path to the item if it was specified on the command line.
/// </param>
/// <param name="context">
/// The context which the core command is running.
/// </param>
/// <returns>
/// An object that has properties and fields decorated with
/// parsing attributes similar to a cmdlet class.
/// </returns>
/// <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>
/// <exception cref="ItemNotFoundException">
/// If <paramref name="path"/> does not contain glob characters and
/// could not be found.
/// </exception>
internal object GetChildNamesDynamicParameters(
string path,
CmdletProviderContext context)
{
if (path == null)
{
return null;
}
ProviderInfo provider = null;
CmdletProvider providerInstance = null;
CmdletProviderContext newContext =
new CmdletProviderContext(context);
newContext.SetFilters(
new Collection<string>(),
new Collection<string>(),
null);
Collection<string> providerPaths = null;
try
{
providerPaths =
Globber.GetGlobbedProviderPathsFromMonadPath(
path,
true,
newContext,
out provider,
out providerInstance);
}
catch (ItemNotFoundException)
{
// If the provided path is like c:\fakepath\aa*, since we cannot resolve c:\fakepath, an
// ItemNotFoundException will be thrown out. In this case, we catch the exception
// and check if the "providerInstance" is identified. If providerInstance is not null,
// we can carry on with the get-dynamic-parameters method.
if (providerInstance == null)
{
throw;
}
}
object result = null;
if (providerPaths != null && providerPaths.Count > 0)
{
// Get the dynamic parameters for the first resolved path
result = GetChildNamesDynamicParameters(providerInstance, providerPaths[0], newContext);
}
else
{
if (providerInstance != null)
{
PSDriveInfo drive = null;
// If we get here, the GetProviderPath should always succeed. This method was already invoked
// in the call to GetGlobbedProviderPathsFromMonadPath, and since "providerInstance" is not null,
// the invocation in method GetGlobbedProviderPathsFromMonadPath should succeed.
string providerPath = Globber.GetProviderPath(path, context, out provider, out drive);
if (providerPath != null)
{
result = GetChildNamesDynamicParameters(providerInstance, providerPath, newContext);
}
}
}
return result;
}
/// <summary>
/// Gets the dynamic parameters for the get-childitem -names cmdlet.
/// </summary>
/// <param name="path">
/// The path to the item if it was specified on the command line.
/// </param>
/// <param name="providerInstance">
/// The instance of the provider to use.
/// </param>
/// <param name="context">
/// The context which the core command is running.
/// </param>
/// <returns>
/// An object that has properties and fields decorated with
/// parsing attributes similar to a cmdlet class.
/// </returns>
/// <exception cref="NotSupportedException">
/// If the <paramref name="providerInstance"/> does not support this operation.
/// </exception>
/// <exception cref="PipelineStoppedException">
/// If the pipeline is being stopped while executing the command.
/// </exception>
/// <exception cref="ProviderInvocationException">
/// If the provider threw an exception.
/// </exception>
private object GetChildNamesDynamicParameters(
CmdletProvider providerInstance,
string path,
CmdletProviderContext context)
{
// All parameters should have been validated by caller
Dbg.Diagnostics.Assert(
providerInstance != null,
"Caller should validate providerId before calling this method");
Dbg.Diagnostics.Assert(
path != null,
"Caller should validate path before calling this method");
Dbg.Diagnostics.Assert(
context != null,
"Caller should validate context before calling this method");
ContainerCmdletProvider containerCmdletProvider =
GetContainerProviderInstance(providerInstance);
object result = null;
try
{
result = containerCmdletProvider.GetChildNamesDynamicParameters(path, context);
}
catch (LoopFlowException)
{
throw;
}
catch (PipelineStoppedException)
{
throw;
}
catch (ActionPreferenceStopException)
{
throw;
}
catch (Exception e) // Catch-all OK, 3rd party callout.
{
throw NewProviderInvocationException(
"GetChildNamesDynamicParametersProviderException",
SessionStateStrings.GetChildNamesDynamicParametersProviderException,
containerCmdletProvider.ProviderInfo,
path,
e);
}
return result;
}
#endregion GetChildNames
#region RenameItem
/// <summary>
/// Renames the item at the specified path to the new name provided.
/// </summary>
/// <param name="path">
/// The path to the item to rename.
/// </param>
/// <param name="newName">
/// The name to which the item should be renamed. This name should always be
/// relative to the parent container.
/// </param>
/// <param name="force">
/// Passed on to providers to force operations.
/// </param>
/// <returns>
/// The item that was renamed at the specified path.
/// </returns>
/// <exception cref="ArgumentNullException">
/// If <paramref name="path"/> or <paramref name="propertyToClear"/> is null.
/// </exception>
/// <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>
internal Collection<PSObject> RenameItem(string path, string newName, bool force)
{
if (path == null)
{
throw PSTraceSource.NewArgumentNullException(nameof(path));
}
CmdletProviderContext context = new CmdletProviderContext(this.ExecutionContext);
context.Force = force;
RenameItem(path, newName, context);
context.ThrowFirstErrorOrDoNothing();
// Since there was no errors return the accumulated objects
return context.GetAccumulatedObjects();
}
/// <summary>
/// Renames the item at the specified path to the new name provided.
/// </summary>
/// <param name="path">
/// The path to the item to rename.
/// </param>
/// <param name="newName">
/// The name to which the item should be renamed. This name should always be
/// relative to the parent container.
/// </param>
/// <param name="context">
/// The context which the core command is running.
/// </param>
/// <returns>
/// Nothing. All items that are renamed are written into the context object.
/// </returns>
/// <exception cref="ArgumentNullException">
/// If <paramref name="path"/> or <paramref name="propertyToClear"/> is null.
/// </exception>
/// <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>
/// <exception cref="ItemNotFoundException">
/// If <paramref name="path"/> does not contain glob characters and
/// could not be found.
/// </exception>
internal void RenameItem(
string path,
string newName,
CmdletProviderContext context)
{
if (path == null)
{
throw PSTraceSource.NewArgumentNullException(nameof(path));
}
ProviderInfo provider = null;
CmdletProvider providerInstance = null;
Collection<string> providerPaths =
Globber.GetGlobbedProviderPathsFromMonadPath(
path,
false,
context,
out provider,
out providerInstance);
// Can only rename one item at a time, so if we glob more than
// one item write out an error.
if (providerPaths.Count == 1)
{
RenameItem(providerInstance, providerPaths[0], newName, context);
}
else
{
ArgumentException argException =
PSTraceSource.NewArgumentException(
nameof(path),
SessionStateStrings.RenameMultipleItemError);
context.WriteError(
new ErrorRecord(
argException,
"RenameMultipleItemError",
ErrorCategory.InvalidArgument,
providerPaths));
}
}
/// <summary>
/// Renames the item at the specified path.
/// </summary>
/// <param name="providerInstance">
/// The provider instance to use.
/// </param>
/// <param name="path">
/// The path to the item if it was specified on the command line.
/// </param>
/// <param name="newName">
/// The new name of the item.
/// </param>
/// <param name="context">
/// The context which the core command is running.
/// </param>
/// <exception cref="NotSupportedException">
/// If the <paramref name="providerInstance"/> does not support this operation.
/// </exception>
/// <exception cref="PipelineStoppedException">
/// If the pipeline is being stopped while executing the command.
/// </exception>
/// <exception cref="ProviderInvocationException">
/// If the provider threw an exception.
/// </exception>
private void RenameItem(
CmdletProvider providerInstance,
string path,
string newName,
CmdletProviderContext context)
{
// All parameters should have been validated by caller
Dbg.Diagnostics.Assert(
providerInstance != null,
"Caller should validate providerInstance before calling this method");
Dbg.Diagnostics.Assert(
path != null,
"Caller should validate path before calling this method");
Dbg.Diagnostics.Assert(
context != null,
"Caller should validate context before calling this method");
ContainerCmdletProvider containerCmdletProvider =
GetContainerProviderInstance(providerInstance);
try
{
containerCmdletProvider.RenameItem(path, newName, context);
}
catch (LoopFlowException)
{
throw;
}
catch (PipelineStoppedException)
{
throw;
}
catch (ActionPreferenceStopException)
{
throw;
}
catch (Exception e) // Catch-all OK, 3rd party callout.
{
throw NewProviderInvocationException(
"RenameItemProviderException",
SessionStateStrings.RenameItemProviderException,
containerCmdletProvider.ProviderInfo,
path,
e);
}
}
/// <summary>
/// Gets the dynamic parameters for the rename-item cmdlet.
/// </summary>
/// <param name="path">
/// The path to the item if it was specified on the command line.
/// </param>
/// <param name="newName">
/// The name to which the item should be renamed. This name should always be
/// relative to the parent container.
/// </param>
/// <param name="context">
/// The context which the core command is running.
/// </param>
/// <returns>
/// An object that has properties and fields decorated with
/// parsing attributes similar to a cmdlet class.
/// </returns>
/// <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>
/// <exception cref="ItemNotFoundException">
/// If <paramref name="path"/> does not contain glob characters and
/// could not be found.
/// </exception>
internal object RenameItemDynamicParameters(
string path,
string newName,
CmdletProviderContext context)
{
if (path == null)
{
return null;
}
ProviderInfo provider = null;
CmdletProvider providerInstance = null;
CmdletProviderContext newContext =
new CmdletProviderContext(context);
newContext.SetFilters(
new Collection<string>(),
new Collection<string>(),
null);
Collection<string> providerPaths =
Globber.GetGlobbedProviderPathsFromMonadPath(
path,
true,
newContext,
out provider,
out providerInstance);
if (providerPaths.Count > 0)
{
// Get the dynamic parameters for the first resolved path
return RenameItemDynamicParameters(providerInstance, providerPaths[0], newName, newContext);
}
return null;
}
/// <summary>
/// Gets the dynamic parameters for the rename-item cmdlet.
/// </summary>
/// <param name="path">
/// The path to the item if it was specified on the command line.
/// </param>
/// <param name="newName">
/// The new name of the item.
/// </param>
/// <param name="providerInstance">
/// The instance of the provider to use.
/// </param>
/// <param name="context">
/// The context which the core command is running.
/// </param>
/// <returns>
/// An object that has properties and fields decorated with
/// parsing attributes similar to a cmdlet class.
/// </returns>
/// <exception cref="NotSupportedException">
/// If the <paramref name="providerInstance"/> does not support this operation.
/// </exception>
/// <exception cref="PipelineStoppedException">
/// If the pipeline is being stopped while executing the command.
/// </exception>
/// <exception cref="ProviderInvocationException">
/// If the provider threw an exception.
/// </exception>
private object RenameItemDynamicParameters(
CmdletProvider providerInstance,
string path,
string newName,
CmdletProviderContext context)
{
// All parameters should have been validated by caller
Dbg.Diagnostics.Assert(
providerInstance != null,
"Caller should validate providerInstance before calling this method");
Dbg.Diagnostics.Assert(
path != null,
"Caller should validate path before calling this method");
Dbg.Diagnostics.Assert(
context != null,
"Caller should validate context before calling this method");
ContainerCmdletProvider containerCmdletProvider =
GetContainerProviderInstance(providerInstance);
object result = null;
try
{
result = containerCmdletProvider.RenameItemDynamicParameters(path, newName, context);
}
catch (LoopFlowException)
{
throw;
}
catch (PipelineStoppedException)
{
throw;
}
catch (ActionPreferenceStopException)
{
throw;
}
catch (Exception e) // Catch-all OK, 3rd party callout.
{
throw NewProviderInvocationException(
"RenameItemDynamicParametersProviderException",
SessionStateStrings.RenameItemDynamicParametersProviderException,
containerCmdletProvider.ProviderInfo,
path,
e);
}
return result;
}
#endregion RenameItem
#region NewItem
/// <summary>
/// Creates a new item at the specified path.
/// </summary>
/// <param name="paths">
/// The path(s) to the container(s) to create the item in.
/// </param>
/// <param name="name">
/// The name of the item to create.
/// </param>
/// <param name="type">
/// The provider specific type of the object to be created.
/// </param>
/// <param name="content">
/// The content of the new item to create.
/// </param>
/// <param name="force">
/// Passed on to providers to force operations.
/// </param>
/// <returns>
/// The item(s) that was created.
/// </returns>
/// <exception cref="ArgumentNullException">
/// If <paramref name="path"/> or <paramref name="propertyToClear"/> is null.
/// </exception>
/// <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>
internal Collection<PSObject> NewItem(string[] paths, string name, string type, object content, bool force)
{
if (paths == null)
{
throw PSTraceSource.NewArgumentNullException(nameof(paths));
}
CmdletProviderContext context = new CmdletProviderContext(this.ExecutionContext);
context.Force = force;
NewItem(paths, name, type, content, context);
context.ThrowFirstErrorOrDoNothing();
// Since there was no errors return the accumulated objects
return context.GetAccumulatedObjects();
}
/// <summary>
/// Creates a new item at the specified path.
/// </summary>
/// <param name="paths">
/// The path(s) to the item(s) to create.
/// </param>
/// <param name="name">
/// The name of the item to create.
/// </param>
/// <param name="type">
/// The provider specific type of the item to be created.
/// </param>
/// <param name="content">
/// The content to create the new item with.
/// </param>
/// <param name="context">
/// The context which the core command is running.
/// </param>
/// <returns>
/// Nothing. The item created is written to the context object.
/// </returns>
/// <exception cref="ArgumentNullException">
/// If <paramref name="path"/> or <paramref name="propertyToClear"/> is null.
/// </exception>
/// <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>
/// <exception cref="ItemNotFoundException">
/// If <paramref name="path"/> does not contain glob characters and
/// could not be found.
/// </exception>
internal void NewItem(
string[] paths,
string name,
string type,
object content,
CmdletProviderContext context)
{
if (paths == null)
{
throw PSTraceSource.NewArgumentNullException(nameof(paths));
}
foreach (string path in paths)
{
string resolvePath = null;
if (path == null)
{
PSTraceSource.NewArgumentNullException(nameof(paths));
}
else if (path.EndsWith((":" + Path.DirectorySeparatorChar), StringComparison.Ordinal) ||
path.EndsWith((":" + Path.AltDirectorySeparatorChar), StringComparison.Ordinal))
{
// path is Windows root
resolvePath = path;
}
else
{
// To be compatible with Linux OS. Which will be either '/' or '\' depends on the OS type.
char[] charsToTrim = { ' ', Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar };
resolvePath = path.TrimEnd(charsToTrim);
}
ProviderInfo provider = null;
PSDriveInfo driveInfo;
CmdletProvider providerInstance = null;
Collection<string> providerPaths = new Collection<string>();
// Only glob the path if the name is specified
if (string.IsNullOrEmpty(name))
{
string providerPath =
Globber.GetProviderPath(resolvePath, context, out provider, out driveInfo);
providerInstance = GetProviderInstance(provider);
providerPaths.Add(providerPath);
}
else
{
providerPaths =
Globber.GetGlobbedProviderPathsFromMonadPath(
resolvePath,
true,
context,
out provider,
out providerInstance);
}
foreach (string providerPath in providerPaths)
{
// Compose the globbed container and the name together to get a path
// to pass on to the provider.
string composedPath = providerPath;
if (!string.IsNullOrEmpty(name))
{
composedPath = MakePath(providerInstance, providerPath, name, context);
}
// Don't support 'New-Item -Type Directory' on the Function provider
// if the runspace has ever been in constrained language mode, as the mkdir
// function can be abused
if (context.ExecutionContext.HasRunspaceEverUsedConstrainedLanguageMode &&
(providerInstance is Microsoft.PowerShell.Commands.FunctionProvider) &&
(string.Equals(type, "Directory", StringComparison.OrdinalIgnoreCase)))
{
throw
PSTraceSource.NewNotSupportedException(SessionStateStrings.DriveCmdletProvider_NotSupported);
}
bool isSymbolicJunctionOrHardLink = false;
// Symbolic link targets are allowed to not exist on both Windows and Linux
bool allowNonexistingPath = false;
if (type != null)
{
WildcardPattern typeEvaluator = WildcardPattern.Get(type + "*", WildcardOptions.IgnoreCase | WildcardOptions.Compiled);
if (typeEvaluator.IsMatch("symboliclink") || typeEvaluator.IsMatch("junction") || typeEvaluator.IsMatch("hardlink"))
{
isSymbolicJunctionOrHardLink = true;
allowNonexistingPath = typeEvaluator.IsMatch("symboliclink");
}
}
if (isSymbolicJunctionOrHardLink)
{
string targetPath;
if (content is null || string.IsNullOrEmpty(targetPath = content.ToString()))
{
throw PSTraceSource.NewArgumentNullException(nameof(content), SessionStateStrings.NewLinkTargetNotSpecified, path);
}
ProviderInfo targetProvider = null;
CmdletProvider targetProviderInstance = null;
var globbedTarget = Globber.GetGlobbedProviderPathsFromMonadPath(
targetPath,
allowNonexistingPath,
context,
out targetProvider,
out targetProviderInstance);
if (!string.Equals(targetProvider.Name, "filesystem", StringComparison.OrdinalIgnoreCase))
{
throw PSTraceSource.NewNotSupportedException(SessionStateStrings.MustBeFileSystemPath);
}
if (globbedTarget.Count > 1)
{
throw PSTraceSource.NewInvalidOperationException(SessionStateStrings.PathResolvedToMultiple, targetPath);
}
if (globbedTarget.Count == 0)
{
throw PSTraceSource.NewInvalidOperationException(SessionStateStrings.PathNotFound, targetPath);
}
// If the original target was a relative path, we want to leave it as relative if it did not require
// globbing to resolve.
if (WildcardPattern.ContainsWildcardCharacters(targetPath))
{
content = globbedTarget[0];
}
}
NewItemPrivate(providerInstance, composedPath, type, content, context);
}
}
}
/// <summary>
/// Creates a new item at the specified path.
/// </summary>
/// <param name="providerInstance">
/// The provider instance to use.
/// </param>
/// <param name="path">
/// The path to the item if it was specified on the command line.
/// </param>
/// <param name="type">
/// The type of the item to create.
/// </param>
/// <param name="content">
/// The content of the item to create.
/// </param>
/// <param name="context">
/// The context which the core command is running.
/// </param>
/// <exception cref="NotSupportedException">
/// If the <paramref name="providerInstance"/> does not support this operation.
/// </exception>
/// <exception cref="PipelineStoppedException">
/// If the pipeline is being stopped while executing the command.
/// </exception>
/// <exception cref="ProviderInvocationException">
/// If the provider threw an exception.
/// </exception>
private void NewItemPrivate(
CmdletProvider providerInstance,
string path,
string type,
object content,
CmdletProviderContext context)
{
// All parameters should have been validated by caller
Dbg.Diagnostics.Assert(
providerInstance != null,
"Caller should validate providerInstance before calling this method");
Dbg.Diagnostics.Assert(
path != null,
"Caller should validate path before calling this method");
ContainerCmdletProvider containerCmdletProvider =
GetContainerProviderInstance(providerInstance);
try
{
containerCmdletProvider.NewItem(path, type, content, context);
}
catch (LoopFlowException)
{
throw;
}
catch (PipelineStoppedException)
{
throw;
}
catch (ActionPreferenceStopException)
{
throw;
}
catch (Exception e) // Catch-all OK, 3rd party callout.
{
throw NewProviderInvocationException(
"NewItemProviderException",
SessionStateStrings.NewItemProviderException,
containerCmdletProvider.ProviderInfo,
path,
e);
}
}
/// <summary>
/// Gets the dynamic parameters for the new-item cmdlet.
/// </summary>
/// <param name="path">
/// The path to the item if it was specified on the command line.
/// </param>
/// <param name="type">
/// The provider specific type of the item to be created.
/// </param>
/// <param name="newItemValue">
/// The content to create the new item with.
/// </param>
/// <param name="context">
/// The context which the core command is running.
/// </param>
/// <returns>
/// An object that has properties and fields decorated with
/// parsing attributes similar to a cmdlet class.
/// </returns>
/// <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>
/// <exception cref="ItemNotFoundException">
/// If <paramref name="path"/> does not contain glob characters and
/// could not be found.
/// </exception>
internal object NewItemDynamicParameters(
string path,
string type,
object newItemValue,
CmdletProviderContext context)
{
if (path == null)
{
return null;
}
ProviderInfo provider = null;
CmdletProvider providerInstance = null;
CmdletProviderContext newContext =
new CmdletProviderContext(context);
newContext.SetFilters(
new Collection<string>(),
new Collection<string>(),
null);
Collection<string> providerPaths =
Globber.GetGlobbedProviderPathsFromMonadPath(
path,
true,
newContext,
out provider,
out providerInstance);
if (providerPaths.Count > 0)
{
// Get the dynamic parameters for the first resolved path
return NewItemDynamicParameters(providerInstance, providerPaths[0], type, newItemValue, newContext);
}
return null;
}
/// <summary>
/// Gets the dynamic parameters for the new-item cmdlet.
/// </summary>
/// <param name="path">
/// The path to the item if it was specified on the command line.
/// </param>
/// <param name="type">
/// The type of the new item.
/// </param>
/// <param name="newItemValue">
/// The value of the new item
/// </param>
/// <param name="providerInstance">
/// The instance of the provider to use.
/// </param>
/// <param name="context">
/// The context which the core command is running.
/// </param>
/// <returns>
/// An object that has properties and fields decorated with
/// parsing attributes similar to a cmdlet class.
/// </returns>
/// <exception cref="NotSupportedException">
/// If the <paramref name="providerInstance"/> does not support this operation.
/// </exception>
/// <exception cref="PipelineStoppedException">
/// If the pipeline is being stopped while executing the command.
/// </exception>
/// <exception cref="ProviderInvocationException">
/// If the provider threw an exception.
/// </exception>
private object NewItemDynamicParameters(
CmdletProvider providerInstance,
string path,
string type,
object newItemValue,
CmdletProviderContext context)
{
// All parameters should have been validated by caller
Dbg.Diagnostics.Assert(
providerInstance != null,
"Caller should validate providerInstance before calling this method");
Dbg.Diagnostics.Assert(
path != null,
"Caller should validate path before calling this method");
Dbg.Diagnostics.Assert(
context != null,
"Caller should validate context before calling this method");
ContainerCmdletProvider containerCmdletProvider =
GetContainerProviderInstance(providerInstance);
object result = null;
try
{
result = containerCmdletProvider.NewItemDynamicParameters(path, type, newItemValue, context);
}
catch (LoopFlowException)
{
throw;
}
catch (PipelineStoppedException)
{
throw;
}
catch (ActionPreferenceStopException)
{
throw;
}
catch (Exception e) // Catch-all OK, 3rd party callout.
{
throw NewProviderInvocationException(
"NewItemDynamicParametersProviderException",
SessionStateStrings.NewItemDynamicParametersProviderException,
containerCmdletProvider.ProviderInfo,
path,
e);
}
return result;
}
#endregion NewItem
#region HasChildItems
/// <summary>
/// Determines if the item at the specified path has children.
/// </summary>
/// <param name="path">
/// The path to the item to see if it has children.
/// </param>
/// <param name="force">
/// Passed on to providers to force operations.
/// </param>
/// <param name="literalPath">
/// If true, globbing is not done on paths.
/// </param>
/// <returns>
/// True if the item has children, false otherwise.
/// </returns>
/// <exception cref="ArgumentNullException">
/// If <paramref name="path"/> is null.
/// </exception>
/// <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>
internal bool HasChildItems(string path, bool force, bool literalPath)
{
if (path == null)
{
throw PSTraceSource.NewArgumentNullException(nameof(path));
}
CmdletProviderContext context = new CmdletProviderContext(this.ExecutionContext);
context.Force = force;
context.SuppressWildcardExpansion = literalPath;
bool result = HasChildItems(path, context);
context.ThrowFirstErrorOrDoNothing();
return result;
}
/// <summary>
/// Determines if the item at the specified path has children.
/// </summary>
/// <param name="path">
/// The path to the item to see if it has children.
/// </param>
/// <param name="context">
/// The context which the core command is running.
/// </param>
/// <returns>
/// True if the item has children, false otherwise.
/// </returns>
/// <exception cref="ArgumentNullException">
/// If <paramref name="path"/> is null.
/// </exception>
/// <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>
/// <exception cref="ItemNotFoundException">
/// If <paramref name="path"/> does not contain glob characters and
/// could not be found.
/// </exception>
internal bool HasChildItems(
string path,
CmdletProviderContext context)
{
if (path == null)
{
throw PSTraceSource.NewArgumentNullException(nameof(path));
}
ProviderInfo provider = null;
CmdletProvider providerInstance = null;
Collection<string> providerPaths =
Globber.GetGlobbedProviderPathsFromMonadPath(
path,
false,
context,
out provider,
out providerInstance);
bool result = false;
foreach (string providerPath in providerPaths)
{
result = HasChildItems(providerInstance, providerPath, context);
if (result)
{
break;
}
}
return result;
}
/// <summary>
/// Determines if the item at the specified path has children.
/// </summary>
/// <param name="providerId">
/// The provider to use.
/// </param>
/// <param name="path">
/// The path to the item if it was specified on the command line.
/// </param>
/// <exception cref="NotSupportedException">
/// If the <paramref name="providerInstance"/> does not support this operation.
/// </exception>
/// <exception cref="PipelineStoppedException">
/// If the pipeline is being stopped while executing the command.
/// </exception>
/// <exception cref="ProviderInvocationException">
/// If the provider threw an exception.
/// </exception>
internal bool HasChildItems(
string providerId,
string path)
{
bool result = false;
if (string.IsNullOrEmpty(providerId))
{
throw PSTraceSource.NewArgumentException(nameof(providerId));
}
if (path == null)
{
throw PSTraceSource.NewArgumentNullException(nameof(path));
}
CmdletProviderContext context = new CmdletProviderContext(this.ExecutionContext);
result = HasChildItems(providerId, path, context);
context.ThrowFirstErrorOrDoNothing();
return result;
}
/// <summary>
/// Determines if the item at the specified path has children.
/// </summary>
/// <param name="providerId">
/// The provider to use.
/// </param>
/// <param name="path">
/// The path to the item if it was specified on the command line.
/// </param>
/// <param name="context">
/// The context under which the command is running.
/// </param>
/// <exception cref="NotSupportedException">
/// If the <paramref name="providerInstance"/> does not support this operation.
/// </exception>
/// <exception cref="PipelineStoppedException">
/// If the pipeline is being stopped while executing the command.
/// </exception>
/// <exception cref="ProviderInvocationException">
/// If the provider threw an exception.
/// </exception>
internal bool HasChildItems(
string providerId,
string path,
CmdletProviderContext context)
{
ContainerCmdletProvider providerInstance = GetContainerProviderInstance(providerId);
return HasChildItems(providerInstance, path, context);
}
/// <summary>
/// Determines if the item at the specified path has children.
/// </summary>
/// <param name="providerInstance">
/// The provider instance to use.
/// </param>
/// <param name="path">
/// The path to the item if it was specified on the command line.
/// </param>
/// <param name="context">
/// The context which the core command is running.
/// </param>
/// <exception cref="NotSupportedException">
/// If the <paramref name="providerInstance"/> does not support this operation.
/// </exception>
/// <exception cref="PipelineStoppedException">
/// If the pipeline is being stopped while executing the command.
/// </exception>
/// <exception cref="ProviderInvocationException">
/// If the provider threw an exception.
/// </exception>
private bool HasChildItems(
CmdletProvider providerInstance,
string path,
CmdletProviderContext context)
{
// All parameters should have been validated by caller
Dbg.Diagnostics.Assert(
providerInstance != null,
"Caller should validate providerInstance before calling this method");
Dbg.Diagnostics.Assert(
path != null,
"Caller should validate path before calling this method");
Dbg.Diagnostics.Assert(
context != null,
"Caller should validate context before calling this method");
ContainerCmdletProvider containerCmdletProvider =
GetContainerProviderInstance(providerInstance);
bool result = false;
try
{
result = containerCmdletProvider.HasChildItems(path, context);
}
catch (LoopFlowException)
{
throw;
}
catch (PipelineStoppedException)
{
throw;
}
catch (ActionPreferenceStopException)
{
throw;
}
catch (Exception e) // Catch-all OK, 3rd party callout.
{
throw NewProviderInvocationException(
"HasChildItemsProviderException",
SessionStateStrings.HasChildItemsProviderException,
containerCmdletProvider.ProviderInfo,
path,
e);
}
return result;
}
#endregion HasChildItems
#region CopyItem
/// <summary>
/// Copies an item at the specified path to an item at the <paramref name="copyPath"/>.
/// </summary>
/// <param name="paths">
/// The path(s) of the item(s) to copy.
/// </param>
/// <param name="copyPath">
/// The path of the item to copy to.
/// </param>
/// <param name="recurse">
/// Tells the provider to recurse sub-containers when copying.
/// </param>
/// <param name="copyContainers">
/// Determines how the source container is used in the copy operation.
/// </param>
/// <param name="force">
/// Passed on to providers to force operations.
/// </param>
/// <param name="literalPath">
/// If true, globbing is not done on paths.
/// </param>
/// <returns>
/// The objects that were copied.
/// </returns>
/// <exception cref="ArgumentNullException">
/// If <paramref name="path"/> is null.
/// </exception>
/// <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>
internal Collection<PSObject> CopyItem(string[] paths,
string copyPath,
bool recurse,
CopyContainers copyContainers,
bool force,
bool literalPath)
{
if (paths == null)
{
throw PSTraceSource.NewArgumentNullException(nameof(paths));
}
if (copyPath == null)
{
copyPath = string.Empty;
}
CmdletProviderContext context = new CmdletProviderContext(this.ExecutionContext);
context.Force = force;
context.SuppressWildcardExpansion = literalPath;
CopyItem(paths, copyPath, recurse, copyContainers, context);
context.ThrowFirstErrorOrDoNothing();
return context.GetAccumulatedObjects();
}
/// <summary>
/// Copies an item at the specified path to an item at the <paramref name="copyPath"/>.
/// </summary>
/// <param name="paths">
/// The path(s) of the item(s) to copy.
/// </param>
/// <param name="copyPath">
/// The path of the item to copy to.
/// </param>
/// <param name="recurse">
/// Tells the provider to recurse sub-containers when copying.
/// </param>
/// <param name="copyContainers">
/// Determines how the source container is used in the copy operation.
/// </param>
/// <param name="context">
/// The context which the core command is running.
/// </param>
/// <exception cref="ArgumentNullException">
/// If <paramref name="path"/> is null.
/// </exception>
/// <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>
/// <exception cref="ItemNotFoundException">
/// If <paramref name="path"/> does not contain glob characters and
/// could not be found.
/// </exception>
internal void CopyItem(
string[] paths,
string copyPath,
bool recurse,
CopyContainers copyContainers,
CmdletProviderContext context)
{
if (paths == null)
{
throw PSTraceSource.NewArgumentNullException(nameof(paths));
}
if (copyPath == null)
{
copyPath = string.Empty;
}
// Get the provider specific path for the destination
PSDriveInfo unusedDrive = null;
ProviderInfo destinationProvider = null;
Microsoft.PowerShell.Commands.CopyItemDynamicParameters dynamicParams = context.DynamicParameters as Microsoft.PowerShell.Commands.CopyItemDynamicParameters;
bool destinationIsRemote = false;
bool sourceIsRemote = false;
string providerDestinationPath;
Runspaces.PSSession session = null;
if (dynamicParams != null)
{
if (dynamicParams.FromSession != null)
{
sourceIsRemote = true;
session = dynamicParams.FromSession;
}
if (dynamicParams.ToSession != null)
{
destinationIsRemote = true;
session = dynamicParams.ToSession;
}
}
if (sourceIsRemote && destinationIsRemote)
{
context.WriteError(new ErrorRecord(
new ArgumentException(
string.Format(System.Globalization.CultureInfo.InvariantCulture, SessionStateStrings.CopyItemFromSessionToSession, "FromSession", "ToSession")),
"InvalidInput",
ErrorCategory.InvalidArgument,
dynamicParams));
return;
}
// Validate that the session is available and the language mode is not set to ConstrainedLanguage or NoLanguage.
PSLanguageMode? remoteLanguageMode = null;
if (sourceIsRemote || destinationIsRemote)
{
if (!isValidSession(session, context, out remoteLanguageMode))
{
return;
}
}
if (!destinationIsRemote)
{
providerDestinationPath =
Globber.GetProviderPath(
copyPath,
context,
out destinationProvider,
out unusedDrive);
}
else
{
// Validate remote destination path
providerDestinationPath = copyPath;
if (string.IsNullOrEmpty(providerDestinationPath))
{
context.WriteError(new ErrorRecord(
new ArgumentNullException(
string.Format(
System.Globalization.CultureInfo.InvariantCulture,
SessionStateStrings.CopyItemRemotelyPathIsNullOrEmpty,
"Destination")),
"CopyItemRemoteDestinationIsNullOrEmpty",
ErrorCategory.InvalidArgument,
providerDestinationPath));
return;
}
string root = ValidateRemotePathAndGetRoot(providerDestinationPath, session, context, remoteLanguageMode, false);
if (root == null)
{
return;
}
}
s_tracer.WriteLine("providerDestinationPath = {0}", providerDestinationPath);
ProviderInfo provider = null;
CmdletProvider providerInstance = null;
foreach (string path in paths)
{
if (path == null)
{
throw PSTraceSource.NewArgumentNullException(nameof(paths));
}
Collection<string> providerPaths;
if (sourceIsRemote)
{
// Get the root for the remote path
string root = ValidateRemotePathAndGetRoot(path, session, context, remoteLanguageMode, true);
if (root == null)
{
return;
}
providerInstance = ExecutionContext.SessionState.Internal.GetProviderInstance("FileSystem");
providerPaths = new Collection<string>();
providerPaths.Add(path);
}
else
{
providerPaths =
Globber.GetGlobbedProviderPathsFromMonadPath(
path,
false,
context,
out provider,
out providerInstance);
}
// Ensure that the source and destination are the same provider. Copying between
// providers is not supported
if (!sourceIsRemote && !destinationIsRemote && provider != destinationProvider)
{
ArgumentException argException =
PSTraceSource.NewArgumentException(
"path",
SessionStateStrings.CopyItemSourceAndDestinationNotSameProvider);
context.WriteError(
new ErrorRecord(
argException,
"CopyItemSourceAndDestinationNotSameProvider",
ErrorCategory.InvalidArgument,
providerPaths));
return;
}
bool destinationIsContainer = false;
if (!destinationIsRemote)
{
destinationIsContainer = IsItemContainer(
providerInstance,
providerDestinationPath,
context);
s_tracer.WriteLine("destinationIsContainer = {0}", destinationIsContainer);
}
foreach (string providerPath in providerPaths)
{
// Making sure to obey the StopProcessing.
if (context.Stopping)
{
return;
}
if (sourceIsRemote || destinationIsRemote)
{
CopyItem(
providerInstance,
providerPath,
providerDestinationPath,
recurse,
context);
continue;
}
bool sourceIsContainer =
IsItemContainer(
providerInstance,
providerPath,
context);
s_tracer.WriteLine("sourceIsContainer = {0}", sourceIsContainer);
if (sourceIsContainer)
{
if (destinationIsContainer)
{
if (!recurse && copyContainers == CopyContainers.CopyChildrenOfTargetContainer)
{
// Copying a container to a container without the -container or -recurse
// switch is an error.
Exception e =
PSTraceSource.NewArgumentException(
"path",
SessionStateStrings.CopyContainerToContainerWithoutRecurseOrContainer);
context.WriteError(new ErrorRecord(
e,
"CopyContainerToContainerWithoutRecurseOrContainer",
ErrorCategory.InvalidArgument,
providerPath));
}
else if (recurse && copyContainers == CopyContainers.CopyChildrenOfTargetContainer)
{
// Copy all the leaf items to a single container
CopyRecurseToSingleContainer(
providerInstance,
providerPath,
providerDestinationPath,
context);
}
else
{
// Call the provider to do a recurse copy of all the items
CopyItem(
providerInstance,
providerPath,
providerDestinationPath,
recurse,
context);
}
}
else
{
// Since we know the destination isn't a container, check to
// see if it exists.
if (ItemExists(providerInstance, providerDestinationPath, context))
{
// Since the item exists and is not a container it must
// be a leaf. Copying a container to a leaf is an error
Exception e =
PSTraceSource.NewArgumentException(
"path",
SessionStateStrings.CopyContainerItemToLeafError);
context.WriteError(new ErrorRecord(
e,
"CopyContainerItemToLeafError",
ErrorCategory.InvalidArgument,
providerPath));
}
else
{
// Copy the container to a non-existing path
CopyItem(
providerInstance,
providerPath,
providerDestinationPath,
recurse,
context);
}
}
}
else
{
// Copy a leaf to the destination
CopyItem(
providerInstance,
providerPath,
providerDestinationPath,
recurse,
context);
}
}
}
}
/// <summary>
/// Copies the specified item(s) to the specified destination.
/// </summary>
/// <param name="providerInstance">
/// The provider instance to use.
/// </param>
/// <param name="path">
/// The path to the item if it was specified on the command line.
/// </param>
/// <param name="copyPath">
/// The path to copy the item(s) to.
/// </param>
/// <param name="recurse">
/// If true all sub-containers and their children should be copied.
/// </param>
/// <param name="context">
/// The context which the core command is running.
/// </param>
/// <exception cref="NotSupportedException">
/// If the <paramref name="providerInstance"/> does not support this operation.
/// </exception>
/// <exception cref="PipelineStoppedException">
/// If the pipeline is being stopped while executing the command.
/// </exception>
/// <exception cref="ProviderInvocationException">
/// If the provider threw an exception.
/// </exception>
private void CopyItem(
CmdletProvider providerInstance,
string path,
string copyPath,
bool recurse,
CmdletProviderContext context)
{
// All parameters should have been validated by caller
Dbg.Diagnostics.Assert(
providerInstance != null,
"Caller should validate providerInstance before calling this method");
Dbg.Diagnostics.Assert(
path != null,
"Caller should validate path before calling this method");
Dbg.Diagnostics.Assert(
context != null,
"Caller should validate context before calling this method");
ContainerCmdletProvider containerCmdletProvider =
GetContainerProviderInstance(providerInstance);
try
{
containerCmdletProvider.CopyItem(path, copyPath, recurse, context);
}
catch (LoopFlowException)
{
throw;
}
catch (PipelineStoppedException)
{
throw;
}
catch (ActionPreferenceStopException)
{
throw;
}
catch (Exception e) // Catch-all OK, 3rd party callout.
{
throw NewProviderInvocationException(
"CopyItemProviderException",
SessionStateStrings.CopyItemProviderException,
containerCmdletProvider.ProviderInfo,
path,
e);
}
}
/// <summary>
/// Recursively copies many items to a single container.
/// </summary>
/// <param name="providerInstance">
/// The provider instance to use.
/// </param>
/// <param name="sourcePath">
/// The path to the item if it was specified on the command line.
/// </param>
/// <param name="destinationPath">
/// The path to copy the item(s) to.
/// </param>
/// <param name="context">
/// The context which the core command is running.
/// </param>
/// <exception cref="NotSupportedException">
/// If the <paramref name="providerInstance"/> does not support this operation.
/// </exception>
/// <exception cref="PipelineStoppedException">
/// If the pipeline is being stopped while executing the command.
/// </exception>
/// <exception cref="ProviderInvocationException">
/// If the provider threw an exception.
/// </exception>
private void CopyRecurseToSingleContainer(
CmdletProvider providerInstance,
string sourcePath,
string destinationPath,
CmdletProviderContext context)
{
Dbg.Diagnostics.Assert(
providerInstance != null,
"The providerInstance should have been verified by the caller");
Dbg.Diagnostics.Assert(
!string.IsNullOrEmpty(sourcePath),
"The sourcePath should have been verified by the caller");
Dbg.Diagnostics.Assert(
!string.IsNullOrEmpty(destinationPath),
"The destinationPath should have been verified by the caller");
Dbg.Diagnostics.Assert(
context != null,
"The context should have been verified by the caller");
ContainerCmdletProvider containerProviderInstance =
GetContainerProviderInstance(providerInstance);
// Use GetChildNames to get the relative paths of all the children
// to be copied
Collection<string> children =
GetChildNames(
new string[] { sourcePath },
ReturnContainers.ReturnMatchingContainers,
true, uint.MaxValue, false, false);
foreach (string childName in children)
{
// Making sure to obey the StopProcessing.
if (context.Stopping)
{
return;
}
// Now convert each relative path into a provider-internal path
string childPath = MakePath(providerInstance.ProviderInfo, sourcePath, childName, context);
// And then copy the item to the destination
CopyItem(containerProviderInstance, childPath, destinationPath, false, context);
}
}
/// <summary>
/// Gets the dynamic parameters for the copy-item cmdlet.
/// </summary>
/// <param name="path">
/// The path to the item if it was specified on the command line.
/// </param>
/// <param name="destination">
/// The path of the item to copy to.
/// </param>
/// <param name="recurse">
/// Tells the provider to recurse sub-containers when copying.
/// </param>
/// <param name="context">
/// The context which the core command is running.
/// </param>
/// <returns>
/// An object that has properties and fields decorated with
/// parsing attributes similar to a cmdlet class.
/// </returns>
/// <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>
/// <exception cref="ItemNotFoundException">
/// If <paramref name="path"/> does not contain glob characters and
/// could not be found.
/// </exception>
internal object CopyItemDynamicParameters(
string path,
string destination,
bool recurse,
CmdletProviderContext context)
{
if (path == null)
{
return null;
}
ProviderInfo provider = null;
CmdletProvider providerInstance = null;
CmdletProviderContext newContext =
new CmdletProviderContext(context);
newContext.SetFilters(
new Collection<string>(),
new Collection<string>(),
null);
string providerPath = null;
bool pathNotFoundOnClient = false;
try
{
Collection<string> providerPaths =
Globber.GetGlobbedProviderPathsFromMonadPath(
path,
true,
newContext,
out provider,
out providerInstance);
if (providerPaths.Count > 0)
providerPath = providerPaths[0];
}
catch (DriveNotFoundException)
{
// This exception is expected for remote sessions where drives exist in a remote session but not
// on the client.
pathNotFoundOnClient = true;
}
catch (ItemNotFoundException)
{
// This exception is expected for remote sessions where item exist in a remote session but not
// on the client.
pathNotFoundOnClient = true;
}
if (pathNotFoundOnClient)
{
// At this point, we don't know if this is a remote use of copy-item because the FromSession
// and ToSession dynamic parameters have not been retrieved yet.
// Ignore these exceptions and use the FileSystem provider as default. If this is a real drive
// issue, or if the item does not exist, it will be caught later when the drive or item path is used.
var fileSystemProviders = Providers["FileSystem"];
if (fileSystemProviders.Count > 0)
{
providerPath = path;
providerInstance = ExecutionContext.EngineSessionState.GetProviderInstance(
fileSystemProviders[0]);
}
}
if (providerInstance != null)
{
// Get the dynamic parameters for the first resolved path
return CopyItemDynamicParameters(providerInstance, providerPath, destination, recurse, newContext);
}
return null;
}
/// <summary>
/// Gets the dynamic parameters for the copy-item cmdlet.
/// </summary>
/// <param name="path">
/// The path to the item if it was specified on the command line.
/// </param>
/// <param name="destination">
/// The path to copy the item to.
/// </param>
/// <param name="recurse">
/// If true, subcontainers and their children should be copied.
/// </param>
/// <param name="providerInstance">
/// The instance of the provider to use.
/// </param>
/// <param name="context">
/// The context which the core command is running.
/// </param>
/// <returns>
/// An object that has properties and fields decorated with
/// parsing attributes similar to a cmdlet class.
/// </returns>
/// <exception cref="NotSupportedException">
/// If the <paramref name="providerInstance"/> does not support this operation.
/// </exception>
/// <exception cref="PipelineStoppedException">
/// If the pipeline is being stopped while executing the command.
/// </exception>
/// <exception cref="ProviderInvocationException">
/// If the provider threw an exception.
/// </exception>
private object CopyItemDynamicParameters(
CmdletProvider providerInstance,
string path,
string destination,
bool recurse,
CmdletProviderContext context)
{
// All parameters should have been validated by caller
Dbg.Diagnostics.Assert(
providerInstance != null,
"Caller should validate providerInstance before calling this method");
Dbg.Diagnostics.Assert(
context != null,
"Caller should validate context before calling this method");
ContainerCmdletProvider containerCmdletProvider =
GetContainerProviderInstance(providerInstance);
object result = null;
try
{
result = containerCmdletProvider.CopyItemDynamicParameters(path, destination, recurse, context);
}
catch (LoopFlowException)
{
throw;
}
catch (PipelineStoppedException)
{
throw;
}
catch (ActionPreferenceStopException)
{
throw;
}
catch (Exception e) // Catch-all OK, 3rd party callout.
{
throw NewProviderInvocationException(
"CopyItemDynamicParametersProviderException",
SessionStateStrings.CopyItemDynamicParametersProviderException,
containerCmdletProvider.ProviderInfo,
path,
e);
}
return result;
}
// This function validates a remote path, and if it exists, it returns the root path.
//
private static string ValidateRemotePathAndGetRoot(string path, Runspaces.PSSession session, CmdletProviderContext context, PSLanguageMode? languageMode, bool sourceIsRemote)
{
Hashtable op = null;
using (PowerShell ps = PowerShell.Create())
{
ps.Runspace = session.Runspace;
// Check to see if the remote PSSession is running in constrained or no language mode and if so
// then also if the path validation function already exists in the session (for the User drive
// custom endpoint case). Otherwise error out.
if (languageMode.HasValue &&
(languageMode.Value == PSLanguageMode.ConstrainedLanguage || languageMode.Value == PSLanguageMode.NoLanguage))
{
ps.Runspace = session.Runspace;
ps.AddCommand("Get-Command").AddArgument(CopyFileRemoteUtils.PSCopyRemoteUtilsName);
var result = ps.Invoke<bool>();
if (result.Count == 0)
{
context.WriteError(new ErrorRecord(
new InvalidOperationException(
string.Format(
System.Globalization.CultureInfo.InvariantCulture,
SessionStateStrings.CopyItemSessionProperties,
"LanguageMode",
session.Runspace.SessionStateProxy.LanguageMode)
),
"SessionIsNotInFullLanguageMode",
ErrorCategory.InvalidOperation,
session.Availability
)
);
return null;
}
ps.Commands.Clear();
ps.Streams.ClearStreams();
ps.AddCommand(CopyFileRemoteUtils.PSCopyRemoteUtilsName);
}
else
{
ps.AddScript(CopyFileRemoteUtils.PSValidatePathDefinition);
}
ps.AddParameter("pathToValidate", path);
if (sourceIsRemote)
{
ps.AddParameter(nameof(sourceIsRemote), true);
}
op = Microsoft.PowerShell.Commands.SafeInvokeCommand.Invoke(ps, null, context);
}
if (op == null)
{
context.WriteError(new ErrorRecord(
new InvalidOperationException(
string.Format(
System.Globalization.CultureInfo.InvariantCulture, SessionStateStrings.CopyItemValidateRemotePath, path)),
"FailedToValidateRemotePath",
ErrorCategory.InvalidOperation,
path));
return null;
}
// If the remote path is not absolute, display an error to the user.
if (op["IsAbsolute"] != null)
{
bool isAbsolute = (bool)op["IsAbsolute"];
if (!isAbsolute)
{
context.WriteError(new ErrorRecord(
new ArgumentException(
string.Format(
System.Globalization.CultureInfo.InvariantCulture, SessionStateStrings.CopyItemRemotelyPathIsNotAbsolute, path)),
"RemotePathIsNotAbsolute",
ErrorCategory.InvalidArgument,
path));
return null;
}
}
bool pathExist = false;
string root = null;
if (op["Exists"] != null)
pathExist = (bool)op["Exists"];
if (op["Root"] != null)
root = (string)op["Root"];
// Here there are two scenarios:
// 1) If the source is remote and the path does not exist, error out.
bool invalidRemoteSource = (sourceIsRemote && (!pathExist));
// 2) For a remote destination, if the root does not exist, error out.
bool invalidRemoteDestination = (root == null);
if (invalidRemoteSource || invalidRemoteDestination)
{
context.WriteError(new ErrorRecord(
new ArgumentException(
string.Format(
System.Globalization.CultureInfo.InvariantCulture, SessionStateStrings.PathNotFound, path)),
"RemotePathNotFound",
ErrorCategory.InvalidArgument,
path));
return null;
}
return root;
}
private static bool isValidSession(PSSession session, CmdletProviderContext context, out PSLanguageMode? languageMode)
{
// session == null is validated by the parameter binding
if (session.Availability != RunspaceAvailability.Available)
{
context.WriteError(new ErrorRecord(
new InvalidOperationException(
string.Format(System.Globalization.CultureInfo.InvariantCulture,
SessionStateStrings.CopyItemSessionProperties,
"Availability", session.Availability)),
"SessionIsNotAvailable",
ErrorCategory.InvalidOperation,
session.Availability));
languageMode = null;
return false;
}
languageMode = session.Runspace.SessionStateProxy.LanguageMode;
return true;
}
#endregion CopyItem
#endregion ContainerCmdletProvider accessors
}
/// <summary>
/// Defines the action to be taken for Navigation cmdlets.
/// </summary>
internal enum ProcessMode
{
/// <summary>
/// Write out the details.
/// </summary>
Enumerate = 1,
/// <summary>
/// Delete the item.
/// </summary>
Delete = 2
}
}
#pragma warning restore 56500