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.
 
 

331 lines
11 KiB

using Alphaleonis.Win32.Filesystem;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Management.Automation;
using System.Linq;
namespace NTFSSecurity
{
[Cmdlet(VerbsCommon.Get, "ChildItem2")]
[OutputType(typeof(FileInfo), typeof(DirectoryInfo))]
public class GetChildItem2 : BaseCmdlet
{
private string filter = "*";
private SwitchParameter recurse;
private SwitchParameter directory;
private SwitchParameter file;
private System.IO.FileAttributes attributes;
private SwitchParameter hidden;
private SwitchParameter system;
private SwitchParameter readOnly;
private SwitchParameter force;
private SwitchParameter skipMountPoints;
private SwitchParameter skipSymbolicLinks;
private bool getFileSystemModeProperty = false;
private bool identifyHardLinks = false;
private int? depth;
WildcardPattern wildcard = null;
System.Reflection.MethodInfo modeMethodInfo = null;
[Parameter(Position = 1, ValueFromPipeline = true, ValueFromPipelineByPropertyName = true)]
[ValidateNotNullOrEmpty]
[Alias("FullName")]
public string[] Path
{
get { return paths.ToArray(); }
set
{
paths.Clear();
paths.AddRange(value);
}
}
[Parameter(Position = 2)]
public string Filter
{
get { return filter; }
set { filter = value; }
}
[Parameter]
public SwitchParameter Recurse
{
get { return recurse; }
set { recurse = value; }
}
[Parameter]
public SwitchParameter Directory
{
get { return directory; }
set { directory = value; }
}
[Parameter]
public SwitchParameter File
{
get { return file; }
set { file = value; }
}
[Parameter]
public System.IO.FileAttributes Attributes
{
get { return attributes; }
set { attributes = value; ; }
}
[Parameter()]
public SwitchParameter Hidden
{
get { return hidden; }
set { hidden = value; }
}
[Parameter]
public SwitchParameter System
{
get { return system; }
set { system = value; }
}
[Parameter]
public SwitchParameter ReadOnly
{
get { return readOnly; }
set { readOnly = value; }
}
[Parameter]
public SwitchParameter Force
{
get { return force; }
set { force = value; }
}
[Parameter]
public SwitchParameter SkipMountPoints
{
get { return skipMountPoints; }
set { skipMountPoints = value; }
}
[Parameter]
public SwitchParameter SkipSymbolicLinks
{
get { return skipSymbolicLinks; }
set { skipSymbolicLinks = value; }
}
[Parameter]
public int? Depth
{
get { return depth; }
set { depth = value; }
}
protected override void BeginProcessing()
{
base.BeginProcessing();
if (paths.Count == 0)
{
paths = new List<string>() { GetVariableValue("PWD").ToString() };
}
wildcard = new WildcardPattern(filter, WildcardOptions.Compiled | WildcardOptions.IgnoreCase);
modeMethodInfo = typeof(FileSystemCodeMembers).GetMethod("Mode");
getFileSystemModeProperty = (bool)((Hashtable)MyInvocation.MyCommand.Module.PrivateData)["GetFileSystemModeProperty"];
identifyHardLinks = (bool)((Hashtable)MyInvocation.MyCommand.Module.PrivateData)["IdentifyHardLinks"];
}
protected override void ProcessRecord()
{
foreach (var path in paths)
{
DirectoryInfo di = null;
try
{
di = (DirectoryInfo)GetFileSystemInfo2(path);
}
catch (System.IO.FileNotFoundException ex)
{
WriteError(new ErrorRecord(ex, "FileNotFound", ErrorCategory.ObjectNotFound, path));
continue;
}
try
{
WriteFileSystem(di, 0);
}
catch (PipelineStoppedException ex)
{
throw ex;
}
}
}
private void WriteFileSystem(FileSystemInfo fsi, int currentDepth)
{
var di = fsi as DirectoryInfo;
try
{
if (di != null)
{
if (directory)
{
var files = di.EnumerateDirectories(filter, global::System.IO.SearchOption.TopDirectoryOnly);
WriteFileSystemInfoCollection(files.GetEnumerator());
}
else if (file)
{
var files = di.EnumerateFiles(filter, global::System.IO.SearchOption.TopDirectoryOnly);
WriteFileSystemInfoCollection(files.GetEnumerator());
}
else
{
var files = di.EnumerateFileSystemInfos(filter, global::System.IO.SearchOption.TopDirectoryOnly);
WriteFileSystemInfoCollection(files.GetEnumerator());
}
}
if (recurse)
{
try
{
var subDis = di.EnumerateDirectories("*", global::System.IO.SearchOption.TopDirectoryOnly);
var subDisEnumerator = subDis.GetEnumerator();
foreach (var subDi in subDis)
{
//if ((subDi.Attributes & global::System.IO.FileAttributes.Hidden) == global::System.IO.FileAttributes.Hidden & !hidden)
// continue;
subDi.RefreshEntryInfo();
if (subDi.EntryInfo.IsMountPoint && skipMountPoints) { continue; }
if (subDi.EntryInfo.IsSymbolicLink && skipSymbolicLinks) { continue; }
if (depth.HasValue)
{
if (currentDepth < depth)
WriteFileSystem(subDi, currentDepth + 1);
}
else
WriteFileSystem(subDi, 0);
}
}
catch (PipelineStoppedException ex)
{
throw ex;
}
catch (Exception)
{
WriteVerbose(string.Format("Cannot access folder '{0}' for recursive operation", di));
}
}
}
catch (UnauthorizedAccessException ex)
{
WriteError(new ErrorRecord(ex, "DirUnauthorizedAccessError", ErrorCategory.PermissionDenied, di.FullName));
}
catch (PipelineStoppedException ex)
{
throw ex;
}
catch (Exception ex)
{
//System.Management.Automation.BreakException or System.Management.Automation.ContinueException cannot be caught due to its protection level in PowerShell v2
if (ex.GetType().FullName == "System.Management.Automation.BreakException" | ex.GetType().FullName == "System.Management.Automation.ContinueException")
{
throw ex;
}
WriteError(new ErrorRecord(ex, "DirUnspecifiedError", ErrorCategory.NotSpecified, di.FullName));
}
}
protected void WriteFileSystemInfoCollection(IEnumerator fileSystemInfos)
{
while (fileSystemInfos.MoveNext())
{
FileSystemInfo current = (FileSystemInfo)fileSystemInfos.Current;
if (!wildcard.IsMatch(current.Name))
{
continue;
}
var writeItem = force.ToBool();
if (MyInvocation.BoundParameters.ContainsKey("Attributes"))
{
if ((current.Attributes & attributes) != attributes)
continue;
writeItem = true;
}
else
{
if (hidden)
force = true;
if ((current.Attributes & global::System.IO.FileAttributes.Hidden) != global::System.IO.FileAttributes.Hidden)
writeItem = true;
if (hidden)
if ((current.Attributes & global::System.IO.FileAttributes.Hidden) != global::System.IO.FileAttributes.Hidden)
writeItem = false;
if (system)
if ((current.Attributes & global::System.IO.FileAttributes.System) != global::System.IO.FileAttributes.System)
writeItem = false;
if (readOnly)
if ((current.Attributes & global::System.IO.FileAttributes.ReadOnly) != global::System.IO.FileAttributes.ReadOnly)
writeItem = false;
}
if (writeItem)
{
PSObject item;
if (current is FileInfo)
{
item = new PSObject((FileInfo)current);
}
else
{
item = new PSObject((DirectoryInfo)current);
}
//can be disabled for a better performance in the PSD1 file, PrivateData section, GetFileSystemModeProperty = $true / $false
if (getFileSystemModeProperty)
item.Properties.Add(new PSCodeProperty("Mode", modeMethodInfo));
if (identifyHardLinks == true && current is FileInfo)
{
try
{
item.Properties.Add(new PSNoteProperty("HardLinkCount", Alphaleonis.Win32.Filesystem.File.EnumerateHardlinks(current.FullName).Count()));
}
catch
{
WriteDebug(string.Format("Could not read hard links for '{0}'", current.FullName));
}
}
WriteObject(item);
}
}
}
protected override void EndProcessing()
{
base.EndProcessing();
}
}
}