modify permission on root folder as well as sub-folders

Hello,

I have a script to modify permissions on all sub-folders and files of any folder i point it too.  For example, I can point the script at a folder I want to modify say:  "Z:\data_folder".

 So this script works great if I want to modify permissions on all files and folders below "Z:\data_folder" but it doesn't touch the "z:\data_folder" itself.  I've been scratching my head but I can't work out the best to get the script to modify permissions on "Z:\data_folder" as well as modifying permissions on the sub-folders and files, and I can't simply change the path to "Z:" as there are other folders on "Z:" I don't want touched.



Basic script is below:

$rights = [System.Security.AccessControl.FileSystemRights]::FullControl
$inheritance = [System.Security.AccessControl.InheritanceFlags]"ContainerInherit,ObjectInherit"
$propagation = [System.Security.AccessControl.PropagationFlags]::None
$allowdeny = [System.Security.AccessControl.AccessControlType]::Allow


# Customize the domain name
$myDomain = "Domain"
$adminUserName = "AD_Group"

[string]$ErrorLog = 'c:\temp\Permission_Errors.txt'

$foldernames=cmd /c 'dir \\?\Z:\data_folder\ /s /ad /b| findstr "\\\\?\\"'
$foldernames.substring(4) | ForEach `
{
    $folder = $_

            $Account = [System.Security.Principal.NTAccount]"$myDomain\$adminUserName"
            
            $Acl = Get-Acl $folder 
            $newAcl = @((Get-Acl $folder).Access | Select-Object -ExpandProperty IdentityReference)


            If ($newAcl -Contains $Account)    
            {
                Write-Host  "Skipping folder.  This user account already has permission: " $Account
                Write-Host  "To the folder: $($folder)"
            }       
            Else
            {
                $Ace = New-Object System.Security.AccessControl.FileSystemAccessRule ($Account,$rights,$inheritance,$propagation,$allowdeny)
                $Acl.AddAccessRule($Ace)
            
                Write-Host "Setting permission for folder: $($folder)" -ForegroundColor Yellow

            $error.Clear()

            Try
            {
                Set-Acl $folder -AclObject $Acl `
                -erroraction Stop
            } 
            catch {
                        Write-Warning "Problem setting permission to folder:  $($folder)"
                        Write-Warning "The following error occurred: $error " 

                        "Problem setting permission to folder: '$($folder)'.  The Error encountered was: '$error'" | Out-File $ErrorLog -Append
                  }
            }
}

Open in new window

carbonbaseAsked:
Who is Participating?

[Product update] Infrastructure Analysis Tool is now available with Business Accounts.Learn More

x
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

oBdACommented:
Any specific reason why you're shelling out to cmd, then use the "\\?\" prefix, only to strip it off again? A simple Get-ChildItem will get the same result.
To process the start folder as well, replace lines 13-14 in your original script with this:
$StartFolder = "Z:\data_folder"
$StartFolder, (Get-ChildItem -Path $StartFolder -Recurse -Directory | Select -ExpandProperty FullName) | ForEach `

Open in new window

The whole script with this change:
$rights = [System.Security.AccessControl.FileSystemRights]::FullControl
$inheritance = [System.Security.AccessControl.InheritanceFlags]"ContainerInherit,ObjectInherit"
$propagation = [System.Security.AccessControl.PropagationFlags]::None
$allowdeny = [System.Security.AccessControl.AccessControlType]::Allow


# Customize the domain name
$myDomain = "Domain"
$adminUserName = "AD_Group"

[string]$ErrorLog = 'c:\temp\Permission_Errors.txt'

$StartFolder = "Z:\data_folder"
$StartFolder, (Get-ChildItem -Path $StartFolder -Recurse -Directory | Select -ExpandProperty FullName) | ForEach `
{
    $folder = $_

            $Account = [System.Security.Principal.NTAccount]"$myDomain\$adminUserName"
            
            $Acl = Get-Acl $folder 
            $newAcl = @((Get-Acl $folder).Access | Select-Object -ExpandProperty IdentityReference)


            If ($newAcl -Contains $Account)    
            {
                Write-Host  "Skipping folder.  This user account already has permission: " $Account
                Write-Host  "To the folder: $($folder)"
            }       
            Else
            {
                $Ace = New-Object System.Security.AccessControl.FileSystemAccessRule ($Account,$rights,$inheritance,$propagation,$allowdeny)
                $Acl.AddAccessRule($Ace)
            
                Write-Host "Setting permission for folder: $($folder)" -ForegroundColor Yellow

            $error.Clear()

            Try
            {
                Set-Acl $folder -AclObject $Acl `
                -erroraction Stop
            } 
            catch {
                        Write-Warning "Problem setting permission to folder:  $($folder)"
                        Write-Warning "The following error occurred: $error " 

                        "Problem setting permission to folder: '$($folder)'.  The Error encountered was: '$error'" | Out-File $ErrorLog -Append
                  }
            }
}

Open in new window

0
carbonbaseAuthor Commented:
i'm calling CMD to get round errors with long file paths that i was getting with get-childitem.  

I don't mind using a combination of the CMD command to do the sub-folders and files and get-childitem to do the top level folder only, where i don't have to worry about long file paths.

Maybe i could run the CMD command on sub-folders and files, then run the get-childitem (without -recurse) to take care of the top level folder?
0
oBdACommented:
You might be able to read the long paths with the cmd solution, but doesn't Get-Acl then choke on the the long path?
This is mostly the original cmd solution, better optimized for speed (packing the "dir" output into a variable will hold the script until the "dir" is finished, whereas dropping the output into the pipeline will allow the ForEach loop to start consuming the results immediately), and moved the Try to cope with the Getr-Acl as well.
I removed the findstr, too; it's not required with the /b, because /b doesn't generate the header and metadata output that a normal "dir" does.
$rights = [System.Security.AccessControl.FileSystemRights]::FullControl
$inheritance = [System.Security.AccessControl.InheritanceFlags]"ContainerInherit,ObjectInherit"
$propagation = [System.Security.AccessControl.PropagationFlags]::None
$allowdeny = [System.Security.AccessControl.AccessControlType]::Allow

# Customize the domain name
$myDomain = "Domain"
$adminUserName = "AD_Group"
[string]$ErrorLog = 'c:\temp\Permission_Errors.txt'
$StartFolder = "Z:\data_folder"

$Account = [System.Security.Principal.NTAccount]"$myDomain\$adminUserName"
& cmd.exe /c "echo \\?\$($StartFolder)&dir /s /a:d /b \\?\$($StartFolder)" | ForEach `
{
	$folder = $_.SubString(4)
	Try {
		$Acl = Get-Acl -Path $folder -ErrorAction Stop
		$CurrentAccess = @($Acl.Access | Select-Object -ExpandProperty IdentityReference)
		If ($CurrentAccess -Contains $Account)    
		{
			Write-Host  "Skipping folder.  This user account already has permission: $Account"
			Write-Host  "To the folder: $($folder)"
		}       
		Else
		{
			$Ace = New-Object System.Security.AccessControl.FileSystemAccessRule -ArgumentList $Account, $rights, $inheritance, $propagation, $allowdeny
			$Acl.AddAccessRule($Ace)
			Write-Host "Setting permission for folder: $($folder)" -ForegroundColor Yellow
			$error.Clear()
			Set-Acl -Path $folder -AclObject $Acl -ErrorAction Stop
		} 
	}
	Catch
	{
		Write-Warning "Problem setting permission to folder:  $($folder)"
		Write-Warning "The following error occurred: $error " 
		"Problem getting/setting permission to folder: '$($folder)'.  The Error encountered was: '$error'" | Out-File $ErrorLog -Append
	}
}

Open in new window

0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
Simplify Active Directory Administration

Administration of Active Directory does not have to be hard.  Too often what should be a simple task is made more difficult than it needs to be.The solution?  Hyena from SystemTools Software.  With ease-of-use as well as powerful importing and bulk updating capabilities.

carbonbaseAuthor Commented:
Sorry not got back sooner...

Script works well thanks!  Yes i still get a few long file name errors but not nearly as many as when I was using get-childitem

Thanks again.
0
carbonbaseAuthor Commented:
Having a problem with line 10 of the code

It works fine when i enter:

$startfolder="Z:\data_folder"

but when i enter a path containing spaces (e.g.)

$startfolder="Z:\data folder"

I get the following error:

WARNING:  Problem setting permission to folder:  Z:\data folder
WARNING:  The following error occurred:  Cannot find drive.  A drive with the name '"Z' does not exist.
0
oBdACommented:
Replace line 13 with the following (note the escaped double quotes before and after the search path):
& cmd.exe /c "echo \\?\$($StartFolder)&dir /s /a:d /b `"\\?\$($StartFolder)`"" | ForEach `

Open in new window

0
carbonbaseAuthor Commented:
That's great, was wondering where to place those escaped quotes.  Thanks very much!
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Powershell

From novice to tech pro — start learning today.