Script to Recurse Certain Directorys and Change Owner & Permissions

Users have about 800 users with roaming profiles on a drive-- call it E:\User_Profiles (which is shared out to the network).   Profiles are stored in the format:

E:\User_Profiles\bob.jones
E:\User_Profiles\john.smith
E:\User_Profiles\rick.james

And so forth.  We're trying to do a wildcard copy of all files inside E:\User_Profiles to another disk.  

  xcopy E:\User_Profiles\*.* J:\User_Profiles\  /C /E /Y

Under each profile is the obligatory "My Documents" folder.  All profiles are readable to the Administrators group-- except the "My Documents" folder.   For whatever reason Administrators have no permission on each user's My Documents folder. This prevents copying with an "access denied" error.

We have to goto each profile, take ownership of My Documents, add permission for Administrators, then give ownership back to the user.

For 5 users this would be ok, but for 800 users this is an unworkable solution.

Can somone suggest a script that will recurse the entire E:\User_Profiles directory tree, and add the Administrators group with Full Control permissions to every "My Documents" folder in the tree?

If permissions cannot be added without taking ownership first, the script would have to detect the current owner (which appears to always be the user of the profile), temporarily change owner to Administrators, add full control permissions for Administrators, then return ownership to the original owner.

Suggestions, please.  Thanks in advance.

EcomproAsked:
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.

chakkoCommented:
I have a kixtart script already that does this.
It uses the AD username as the basis.  My script searches the AD user accounts, then finds the matching folder name,  and resets the permissions and makes the user the owner
So, if your user accounts are bob.smith and the folder is bob.smith it will work.

For your case, You can take ownership of the folders, move/copy them to the new location and then run my script.
On the new folder just set the Domain Admins at the top level folder and allow inheritance.  My script does not specifically add Administrators for access.

If your username in AD is different then please describe that, ie. what info can we use from AD to build a name that matches the folder.


kixtart32 script.kix

You can create some test folder structure first to verify it does what you need.  
In the script (text file type) you have to set your Domain and the Root/Scan folder - at the top of the script


;--------------------------------------------------------------
$ScanFolder = "e:\folder"
$DomainName = "Domain"
$DomObj = getobject("WinNT://@LDomain")
$DomObj.filter = "user",""
for each $user in $DomObj
    $username = $user.name
    $userhome = TranslateName (3, "", 3, "@LDomain\$username", 1)
    $userinfo = GetObject("LDAP://" + $userhome[0])
        $TempUser = $userinfo.sAMAccountName
       $UserFolder = $ScanFolder + "\" + $TempUser
        $FullName = $DomainName + "\" + $TempUser
       if Exist($UserFolder) = 1
           ? "Process folder: " + $UserFolder
               RUN ('ICACLS $UserFolder /grant $FullName:(CI)f /T')
            ? "Process Ownership :" + $FullName
               RUN ('ICACLS $UserFolder /setowner $FullName /T')
      endif
next
 
? "Finished"
exit

; TranslateName function authored by Howard A. Bullock
Function TranslateName ($InitType, $BindName, $LookupNameType, $LookupName, $ReturnNameType)
    Dim $InitType, $BindName, $LookupNameType, $LookupName, $ReturnNameType
    Dim $NameTranslate, $ReturnName, $Error, $ErrorText
    $Error = 0
    $ErrorText = ""
    $ReturnName = ""
    $NameTranslate = CREATEOBJECT ("NameTranslate")
    $Error = @error
    $ErrorText = @serror
    if $Error = 0
        $NameTranslate.Init ($InitType, $BindName)
        $Error = @error
        $ErrorText = @serror
        if $Error = 0
            $NameTranslate.Set ($LookupNameType, $LookupName)
            $Error = @error
            $ErrorText = @serror
            if $Error = 0
                $ReturnName = $NameTranslate.Get($ReturnNameType)
                $Error = @error
                $ErrorText = @serror
            endif
        endif
    endif
    $TranslateName = $ReturnName, $Error, $ErrorText
Endfunction
0
chakkoCommented:
If you have the access denied, then you should check that folder manually and see if you can add permissions manually for the folder.  Otherwise, you will need to take control before you can add the permissions.

If you can add Administrators to the MyDocuments folder without taking control then I can adjust the script to just include Administrators (just add them).
0
chakkoCommented:
I mentioned before about copying the folders, which is optional.

If you want to fix the permissions on your current folders then I would do the following:
1. Take ownership as admin at the top level and apply to all child objects
2. Set your permissions on the Top level folder (administrators Full, creator/owner Full, etc,) and set them to inherit to children folders.
3.  Then run my script and it will reset the permissions on the subfolders.

If you want to copy after this then you should have access as an admin.
0
Cloud Class® Course: Microsoft Windows 7 Basic

This introductory course to Windows 7 environment will teach you about working with the Windows operating system. You will learn about basic functions including start menu; the desktop; managing files, folders, and libraries.

EcomproAuthor Commented:
I believe the problem with going to the directory root (E:\User_Profiles) and propagating permissions downward is that any permissions that are set at the root, but not on individual profile directories, will suddenly be present on those subdirectories.  But assuming we could work around that, one other question--

How does your script handle directories that are named diffrently than the username?  For example, user was originally set up as Suzie.Smith and that's how her profile directory was named.  Then she got married and her username changed to Suzie.Jones, but the directory name stayed the same.  Out of 800 users, we have quite a few users whose names have changed over the years due to marriage, divorce, etc., so their profile directory name is no longer an exact match to the username.

I'm still hoping someone can suggest a script that does not rely on AD-- and will do the following:

Recurse E:\User_Profiles.  For each profile directory:

  a)  Read username of current owner.
  b)  Take ownership of the profile directory and propagate down to all subdirectories and objects.
  c)  Add Full Control permissions for Adminsitrators group and propagate down to all subdirectories and objects.
  d)   Revert ownership back to the user discovered in step (a) above.

0
EcomproAuthor Commented:
Correction.  Step (d) above should read:

d)   Revert ownership back to the user discovered in step (a) above and propagate down to all subdirs & objects.

0
chakkoCommented:
my script was made for a different purpose but it can reset permissions.
It does rely on the AD username, but if you have a lot of changed user names which don't correspond to the folder name then my script will fail on those folders.
When I setup these types of folders I set the admin access at the root and let it propagate down through the user folders.  It doesn't have to be that way.

The algorithm you described is better suited to your task.
If I have some time I will see if I can adjust my script.

0
chakkoCommented:
here is a new kixtart script.

It will do as you requested:

a)  Read username of current owner.
  b)  Take ownership of the profile directory and propagate down to all subdirectories and objects.
  c)  Add Full Control permissions for Adminsitrators group and propagate down to all subdirectories and objects.
  d)  Add user (step a) Full control and  set ownership back to the user discovered in step (a) above.

set your Domain Admin account and the basedir.


;-------------


$AdminName= "Domain\domain admins"
$basedir = "E:\111"

$Name = Dir("$basedir")
While $Name <> "" and @ERROR = 0
  If ($Name <> ".") And ($Name <> "..") And (GetFileAttr($basedir+"\"+$name) & 16)
     $Folder = $basedir + "\" + $Name
     $Owner = GetOwner($Folder)
     $FullName = $Owner[1] + "\" + $Owner[0]
     ? "Process Folder:  " + $Folder + "      Owner: " + $FullName
     RUN ("TAKEOWN /F " + $Folder + " /R /D N")
     RUN ('ICACLS $Folder /grant "$AdminName":(CI)f /T')
     RUN ('ICACLS $Folder /grant $FullName:(CI)f /T')
     RUN ('ICACLS $Folder /setowner $FullName /T')

  EndIf
  $Name = Dir()
Loop
 
   


 
? "Finished"

exit


;FUNCTION      GetOwner($fileinput)
;
;AUTHOR            BrianTX
;
;ACTION            Gets the Owner of a file's username and domain and
;            returns them in the form of an array.
;
;SYNTAX            GetOwner($fileinput)
;
;PARAMETERS      $fileinput (Required) -  Name of a file including the
;            full path. UNC names are NOT supported.
;
;REMARKS      This UDF is designed to allow processing on files based
;            on who their owner is.
;            
;RETURNS      Always an array of 2 dimensions -- username, domain
;            Invalid filenames will return an array of 2 blank columns.
;
;DEPENDENCIES      Windows NT 4.0 or later (with WMI installed)
;
;EXAMPLE      $Owner = GetOwner("M:\testfile.txt")
;            RETURNS:
;            $Owner[0] = "MyUserID"
;            $Owner[1] = "MYDOMAIN"
;            
;NOTE            Sometimes the domain returns as BUILTIN instead of the
;            actual domain, especially when there is group ownership.


Function GetOwner($fileinput)
 $wmiobj=GetObject("Winmgmts:")
 $SIDObj = $wmiobj.ExecQuery("ASSOCIATORS OF {Win32_LogicalFileSecuritySetting='$fileinput'}
                              WHERE AssocClass=Win32_LogicalFileOwner ResultRole=Owner")
 For each $SID in $SIDobj
 $GetOwner = $SID.AccountName, $SID.ReferencedDomainName
 Next
 If VarType($GetOwner)=0 $GetOwner = "","" ENDIF  
EndFunction


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
chakkoCommented:
you will need the util called takeown.exe  

http://www.petri.co.il/download_free_reskit_tools.htm     
link in that page for the download

also, run that script under an Admin level account so that the takeown.exe can take ownership.
0
chakkoCommented:
Also, if you only have user accounts in 1 domain then you may want to change this line.  The script function I copied says that it may return BUILTIN for some groups if they have ownership of the folder.
If you are sure that only user accounts have ownership then it should not matter.

$FullName = $Owner[1] + "\" + $Owner[0]

to your Domain

$FullName = "Domain\" + $Owner[0]
0
EcomproAuthor Commented:
Thanks for the effort you put into this answer.
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
Windows Server 2003

From novice to tech pro — start learning today.

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.