Creating a Thumbnail of a Word Document using PowerShell

I was in the process of configuring a number of documents for custom Microsoft Office Templates as per Deploy custom templates in Office 2010 http://technet.microsoft.com/en-us/library/cc178976.aspx

As I had a lot of documents I thought it would be good to automate the generation of first page document previews.

For fun I decided to try and do this using PowerShell, and without some of the tricks like "screen capture" I’ve seen in other scripts.

This process however does have some pre-requisites on installed machine (other than PowerShell)

– Microsoft Office Interop Assemblies (Office 2010 installed by default, 2007 you may need to install)

-Microsoft XPS Document Writer printer Enabled (This is default in Windows 7)

# by Malcolm McCaffery
# converts first page of a Word Document to PNG file
# using Word Interop & XPS Document Writer
# TODO: add robustness/error checking/etc,etc

function New-ThumbnailFromWordDocument([string] $inputfilename,[string] $outputimagefilename)
{
    # Add interop dll & create reference to Microsoft Word Interop – requires Office installed
    add-type -AssemblyName "Microsoft.Office.Interop.Word"
    $Word = New-Object -ComObject "Word.Application"

    # Set active printer – available by default in Windows 7
    $Word.ActivePrinter="Microsoft XPS Document Writer"

    # the special “missing” value for non-specified parametersm
    $missing = [System.Reflection.Missing]::Value

    # Open in read only mode
    $doc=$Word.Documents.Open(
        $inputfilename,
        $missing,
        $true)
       
    $doc.Activate()

    # Print the current page of the word document – which will be the first page
    $WdPrintOutRange="Microsoft.Office.Interop.Word.WdPrintoutRange" -as [type]
    $WdPrintOutItem="Microsoft.Office.Interop.Word.WdPrintOutItem" -as [type]
    $WdPrintOutPages="Microsoft.Office.Interop.Word.WdPrintOutPages" -as [type]
    $copies = "1"
    $pages = "1"
    $range = $WdPrintOutRange::wdPrintCurrentPage
    $items = $WdPrintOutItem::wdPrintDocumentContent
    $pageType = $WdPrintOutPages::wdPrintAllPages

    # temporary output file will be XPS format
    $outputfilename=$outputimagefilename + ".xps"
  
    # check if output file already exists – we must delete it otherwise print will fail
    if (Test-Path $outputfilename) {
        Remove-Item $outputfilename -Force
    }

    if (Test-Path $outputimagefilename) {
        Remove-Item $outputimagefilename -Force
    }

    # print the file to XPS
    $doc.PrintOut(
        [REF]$false, [REF]$false, [REF]$range, [REF]$outputfilename,[REF]$missing, [REF]$missing,
        [REF]$items, [REF]$copies, [REF]$pages, [REF]$pageType, [REF]$false, [REF]$true,
        [REF]$missing, [REF]$false, [REF]$missing, [REF]$missing, [REF]$missing, [REF]$missing)

    # Close file without saving changes
    $doc.Close([REF]$false)
    $Word.Quit()

    # Now we need the reach framework which contains XPS APIs
    Add-Type -Assembly "ReachFramework"

    # Load the XPS document
    $xpsDocument = New-Object System.Windows.Xps.Packaging.XpsDocument($outputfilename, [System.IO.FileAccess]::Read)

    # load WPF Presentation Core with all its Media.Imaging goodness
    $null=[Reflection.Assembly]::LoadWithPartialName("PresentationCore")

    $docSeq=$xpsDocument.GetFixedDocumentSequence()
    $docPage=$docSeq.DocumentPaginator.GetPage(0)

    # create the Bitmap object
    $bitmap=New-Object -TypeName System.Windows.Media.Imaging.BitmapImage
    $renderTarget=New-Object -TypeName System.Windows.Media.Imaging.RenderTargetBitmap(
        $docPage.Size.Width,
        $docPage.Size.Height,
        96, # WPF units are 96 DPI based
        96,
        ([System.Windows.Media.PixelFormats]::Default)
        )

    # render the page
    $renderTarget.Render($docPage.Visual)

    # change to jpeg/bmp/etc as required
    $encoder=New-Object -TypeName System.Windows.Media.Imaging.PngBitmapEncoder

    $encoder.Frames.Add([System.Windows.Media.Imaging.BitmapFrame]::Create($renderTarget))

    $pageOutStream=New-Object System.IO.FileStream(
        $outputimagefilename,
        ([System.IO.FileMode]::Create),
        ([System.IO.FileAccess]::Write))

    # save the encoded output as an image
    $encoder.Save($pageOutStream)

    # close up shop
    $pageOutStream.Close()
    $xpsDocument.Close()

    # delete the XPS file
    Remove-Item $outputfilename -Force
}

# usage example
New-ThumbnailFromWordDocument -inputfilename "C:\Users\Public\test.docx" -outputimagefilename "C:\Users\Public\test.png"

About chentiangemalc

specializes in end-user computing technologies. disclaimer 1) use at your own risk. test any solution in your environment. if you do not understand the impact/consequences of what you're doing please stop, and ask advice from somebody who does. 2) views are my own at the time of posting and do not necessarily represent my current view or the view of my employer and family members/relatives. 3) over the years Microsoft/Citrix/VMWare have given me a few free shirts, pens, paper notebooks/etc. despite these gifts i will try to remain unbiased.
This entry was posted in Uncategorized. Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s