title: Write-Protect System Variables
body: <p>I'm trying to create a script to write-protect the environment variables and then unlock them whenever we need a script to update them. We've recently had a rash of "admins" that can't read and have been completely wiping out the entire <code>%PATH%</code> variable when told to add a single entry.</p>
  
  <p>I've worked out how we can script that so that there's less risk of such things, but I'd also like to have <code>%PATH%</code> uneditable except for when we need it.</p>
  
  <p>I've successfully created a PowerShell function that does this, however it also prevents me from removing the rule when it needs to be edited. I've left all the default permissions on the key alone, as I ONLY want to add a restriction against editing the keys themselves.</p>
  
  <pre><code>function regLock
  {
      Write-Host "LOCKING SYSTEM ENVIRONMENT VARIABLES" -ForegroundColor Yellow
      $key = 'HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager\Environment'
      $acl = Get-Acl $key
      $rule = New-Object System.Security.AccessControl.RegistryAccessRule("Administrators", "SetValue", "None", "InheritOnly" , "Deny")
      $acl.SetAccessRule($rule)
      Set-Acl -AclObject $acl -Path $key
  }
  
  function regUnlock
  {
      Write-Host "UNLOCKING SYSTEM ENVIRONMENT VARIABLES" -ForegroundColor Green
      $key = 'HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager\Environment'
      $acl = Get-Acl $key
      $rule = New-Object System.Security.AccessControl.RegistryAccessRule("Administrators", "SetValue", "None", "InheritOnly" , "Deny")
      $acl.RemoveAccessRule($rule)
      Set-Acl -AclObject $acl -Path $key
  }
  </code></pre>
  
  <p>Of course if I go into regedit I can remove the lockout key, but that defeats the purpose of keeping them out of places they shouldn't be. I thought the <code>SetValue</code> permission only applied to changing/creating values, not ACL permissions.</p>