In my on-going attempts to simplify the deployment of our web application here at Day Job, I have created a PowerShell script that sets the permissions on all the directories used by the app.  It’s amazing how much simpler something like this is in PowerShell compared to VBScript.   Here’s some code that will give the NetworkService user read-access to a directory (useful for data files that your web app needs to access):

   1: #These constants are used to set permissions
   2: $inherit = [system.security.accesscontrol.InheritanceFlags]"ContainerInherit, ObjectInherit"
   3: $propagation = [system.security.accesscontrol.PropagationFlags]"None"
   4:  
   5: #Set directory permissions
   6: $directory = "DataFiles"
   7: $acl = Get-Acl $directory
   8: $accessRule = New-Object System.Security.AccessControl.FileSystemAccessRule("NetworkService", "ReadAndExecute", $inherit, $propagation, "Allow")
   9: $acl.AddAccessRule($accessRule)
  10: Set-Acl -aclobject $acl $directory

You need to pass in enumeration members to insure that the permission change is applied correctly, so the first block of code just grabs the needed values from the appropriate enumerations.  With those in hand, all you have to do is use the FileSystemAccessRule class to add a new rule, then apply it to the directory. 

One tricky thing I ran into was handling the Internet Guest Account.  Recall from my WiX ordeals that IIS 7.0 systems (Vista and Windows 2008) use IIS_USRS while IIS 6 systems use IUSR_[MachineName].  I couldn’t come up with an elegant way to handle it, but this hackery does the trick:

   1: $computerName = (Get-WmiObject win32_computersystem).name
   2: #This determines which user is the guest user for IIS.  Windows Vista and 08 use the IIS_USRS group, Previous version use 
   3: #IUSR_[MachineName]
   4: if ([environment]::osversion.Version.Major -eq 6) {$webUser="IIS_IUSRS"} else {$webUser="IUSR_" + $computerName}
   5:  
   6: $directory = "Web"
   7: $acl = Get-Acl $directory
   8: $accessRule = New-Object System.Security.AccessControl.FileSystemAccessRule("NetworkService", "ReadAndExecute", $inherit, $propagation, "Allow")
   9: $acl.AddAccessRule($accessRule)
  10: $accessRule = New-Object System.Security.AccessControl.FileSystemAccessRule($webUser, "ReadAndExecute", $inherit, $propagation, "Allow")
  11: $acl.AddAccessRule($accessRule)
  12: Set-Acl -aclobject $acl $directory

The above snippet Grants the NetworkService and IIS guest account read permissions on the Web directory, which will allow our ASP.NET located in Web to execute once the virtual directory is created in IIS (which I’ll describe how to do just as soon as I figure it out).