<img alt="" src="https://secure.hims1nice.com/151009.png" style="display:none;">
Skip to main content

Block use of ‘Show Hidden Items’ button via Intune

Recently, a colleague requested assistance with what seemed like a simple task. Our customer required a non-standard ...

Nate Berrier
Posted by Nate Berrier
Block use of ‘Show Hidden Items’ button via Intune
image-3

In today's fast-paced business landscape, staying ahead of the competition requires efficient and effective solutions. According to Microsoft’s Work Trend Index, nearly 70% of employee report that they don’t have sufficient time in the day to focus on “work”, with more time being spent Communicating than Creating.

Microsoft 365 Copilot is designed, with Microsoft’s cloud trust platform at its core, to allow for employees to both be more productive, reduce the time spent searching for information, performing mundane tasks, and other low-value activities.

Recently, a colleague requested assistance with what seemed like a simple task. Our customer required a non-standard kiosk-style profile via Intune. Devices should be locked down as much as possible, with access to a single app and network share. The customer was happy with our solution, but wanted to make sure users did not have the opportunity to accidentally delete hidden files. Specifically hoping to disable the ‘Hidden Items’ button within file explorer ribbon UI.

 

Picture1-2

 

We found an old blog targeted at Server 2012 (the language is a bit colorful) which claimed to have the secret for disabling this pesky checkbox. Server 2012 - Ribbon UI: Disable Hidden Items Checkbox - Paper Street Online

Simple enough to write a PowerShell script to deploy a few registry changes, right? Wrong. Upon testing with a local VM, we discovered that even local system was relegated to read access. The solution to the problem is to take ownership of the value and delegate permissions as necessary. Doing so in PowerShell isn’t particularly pretty, but most things are possible in PS if you can plug your nose.

Its not often that I find pre-written code snippets to do exactly what is needed, but clever searching brought us close. StackOverflow User SaintFrag (User SaintFrag - Stack Overflow) provided a function with examples in this post How do I take ownership of a registry key via PowerShell? - Stack Overflow

 

function Take-Permissions {

   # Developed for PowerShell v4.0

   # Required Admin privileges

   # Links:

   #   http://shrekpoint.blogspot.ru/2012/08/taking-ownership-of-dcom-registry.html

   #   http://www.remkoweijnen.nl/blog/2012/01/16/take-ownership-of-a-registry-key-in-powershell/

   #   https://powertoe.wordpress.com/2010/08/28/controlling-registry-acl-permissions-with-powershell/

 

   param($rootKey, $key, [System.Security.Principal.SecurityIdentifier]$sid = 'S-1-5-32-545', $recurse = $true)

 

   switch -regex ($rootKey) {

       'HKCU|HKEY_CURRENT_USER'   { $rootKey = 'CurrentUser' }

       'HKLM|HKEY_LOCAL_MACHINE'   { $rootKey = 'LocalMachine' }

       'HKCR|HKEY_CLASSES_ROOT'   { $rootKey = 'ClassesRoot' }

       'HKCC|HKEY_CURRENT_CONFIG' { $rootKey = 'CurrentConfig' }

       'HKU|HKEY_USERS'           { $rootKey = 'Users' }

   }

 

   ### Step 1 - escalate current process's privilege

   # get SeTakeOwnership, SeBackup and SeRestore privileges before executes next lines, script needs Admin privilege

   $import = '[DllImport("ntdll.dll")] public static extern int RtlAdjustPrivilege(ulong a, bool b, bool c, ref bool d);'

   $ntdll = Add-Type -Member $import -Name NtDll -PassThru

   $privileges = @{ SeTakeOwnership = 9; SeBackup = 17; SeRestore = 18 }

   foreach ($i in $privileges.Values) {

       $null = $ntdll::RtlAdjustPrivilege($i, 1, 0, [ref]0)

   }

 

   function Take-KeyPermissions {

       param($rootKey, $key, $sid, $recurse, $recurseLevel = 0)

 

       ### Step 2 - get ownerships of key - it works only for current key

       $regKey = [Microsoft.Win32.Registry]::$rootKey.OpenSubKey($key, 'ReadWriteSubTree', 'TakeOwnership')

       $acl = New-Object System.Security.AccessControl.RegistrySecurity

       $acl.SetOwner($sid)

       $regKey.SetAccessControl($acl)

 

       ### Step 3 - enable inheritance of permissions (not ownership) for current key from parent

       $acl.SetAccessRuleProtection($false, $false)

       $regKey.SetAccessControl($acl)

 

       ### Step 4 - only for top-level key, change permissions for current key and propagate it for subkeys

       # to enable propagations for subkeys, it needs to execute Steps 2-3 for each subkey (Step 5)

       if ($recurseLevel -eq 0) {

           $regKey = $regKey.OpenSubKey('', 'ReadWriteSubTree', 'ChangePermissions')

           $rule = New-Object System.Security.AccessControl.RegistryAccessRule($sid, 'FullControl', 'ContainerInherit', 'None', 'Allow')

           $acl.ResetAccessRule($rule)

           $regKey.SetAccessControl($acl)

       }

 

       ### Step 5 - recursively repeat steps 2-5 for subkeys

       if ($recurse) {

           foreach($subKey in $regKey.OpenSubKey('').GetSubKeyNames()) {

               Take-KeyPermissions $rootKey ($key+'\'+$subKey) $sid $recurse ($recurseLevel+1)

           }

       }

   }

 

   Take-KeyPermissions $rootKey $key $sid $recurse

}

 

 

To make use of this function, we must feed it the appropriate parameters. Our registry changes will take place in HKEY_LOCAL_MACHINE, so this must be specified for -RootKey.

The rest of the registry path is Software\Microsoft\Windows\CurrentVersion\Explorer\CommandStore\shell\Windows.ShowHiddenFiles and should be specified for -Key parameter.

The final property we need to specify is the -SID for the local system account which is S-1-5-32-544.

Our command looks like the following, with the -recurse switch defaulting to true.

 

Take-Permissions -rootKey "HKLM" -key "Software\Microsoft\Windows\CurrentVersion\Explorer\CommandStore\shell\Windows.ShowHiddenFiles" -sid S-1-5-32-544

 

Now local system has full control for the key (and any subkeys if they existed). If you wanted to change permissions for additional users, the following bits can be used, changing the account listed under $rule:

 

#Set ACLS for Local System to have permissions.

$acl= get-acl -path 'HKLM:\Software\Microsoft\Windows\CurrentVersion\Explorer\CommandStore\shell\Windows.ShowHiddenFiles'

$inherit = [system.security.accesscontrol.InheritanceFlags]"None"

$propagation = [system.security.accesscontrol.PropagationFlags]"None"

$rights = "QueryValues,SetValue,CreateSubKey"

$rule=new-object system.security.accesscontrol.registryaccessrule "NT AUTHORITY\SYSTEM",$rights,$inherit,$propagation,"Allow"

$acl.addaccessrule($rule)

$acl | set-acl

 

Finally, we can set our registry values:

 

Set-Location -Path HKLM:\

 

$RegistryPath = 'HKLM:\Software\Microsoft\Windows\CurrentVersion\Explorer\CommandStore\shell\Windows.ShowHiddenFiles'

$Name         = 'AttributeMask'

$Value       = '00100000'

New-ItemProperty -Path $RegistryPath -Name $Name -Value $Value -PropertyType DWORD -Force

 

$Name         = 'AttributeValue'

$Value       = '00100000'

New-ItemProperty -Path $RegistryPath -Name $Name -Value $Value -PropertyType DWORD -Force

 

 

$Name         = 'ImpliedSelectionModel'

$Value       = '00000000'

New-ItemProperty -Path $RegistryPath -Name $Name -Value $Value -PropertyType DWORD -Force

 

 

Set-ItemProperty -Path $RegistryPath -Name ExplorerCommandHandler -Value "" -Force

 

Using a test machine to run the commands, it appears we are successful! Full script is below, this can be added to Intune, SCCM, GPO, or run manually.

 

#Load function to take ownership of HKLM

 

function Take-Permissions {

   # Developed for PowerShell v4.0

   # Required Admin privileges

   # Links:

   #   http://shrekpoint.blogspot.ru/2012/08/taking-ownership-of-dcom-registry.html

   #   http://www.remkoweijnen.nl/blog/2012/01/16/take-ownership-of-a-registry-key-in-powershell/

   #   https://powertoe.wordpress.com/2010/08/28/controlling-registry-acl-permissions-with-powershell/

 

   param($rootKey, $key, [System.Security.Principal.SecurityIdentifier]$sid = 'S-1-5-32-545', $recurse = $true)

 

   switch -regex ($rootKey) {

       'HKCU|HKEY_CURRENT_USER'   { $rootKey = 'CurrentUser' }

       'HKLM|HKEY_LOCAL_MACHINE'   { $rootKey = 'LocalMachine' }

       'HKCR|HKEY_CLASSES_ROOT'   { $rootKey = 'ClassesRoot' }

       'HKCC|HKEY_CURRENT_CONFIG' { $rootKey = 'CurrentConfig' }

       'HKU|HKEY_USERS'           { $rootKey = 'Users' }

   }

 

   ### Step 1 - escalate current process's privilege

   # get SeTakeOwnership, SeBackup and SeRestore privileges before executes next lines, script needs Admin privilege

   $import = '[DllImport("ntdll.dll")] public static extern int RtlAdjustPrivilege(ulong a, bool b, bool c, ref bool d);'

   $ntdll = Add-Type -Member $import -Name NtDll -PassThru

   $privileges = @{ SeTakeOwnership = 9; SeBackup = 17; SeRestore = 18 }

   foreach ($i in $privileges.Values) {

       $null = $ntdll::RtlAdjustPrivilege($i, 1, 0, [ref]0)

   }

 

   function Take-KeyPermissions {

       param($rootKey, $key, $sid, $recurse, $recurseLevel = 0)

 

       ### Step 2 - get ownerships of key - it works only for current key

       $regKey = [Microsoft.Win32.Registry]::$rootKey.OpenSubKey($key, 'ReadWriteSubTree', 'TakeOwnership')

       $acl = New-Object System.Security.AccessControl.RegistrySecurity

       $acl.SetOwner($sid)

       $regKey.SetAccessControl($acl)

 

       ### Step 3 - enable inheritance of permissions (not ownership) for current key from parent

       $acl.SetAccessRuleProtection($false, $false)

       $regKey.SetAccessControl($acl)

 

       ### Step 4 - only for top-level key, change permissions for current key and propagate it for subkeys

       # to enable propagations for subkeys, it needs to execute Steps 2-3 for each subkey (Step 5)

       if ($recurseLevel -eq 0) {

           $regKey = $regKey.OpenSubKey('', 'ReadWriteSubTree', 'ChangePermissions')

           $rule = New-Object System.Security.AccessControl.RegistryAccessRule($sid, 'FullControl', 'ContainerInherit', 'None', 'Allow')

           $acl.ResetAccessRule($rule)

           $regKey.SetAccessControl($acl)

       }

 

       ### Step 5 - recursively repeat steps 2-5 for subkeys

       if ($recurse) {

           foreach($subKey in $regKey.OpenSubKey('').GetSubKeyNames()) {

               Take-KeyPermissions $rootKey ($key+'\'+$subKey) $sid $recurse ($recurseLevel+1)

           }

       }

   }

 

   Take-KeyPermissions $rootKey $key $sid $recurse

}

 

#Take Ownership of Key with values we need to change

Take-Permissions -rootKey "HKLM" -key "Software\Microsoft\Windows\CurrentVersion\Explorer\CommandStore\shell\Windows.ShowHiddenFiles" -sid S-1-5-32-544

 

Set-Location -Path HKLM:\

 

$RegistryPath = 'HKLM:\Software\Microsoft\Windows\CurrentVersion\Explorer\CommandStore\shell\Windows.ShowHiddenFiles'

$Name         = 'AttributeMask'

$Value       = '00100000'

New-ItemProperty -Path $RegistryPath -Name $Name -Value $Value -PropertyType DWORD -Force

 

$Name         = 'AttributeValue'

$Value       = '00100000'

New-ItemProperty -Path $RegistryPath -Name $Name -Value $Value -PropertyType DWORD -Force

 

 

$Name         = 'ImpliedSelectionModel'

$Value       = '00000000'

New-ItemProperty -Path $RegistryPath -Name $Name -Value $Value -PropertyType DWORD -Force

 

 

Set-ItemProperty -Path $RegistryPath -Name ExplorerCommandHandler -Value "" -Force

Looking for help with PowerShell?

 

Contact Us

KiZAN Logo Blue

KiZAN is a Microsoft National Solutions Provider with numerous gold and silver Microsoft competencies, including gold data analytics. Our primary offices are located in Louisville, KY, and Cincinnati, OH, with additional sales offices located in Tennessee, Indiana, Michigan, Pennsylvania, Florida, North Carolina, South Carolina, Georgia and Texas.