VBS Script to remove/set folder inheritance

I need a vbs script that will clear inheritance for all subfolders and files under a specified parent folder.  Then go back and re-allow inheritance for those same subfolders and files.

Some background information on the problem I am having can be found in my previous question here:
http://www.experts-exchange.com/OS/Microsoft_Operating_Systems/Server/Windows_2003_Active_Directory/Q_23130876.html#a20820026

The only solution is to uncheck allow inheritance, then click apply.  Then check  allow inheritance again and then apply again.  Then all the inherited permissions from the parent folders will be applied.

Now my problem is that there thousands of folders that need this to be done.

According to this article, http://support.microsoft.com/kb/320246/en-us, a vbs script can be written to automate this process.

Can anyone help me with this script?
orbitrodAsked:
Who is Participating?
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.

Chris DentPowerShell DeveloperCommented:

Hey,

I've done this one before, NTFS permissions are quite complex (even if it's just inheritance), so please run this on a small set of folders first to make sure it actually does what you want.

HTH

Chris
Option Explicit
 
' Reset Inheritance
'
' Author: Chris Dent
' Modified: 16/08/2006
 
Const FS_TREE_ROOT = "C:\Temp"
 
Const SE_DACL_PRESENT = 4
Const SE_DACL_AUTO_INHERITED = 1024
Const SE_DACL_PROTECTED = 4096
Const SE_SELF_RELATIVE = 32768
 
Const ENABLE_INHERITANCE = 1
Const COPY_AND_TURN_OFF_INHERITANCE = 2
Const REMOVE_AND_TURN_OFF_INHERITANCE = 3
 
'
' Subroutines
'
 
Sub ResetInheritance(strPath, intWhatToDoWithInheritance)
	Dim objFileSecSetting, objSecurityDescriptor, objMethod, objInParam
	Dim intControlFlagsVar
	
	Set objFileSecSetting = objService.Get("Win32_LogicalFileSecuritySetting.Path=""" &_
		Replace(strPath,"\","\\") & """")
	objFileSecSetting.GetSecurityDescriptor objSecurityDescriptor	
 
	Select Case intWhatToDoWithInheritance
	Case ENABLE_INHERITANCE
		intControlFlagsVar = SE_DACL_PRESENT + SE_DACL_AUTO_INHERITED + SE_SELF_RELATIVE
	Case COPY_AND_TURN_OFF_INHERITANCE, REMOVE_AND_TURN_OFF_INHERITANCE
		intControlFlagsVar = SE_DACL_PRESENT + SE_DACL_PROTECTED + SE_SELF_RELATIVE	
	End Select
	
	objSecurityDescriptor.ControlFlags = intControlFlagsVar
		
	Set objMethod = objFileSecSetting.Methods_("SetSecurityDescriptor")
	Set objInParam = objMethod.inParameters.SpawnInstance_()
	objInParam.Properties_.item("Descriptor") = objSecurityDescriptor
	
	objFileSecSetting.ExecMethod_ "SetSecurityDescriptor", objInParam
End Sub
 
Sub DoWorkOnFolders(strPath, intWhatToDoWithInheritance)
	Dim objWorkingFolder, objWorkingFile, objWorkingSubFolder
 
	Set objWorkingFolder = objFileSystem.GetFolder(strPath)
 
	WScript.Echo "Working on " & strPath
	
	For Each objWorkingFile in objWorkingFolder.Files
		ResetInheritance objWorkingFile.Path, intWhatToDoWithInheritance
	Next
 
	For Each objWorkingSubFolder in objWorkingFolder.SubFolders
		DoWorkOnFolders objWorkingSubFolder.Path
	Next
End Sub
 
'
' Main Code
'
 
Dim objFileSystem, objLocator, objService, objRootFolder, objFile, objFolder
 
Set objFileSystem = CreateObject("Scripting.FileSystemObject")
Set objLocator = CreateObject("WbemScripting.SWbemLocator")
Set objService = objLocator.ConnectServer (".", "root/cimv2")
 
Set objRootFolder = objFileSystem.GetFolder(FS_TREE_ROOT)
 
For Each objFile in objRootFolder.Files
	ResetInheritance objFile.Path, REMOVE_AND_TURN_OFF_INHERITANCE
	ResetInheritance objFile.Path, ENABLE_INHERITANCE
Next	
 
Set objFile = Nothing
 
For Each objFolder in objRootFolder.SubFolders
	DoWorkOnFolders objFolder.Path, REMOVE_AND_TURN_OFF_INHERITANCE
	DoWorkOnFolders objFolder.Path, ENABLE_INHERITANCE
Next
 
Set objFolder = Nothing
 
Set objRootFolder = Nothing
Set objService = Nothing
Set objLocator = Nothing
Set objFileSystem = Nothing

Open in new window

0
Chris DentPowerShell DeveloperCommented:

Sorry... made a mistake in the script above, corrected here.
Option Explicit
 
' Reset Inheritance
'
' Author: Chris Dent
' Modified: 16/08/2006
 
Const FS_TREE_ROOT = "C:\Temp"
 
Const SE_DACL_PRESENT = 4
Const SE_DACL_AUTO_INHERITED = 1024
Const SE_DACL_PROTECTED = 4096
Const SE_SELF_RELATIVE = 32768
 
Const ENABLE_INHERITANCE = 1
Const COPY_AND_TURN_OFF_INHERITANCE = 2
Const REMOVE_AND_TURN_OFF_INHERITANCE = 3
 
'
' Subroutines
'
 
Sub ResetInheritance(strPath, intWhatToDoWithInheritance)
	Dim objFileSecSetting, objSecurityDescriptor, objMethod, objInParam
	Dim intControlFlagsVar
	
	Set objFileSecSetting = objService.Get("Win32_LogicalFileSecuritySetting.Path=""" &_
		Replace(strPath,"\","\\") & """")
	objFileSecSetting.GetSecurityDescriptor objSecurityDescriptor	
 
	Select Case intWhatToDoWithInheritance
	Case ENABLE_INHERITANCE
		intControlFlagsVar = SE_DACL_PRESENT + SE_DACL_AUTO_INHERITED + SE_SELF_RELATIVE
	Case COPY_AND_TURN_OFF_INHERITANCE, REMOVE_AND_TURN_OFF_INHERITANCE
		intControlFlagsVar = SE_DACL_PRESENT + SE_DACL_PROTECTED + SE_SELF_RELATIVE	
	End Select
	
	objSecurityDescriptor.ControlFlags = intControlFlagsVar
		
	Set objMethod = objFileSecSetting.Methods_("SetSecurityDescriptor")
	Set objInParam = objMethod.inParameters.SpawnInstance_()
	objInParam.Properties_.item("Descriptor") = objSecurityDescriptor
	
	objFileSecSetting.ExecMethod_ "SetSecurityDescriptor", objInParam
End Sub
 
Sub DoWorkOnFolders(strPath, intWhatToDoWithInheritance)
	Dim objWorkingFolder, objWorkingFile, objWorkingSubFolder
 
	Set objWorkingFolder = objFileSystem.GetFolder(strPath)
 
	WScript.Echo "Working on " & strPath
	
	For Each objWorkingFile in objWorkingFolder.Files
		ResetInheritance objWorkingFile.Path, intWhatToDoWithInheritance
	Next
 
	For Each objWorkingSubFolder in objWorkingFolder.SubFolders
		DoWorkOnFolders objWorkingSubFolder.Path, intWhatToDoWithInheritance
	Next
End Sub
 
'
' Main Code
'
 
Dim objFileSystem, objLocator, objService, objRootFolder, objFile, objFolder
 
Set objFileSystem = CreateObject("Scripting.FileSystemObject")
Set objLocator = CreateObject("WbemScripting.SWbemLocator")
Set objService = objLocator.ConnectServer (".", "root/cimv2")
 
Set objRootFolder = objFileSystem.GetFolder(FS_TREE_ROOT)
 
For Each objFile in objRootFolder.Files
	ResetInheritance objFile.Path, REMOVE_AND_TURN_OFF_INHERITANCE
	ResetInheritance objFile.Path, ENABLE_INHERITANCE
Next	
 
Set objFile = Nothing
 
For Each objFolder in objRootFolder.SubFolders
	DoWorkOnFolders objFolder.Path, REMOVE_AND_TURN_OFF_INHERITANCE
	DoWorkOnFolders objFolder.Path, ENABLE_INHERITANCE
Next
 
Set objFolder = Nothing
 
Set objRootFolder = Nothing
Set objService = Nothing
Set objLocator = Nothing
Set objFileSystem = Nothing

Open in new window

0
orbitrodAuthor Commented:
Chris-Dent, the script doesn't appear to be working.  From my experience when doing to folder inheritance manually, you have to remove the inhertiance then click APPLY, then allow it and click apply again.   The apply process seems to be a very crucial step or the folder won't inherit properly.  Maybe I need to run 2 different scripts.  One to completely remove inheritance and copy permissions, then one to re-allow inheritance.

I tried to play with your script to do this, but I am no programmer and had no success.
0
Problems using Powershell and Active Directory?

Managing Active Directory does not always have to be complicated.  If you are spending more time trying instead of doing, then it's time to look at something else. For nearly 20 years, AD admins around the world have used one tool for day-to-day AD management: Hyena. Discover why

Chris DentPowerShell DeveloperCommented:

The GUI makes it look so easy :) I'll have another look in the morning if that's okay, a bit late in the evening for something so involved.

Anyway, I know it works to enable Inheritance, but it doesn't do much else than toggle it off and on at the moment.

Copying the ACL from the parent isn't particularly easy. We would have to flush out the explicit entries added immediately afterwards when we re-enable inheritance, almost certain to break something.

Chris
0
orbitrodAuthor Commented:
Flushing out explicit entries is exactly what I was thinking.  Because if the subfolders and files are inheriting properly they will get all permissions from the parent.
0
Chris DentPowerShell DeveloperCommented:

Fair enough, I know how to do that, so I'll have a look in the morning :)

Chris
0
orbitrodAuthor Commented:
Hey Chris

I was just wondering if you had that updated script for me? I think if all the script did was disable and copy permissions it would work fine.

But one other big question I have is why doesn't the Xcalc function work.  I have tried using that thing so many times but it never disables inheritance.
0
RobSampsonCommented:
Hey guys, have a look at SetACL.exe, seems to work better....
http://setacl.sourceforge.net/html/examples.html

This script will use that tool to force "Replace permission entries on all child objects"

'================
Set objNetwork = CreateObject("WScript.Network")
Set objShell = CreateObject("WScript.Shell")
Set objFSO = CreateObject("Scripting.FileSystemObject")
strFolder = "C:\temp\temp\Test script\Test\folder3"
strFolder = objFSO.GetFolder(strFolder).ShortPath
strSetACLPath = Replace(WScript.ScriptFullName, WScript.ScriptName, "") & "SetACL.exe"
strSetACLPath = objFSO.GetFile(strSetACLPath).ShortPath
strSetACLLog = Replace(WScript.ScriptFullName, WScript.ScriptName, "") & "SetACLLog.txt"
strSetACLLog = objFSO.GetFile(strSetACLLog).ShortPath
Set objLog = objFSO.CreateTextFile(strSetACLLog, True)
objLog.Close
Set objLog = Nothing
strCommand = "cmd /c " & strSetACLPath & " -on " & strFolder & " -ot file -actn ace " & _
           "-ace ""n:S-1-5-32-544;p:full;s:y"" " & _
           "-actn clear -clr ""dacl,sacl"" " & _
           "-actn rstchldrn -rst ""dacl,sacl"" " & _
           "-log " & strSetACLLog
'MsgBox strCommand
objShell.Run strCommand, 0, True
MsgBox "Log file was written to: " & strSetACLLog
'================

Regards,

Rob.
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
orbitrodAuthor Commented:
Rob, who do you use the SetACL.exe? Are there any instructions on the internet on how it should be used?
0
Chris DentPowerShell DeveloperCommented:

That would be good considering I'd completely forgotten to finish this off. Yell if you don't have any luck with SetACL and I'll make myself useful again.

Chris
0
orbitrodAuthor Commented:
Sorry Rob I meant to say how do you use the SetACL.exe?

Do I just paste all that code into a vbs file then execute it?
0
RobSampsonCommented:
Yes, from the link I posted, that shows examples:
http://setacl.sourceforge.net/html/examples.html

and you can download the CmdLine binary by clicking the Download link at the top of that page.

There is also an ActiveX version which I haven't used, but could be nice to work with.....time permitting!

So you need to have SetACL in the same folder as this script, and then it should execute it.  The script is the code I posted, which you need to save as a VBS file.

Basically this part:
strCommand = "cmd /c " & strSetACLPath & " -on " & strFolder & " -ot file -actn ace " & _
           "-ace ""n:S-1-5-32-544;p:full;s:y"" " & _
           "-actn clear -clr ""dacl,sacl"" " & _
           "-actn rstchldrn -rst ""dacl,sacl"" " & _
           "-log " & strSetACLLog

execute the SetACL command, setting Local administrators (S-1-5-32-544) to Full control, clearing any explicit entries, and setting the inheritance on all child objects.

If you don't want to do those permissions, have a look at the examples and see what may suit, describe what you need here, and we'll try to get the command right for you....

Regards,

Rob.
0
orbitrodAuthor Commented:
Hi Rob, I was able to figure out how to run the script, but  I want my marketing_group security group to have full control of everything
0
RobSampsonCommented:
OK, so if you change this:
strCommand = "cmd /c " & strSetACLPath & " -on " & strFolder & " -ot file -actn ace " & _
           "-ace ""n:S-1-5-32-544;p:full;s:y"" " & _
           "-actn clear -clr ""dacl,sacl"" " & _
           "-actn rstchldrn -rst ""dacl,sacl"" " & _
           "-log " & strSetACLLog

to this:
strCommand = "cmd /c " & strSetACLPath & " -on " & strFolder & " -ot file -actn ace " & _
           "-ace ""n:S-1-5-32-544;p:full;s:y"" " & _
           "-ace ""n:" & objNetwork.UserDomain & "\marketing_group" & ";p:full;s:y"" " & _
           "-actn clear -clr ""dacl,sacl"" " & _
           "-actn rstchldrn -rst ""dacl,sacl"" " & _
           "-log " & strSetACLLog

does that give them access?

Regards,

Rob.
0
orbitrodAuthor Commented:
Heres an update on the situation.  It turns out that resetting the ACL wasn't working for me, instead what I did was remove the

"-actn clear -clr ""dacl,sacl"" " & _
"-actn rstchldrn -rst ""dacl,sacl"" " & _

lines from the code.  And instead I just added the the users to the ACL and it seemed to fix my broken inheritance problem.

Lastly the
"-ace ""n:" & objNetwork.UserDomain & "\marketing_group" & ";p:full;s:y"" " & _
line of code, didn't work for me. I kept getting an error, so I ended up using psgetsid.exe to get the SIDs of the security groups. And then using the SID in the script.
0
RobSampsonCommented:
Yeah, I also found that using the domain and username didn't work....it said SID not found....so yeah, PSGetSID is a great solution!  Nice work, and thanks for posting the update.

Regards,

Rob.
0
RobSampsonCommented:
Thanks for the grade.

Regards,

Rob.
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
Active Directory

From novice to tech pro — start learning today.