I recently ran into a problem where I need to have a user added to every folder underneath a folder structure on one of our local file servers.  Now normally, this wouldn’t be a problem as we are using NTFS and could just add the new permission at the top and let it propagate down.  The kicker in this case was that the file server housed our user home shares, and inheritance was blocked at the root of each user folder; and I was told that I was not allowed to overwrite permissions.

The server administrators assigned to assist me in the project started bantering about writing C# programs, VB Scripts and performing the changes manually.  With over 30,000 user folders to chug through, I threw out the last idea immediately.  Being a former server administrator, it struck me that both of the server administrators I was working with were overlooking an obvious solution which they had at hand, PowerShell Scripting.

Windows PowerShell is a command line shell that supports a scripting language designed to ease administrative tasks for IT professionals.  It contains over 130 different standard command line tools useful for gathering information and automating routines.

For this program, I wanted to do the following things:

  1. Accept a path parameter from the command line
  2. Add a Read-Only permission at the root level of the path parameter, or the root location where the script was called.
  3. For each of the sub directories of the path, add a Read-Only permission if the sub-directory had inheritance blocked.

As I was only writing a script, I skipped creating a master function, and used the param() keyword to designate my path parameter on execution.

# This script takes an optional parameter of a path.  If excluded, the path will
# be taken from the location where the PowerShell script is called.
param([String[]] $path=(get-location).Path)

This method is fairly straight forward, it declares a parameter of type String Array named $path and sets it equal to the path of the current location.

Since I was going to have to add the same permission to every object whose inheritance was blocked, I felt it more efficient to define the permissions rule once, outside of the for loop which would cycle through the child objects.  In researching how to set permissions, I discovered this article that described the process in great detail and also pointed out some of the limitations with using PowerShell.  This article pointed out that I needed to use the System.Security.AccessControl.FileSystemAccessRule() function to create a rule to be added using the Get-ACL and Set-ACL PowerShell cmdlets as well as an excellent reference.

# The following information determines the user/group that will be used and the
# permissions that will be set accordingly at every location that matches the
# criteria of having inheritance blocked.
# $Identity             – Identity of the user or group being granted permissions
# $Rights                  – The rights to be assigned
# $Inheritance     - Defines if subsequent objects and containers will receive the
#                                         the new permissions.
# $Propagation     – Defines how permissions are propagated to all child objects
# $Type                      – Defines whether access is Allowed or Denied
$Identity = “DOMAIN\USER”
$Rights = “Read”
$Inheritance = @(“ObjectInherit”, “ContainerInherit”)
$Propagation = “None”
$Type = “Allow”
$Rule = New-Object System.Security.AccessControl.FileSystemAccessRule( `
$Identity, $Rights, $Inheritance, $Propagation, $Type)

Once I had the rule created and instantiated, using it took three simple steps:

  1. Get the security descriptor for the top level patch
  2. Add the access rule to the security descriptor
  3. Save the security descriptor

# Get the security descriptor for the $path or location where the script was
# run from and add the previous rule to the location.
$TopACL = Get-ACL $path
$TopACL.AddAccessRule($Rule)
Set-ACL $path -AclObject $TopACL

With the top level set with the Read-Only permissions, all sub-directories and files that inherit those permissions are now correctly set, so all that was left was to check for sub-directories where inheritance had been blocked and assign permissions accordingly.  I found the following snippet posted by AbqBill, a moderator at The Official Scripting Guys Forum!, on June 30, 2009 at 9:29 PM (you may need to search by date).  AbqBill came up with the idea to use the Get-ACL.Access.Count method to set a value in an output property.  I took this snippet and modified it down to two lines which set a Boolean value that I could then check for inheritance.

The steps I took for this stage were:

  1. Iterate through the sub-directories of the root path
  2. Check for the inheritance flag, if found, set $inherit = TRUE
  3. If $inherit == FALSE, set the Read-Only permission and save the new permissions

# Recurse all folders and sub-folders contained in the original path or location
# where the script was called
get-childitem $path -recurse -force | where-object { $_.PsIsContainer } |
foreach-object {

# Get the access rules for the child object
$access = (get-acl $_.FullName).Access

# Select the IsInherited field and set $inherit to the number of times it
# occurs, should be 1 or 0, or TRUE/FALSE respectively.
$inherit = $access.Count -eq ($access | where-object { $_.IsInherited }).Count

# If inheritance is blocked, $inherit is NOT true, add the accessrule to the
# child object and apply it.
if( !$inherit )
{
$ACL.AddAccessRule($Rule)
Set-ACL $_.FullName -AclObject $ACL
}

}

As you can see in the last code block, to set the permissions on the sub-directories I used roughly the same syntax and $Rule that I setup before my foreach-object loop.

As with all snippets and utility code, you should test thoroughly.  In order to run this script you will need elevated privileges on the file share or drive you want to modify permissions for.   Below you will find the full text of the PowerShell script, I hope that you find it as useful as I did.  To use it, simply copy the contents of into a .ps1 file and run from within PowerShell.

Edit – 2010/2/22 – As pointed out by bdees, you’ll need to change the DOMAIN\USER in the script to coincide with the user in your domain, or utilize the SID as described in the comments.  Apologies for the oversight, and thanks for the comments.

Cheers!

Jason

# This script takes an optional parameter of a path.  If excluded, the path will
# be taken from the location where the PowerShell script is called.
param([String[]] $path=(get-location).Path)

# The following information determines the user/group that will be used and the
# permissions that will be set accordingly at every location that matches the
# criteria of having inheritance blocked.
# $Identity               – Identity of the user or group being granted permissions
# $Rights                   – The rights to be assigned
# $Inheritance     – Defines if subsequent objects and containers will receive the
#                                         the new permissions.
# $Propagation     – Defines how permissions are propagated to all child objects
# $Type                      – Defines whether access is Allowed or Denied
$Identity = “DOMAIN\USER”
$Rights = “Read”
$Inheritance = @(“ObjectInherit”, “ContainerInherit”)
$Propagation = “None”
$Type = “Allow”
$Rule = New-Object System.Security.AccessControl.FileSystemAccessRule( `
$Identity, $Rights, $Inheritance, $Propagation, $Type)

# Get the security descriptor for the $path or location where the script was
# run from and add the previous rule to the location.
$TopACL = Get-ACL $path
$TopACL.AddAccessRule($Rule)
Set-ACL $path -AclObject $TopACL

# Recurse all folders and sub-folders contained in the original path or location
# where the script was called
get-childitem $path -recurse -force | where-object { $_.PsIsContainer } |
foreach-object {
# Get the security descriptor for the child object
$ACL = Get-ACL $_.FullName

# Get the access rules for the child object
$access = (get-acl $_.FullName).Access

# Select the IsInherited field and set $inherit to the number of times it
# occurs, should be 1 or 0, or TRUE/FALSE respectively.
$inherit = $access.Count -eq ($access | where-object { $_.IsInherited }).Count

# If inheritance is blocked, $inherit is NOT true, add the accessrule to the
# child object and apply it.
if( !$inherit )
{
$ACL.AddAccessRule($Rule)
Set-ACL $_.FullName -AclObject $ACL
}
}

http://www.xbtechnologyreview.com/wp-content/plugins/sociofluid/images/digg_32.png http://www.xbtechnologyreview.com/wp-content/plugins/sociofluid/images/reddit_32.png http://www.xbtechnologyreview.com/wp-content/plugins/sociofluid/images/delicious_32.png http://www.xbtechnologyreview.com/wp-content/plugins/sociofluid/images/furl_32.png http://www.xbtechnologyreview.com/wp-content/plugins/sociofluid/images/newsvine_32.png http://www.xbtechnologyreview.com/wp-content/plugins/sociofluid/images/technorati_32.png http://www.xbtechnologyreview.com/wp-content/plugins/sociofluid/images/google_32.png http://www.xbtechnologyreview.com/wp-content/plugins/sociofluid/images/facebook_32.png http://www.xbtechnologyreview.com/wp-content/plugins/sociofluid/images/twitter_32.png

{ 1 comment }

I recently attempted to connect my home computer to my plasma television in order to catch up on some of my favorite shows on Hulu.com. Unfortunately, I discovered that my home computer didn’t have an HDMI connection. After a bit of research I found the Atlone USB 2.0 to HDMI Converter and thought that my problems were over. Unfortunately, they were not.

I purchased the Atlona converter Atlona Converter from Frys here in Sacramento and took it home. The packaging was clean without a lot of extra material, which I appreciate being in California (less garbage to throw away) and the device was a no-frills, extra switch setup…which theoretically meant a plug-n-play installation. Sadly, my experience wasn’t that simple.

I followed the instructions and installed the software, connecting the device at the appropriate time and yet, when the little green light was supposed to come on…there was nothing. I went through the troubleshooting steps provided in the documentation as well as looked out on the forums. I even included upgrading the firmware for the device. Finally after several hours of exhausting every path I could think of, I decided to take the device back to pick up another one…after all, I’ve dealt with broken parts before.

The Frys return policy was as easy as ever, and soon I was once again home with a new device in hand. Once again I followed the instructions, and once again…no little green light. So, I can see one device being bad, but two?…not likely. So at this point I took the extreme step of completely uninstalling my anti-virus utility (McAfee) from my system. Previously I had simply disabled it while performing the installation. I rebooted and went through Atlona Coverterthe installation procedures again and behold…the little green light came on and I was receiving picture on my television.

Unfortunately, the saga didn’t end there. I inadvertently switched the EDID button and the unit started showing resolutions that my television would not support. I tried switching it back, but the resolutions remained. SO…thinking it would reset if I unplugged it…I unplugged it…afterwhich the little green light remained off. No amount of rebooting helped either.

I posted a note on the company’s support forums on April 21st and have yet to recieve a reply.
Here’s a link if you’d like to see the problem as I documented for the company, my system specs and their response, or lack there of:  http://forum.atlona.com/viewtopic.php?f=23&t=309

I have long since returned the device to Frys and don’t recommend the unit to anyone running the Vista operating system. Additionally, their tech support group is non-responsive and in reading other forum responses can come off as condescending and rude, treating their customers badly.

Overall result, I’m not really impressed with Atlona as a company or their products.

http://www.xbtechnologyreview.com/wp-content/plugins/sociofluid/images/digg_32.png http://www.xbtechnologyreview.com/wp-content/plugins/sociofluid/images/reddit_32.png http://www.xbtechnologyreview.com/wp-content/plugins/sociofluid/images/delicious_32.png http://www.xbtechnologyreview.com/wp-content/plugins/sociofluid/images/furl_32.png http://www.xbtechnologyreview.com/wp-content/plugins/sociofluid/images/newsvine_32.png http://www.xbtechnologyreview.com/wp-content/plugins/sociofluid/images/technorati_32.png http://www.xbtechnologyreview.com/wp-content/plugins/sociofluid/images/google_32.png http://www.xbtechnologyreview.com/wp-content/plugins/sociofluid/images/facebook_32.png http://www.xbtechnologyreview.com/wp-content/plugins/sociofluid/images/twitter_32.png

{ 1 comment }

Stopping Secure and Nonsecure Items Warning Message

April 16, 2009

[ad]Ok, here is another tip to help stop annoying pop-ups.  When you access a secure website, it normally shows a lock or key to let you know it is secure.  However, sometimes when you exit these pages it displays the following error message. This occurs when some of the data being displayed is not directly [...]

Read the full article →

Trouble Opening Word Files

February 18, 2009

[ad]I recently had an instructor call in with a unique (at least to me) problem. Whenever he double-clicked a Microsoft Office file to open it, he would get the following error: “The document name or path is invalid…” After a few questions, I discovered it was only happening on files that contained spaces in the [...]

Read the full article →

Forwarding a Distribution List in Outlook 2007

December 12, 2008

[ad]A common request I receive is how to send a distribution list to another Outlook user.  There are actually two ways to do this and I’ll go over them both below.  I’ve also included how the other person can save it to their own contact list. 1. Open your Contact Tab 2. Find the Distribution List you’d [...]

Read the full article →