mirror of https://github.com/raandree/NTFSSecurity
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
162 lines
5.9 KiB
162 lines
5.9 KiB
using Alphaleonis.Win32.Filesystem;
|
|
using System;
|
|
using System.Management.Automation;
|
|
|
|
namespace NTFSSecurity
|
|
{
|
|
[Cmdlet(VerbsCommon.Copy, "Item2", SupportsShouldProcess = true)]
|
|
[OutputType(typeof(FileInfo), typeof(DirectoryInfo))]
|
|
public class CopyItem2 : BaseCmdlet
|
|
{
|
|
private string destination;
|
|
private SwitchParameter force;
|
|
private bool passThru;
|
|
|
|
[Parameter(Position = 1, Mandatory = true, ValueFromPipeline = true, ValueFromPipelineByPropertyName = true)]
|
|
[ValidateNotNullOrEmpty]
|
|
[Alias("FullName")]
|
|
[FileSystemPathTransformation]
|
|
public string[] Path
|
|
{
|
|
get { return paths.ToArray(); }
|
|
set
|
|
{
|
|
paths.Clear();
|
|
paths.AddRange(value);
|
|
}
|
|
}
|
|
|
|
[Parameter(Position = 2, Mandatory = true, ValueFromPipelineByPropertyName = true)]
|
|
[FileSystemPathTransformation]
|
|
public string Destination
|
|
{
|
|
get { return destination; }
|
|
set { destination = value; }
|
|
}
|
|
|
|
[Parameter]
|
|
public SwitchParameter Force
|
|
{
|
|
get { return force; }
|
|
set { force = value; }
|
|
}
|
|
|
|
[Parameter]
|
|
public bool PassThru
|
|
{
|
|
get { return passThru; }
|
|
set { passThru = value; }
|
|
}
|
|
|
|
protected override void BeginProcessing()
|
|
{
|
|
base.BeginProcessing();
|
|
|
|
destination = GetRelativePath(destination);
|
|
WriteVerbose(string.Format("Destination path is '{0}'", destination));
|
|
}
|
|
|
|
protected override void ProcessRecord()
|
|
{
|
|
foreach (var path in paths)
|
|
{
|
|
WriteVerbose(string.Format("Copying item '{0}'", path));
|
|
|
|
FileSystemInfo item = null;
|
|
var actualDestination = string.Empty;
|
|
|
|
var resolvedPath = GetRelativePath(path);
|
|
|
|
try
|
|
{
|
|
item = GetFileSystemInfo2(resolvedPath);
|
|
}
|
|
catch (System.IO.FileNotFoundException ex)
|
|
{
|
|
WriteError(new ErrorRecord(ex, "FileNotFound", ErrorCategory.ObjectNotFound, resolvedPath));
|
|
continue;
|
|
}
|
|
|
|
//destination is a directory
|
|
if (Directory.Exists(destination))
|
|
{
|
|
//hence adding the file name to the destination path
|
|
actualDestination = System.IO.Path.Combine(destination, System.IO.Path.GetFileName(resolvedPath));
|
|
}
|
|
else
|
|
{
|
|
actualDestination = destination;
|
|
}
|
|
|
|
// A folder at the destination counts as well; before 5.0.0-rc6, only a file did.
|
|
var destinationExists = !force && (File.Exists(actualDestination) || Directory.Exists(actualDestination));
|
|
|
|
// Report a conflict only for an operation that runs; -WhatIf names it in a verbose message (#108).
|
|
if (!ShouldProcess(resolvedPath, item is FileInfo ? "Copy File" : "Copy Directory"))
|
|
{
|
|
if (destinationExists)
|
|
{
|
|
WriteVerbose(string.Format("The destination '{0}' already exists; without -Force, the copy would fail", actualDestination));
|
|
}
|
|
else
|
|
{
|
|
var missingFolder = GetMissingDestinationFolder(actualDestination);
|
|
if (missingFolder != null)
|
|
{
|
|
WriteVerbose(string.Format("The destination folder '{0}' does not exist; the copy would fail", missingFolder));
|
|
}
|
|
}
|
|
|
|
continue;
|
|
}
|
|
|
|
if (destinationExists)
|
|
{
|
|
WriteError(new ErrorRecord(new AlreadyExistsException(), "DestinationFileAlreadyExists", ErrorCategory.ResourceExists, actualDestination));
|
|
continue;
|
|
}
|
|
|
|
if (WriteMissingDestinationFolderError(actualDestination, "CopyError"))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
try
|
|
{
|
|
FileSystemInfo copy = null;
|
|
|
|
if (item is FileInfo)
|
|
{
|
|
copy = ((FileInfo)item).CopyTo(actualDestination, force ? CopyOptions.None : CopyOptions.FailIfExists, PathFormat.RelativePath);
|
|
WriteVerbose(string.Format("File '{0}' copied to '{1}'", resolvedPath, actualDestination));
|
|
}
|
|
else
|
|
{
|
|
// AlphaFS 2.2 copies into an existing folder only and otherwise fails with a
|
|
// DirectoryNotFoundException for the first file.
|
|
Directory.CreateDirectory(actualDestination);
|
|
copy = ((DirectoryInfo)item).CopyTo(actualDestination, force ? CopyOptions.None : CopyOptions.FailIfExists, PathFormat.RelativePath);
|
|
WriteVerbose(string.Format("Directory '{0}' copied to '{1}'", resolvedPath, actualDestination));
|
|
}
|
|
|
|
// Write the object for the copy that CopyTo returns, not the source item.
|
|
if (passThru)
|
|
WriteObject(copy);
|
|
}
|
|
catch (System.IO.IOException ex)
|
|
{
|
|
WriteError(new ErrorRecord(ex, "CopyError", ErrorCategory.InvalidData, resolvedPath));
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
WriteError(new ErrorRecord(ex, "CopyError", ErrorCategory.NotSpecified, resolvedPath));
|
|
}
|
|
}
|
|
}
|
|
|
|
protected override void EndProcessing()
|
|
{
|
|
base.EndProcessing();
|
|
}
|
|
}
|
|
}
|
|
|