Unable to recurse using .NET System.IO.Directory.EnumerateDirectories

Hello!

I have a requirement to recursively search N levels of directories and log where the folder NTFS Inheritance permission is disabled. E.g.

C:\ACLTest
C:\ACLTest\myFolder1-InheritOn
C:\ACLTest\myFolder2-InheritOff  <- - NTFS Inheritance is disabled; log this directory in my output
C:\ACLTest\myFolder3-InheritOn\mySubFolderA-InheritOFF  <- - NTFS Inheritance is disabled; log this directory in my output

Specifics:
• The directories are very large – 10s of thousands of directories
• I only need to know if one (1) ACL is NOT inherited.

First, I started with Get-ChildItem for the directory list. But that proved very inefficient/slow for the number of directories I’m working with. I did some research and found that the .NET assembly System.IO.Directory.EnumerateDirectories is much faster. That’s the rabbit hole I’m in now. I’m following the Microsoft Docs .NET reference found here.

Here is a sample of what I’m doing:

$enumFolders = [System.IO.Directory]::EnumerateDirectories('C:\ACLTest')
Foreach ($myDir in $enumFolders){
    $myDirACL = Get-Acl -Path $myDir
    If ($myDirACL[0].Access.IsInherited -eq $false){ # only need to find one, NTFS persmissions lists the non-inherited permissions first.
        Write-Output "Non-Inherited Folder $myDir"
    }
}

Output (Missing subdirectory C:\ACLTest\myFolder3-InheritOn\mySubFolderA-InheritOFF ):

PS C:\ACLTest> C:\ACLTest\Get-ACLEnum.ps1
Non-Inherited Folder C:\ACLTest\myFolder2-InheritOff
PS C:\ACLTest>

Now, referencing the Microsoft Docs, I found that I can use EnumerationOptions which is “An object that describes the search and enumeration configuration to use.” Following the Docs, I then find another page that describes an EnumerationOptions Boolean Property named “RecurseSubdirectories.” However, I have yet to figure out how to create “An object that describes the search and enumeration configuration to use” and use it in my code.
I’ve tried many variations such as (see below) but none have worked.

$enumOptions = New-Object -TypeName psobject -Property @{'RecurseSubDirectories' = $true}
#$enumFolders = [System.IO.Directory]::EnumerateDirectories('C:\ACLTest')
#From the MS Docs EnumerateDirectories(String, String, EnumerationOptions) or EnumerateDirectories(<path>, <search pattern>, EnumerationOptions)
$enumFolders = [System.IO.Directory]::EnumerateDirectories('C:\ACLTest', '*', $enumOptions)
Foreach ($myDir in $enumFolders){
    $myDirACL = Get-Acl -Path $myDir
    If ($myDirACL[0].Access.IsInherited -eq $false){ # only need to find one, NTFS persmissions lists the non-inherited permissions first.
        Write-Output "Non-Inherited Folder $myDir"
    }
}

Output:

PS C:\ACLTest> c:\ACLTest\Get-ACLEnum.ps1
Cannot find an overload for "EnumerateDirectories" and the argument count: "3".
At C:\ACLTest\Get-ACLEnum.ps1:5 char:1
+ $enumFolders = [System.IO.Directory]::EnumerateDirectories('C:\ACLTes ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [], MethodException
    + FullyQualifiedErrorId : MethodCountCouldNotFindBest
 
Non-Inherited Folder C:\ACLTest\myFolder2-InheritOff
PS C:\ACLTest>

The way I read the docs is that I can overload the EnumerateDirectories method with three arguments. I’ve yet to find the proper syntax to recurse subdirectories. I would be very thankful if someone could point me in the right direction.
Thank you!

BoBoTheClown,
Welcome to the forum. :wave:t4:

I’m not sure if I completely understand what you’re actually trying to do but are you sure you’re using the right .Net version? The overload you’re refering to only exists in .Net versions starting with 5 or higher.

Olaf,
Thanks for the welcome! Okay, I just learned that there is a difference between .NET Framework and .NET Runtime. With that said, I installed .NET 5 Desktop Runtime but the overload error still persists. Do I need to tell PowerShell to use .NET 5? Should PS automatically pick that up?

Windows powershell uses .net framework. Powershell (formerly powershell core) uses newer .net. You don’t have to install the runtime, just install powershell core

If you just want all directories, you can use that search option:

$enumFolders = [System.IO.Directory]::EnumerateDirectories('C:\ACLTest', '*',[System.IO.SearchOption]::AllDirectories)

That might not be what you want though. Wouldn’t you want to stop checking subfolders when you find a parent that hasn’t inherited the ACL?

All, thanks for the input. Ultimately, I just needed to install PowerShell v7 to make EnumerationsOptions available.