PowerShell script is taking amazing long time to run.

Jim 306 Reputation points
2023-08-14T14:03:13.6833333+00:00

I have one file share on our 2012 server. Users have it mapped to a drive. I want to create a spreadsheet of each folder on the share (recursively), what security groups have access to it, and what rights those groups have to the data within the folder.

Now, I have found and run several scripts. They all take an enormous amount of time. For example I am running one now on a small folder (393 files, 29 folders) it is still running after 23 minutes. To run this script on the entire file share of around 223,339 Files, 34,644 Folders will take many hours. I want to be able to get this info monthly to keep an audit trail on it.

All the scripts I find use the same basic methods to recursively search a tree. Does anybody else know a way to either speed this up or use something else? Bottom line I want a spreadsheet I can manipulate to see who can see or modify what with out having to look at each folder to confirm.

The script running on the whole share has been running for 11 hours and 15 minutes at this writing. It is running on the server.

Script:

# Define the parent folder to check permissions on

$foldertosearch = "c:\Company\";

# Where to save the results
$exportfile = "C:\Company\Scripts\Output\FolderPermissions.csv"

# Delimiter used in the output file - DO NOT use a comma
$exportdelimiter = "^";

# Get all folder and sub-folder paths
$parentfolder = @(get-item $foldertosearch);
$subfolders = @(get-childitem $foldertosearch -recurse);
$allfolders = $parentfolder + $subfolders;

# Get domain name as a wildcard
$domainwildcard = (get-addomain).netbiosname + "*";


# Recursive function to find groups and sub groups
function get-subgroups ($groupname, $foldername, $rights) {

    # Get all members of the group    
    $members = get-adgroup $groupname | get-adgroupmember;

    # Loop through each member
    foreach ($member in $members) {

        # If a sub-group is found, recurse
        if ($member.objectclass -eq "group") {

            get-subgroups $member.samaccountname $foldername $rights;
        }

        # If a user is found, export results
        if ($member.objectclass -eq "user") {

            $output = ($folder.fullname, $permission.filesystemrights, $groupname, $member.name) -join $script:exportdelimiter;
            $output >> $script:exportfile;
        }
    }
}

# Loop through each folder
foreach ($folder in $allfolders) {

    # Get ACLS
    $acls = get-acl $folder.fullname;
    
    # Loop through each ACL on the folder
    foreach ($acl in $acls) {
 
        $access = $acl.access;

        # Loop through each permission within the ACL
        foreach ($permission in $access) {

            # Only check identities matching the domain name
            if ($permission.identityreference -like $domainwildcard) {

                # Remove the domain name from the identity
                $identity = ($permission.identityreference -split "\\")[1];

                # Get AD Object
                $adobject = get-adobject -filter 'SamAccountName -eq $identity';
           
                # If the identity is a group, recurse
                if ($adobject.objectclass -eq "group") {

                  get-subgroups $identity $folder.fullname $permission.filesystemrights;
                    
                }

                # If a user is found, export results
                if ($adobject.objectclass -eq "user") {

                    $output = ($folder.fullname, $permission.filesystemrights, "Direct Assignment", $identity) -join $exportdelimiter;
                    $output >> $exportfile;
                }
            }
        }
    }
}
Windows for business Windows Server User experience PowerShell
{count} votes

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.