Categories

Unblocking files

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 {
    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')
            $fs.Delete()
        }
    }
    else {Write-Host "File Not found"}
}

 

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.

Leave a Reply