Categories

10564

Boot partition

Do you know which disk partition your system boots from?

Its easy to find out

function get-bootpartition {            
[CmdletBinding()]            
param (            
 [parameter(ValueFromPipeline=$true,            
   ValueFromPipelineByPropertyName=$true)]            
 [string]$computername="$env:COMPUTERNAME"            
)            
PROCESS{                
              
  Get-WmiObject -Class Win32_DiskPartition -Filter "BootPartition = $true" -ComputerName $computername            
              
}            
}


 



The filter only returns the partition where BootPartition is set to True

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.

Hidden Files

The last post got me thinking about hidden files and file attributes and how we can manipulate them in PowerShell.  Lets start by creating a PowerShell script.

PS> "'hello world'" > test.ps1
PS> ./test.ps1

We can see the file in a directory listing

PS> Get-ChildItem test.ps1

    Directory: C:\scripts

Mode                LastWriteTime     Length Name
----                -------------     ------ ----
-a---        30/05/2009     13:57         32 test.ps1

 

We can view the file attributes

PS> Get-ItemProperty -Path test.ps1 -Name Attributes

PSPath       : Microsoft.PowerShell.Core\FileSystem::C:\scripts\test.ps1
PSParentPath : Microsoft.PowerShell.Core\FileSystem::C:\scripts
PSChildName  : test.ps1
PSDrive      : C
PSProvider   : Microsoft.PowerShell.Core\FileSystem
Attributes   : Archive

We can set the attributes so the file becomes hidden using the Fileattributes enumeration

PS> Set-ItemProperty -Path test.ps1 -Name Attributes -Value ([System.IO.FileAttributes]::Hidden)

as shown previously we have to use the force to get a listing

PS> Get-ChildItem test.ps1 -Force

    Directory: C:\scripts

Mode                LastWriteTime     Length Name
----                -------------     ------ ----
---h-        30/05/2009     13:57         32 test.ps1

But we have over written the existing attributes – oops.  Need to recreate the file and try again.  This time we will add the attribute.

PS> Set-ItemProperty -Path test.ps1 -Name Attributes -Value ((Get-ItemProperty -Path test.ps1).Attributes -bxor [System.IO.FileAttributes]::Hidden)

and we now see the existing attributes are preserved


PS> Get-ChildItem test.ps1 -Force

    Directory: C:\scripts

Mode                LastWriteTime     Length Name
----                -------------     ------ ----
-a-h-        30/05/2009     14:11         32 test.ps1

We can clear all the attributes or just rest to those we require

PS> Set-ItemProperty -Path test.ps1 -Name Attributes -Value ([System.IO.FileAttributes]::Normal) -Force
PS> Get-ChildItem test.ps1 -Force

    Directory: C:\scripts

Mode                LastWriteTime     Length Name
----                -------------     ------ ----
-----        30/05/2009     14:11         32 test.ps1

The full range of attributes can be seen

PS> [enum]::GetNames([System.IO.FileAttributes])
ReadOnly
Hidden
System
Directory
Archive
Device
Normal
Temporary
SparseFile
ReparsePoint
Compressed
Offline
NotContentIndexed
Encrypted

Normal rules still apply so we can’t compress an encrypted file

Removing Hidden files

I used the OneNote 2007 Side Note utility this morning and for some reason it created a table of contents file ( .onetoc2 ) file in each of the folders in which I keep my PowerShell. Strange behaviour.  Any way there are more of them than I want to delete by hand.

Get-ChildItem doesn’t show them – they are hidden files so we need to use

Get-ChildItem -Filter "*.onetoc2" -Force –Recurse

then we can pipe that into Remove-Item

Get-ChildItem -Filter "*.onetoc2" -Force -Recurse | Remove-Item –Force

again using the Force.  All gone.

And that young Luke is how you get rid of hidden files. Pity I didn’t post this on 4th May

Technorati Tags: ,