When I download files from the Internet to Vista or Windows 7 the file is blocked and I can’t execute it until its unblocked. This is especially annoying with zip files because if I unzip them all the contents are blocked. I have been meaning to do something in PowerShell for this and finally got round to it. The blocking is because of a zone identifier in an alternate data stream (ADS) attached to the file. If you have been around PowerShell for any length of time you may remember MoWs post on this subject – http://thepowershellguy.com/blogs/posh/archive/2007/01/27/powershell-accessing-alternative-data-streams-of-files-on-an-ntfs-volume.aspx
This was my starting point but when went to download the file containing the .NET classes we need to access the ADS from http://www.codeproject.com/KB/cs/ntfsstreams.aspx I found that the classes had been updated. So first off download the .NET stuff and extract the dll containing the classes (after unblocking the zip file).
I decided to add this functionality into my module for working with files.
First point is that I need to load the .NET assemblies from the dll. I can do this in the .psd1 file by adding this line
RequiredAssemblies = ‘Trinet.Core.IO.Ntfs.dll’
I then added two functions into the module. One to test if a zone identifier exists and another to delete it
001
002 003 004 005 006 007 008 009 010 011 012 013 014 015 016 017 018 019 020 021 022 023 024 025 026 027 028 029 030 031 |
function Test-ZoneIdentifier {
param ( [Parameter(ValueFromPipeline=$true)] $file ) if (Test-Path $file) { if ([Trinet.Core.IO.Ntfs.FileSystem]::AlternateDataStreamExists($file, ‘Zone.Identifier’)){ $fs = [Trinet.Core.IO.Ntfs.FileSystem]::GetAlternateDataStream($file, ‘Zone.Identifier’) $ads = ($fs.OpenText()).ReadToEnd() $type = $ads.SubString( ($ads.IndexOf("ZoneId=") + 7), 1) -as [ZoneIdentifier] Write-Host "Zone.Identifier present. Type $type If of Type Internet the file will be blocked." } else {[Trinet.Core.IO.Ntfs.FileSystem]::ListAlternateDataStreams($file)} ## test if other ADS } else {Write-Host "File Not found"} } function Remove-ZoneIdentifier { |
The Test-ZoneIdentifier function will accept a file from the pipeline and test the path to the file. If the file exists the function will then test to see if a Zone.Identifer ADS exists. If it does it will read the ADS and work out the zone using the ZoneIdentifier enum which we create in the module as well.
001
002 003 004 005 006 007 008 009 |
$values = "NoZone = -1", "MyComputer = 0", "Intranet = 1", "Trusted = 2", "Internet = 3", "Untrusted = 4"
$code = @" public enum ZoneIdentifier : int { $($values -join ",`n") } "@ Add-Type $code |
This is adapted from MoWs code at http://thepowershellguy.com/blogs/posh/archive/2008/06/02/powershell-v2-ctp2-making-custom-enums-using-add-type.aspx
A hash table could also be used at this point if preferred.
The function Remove-ZoneIdentifier will delete the ADS and unblock the file. By enabling these functions to work on the pipeline we can process a number of files in one hit.
The functions are used as follows
PS> Import-Module filefunctions
PS> Get-ChildItem -Path c:\test\NtfsStreams.zip | Test-ZoneIdentifier
Zone.Identifier present. Type Internet If of Type Internet the file will be blocked.
PS> Get-ChildItem -Path c:\test\NtfsStreams.zip | Remove-ZoneIdentifier
True
PS> Get-ChildItem -Path c:\test\NtfsStreams.zip | Test-ZoneIdentifier
I’ve uploaded the module files to my skydrive at http://cid-43cfa46a74cf3e96.skydrive.live.com/self.aspx/PowerShell%20Scripts/FileFunctions.zip
The ntfs streams dll you will need to download separately.