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.
 
 

332 lines
11 KiB

  1. using Alphaleonis.Win32.Filesystem;
  2. using System;
  3. using System.Collections;
  4. using System.Collections.Generic;
  5. using System.Management.Automation;
  6. using System.Linq;
  7. namespace NTFSSecurity
  8. {
  9. [Cmdlet(VerbsCommon.Get, "ChildItem2")]
  10. [OutputType(typeof(FileInfo), typeof(DirectoryInfo))]
  11. public class GetChildItem2 : BaseCmdlet
  12. {
  13. private string filter = "*";
  14. private SwitchParameter recurse;
  15. private SwitchParameter directory;
  16. private SwitchParameter file;
  17. private System.IO.FileAttributes attributes;
  18. private SwitchParameter hidden;
  19. private SwitchParameter system;
  20. private SwitchParameter readOnly;
  21. private SwitchParameter force;
  22. private SwitchParameter skipMountPoints;
  23. private SwitchParameter skipSymbolicLinks;
  24. private bool getFileSystemModeProperty = false;
  25. private bool identifyHardLinks = false;
  26. private int? depth;
  27. WildcardPattern wildcard = null;
  28. System.Reflection.MethodInfo modeMethodInfo = null;
  29. [Parameter(Position = 1, ValueFromPipeline = true, ValueFromPipelineByPropertyName = true)]
  30. [ValidateNotNullOrEmpty]
  31. [Alias("FullName")]
  32. public string[] Path
  33. {
  34. get { return paths.ToArray(); }
  35. set
  36. {
  37. paths.Clear();
  38. paths.AddRange(value);
  39. }
  40. }
  41. [Parameter(Position = 2)]
  42. public string Filter
  43. {
  44. get { return filter; }
  45. set { filter = value; }
  46. }
  47. [Parameter]
  48. public SwitchParameter Recurse
  49. {
  50. get { return recurse; }
  51. set { recurse = value; }
  52. }
  53. [Parameter]
  54. public SwitchParameter Directory
  55. {
  56. get { return directory; }
  57. set { directory = value; }
  58. }
  59. [Parameter]
  60. public SwitchParameter File
  61. {
  62. get { return file; }
  63. set { file = value; }
  64. }
  65. [Parameter]
  66. public System.IO.FileAttributes Attributes
  67. {
  68. get { return attributes; }
  69. set { attributes = value; ; }
  70. }
  71. [Parameter()]
  72. public SwitchParameter Hidden
  73. {
  74. get { return hidden; }
  75. set { hidden = value; }
  76. }
  77. [Parameter]
  78. public SwitchParameter System
  79. {
  80. get { return system; }
  81. set { system = value; }
  82. }
  83. [Parameter]
  84. public SwitchParameter ReadOnly
  85. {
  86. get { return readOnly; }
  87. set { readOnly = value; }
  88. }
  89. [Parameter]
  90. public SwitchParameter Force
  91. {
  92. get { return force; }
  93. set { force = value; }
  94. }
  95. [Parameter]
  96. public SwitchParameter SkipMountPoints
  97. {
  98. get { return skipMountPoints; }
  99. set { skipMountPoints = value; }
  100. }
  101. [Parameter]
  102. public SwitchParameter SkipSymbolicLinks
  103. {
  104. get { return skipSymbolicLinks; }
  105. set { skipSymbolicLinks = value; }
  106. }
  107. [Parameter]
  108. public int? Depth
  109. {
  110. get { return depth; }
  111. set { depth = value; }
  112. }
  113. protected override void BeginProcessing()
  114. {
  115. base.BeginProcessing();
  116. if (paths.Count == 0)
  117. {
  118. paths = new List<string>() { GetVariableValue("PWD").ToString() };
  119. }
  120. wildcard = new WildcardPattern(filter, WildcardOptions.Compiled | WildcardOptions.IgnoreCase);
  121. modeMethodInfo = typeof(FileSystemCodeMembers).GetMethod("Mode");
  122. getFileSystemModeProperty = (bool)((Hashtable)MyInvocation.MyCommand.Module.PrivateData)["GetFileSystemModeProperty"];
  123. identifyHardLinks = (bool)((Hashtable)MyInvocation.MyCommand.Module.PrivateData)["IdentifyHardLinks"];
  124. }
  125. protected override void ProcessRecord()
  126. {
  127. foreach (var path in paths)
  128. {
  129. DirectoryInfo di = null;
  130. try
  131. {
  132. di = (DirectoryInfo)GetFileSystemInfo2(path);
  133. }
  134. catch (System.IO.FileNotFoundException ex)
  135. {
  136. WriteError(new ErrorRecord(ex, "FileNotFound", ErrorCategory.ObjectNotFound, path));
  137. continue;
  138. }
  139. try
  140. {
  141. WriteFileSystem(di, 0);
  142. }
  143. catch (PipelineStoppedException ex)
  144. {
  145. throw ex;
  146. }
  147. }
  148. }
  149. private void WriteFileSystem(FileSystemInfo fsi, int currentDepth)
  150. {
  151. var di = fsi as DirectoryInfo;
  152. try
  153. {
  154. if (di != null)
  155. {
  156. if (directory)
  157. {
  158. var files = di.EnumerateDirectories(filter, global::System.IO.SearchOption.TopDirectoryOnly);
  159. WriteFileSystemInfoCollection(files.GetEnumerator());
  160. }
  161. else if (file)
  162. {
  163. var files = di.EnumerateFiles(filter, global::System.IO.SearchOption.TopDirectoryOnly);
  164. WriteFileSystemInfoCollection(files.GetEnumerator());
  165. }
  166. else
  167. {
  168. var files = di.EnumerateFileSystemInfos(filter, global::System.IO.SearchOption.TopDirectoryOnly);
  169. WriteFileSystemInfoCollection(files.GetEnumerator());
  170. }
  171. }
  172. if (recurse)
  173. {
  174. try
  175. {
  176. var subDis = di.EnumerateDirectories("*", global::System.IO.SearchOption.TopDirectoryOnly);
  177. var subDisEnumerator = subDis.GetEnumerator();
  178. foreach (var subDi in subDis)
  179. {
  180. //if ((subDi.Attributes & global::System.IO.FileAttributes.Hidden) == global::System.IO.FileAttributes.Hidden & !hidden)
  181. // continue;
  182. subDi.RefreshEntryInfo();
  183. if (subDi.EntryInfo.IsMountPoint && skipMountPoints) { continue; }
  184. if (subDi.EntryInfo.IsSymbolicLink && skipSymbolicLinks) { continue; }
  185. if (depth.HasValue)
  186. {
  187. if (currentDepth < depth)
  188. WriteFileSystem(subDi, currentDepth + 1);
  189. }
  190. else
  191. WriteFileSystem(subDi, 0);
  192. }
  193. }
  194. catch (PipelineStoppedException ex)
  195. {
  196. throw ex;
  197. }
  198. catch (Exception)
  199. {
  200. WriteVerbose(string.Format("Cannot access folder '{0}' for recursive operation", di));
  201. }
  202. }
  203. }
  204. catch (UnauthorizedAccessException ex)
  205. {
  206. WriteError(new ErrorRecord(ex, "DirUnauthorizedAccessError", ErrorCategory.PermissionDenied, di.FullName));
  207. }
  208. catch (PipelineStoppedException ex)
  209. {
  210. throw ex;
  211. }
  212. catch (Exception ex)
  213. {
  214. //System.Management.Automation.BreakException or System.Management.Automation.ContinueException cannot be caught due to its protection level in PowerShell v2
  215. if (ex.GetType().FullName == "System.Management.Automation.BreakException" | ex.GetType().FullName == "System.Management.Automation.ContinueException")
  216. {
  217. throw ex;
  218. }
  219. WriteError(new ErrorRecord(ex, "DirUnspecifiedError", ErrorCategory.NotSpecified, di.FullName));
  220. }
  221. }
  222. protected void WriteFileSystemInfoCollection(IEnumerator fileSystemInfos)
  223. {
  224. while (fileSystemInfos.MoveNext())
  225. {
  226. FileSystemInfo current = (FileSystemInfo)fileSystemInfos.Current;
  227. if (!wildcard.IsMatch(current.Name))
  228. {
  229. continue;
  230. }
  231. var writeItem = force.ToBool();
  232. if (MyInvocation.BoundParameters.ContainsKey("Attributes"))
  233. {
  234. if ((current.Attributes & attributes) != attributes)
  235. continue;
  236. writeItem = true;
  237. }
  238. else
  239. {
  240. if (hidden)
  241. force = true;
  242. if ((current.Attributes & global::System.IO.FileAttributes.Hidden) != global::System.IO.FileAttributes.Hidden)
  243. writeItem = true;
  244. if (hidden)
  245. if ((current.Attributes & global::System.IO.FileAttributes.Hidden) != global::System.IO.FileAttributes.Hidden)
  246. writeItem = false;
  247. if (system)
  248. if ((current.Attributes & global::System.IO.FileAttributes.System) != global::System.IO.FileAttributes.System)
  249. writeItem = false;
  250. if (readOnly)
  251. if ((current.Attributes & global::System.IO.FileAttributes.ReadOnly) != global::System.IO.FileAttributes.ReadOnly)
  252. writeItem = false;
  253. }
  254. if (writeItem)
  255. {
  256. PSObject item;
  257. if (current is FileInfo)
  258. {
  259. item = new PSObject((FileInfo)current);
  260. }
  261. else
  262. {
  263. item = new PSObject((DirectoryInfo)current);
  264. }
  265. //can be disabled for a better performance in the PSD1 file, PrivateData section, GetFileSystemModeProperty = $true / $false
  266. if (getFileSystemModeProperty)
  267. item.Properties.Add(new PSCodeProperty("Mode", modeMethodInfo));
  268. if (identifyHardLinks == true && current is FileInfo)
  269. {
  270. try
  271. {
  272. item.Properties.Add(new PSNoteProperty("HardLinkCount", Alphaleonis.Win32.Filesystem.File.EnumerateHardlinks(current.FullName).Count()));
  273. }
  274. catch
  275. {
  276. WriteDebug(string.Format("Could not read hard links for '{0}'", current.FullName));
  277. }
  278. }
  279. WriteObject(item);
  280. }
  281. }
  282. }
  283. protected override void EndProcessing()
  284. {
  285. base.EndProcessing();
  286. }
  287. }
  288. }