Changing a user’s Desktop folder Permissions with PowerShell Script </h3>
This PowerShell scripts helps in quickly setting the users desktop permissions so that it’s only modifiable by an admin. I did this today because of a Reddit user was asking how to set the Desktop folder such that only an Administrator can edit it’s content, Still users have to be able to browse and use their shortcuts.
Set-RestrictedDesktopAccess </h3>
This script is used to change the access control on a user’s desktop folder so that only the administrator can modify it. The user can still open/execute shortcuts but not change the content of the desktop folder.
Details
The file receive the name of a local user as an argument. There is autocompletion to avoid bad entries. The execution needs to be done as admin Then the function resolve the user desktop folder, will get the list of files and sub folders and change the ACLs, and remove the inheritance.
Reset-AccessRights
This function will revert the changes done by Set-RestrictedDesktopAccess
by re-enabling inheritance and purging the added acls.
How To Use
to test before -WhatIF
# This is for a TEST (will not change anything) -- RECOMMENDED BEFORE DOING SOMETHING MORE
$Changed = .\Set-RestrictedDesktopAccess.ps1 -UserName JohnDoe -WhatIf -Verbose
# List the changes
$Changed
# as administrator
$Changed = .\Set-RestrictedDesktopAccess.ps1 -UserName JohnDoe
Quick Demo
function Set-RestrictedAccessRights{
[CmdletBinding(SupportsShouldProcess)]
param (
[Parameter(Mandatory=$true,Position=0)]
[Alias('p', 'f','File')]
[string[]]$Paths,
[Parameter(Mandatory=$true,Position=1)]
[Alias('u')]
[ValidateScript({
if ([string]::IsNullOrEmpty($_)) {
throw "Invalid username specified `"$1`""
}
else {
$Owner = $_
$UsrOrNull = (Get-LocalUser -ErrorAction Ignore).Name | Where-Object { $_ -match "$Owner"}
if ([string]::IsNullOrEmpty($UsrOrNull)) {
throw "Invalid username specified `"$Owner`""
}
}
return $true
})]
[string]$Owner
)
Begin{
$is_admin = (New-Object Security.Principal.WindowsPrincipal ([Security.Principal.WindowsIdentity]::GetCurrent())).IsInRole([Security.Principal.WindowsBuiltinRole]::Administrator)
if($False -eq $is_admin) { throw "Administrator privileges required" }
$object_count = $Paths.Count
$username = (Get-LocalUser).Name -replace '(.*\s.*)',"'`$1'" | Where-Object { $_ -match "$Owner"}
Write-Verbose "Set-RestrictedAccessRights for owner $Owner. Num $object_count paths"
$admin_account_name = Get-AdminAccountName
Write-Verbose "Get-AdminAccountName => $admin_account_name"
}
Process{
try{
$usr_allow = "$ENV:USERDOMAIN\$username" , 'ReadAndExecute,Synchronize' , 'none, none' , 'None', 'Allow'
$adm_allow = "$ENV:USERDOMAIN\$admin_account_name" , 'FullControl' , 'none, none' , 'None', 'Allow'
$secobj_admin_allow = New-Object System.Security.AccessControl.FileSystemAccessRule $adm_allow
$secobj_user_allow = New-Object System.Security.AccessControl.FileSystemAccessRule $usr_allow
if($Null -eq $secobj_admin_allow) { throw "Error on FileSystemAccessRule creation $adm_allow" }
if($Null -eq $secobj_user_allow) { throw "Error on FileSystemAccessRule creation $usr_allow" }
[system.collections.arraylist]$results = [system.collections.arraylist]::new()
ForEach($obj in $Paths){
$userobject = New-Object System.Security.Principal.NTAccount("$ENV:USERDOMAIN", "$username")
$acl = Get-Acl -Path $obj
$acl.SetAccessRuleProtection($true, $false)
$acl.SetAccessRule($secobj_user_allow)
$acl.AddAccessRule($secobj_admin_allow)
$acl.SetOwner($userobject)
Write-Verbose "Save the access rules for `"$obj`""
# Save the access rules to disk:
try{
$acl | Set-Acl $obj -ErrorAction Stop
#Write-Host "Set-RestrictedAccessRights `"$obj`""
[void]$results.Add($obj)
}catch{
Write-Host "Set-Acl ERROR `"$obj`" $_" -f Red
}
}
Write-Verbose "$($results.Count) paths modified"
$results
}catch{
Write-Error $_
}
}
}
Reset-AccessRights
This is how we change the folders ACLS. Resetting the owner at the same time:
function Reset-AccessRights{
[CmdletBinding(SupportsShouldProcess)]
param (
[Parameter(Mandatory=$true,Position=0)]
[Alias('p', 'f','File')]
[string[]]$Paths,
[Parameter(Mandatory=$true,Position=1)]
[Alias('u')]
[ValidateScript({
if ([string]::IsNullOrEmpty($_)) {
throw "Invalid username specified `"$1`""
}
else {
$Owner = $_
$UsrOrNull = (Get-LocalUser -ErrorAction Ignore).Name | Where-Object { $_ -match "$Owner"}
if ([string]::IsNullOrEmpty($UsrOrNull)) {
throw "Invalid username specified `"$Owner`""
}
}
return $true
})]
[string]$Owner
)
Begin{
$is_admin = (New-Object Security.Principal.WindowsPrincipal ([Security.Principal.WindowsIdentity]::GetCurrent())).IsInRole([Security.Principal.WindowsBuiltinRole]::Administrator)
if($False -eq $is_admin) { throw "Administrator privileges required" }
$object_count = $Paths.Count
$username = (Get-LocalUser).Name -replace '(.*\s.*)',"'`$1'" | Where-Object { $_ -match "$Owner"}
Write-Verbose "Reset-AccessRights for owner $Owner. Num $object_count paths"
$admin_account_name = Get-AdminAccountName
Write-Verbose "Get-AdminAccountName => $admin_account_name"
}
Process{
try{
$usr_allow = "$ENV:USERDOMAIN\$username" , 'FullControl' , "none, none","none","Allow"
$secobj_user_allow = New-Object System.Security.AccessControl.FileSystemAccessRule $usr_allow
$i = 0
Write-Progress -Activity 'Reset-AccessRights' -Status "Done $i on $object_count. $per %" -PercentComplete 0
if($Null -eq $secobj_user_allow) { throw "Error on FileSystemAccessRule creation $usr_allow" }
[system.collections.arraylist]$results = [system.collections.arraylist]::new()
ForEach($obj in $Paths){
if($obj.Contains('[') ){ Write-Host "$_" ; continue; }
$userobject = New-Object System.Security.Principal.NTAccount("$ENV:USERDOMAIN", "$username")
$acl = Get-Acl -Path $obj
#foreach ($aceToRemove in $acl.Access){
# $r= $acl.RemoveAccessRule($aceToRemove)
#}
$acl.SetAccessRuleProtection($false, $false)
$acl.SetAccessRule($secobj_user_allow)
$acl.SetOwner($userobject)
Write-Verbose "Save the access rules for `"$obj`""
# Save the access rules to disk:
try{
$acl | Set-Acl $obj -ErrorAction Stop
[int]$per=[math]::Round($i / $object_count * 100)
Write-Progress -Activity 'Reset-AccessRights' -Status "Done $i on $object_count. $per %" -PercentComplete $per
#[void]$results.Add($obj)
$i++
}catch{
Write-Host "Set-Acl ERROR `"$obj`" $_" -f Red
}
}
Write-Progress -Activity 'Reset-AccessRights' -Complete
Write-Verbose "$($results.Count) paths modified"
$results
}catch{
Write-Error $_
}
}
}
Get the code
RestrictDesktopPermissions on GitHub
Important Note Do You have Issues accessing the core repository? Don’t be shy and send me an EMAIL at guillaumeplante.qc@gmail.com and I will fix access for you