Creating a Home Drive with Windows PowerShell: Part 3

Creating a Home Drive with Windows PowerShell: Part 3

  • Comments 16
  • Likes

Summary: Microsoft PowerShell MVP, Sean Kearney, concludes his series about creating a home drive with Windows PowerShell.

Microsoft Scripting Guy, Ed Wilson, is here. If you are a seasoned Hey, Scripting Guy! Blog reader, you know that the most frequent guest blogger is Sean Kearney. If you are new to the blog, I welcome you, and I encourage you to catch up with Sean’s previous blogs.

Sean is a Windows PowerShell MVP and an Honorary Scripting Guy. Sean has been selected to present sessions called Integrating with Microsoft System Center 2012 and Windows PowerShell at TechEd NA and TechEd Europe this year. In his free time, Sean has written several blog posts about Hyper-V and some other cool stuff. Sean will be the blogger all week, and today he is writing about home folders.

BTW, if you are in New Orleans for TechEd this week, be sure to come by the Scripting Guys booth and say hello. The Scripting Wife and I will be there in addition to Chris Duck and Brian Wilhite. We also invited www.powershell.org to share the booth with us, so come by say hello to Don Jones, Jason Helmick, and Mike Robbins. I am also sure Sean will be hanging out at the booth.

Before you read this blog post, check out the earlier parts:

With the access rule created, we need only add it in to our list of rules for the users’ home drive. Remember, because of how we defined the permissions on the root of the home folder structure, the only accounts that will be inherited for permissions will be Domain Admins and local Administrators.

To add the rule, we perform the following four steps:

  • Get the current access control list from the folder in question by using Get-ACL.
  • Build a new access rule for our user.
  • Run the AddAccessRule method against the current ACL object.
  • Store the new access control list on the folder with Set-ACL.

As simple as it sounds, use Get-ACL on the new user home folder to store the object into a Windows Powershell variable for editing and reuse:

$HomeFolderACL=GET-ACL \\CONTOSO-FPS\Users$\JohnnyTest

Next build the access rule. In our case, this is for JohnnyTest in the CONTOSO domain:

$IdentityReference=’CONTOSO\JohnnyTest’

$FileSystemAccessRights=[System.Security.AccessControl.FileSystemRights]”FullControl”

$InheritanceFlags=[System.Security.AccessControl.InheritanceFlags]”ContainerInherit, ObjectInherit”

$PropagationFlags=[System.Security.AccessControl.PropagationFlags]”None”

$AccessControl=[System.Security.AccessControl.AccessControlType]”Allow”

$AccessRule=NEW-OBJECT [System.Security.AccessControl.FileSystemAccessRule]($IdentityReference,$FileSystemAccessRights,$InheritanceFlags,$PropogationFlags,$AccessControl)

Now add the rule to the access list that is presently stored in $HomeFolderACL:

$HomeFolderACL.AddAccessRule($AccessRule)

Then store the new access rule on the folder with Set-ACL:

SET-ACL –path \\CONTOSO-FPS\Users$\JohnnyTest -AclObject $HomeFolderACL

At this point, we’ll take these new changes and build a small script in Windows Powershell to properly do all the work for us—right down to creating the folder on the remote server. New-Homedrive.ps1 will look like this:

New-Homedrive.ps1

 

PARAM(

$Alias

)

 

# Assign the Drive letter and Home Drive for

# the user in Active Directory

 

$HomeDrive=’Z:’

$UserRoot=’\\CONTOSO-FPS\Users$\’

$HomeDirectory=$UserRoot+$AccountName 

SET-ADUSER $Alias –HomeDrive $HomeDrive –HomeDirectory $HomeDirectory 

 

# Create the folder on the root of the common Users Share

 

NEW-ITEM –path $HomeDirectory -type directory -force 

$Domain=’CONTOSO’

$IdentityReference=$Domain+’\’+$Accountname

 

# Set parameters for Access rule

 

$FileSystemAccessRights=[System.Security.AccessControl.FileSystemRights]”FullControl”

$InheritanceFlags=[System.Security.AccessControl.InheritanceFlags]”ContainerInherit, ObjectInherit”

$PropagationFlags=[System.Security.AccessControl.PropagationFlags]”None”

$AccessControl=[System.Security.AccessControl.AccessControlType]”Allow”

 

# Build Access Rule from parameters

 

$AccessRule=NEW-OBJECT [System.Security.AccessControl.FileSystemAccessRule]($IdentityReference,$FileSystemAccessRights,$InheritanceFlags,$PropogationFlags,$AccessControl)

 

# Get current Access Rule from Home Folder for User

 

$HomeFolderACL.AddAccessRule($AccessRule)

SET-ACL –path $HomeDirectory -AclObject $HomeFolderACL

Now, I could have said, “Here’s a script to do this.” But I think knowing some of the deeper pieces of the process should help you understand how to manipulate the data for Set-ACL.

At the end of it all? Take this script, use it, be more efficient and consistent, and get yourself home a lot earlier. That’s where it all really matters.

~Sean

Thank you, Sean, for a great series.

Join us tomorrow as Sean continues his Friday Hyper-V series.

I invite you to follow me on Twitter and Facebook. If you have any questions, send email to me at scripter@microsoft.com, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.

Ed Wilson, Microsoft Scripting Guy 

Your comment has been posted.   Close
Thank you, your comment requires moderation so it may take a while to appear.   Close
Leave a Comment
  • Hey

    Great post.

    The "# Get current Access Rule from Home Folder for User" command seems to be missing from the end of the post.

  • @Andres

    You're absolutely correct.  After the comment it should have this additional line and read like this

    # Get current Access Rule from Home Folder for User

    $HomeFolderACL=GET-ACL $HomeDirectory

    $HomeFolderACL.AddAccessRule($AccessRule)

    SET-ACL –path $HomeDirectory -AclObject $HomeFolderACL

    Sorry for the typo! Cheers!

    Sean

    The Energized Tech

  • Hi

    When I tried this I got the following error with powershell 2:

    New-Object : Cannot find an overload for "FileSystemAccessRule" and the argument count: "5".

    If I create the new-object with just strings then it works.

    New-Object System.Security.AccessControl.FileSystemAccessRule ('domain\username','FullControl','ContainerInherit, ObjectInherit','None','Allow')

  • @Roundy

    Seems I REALLY should have had that "Good cup of Chickory Coffee" before writing.

    To get the script working right add this one line near the top just before

    $HomeDrive=’Z:’

    Add in $Accountname=$Alias

    so it looks like this

    $Accountname=$Alias

    $HomeDrive=’Z:’

    Also a change to the NEW-OBJECT.  It should read as

    $AccessRule=NEW-OBJECT System.Security.AccessControl.FileSystemAccessRule -arguementlist ($IdentityReference,$FileSystemAccessRights,$InheritanceFlags,$PropogationFlags,$AccessControl)

  • I seem to be getting the same thing Roundy was getting (After making the changes you've suggested):

    New-Object : Cannot find an overload for "FileSystemAccessRule" and the argument count: "5".

    At X:\SCripts\tmp\Permissions.ps1:18 char:23

    + $AccessRule=NEW-OBJECT <<<<  System.Security.AccessControl.FileSystemAccessRule -argumentlist ($Identity,$FileSystemAccessRights,$InheritanceFlags,$PropogationFlags,$AccessControl)

       + CategoryInfo          : InvalidOperation: (:) [New-Object], MethodException

       + FullyQualifiedErrorId : ConstructorInvokedThrowException,Microsoft.PowerShell.Commands.NewObjectCommand

    Exception calling "AddAccessRule" with "1" argument(s): "Value cannot be null.

    Parameter name: rule"

    At X:\SCripts\tmp\Permissions.ps1:20 char:26

    + $HomeDirAcl.AddAccessRule <<<< ($AccessRule)

       + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException

       + FullyQualifiedErrorId : DotNetMethodException

    I'm only really interested in the permissioning part, where I have written the following:

    $Users = Import-CSV \\fs02\SCripts\CSV\New.Joiners.csv

    Foreach ($User in $Users)

    {

    $SamID=(($User.FI) + '_' + ($User.LastName))

    $HomeDriveRoot='\\fs01\userdir$\'

    $HomeDir=$HomeDriveRoot+$SamID

    $Domain='Domain'

    $Identity=$Domain+'\'+$SamID

    $FileSystemAccessRights=[System.Security.AccessControl.FileSystemRights]"FullControl"

    $InheritanceFlags=[System.Security.AccessControl.InheritanceFlags]"ContainerInherit, ObjectInherit"

    $PropagationFlags=[System.Security.AccessControl.PropagationFlags]"InheritOnly"

    $AccessControl=[System.Security.AccessControl.AccessControlType]"Allow"

    New-Item -path $HomeDriveRoot -name $SamID -type directory

    $HomeDirAcl = Get-Acl $HomeDir

    $AccessRule=NEW-OBJECT System.Security.AccessControl.FileSystemAccessRule -argumentlist ($Identity,$FileSystemAccessRights,$InheritanceFlags,$PropogationFlags,$AccessControl)

    $HomeDirAcl.AddAccessRule($AccessRule)

    Set-Acl -path $HomeDir -AclObject $HomeDirAcl

    }

    Ahhh, home time...

  • It's a shame I can't reply to my self...

    Interestingly, when I change the $AccessRule line to:

    $AccessRule=NEW-OBJECT System.Security.AccessControl.FileSystemAccessRule -argumentlist ($Identity,$FileSystemAccessRights,$AccessControl)

    Then the user is permissioned to the directory, but only as 'Special Permissions' even thought everything is ticked...

    How interesting....

  • @Panzerbjørn

    Create an Access Rule part 1:

    $rule=New-Object System.Security.AccessControl.FileSystemAccessRule('.\guest','fULLcONTROL','ContainerInherit, ObjectInherit','InheritOnly','Allow')

    That is all you need to do.  It is not necessary to create every option as an Enum value.  The Framework will do that for you.  All of the arguments are already cast so you only need to use the strings.

    Here is this rule:

    PS C:\scripts> $rule

    FileSystemRights  : FullControl

    AccessControlType : Allow

    IdentityReference : .\guest

    IsInherited       : False

    InheritanceFlags  : ContainerInherit, ObjectInherit

    PropagationFlags  : InheritOnly

    After you add the rule to an ACL the rights may get changed do to other rules already in place.

    Spend some time studying how file security works.  It is not as straight forwards as you think it is.

  • @Panzerbjørn

    Issue #2

    AccessRule=NEW-OBJECT [System.Security.AccessControl.FileSystemAccessRule]($IdentityReference,$FileSystemAccessRights,$InheritanceFlags,$PropogationFlags,$AccessControl)

    You cannot use a type accelerator in New-Object.  Note the {}

  • @Sean, @ed

    Change -

    $AccessRule=NEW-OBJECT [System.Security.AccessControl.FileSystemAccessRule]

    TO

    $AccessRule=NEW-OBJECT System.Security.AccessControl.FileSystemAccessRule

    The {} were put in by mistake.

  • @jrv;

    Many Thanks! :-D

    That worked.

    Oddly, the permissions which I've given don't show up: http://tinyurl.com/q67dzoq

    Although I can see them if I go to advanced: http://tinyurl.com/pokhfa9

    Having said that, according to 'Effective Permissions, he doesn't have any access rights: http://tinyurl.com/o3fb5ka

    Most peculiar...

  • @Panzerbjørn

    The share permissions override the file system.   Set the share to Everyone:Full then the file system will take precedence.

    This is not a scripting issue with this blog post.  You should post your questions in the forums. Post in the forum for you OS.

  • @jrv;

    I fixed it by changing the line to this rather than changing share permissions (Which were already set to Everyone:Full):

    $AccessRule=New-Object System.Security.AccessControl.FileSystemAccessRule @($Identity,"Modify","ObjectInherit, ContainerInherit","None","Allow")

    So it was a scripting issue, IMO, rather than a share permissions issue.

  • Change $PropogationFlags to $PropagationFlags

    $AccessRule=NEW-OBJECT System.Security.AccessControl.FileSystemAccessRule($IdentityReference,$FileSystemAccessRights,$InheritanceFlags,$PropagationFlags,$AccessControl)

  • I'm getting an error that says NEW-OBJECT : Cannot find type [[System.Security.AccessControl.FileSystemAccessRule]]: make sure the assembly containing this type is loaded.

  • Fantastic article!
    Clearly explained, and educational.