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.
 
 

317 lines
10 KiB

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