Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations gkittelson on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Help!! Modify ACL folder script to be recursive 1

Status
Not open for further replies.

Guest_imported

New member
Jan 1, 1970
0
I need help to modify this script to be recursive. It currently only goes two levels down.


<SCRIPT>

Const ForReading = 1, ForWriting = 2, ForAppending = 8

Const FullAccessMask = 2032127, ModifyAccessMask = 1245631, WriteAccessMask = 118009
Const ROAccessMask = 1179817

On Error Resume Next

strComputer = "."
sOutputFile = InputBox("Please Enter the Outputfile", "Output File")

sParentFolder = InputBox("Please Enter folder to gather information on", "Parent Folder")


Set fso = CreateObject("Scripting.FileSystemObject")
Set fsOut = fso_OpenTextFile(sOutputFile, ForAppending, True)
fsOut.Writeline "Folder,User Name,Permission"
fsOut.Close

Call OutputFolderInfo(sParentFolder, sOutputFile)

Set objWMIService = GetObject("winmgmts:" & "{impersonationLevel=impersonate}!\\" & _
strComputer & "\root\cimv2")
Set aSubfolder_1 = objWMIService.ExecQuery("ASSOCIATORS OF {Win32_Directory.Name='" & _
sParentFolder & "'}" _
& "WHERE AssocClass = Win32_Subdirectory " & "ResultRole = PartComponent")

For Each sSubfolder1 In aSubfolder_1
Call OutputFolderInfo(sSubfolder1.Name, sOutputFile)
Set aSubfolder_2 = objWMIService.ExecQuery("ASSOCIATORS OF {Win32_Directory.Name='" & _
sSubfolder1.Name & "'}" _
& "WHERE AssocClass = Win32_Subdirectory " & "ResultRole = PartComponent")
For Each sSubfolder2 In aSubfolder_2
Call OutputFolderInfo(sSubfolder2.Name, sOutputFile)
Set aSubfolder_3 = objWMIService.ExecQuery("ASSOCIATORS OF {Win32_Directory.Name='" & _
sSubfolder2.Name & "'}" _
& "WHERE AssocClass = Win32_Subdirectory " & "ResultRole = PartComponent")
Next
Next


Public Sub OutputFolderInfo(FolderName , sOutfile)

Const FullAccessMask = 2032127, ModifyAccessMask = 1245631, WriteAccessMask = 1180095
Const ROAccessMask = 1179817
Const ForReading = 1, ForWriting = 2, ForAppending = 8
strComputer = "."

'Build the path to the folder because it requites 2 backslashes
folderpath = Replace(FolderName, "\", "\\")

objectpath = "winmgmts:Win32_LogicalFileSecuritySetting.path='" & folderpath & "'"

'Get the security set for the object
Set wmiFileSecSetting = GetObject(objectpath)

'verify that the get was successful
RetVal = wmiFileSecSetting.GetSecurityDescriptor(wmiSecurityDescriptor)
'If Err <> 0 Then
'MsgBox ("GetSecurityDescriptor failed" & vbCrLf & Err.Number & vbCrLf & Err.Description)
'End
'End If


Set objWMIService = GetObject("winmgmts:" & "{impersonationLevel=impersonate}!\\" & _
strComputer & "\root\cimv2")
Set colFolders = objWMIService.ExecQuery("SELECT * FROM Win32_Directory WHERE Name ='" & _
folderpath & "'")
For Each objFolder In colFolders

' Retrieve the DACL array of Win32_ACE objects.
DACL = wmiSecurityDescriptor.DACL

Set fso = CreateObject("Scripting.FileSystemObject")
Set fsOut = fso_OpenTextFile(sOutfile, ForAppending, True)


For Each wmiAce In DACL
' Get Win32_Trustee object from ACE
Set Trustee = wmiAce.Trustee
fsOut.Write objFolder.Name & "," & Trustee.Domain & "\" & Trustee.Name & ","
FoundAccessMask = False
CustomAccessMask = Flase
While Not FoundAccessMask And Not CustomAccessMask
If wmiAce.AccessMask = FullAccessMask Then
AccessType = "Full Control"
FoundAccessMask = True
End If
If wmiAce.AccessMask = ModifyAccessMask Then
AccessType = "Modify"
FoundAccessMask = True
End If
If wmiAce.AccessMask = WriteAccessMask Then
AccessType = "Read/Write Control"
FoundAccessMask = True
End If
If wmiAce.AccessMask = ROAccessMask Then
AccessType = "Read Only"
FoundAccessMask = True
Else
CustomAccessMask = True
End If
Wend

If FoundAccessMask Then
fsOut.Writeline AccessType
Else
fsOut.Writeline "Custom"
End If

Next

Set fsOut = Nothing
Set fso = Nothing

Next

Set fsOut = Nothing
Set fso = Nothing

end sub
WScript.Echo "Done"

<ENDSCRIPT>
 
The FAQ section is a great start: faq329-5515
 
jges: That's great info, thanks.

Unfortunately I couldn't code my way out of a paper bag, or even one of those eco-friendly bags either.

So my plea for help remains to modify this script to check all sub folders recursivly.
 
I made some changes to the original, so it'll do 10 sub folders. It's ugly and clumsy, but it work.

Perhaps someone can help make it cleaner, and configurable?

<SCRIPT>

Const ForReading = 1, ForWriting = 2, ForAppending = 8

Const FullAccessMask = 2032127, ModifyAccessMask = 1245631, WriteAccessMask = 118009
Const ROAccessMask = 1179817

On Error Resume Next

strComputer = "."
sOutputFile = InputBox("Please Enter the Outputfile", "Output File")

sParentFolder = InputBox("Please Enter folder to gather information on", "Parent Folder")


Set fso = CreateObject("Scripting.FileSystemObject")
Set fsOut = fso_OpenTextFile(sOutputFile, ForAppending, True)
fsOut.Writeline "Folder,User Name,Permission"
fsOut.Close

Call OutputFolderInfo(sParentFolder, sOutputFile)

Set objWMIService = GetObject("winmgmts:" & "{impersonationLevel=impersonate}!\\" & _
strComputer & "\root\cimv2")
Set aSubfolder_1 = objWMIService.ExecQuery("ASSOCIATORS OF {Win32_Directory.Name='" & _
sParentFolder & "'}" _
& "WHERE AssocClass = Win32_Subdirectory " & "ResultRole = PartComponent")

For Each sSubfolder1 In aSubfolder_1
Call OutputFolderInfo(sSubfolder1.Name, sOutputFile)
Set aSubfolder_2 = objWMIService.ExecQuery("ASSOCIATORS OF {Win32_Directory.Name='" & _
sSubfolder1.Name & "'}" _
& "WHERE AssocClass = Win32_Subdirectory " & "ResultRole = PartComponent")
For Each sSubfolder2 In aSubfolder_2
Call OutputFolderInfo(sSubfolder2.Name, sOutputFile)
Set aSubfolder_3 = objWMIService.ExecQuery("ASSOCIATORS OF {Win32_Directory.Name='" & _
sSubfolder2.Name & "'}" _
& "WHERE AssocClass = Win32_Subdirectory " & "ResultRole = PartComponent")
Next
For Each sSubfolder3 In aSubfolder_3
Call OutputFolderInfo(sSubfolder3.Name, sOutputFile)
Set aSubfolder_4 = objWMIService.ExecQuery("ASSOCIATORS OF {Win32_Directory.Name='" & _
sSubfolder3.Name & "'}" _
& "WHERE AssocClass = Win32_Subdirectory " & "ResultRole = PartComponent")
Next
For Each sSubfolder4 In aSubfolder_4
Call OutputFolderInfo(sSubfolder4.Name, sOutputFile)
Set aSubfolder_5 = objWMIService.ExecQuery("ASSOCIATORS OF {Win32_Directory.Name='" & _
sSubfolder4.Name & "'}" _
& "WHERE AssocClass = Win32_Subdirectory " & "ResultRole = PartComponent")
Next
For Each sSubfolder5 In aSubfolder_5
Call OutputFolderInfo(sSubfolder5.Name, sOutputFile)
Set aSubfolder_6 = objWMIService.ExecQuery("ASSOCIATORS OF {Win32_Directory.Name='" & _
sSubfolder5.Name & "'}" _
& "WHERE AssocClass = Win32_Subdirectory " & "ResultRole = PartComponent")
Next
For Each sSubfolder6 In aSubfolder_6
Call OutputFolderInfo(sSubfolder6.Name, sOutputFile)
Set aSubfolder_7 = objWMIService.ExecQuery("ASSOCIATORS OF {Win32_Directory.Name='" & _
sSubfolder6.Name & "'}" _
& "WHERE AssocClass = Win32_Subdirectory " & "ResultRole = PartComponent")
Next
For Each sSubfolder7 In aSubfolder_7
Call OutputFolderInfo(sSubfolder7.Name, sOutputFile)
Set aSubfolder_8 = objWMIService.ExecQuery("ASSOCIATORS OF {Win32_Directory.Name='" & _
sSubfolder7.Name & "'}" _
& "WHERE AssocClass = Win32_Subdirectory " & "ResultRole = PartComponent")
Next
For Each sSubfolder8 In aSubfolder_8
Call OutputFolderInfo(sSubfolder8.Name, sOutputFile)
Set aSubfolder_9 = objWMIService.ExecQuery("ASSOCIATORS OF {Win32_Directory.Name='" & _
sSubfolder8.Name & "'}" _
& "WHERE AssocClass = Win32_Subdirectory " & "ResultRole = PartComponent")
Next
For Each sSubfolder9 In aSubfolder_9
Call OutputFolderInfo(sSubfolder9.Name, sOutputFile)
Set aSubfolder_10 = objWMIService.ExecQuery("ASSOCIATORS OF {Win32_Directory.Name='" & _
sSubfolder9.Name & "'}" _
& "WHERE AssocClass = Win32_Subdirectory " & "ResultRole = PartComponent")
Next
For Each sSubfolder10 In aSubfolder_10
Call OutputFolderInfo(sSubfolder10.Name, sOutputFile)
Set aSubfolder_11 = objWMIService.ExecQuery("ASSOCIATORS OF {Win32_Directory.Name='" & _
sSubfolder10.Name & "'}" _
& "WHERE AssocClass = Win32_Subdirectory " & "ResultRole = PartComponent")
Next
Next


Public Sub OutputFolderInfo(FolderName , sOutfile)

Const FullAccessMask = 2032127, ModifyAccessMask = 1245631, WriteAccessMask = 1180095
Const ROAccessMask = 1179817
Const ForReading = 1, ForWriting = 2, ForAppending = 8
strComputer = "."

'Build the path to the folder because it requites 2 backslashes
folderpath = Replace(FolderName, "\", "\\")

objectpath = "winmgmts:Win32_LogicalFileSecuritySetting.path='" & folderpath & "'"

'Get the security set for the object
Set wmiFileSecSetting = GetObject(objectpath)

'verify that the get was successful
RetVal = wmiFileSecSetting.GetSecurityDescriptor(wmiSecurityDescriptor)
'If Err <> 0 Then
'MsgBox ("GetSecurityDescriptor failed" & vbCrLf & Err.Number & vbCrLf & Err.Description)
'End
'End If


Set objWMIService = GetObject("winmgmts:" & "{impersonationLevel=impersonate}!\\" & _
strComputer & "\root\cimv2")
Set colFolders = objWMIService.ExecQuery("SELECT * FROM Win32_Directory WHERE Name ='" & _
folderpath & "'")
For Each objFolder In colFolders

' Retrieve the DACL array of Win32_ACE objects.
DACL = wmiSecurityDescriptor.DACL

Set fso = CreateObject("Scripting.FileSystemObject")
Set fsOut = fso_OpenTextFile(sOutfile, ForAppending, True)


For Each wmiAce In DACL
' Get Win32_Trustee object from ACE
Set Trustee = wmiAce.Trustee
fsOut.Write objFolder.Name & "," & Trustee.Domain & "\" & Trustee.Name & ","
FoundAccessMask = False
CustomAccessMask = Flase
While Not FoundAccessMask And Not CustomAccessMask
If wmiAce.AccessMask = FullAccessMask Then
AccessType = "Full Control"
FoundAccessMask = True
End If
If wmiAce.AccessMask = ModifyAccessMask Then
AccessType = "Modify"
FoundAccessMask = True
End If
If wmiAce.AccessMask = WriteAccessMask Then
AccessType = "Read/Write Control"
FoundAccessMask = True
End If
If wmiAce.AccessMask = ROAccessMask Then
AccessType = "Read Only"
FoundAccessMask = True
Else
CustomAccessMask = True
End If
Wend

If FoundAccessMask Then
fsOut.Writeline AccessType
Else
fsOut.Writeline "Custom"
End If

Next

Set fsOut = Nothing
Set fso = Nothing

Next

Set fsOut = Nothing
Set fso = Nothing

end sub
WScript.Echo "Done"

<ENDSCRIPT>
 
Try this:
Code:
Const ForReading = 1, ForWriting = 2, ForAppending = 8
Const FullAccessMask = 2032127, ModifyAccessMask = 1245631, WriteAccessMask = 118009
Const ROAccessMask = 1179817

On Error Resume Next

strComputer = "."
sOutputFile = InputBox("Please Enter the Outputfile", "Output File")
sParentFolder = InputBox("Please Enter folder to gather information on", "Parent Folder")

Set fso = CreateObject("Scripting.FileSystemObject")
Set fsOut = fso.OpenTextFile(sOutputFile, ForAppending, True)
fsOut.Writeline "Folder,User Name,Permission"

Set objWMIService = GetObject("winmgmts:" & "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")

Call OutputFolderInfo(sParentFolder)

fsOut.Close
WScript.Echo "Done"

'**************************************************************************************************
Public Sub OutputFolderInfo(FolderName)
	
	Const FullAccessMask = 2032127, ModifyAccessMask = 1245631, WriteAccessMask = 1180095
	Const ROAccessMask = 1179817
	Const ForReading = 1, ForWriting = 2, ForAppending = 8
	strComputer = "."
	
	'Build the path to the folder because it requires 2 backslashes
	folderpath = Replace(FolderName, "\", "\\")
	
	objectpath = "winmgmts:Win32_LogicalFileSecuritySetting.path='" & folderpath & "'"
	
	'Get the security set for the object
	Set wmiFileSecSetting = GetObject(objectpath)
	
	'verify that the get was successful
	RetVal = wmiFileSecSetting.GetSecurityDescriptor(wmiSecurityDescriptor)
	'If Err <> 0 Then
		'MsgBox ("GetSecurityDescriptor failed" & vbCrLf & Err.Number & vbCrLf & Err.Description)
		'End
	'End If
	
	Set colFolders = objWMIService.ExecQuery("ASSOCIATORS OF {Win32_Directory.Name='" & FolderName & "'}" _
	& "WHERE AssocClass = Win32_Subdirectory " & "ResultRole = PartComponent")
	
	For Each objFolder In colFolders
		
		' Retrieve the DACL array of Win32_ACE objects.
		DACL = wmiSecurityDescriptor.DACL
	
		For Each wmiAce In DACL
			' Get Win32_Trustee object from ACE
			Set Trustee = wmiAce.Trustee
			fsOut.Write objFolder.Name & "," & Trustee.Domain & "\" & Trustee.Name & ","
			FoundAccessMask = False
			CustomAccessMask = False
			Do While Not FoundAccessMask And Not CustomAccessMask
				If wmiAce.AccessMask = FullAccessMask Then
					AccessType = "Full Control"
					FoundAccessMask = True
				End If
				If wmiAce.AccessMask = ModifyAccessMask Then
					AccessType = "Modify"
					FoundAccessMask = True
				End If
				If wmiAce.AccessMask = WriteAccessMask Then
					AccessType = "Read/Write Control"
					FoundAccessMask = True
				End If
				If wmiAce.AccessMask = ROAccessMask Then
					AccessType = "Read Only"
					FoundAccessMask = True
				Else
					CustomAccessMask = True
				End If
			Loop
			
			If FoundAccessMask Then
				fsOut.Writeline AccessType
			Else
				fsOut.Writeline "Custom"
			End If
       
		Next
		
		Call OutputFolderInfo(objFolder.Name)
	Next
		
End Sub
 
This works really well. Thanks jges.

It however stops after 15 sub-directories though. Is this a limitation of Windows, VBS or something I'm not seeing in the script?

Thanks for the help, I really appreciate it!
 
It stops after 15 subdirectories, or it stops after 15 levels deep?
 
I did some testing with over 20 subdirectories, one of which had a subdirectories 20 levels deep; the script looped through all of them.

Do you get any error message when the script exits, or does it just quit before you think it should? Start the task manager before running the script and keep an eye on the memory usage.
 
Tested the script a few different ways. When using regular folder names, no spaces it goes forever. Past the 50 mark.

The folders causing the stopping issue it seems are in this format; "new folder - copy (2)" and so on...
Many of those in a row seem to kill it.

Farthest it got to was...
"c:\new folder - copy (1)\new folder - copy (2)\new folder - copy (3)\new folder - copy (4)\new folder - copy (5)\new folder - copy (6)\new folder - copy (7)\new folder - copy (8)\new folder - copy (9)\new folder - copy (10)\new folder - copy (11)"


Weird if you ask me.

No memory issues, does the same thing with cscript and wscript running it. I'm also using Windows 7 64-bit and Windows XP SP3 to test. Both with the same results.


Don;t get me wrong, I REALLY appreciate what you did with the script. It's just what I was looking for.

However when something unexpected happens like this, it's a mystery I just want to find out more about.

 
I think you are running into the 255 character limit on file names.
 
Probably... got some funky errors when trying to delete the test folder structure.

I'm calling it good. Thanks, you helped greatly!
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top