I want to be able to set the IIS account for new websites to have modify permissions. I have the following script:

function Set-ModifyPermission ($directory, $username, $domain = 'IIS APPPOOL') {
    $inherit = [system.security.accesscontrol.InheritanceFlags]"ContainerInherit, ObjectInherit"
    $propagation = [system.security.accesscontrol.PropagationFlags]"None"
    $acl = Get-Acl $directory
    $user = New-Object System.Security.Principal.NTAccount($domain, $username )
    $accessrule = New-Object system.security.AccessControl.FileSystemAccessRule($user, "Modify", $inherit, $propagation, "Allow")
    set-acl -aclobject $acl $directory

However, when I run it, I get errors like this:

Set-Acl : The trust relationship between this workstation and the primary domain failed.

I think this is because IIS APPPOOL isn't a real domain, but is a weird prefix on a kind-of-fake account. Is there a correct way to refer to that account so that I can make this work?

5 Answers 5


First of all, use Set-Acl like this, as the directory path is the first positional argument:

Set-Acl $directory $acl

Second, you should create the user object with only one argument:

$user = New-Object System.Security.Principal.NTAccount("$domain\\$username")

UPDATE: Seems that it won't accept the "IIS APPPOOL\AppPoolName" as an NTAccount identifier. Now, there are two ways to accomplish what you are trying to do:

  1. Create a new SID object with the AppPoolIdentities SID and translate it into an NTAccount, like this: http://iformattable.blogspot.com/2007/12/convert-sid-to-ntaccount-with.html, and you should be able to treat it like any other NTAccount object. If you still want to be able to pass domain/usernames for real accounts, built in some simple logic that defaults to the AppPool SID if username is "AweSomeAppPool" and domain is empty, just as an example.

  2. Use PowerShell to invoke icacls.exe, and use it to grant/revoke whatever permissions you want, like this (first normal icacls form command prompt, then powershell, notice the difference):

    icacls.exe test.txt /grant "IIS AppPool\DefaultAppPool":(OI)(CI)M

    cmd /c icacls test.txt /grant "IIS AppPool\DefaultAppPool:(OI)(CI)M"

If you go for the second option, be sure to test them manually first, i haven't had a chance to test these specific examples myself, but it should work

  • Thanks for the help. Doing that, I get an exception calling AddAccessRule: "Some or all identity references could not be translated." Any ideas what that might be?
    – bdukes
    Dec 27, 2011 at 22:59
  • Try to help me understand what you are trying to accomplish here. The thing is, that ApplicationPoolIdentities aren't "real" NT Accounts, they are more like a "virtual account" representation of the NETWORK SERVICE actually. Do you wan't to set permissions on local system resources or networked resources? Depending on your need, a different challenge arises :-) Dec 27, 2011 at 23:16
  • Local system resources. I'm trying to streamline setting/resetting permissions for local development websites that I setup. So, I'd unzip a website package to the file system, set it up in IIS, then run this command to give IIS modify permission. Or, run into a permission issue in the site, run this to make sure something I've added after the site was created has modify permission.
    – bdukes
    Dec 29, 2011 at 14:52
  • Just added some hopefully useful options for you Dec 29, 2011 at 16:52
  • I was able to get icacls working great for me, thanks for the help! I ended up with the body of the function (same parameters as above) being cmd /c icacls "$directory" /grant ("$domain\$username" + ':(OI)(CI)M') /t /c /q (with /t to work recursively on the directory, /c to keep going after any errors, and /q to suppress success messages for each file).
    – bdukes
    Dec 29, 2011 at 19:35

Something like this should do the trick for you. It should be able to resolve IIS APPPOOl\Anything as well...

function Set-AclOnPath
        [string] $Path,

        [string] $DomainAccount

    #Put whatever permission you want here
    $permission = $DomainAccount,"ReadAndExecute","Allow"
    $accessRule = New-Object System.Security.AccessControl.FileSystemAccessRule $permission

    $acl = Get-Acl $Path
    $acl | Set-Acl $Path
  • I get an exception calling SetAccessRule: "Some or all identity references could not be translated."
    – bdukes
    Sep 19, 2012 at 13:58
  • What were your inputs? Sep 20, 2012 at 21:15
  • Set-AclOnPath .\Website "IIS APPPOOL\website.dev", though when I try it again, I get a different error, "The trust relationship between this workstation and the primary domain failed."
    – bdukes
    Sep 21, 2012 at 1:59

The following works in Windows 2012 to get a SID for the IIS site. It requires the IIS Provider which uses the WebAdministration powershell module, but this article indicates it will work on Windows 2008R2.

$appPoolName = 'MyAppPool'
$appPoolSid = (Get-ItemProperty IIS:\AppPools\$appPool).applicationPoolSid
$identifier = New-Object System.Security.Principal.SecurityIdentifier $appPoolSid
$user = $identifier.Translate([System.Security.Principal.NTAccount])
  • I tried to use this approach (on Windows 8), but got this error: "Exception calling 'AddAccessRule' with '1' argument(s): 'Some or all identity references could not be translated.'"
    – bdukes
    Aug 5, 2013 at 17:00
  • Using the link from @Mathias R. Jessen's answer to translate the SID into a real NTAccount worked.
    – bdukes
    Aug 5, 2013 at 17:20
  • I've updated the code in the answer to do the translation. Also, for those trying to take advantage of this, call Import-Module WebAdministration to get the IIS drive from the IIS provider.
    – bdukes
    Aug 5, 2013 at 17:25

As of IIS 10/Windows 10/Server 2016, the WebAdministration module is deprecated and we're expected to use the new IISAdministration Powershell module instead. Here's how to get the application pool SID translated to the virtual user using the new module:

Import-Module IISAdministration
$manager = Get-IISServerManager
$appPoolName = 'MyAppPool'
$appPoolSid = $manager.ApplicationPools["$appPoolName"].RawAttributes['applicationPoolSid']
$identifier = New-Object System.Security.Principal.SecurityIdentifier $appPoolSid
$user = $identifier.Translate([System.Security.Principal.NTAccount])

The following worked for me in Windows 2012, couldn't get the other examples working:

Import-Module WebAdministration


$appPoolSid = (Get-ItemProperty IIS:\AppPools\$appPoolName).applicationPoolSid

Write-Output "App Pool User $appPoolSid"

$identifier = New-Object System.Security.Principal.SecurityIdentifier $appPoolSid
$user = $identifier.Translate([System.Security.Principal.NTAccount])

Write-Output "Translated User $user.Value"

$acl = Get-Acl $folderDirectory
$acl.SetAccessRuleProtection($True, $False)
$rule = New-Object System.Security.AccessControl.FileSystemAccessRule($user, "FullControl", "ContainerInherit", ObjectInherit", "None", "Allow")
$acl | set-acl -path $folderDirectory
  • This also worked for me except one thing. This removed ALL other permissions. If this isn't what you want, comment out this line $acl.SetAccessRuleProtection($True, $False) as the last param here is PreserveInheritance. Thanks for posting this!
    – Kurtis
    Jul 3, 2019 at 10:00

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.