Monthly Archives: September 2009

Word module

I’ve posted a PowerShell module that includes the functions in earlier posts to my skydrive  -   http://cid-43cfa46a74cf3e96.skydrive.live.com/browse.aspx/PowerShell%20Scripts

Enjoy

Technorati Tags: ,,

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.

Codeplex AD Replication Module

The other codeplex project that caught my eye was a brand new one to create a PowerShell module to manage AD replication.  This one will be very useful and one I will be using a lot.

There is still time for suggestions as to content for this project – see http://adreplicationmodule.codeplex.com/

Codeplex PowerShell Configurator

I was looking at codeplex (Microsoft’s Open Source site) and decided to do a search for projects relating to PowerShell. 161 projects were returned.  The first 110 had an obvious PowerShell connection.  This is a tremendous number and really does demonstrate the strength of the PowerShell community.

One project that caught my eye was James O’Neill’s PowerShell configurator for Server 2008 R2 Core and Hyper Server R2.  Its done as a PowerShell v2 module with the following functions

Managing installed software , drivers and updates

Add-Driver, Get-Driver
Add-HotFix ,
Add-InstalledProduct ,Get-InstalledProduct , , Remove-InstalledProduct,
Add-WindowsFeature , Get-WindowsFeature, Remove-WindowsFeature
Add-WindowsUpdate, Get-WindowsUpdateConfig , Set-WindowsUpdateConfig

Managing the windows Firewall

Get-FirewallConfig , Set-FirewallConfig, Get-FirewallProfile , Get-FireWallRule

IP Networking

Get-NetworkAdapter, Get-IpConfig , New-IpConfig , Remove-IpConfig, Set-IpConfig

Licensing

Get-Registration , Register-Computer

Page file

Get-ShutDownTracker , Set-ShutDownTracker

Remote Desktop

Get-RemoteDesktopConfig , Set-RemoteDesktop

Other Windows Configuration

Get-WinRMConfig
Rename-Computer
Set-iSCSIConfig
Set-RegionalConfig

 

There shouldn’t be any reason why it won’t work on full fat Windows so I’ll definitely be trying it out.  Download from http://psconfig.codeplex.com/

Word Add text

Keeping on with our look at Word we need to able to add text to the documents we are creating.

001
002
003
004
005
006
007
008
009
010
011
function Add-Text {
    param (
        [string] $style = "Normal",
        [string] $text 
    )
    $global:paragraph = $doc.Content.Paragraphs.Add()
    $range = $paragraph.Range
    $Paragraph.Range.Text = $Text
    $Paragraph.Range.Style = $Style
    $Paragraph.Range.InsertParagraphAfter()
}

 

Add a paragraph then set the style and the paragraph text.  The text could come from a file using get-content. InsertParagraph() pushes the paragraph into the document.

Instead of setting the style we could explicitly set the font and its size.

Technorati Tags: ,,

Word add data to a table

We created a table in a recent post.  This time round we add some data to the table.

 

001
002
003
004
005
006
007
008
009
function Add-TableData {
    param (
        [int] $row = 1,
        [int] $col = 1,
        [string] $text
    )
    $table.Cell($row,$col).Range.Text = $text
   
}

 

The row and column together with the text to enter into the cell are passed as parameters. 

$table.Cell($row, $col).Range.Style = “style_name” can be used to set the style of the table cell contents.  We can even set the style at the table level if required.

Technorati Tags: ,,,

Module Contents

I’ve been writing a few modules recently and sometimes forget what I have in each module. Simple way to view the functions each module makes available.

001
002
003
004
005
006
007
Clear-Host
Get-Module -ListAvailable | foreach {
    Import-Module $_.Name
    Get-Command -Module $_.Name | Select Module, Name
    Remove-Module $_.Name
    ""
}

 

List the available modules and for each one import the module and then use Get-Command to find the functions each one loads. We can then remove the module.

Technorati Tags: ,

Word Close Document

So far we have created a document and started to add data into the document.

001
002
003
004
005
006
007
008
function Close-WordDocument {
    param (
        [parameter(Mandatory=$true)]
        [string]$file
    )
    $doc.SaveAs([REF]$file)
    $word.Quit()
}

 

We pass a file name in as a parameter. Notice that the parameter is mandatory. If we don’t supply the file name we will be prompted. If just a file name is given it will be saved into your standard word location (usually My Documents). If you want it to save somewhere else then use the full path.

The SaveAs() method is used for the save.  If you give the name of a file that exists it will overwrite!

The final line of the script closes the Word application.

Technorati Tags: ,