Imports System.Collections.Generic
Imports Microsoft.VisualBasic
Imports System.Security.AccessControl
Imports Newtonsoft.Json.Linq
Imports Newtonsoft.Json.Converters
Imports Newtonsoft.Json.Serialization
Public Class DirectoryExtensions
Shared Function GetFileSystemAccessRules(d As DirectoryInfo, ByVal errorHandler As Action(Of Object, DirectoryTraversalErrorEventArgs)) As IEnumerable(Of FileSystemAccessRule)
Dim ds As DirectorySecurity = d.GetAccessControl()
Dim arrRules As AuthorizationRuleCollection = ds.GetAccessRules(True, True, GetType(Security.Principal.NTAccount))
Return arrRules.Cast(Of FileSystemAccessRule)()
If (Not HandleError(errorHandler, d.FullName, ex))
Return Enumerable.Empty(Of FileSystemAccessRule)()
Shared Function EnumerateDirectories(ByVal directory As String, ByVal errorHandler As Action(Of Object, DirectoryTraversalErrorEventArgs)) As IEnumerable(Of DirectoryInfo)
di = new DirectoryInfo(directory)
If (Not HandleError(errorHandler, directory, ex))
Return Enumerable.Empty(Of DirectoryInfo)()
Dim query = RecursiveEnumerableExtensions.Traverse(di,
Return d.GetDirectories()
If (Not HandleError(errorHandler, d.FullName, ex))
Return Enumerable.Empty(Of DirectoryInfo)()
Shared Function EnumerateDirectoryFileSystemAccessRules(ByVal directory As String, ByVal errorHandler As Action(Of Object, DirectoryTraversalErrorEventArgs)) As IEnumerable(Of Tuple(Of DirectoryInfo, IEnumerable(Of FileSystemAccessRule)))
Return EnumerateDirectories(directory, errorHandler).Select(Function(d) Tuple.Create(d, GetFileSystemAccessRules(d, errorHandler)))
Shared Public Function SerializeFileAccessRules(ByVal directory As String, ByVal errorHandler As Action(Of Object, DirectoryTraversalErrorEventArgs), Optional ByVal formatting As Formatting = Formatting.Indented)
Dim query = EnumerateDirectoryFileSystemAccessRules(directory, errorHandler).Select(
Function(tuple) New With {
.directory = tuple.Item1.FullName,
.permissions = tuple.Item2.Select(
.IdentityReference = a.IdentityReference.ToString(),
.AccessControlType = a.AccessControlType.ToString(),
.FileSystemRights = a.FileSystemRights.ToString(),
.IsInherited = a.IsInherited.ToString()
Return JsonConvert.SerializeObject(query, formatting)
Private Shared Function HandleError(ByVal errorHandler As Action(Of Object, DirectoryTraversalErrorEventArgs), ByVal fullName as String, ByVal ex as Exception) As Boolean
If (errorHandler Is Nothing)
Dim args As New DirectoryTraversalErrorEventArgs(fullName, ex)
errorHandler(GetType(DirectoryExtensions), args)
Public Class DirectoryTraversalErrorEventArgs
Private _directory As String
Private _exception As Exception
Public Sub New(ByVal directory as String, ByVal exception as Exception)
Me._directory = directory
Me._exception = exception
Public Property Handled As Boolean = false
Public Readonly Property Directory As String
Public Readonly Property Exception As Exception
Public Module RecursiveEnumerableExtensions
Iterator Function Traverse(Of T)(ByVal root As T, ByVal children As Func(Of T, IEnumerable(Of T)), ByVal Optional includeSelf As Boolean = True) As IEnumerable(Of T)
If includeSelf Then Yield root
Dim stack = New Stack(Of IEnumerator(Of T))()
stack.Push(children(root).GetEnumerator())
Dim enumerator = stack.Peek()
If Not enumerator.MoveNext() Then
stack.Push(children(enumerator.Current).GetEnumerator())
For Each enumerator In stack
Test(Directory.GetCurrentDirectory())
Friend Sub Test(ByVal curDirectory As String)
Console.WriteLine("Testing directory {0}", curDirectory)
Dim errors = New List(Of Tuple(Of String, String))
Dim handler As Action(Of Object, DirectoryTraversalErrorEventArgs) =
errors.Add(Tuple.Create(e.Directory, e.Exception.Message))
Dim json As String = DirectoryExtensions.SerializeFileAccessRules(curDirectory, handler)
Console.WriteLine("Error in directory {0}: {1}", e.Item1, e.Item2)
File.WriteAllText("ABCD.json", json)
Console.WriteLine("Environment version: " & Environment.Version.ToString())
Console.WriteLine("Json.NET version: " & GetType(JsonSerializer).Assembly.FullName)
Directory.CreateDirectory("SubDirectory")
TestClass.Test("C:\TEMP")
Console.WriteLine("Unhandled exception: ")