File Screens, a feature of the File Server Resource Manager tool, allows administrators to restrict the type of files that can be stored on a share. It is both useful and infuriating. Useful to me as I can enable it on our student’s redirected folder location. Infuriating for students because they can’t save any EXEs in this location.*
File Screens has a downside though. It is an all or nothing approach to file type filtering. In the example above, users are either allowed or blocked from saving executable files on the HomeFolders location. The result is dependent on if the rule is active or not.
Let’s say that you don’t really mind that a user saves an executable to their redirected downloads folder. You might have asked a user to download an application so you can deploy it. Or a user might need to run a small application once (such as a online meeting plugin). When file screens are enabled, your users get a nasty accessed denied error. What is needed is something a bit more flexible – say, a PowerShell script (or two).
Cleaning up EXEs with PowerShell
Our first script allows a trial run on your share or DFS Namespace. You will need to modify the Get-ChildItem path in the first line to match your environment. The script will search for any file in that location that has an .EXE extension and has a Last Write Time older than 7 days ago. Each file is then marked as hidden. This allows us to simulate a -whatif scenario.** If you want to see what files will be marked as hidden, run just the $Files line and see what is contained in that variable.
$Files = Get-ChildItem "\\Test.local\data\Staff\" -Recurse | Where-Object {$_.Extension -eq ".EXE" -and $_.Lastwritetime -lt ((Get-Date).AddDays(-7))} | sort Lastwritetime foreach ($File in $Files){ $(Get-Item $File.FullName).Attributes = 'Hidden' }
If your environment is like mine, no one will notice that their EXEs are missing. When you feel confident to actually remove the files (and have a valid backup), run the second script. It has a slightly modified foreach loop that calls the Remove-Item Cmdlet. If the $File item is successfully removed, the file details are written to .\DeletedFiles.csv. The Get-ChildItem and Remove-Item Cmdlets use the additional -force parameter in this script. This parameter allows both Cmdlets to interact with hidden and read-only files. This is needed if you marked all of your EXEs as hidden with the first script.
$Files = Get-ChildItem "\\Test.local\data\staff" -Recurse -Force | Where-Object {$_.Extension -eq ".EXE" -and $_.Lastwritetime -lt ((Get-Date).AddDays(-7))} | sort Lastwritetime foreach ($File in $Files){ Remove-Item -Path $File.FullName -Recurse -Force if ($? -eq $True){ $File | export-csv .\DeletedFiles.csv -NoTypeInformation -Append } }
These two scripts saved almost 60GB of storage in my environment and I hope they help your servers out as well! I now use file screens on certain shares and this script on other shares. And if you are getting tired of folder redirection, don’t despair – you only have two more articles in this series to read. 🙂
*AppLocker would prevent an EXE from running in this location.
**Though now that I think of it, modifying the ACLs on the EXE to add an deny would have been a better way of simulating the actual delete.