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?
 
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
 
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
Creating Active Directory Users from a Text File

If your organization has a need to mass-create AD user accounts, watch this video to see how its done without the need for scripting or other unnecessary complexities.

 
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
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.