Creating PDF files dynamically with PowerShell

So how does one go about creating PDF files dynamically? You need a pinch of the open source PdfSharp library and 10 lines of PowerShell.

Add-Type -Path .\PdfSharp.dll
$doc = New-Object PdfSharp.Pdf.PdfDocument
$doc.Info.Title = "Created dynamically"
$page = $doc.AddPage()
$gfx = [PdfSharp.Drawing.XGraphics]::FromPdfPage($page)
$font = New-Object PdfSharp.Drawing.XFont("Verdana", 20, [PdfSharp.Drawing.XFontStyle]::BoldItalic)
$msg = "Hello World"
$rect = New-Object PdfSharp.Drawing.XRect(0,0,$page.Width, $page.Height)
$gfx.DrawString($msg, $font, [PdfSharp.Drawing.XBrushes]::Black, $rect, [PdfSharp.Drawing.XStringFormats]::Center)
$doc.Save("HelloWorld.pdf")

Creating jUnit/xUnit compatible xml test tesults in PowerShell

I originally wrote this function when I needed to create jUnit/xUnit compatible test results. The resulting xml file was then fed into the jUnit plugin in Jenkins to show the results PowerShell/PSUnit based tests.

Function Write-JunitXml([System.Collections.ArrayList] $Results, [System.Collections.HashTable] $HeaderData, [System.Collections.HashTable] $Statistics, $ResultFilePath)
{
$template = @'
<testsuite name="" file="">
<testcase classname="" name="" time="">
    <failure type=""></failure>
</testcase>
</testsuite>
'@

    $guid = [System.Guid]::NewGuid().ToString("N")
    $templatePath = [System.IO.Path]::Combine([System.IO.Path]::GetTempPath(), $guid + ".txt");

    $template | Out-File $templatePath -encoding UTF8
    # load template into XML object
    $xml = New-Object xml
    $xml.Load($templatePath)
    # grab template user
    $newTestCaseTemplate = (@($xml.testsuite.testcase)[0]).Clone()  

    $className = [System.IO.Path]::GetFileNameWithoutExtension($HeaderData.TestFileName)
    $xml.testsuite.name = $className
    $xml.testsuite.file = $HeaderData.TestFileName

    foreach($result in $Results) 
    {   
        $newTestCase = $newTestCaseTemplate.clone()
        $newTestCase.classname = $className
        $newTestCase.name = $result.Test.ToString()
        $newTestCase.time = $result.Time.ToString()
        if($result.Result -eq "PASS")
        {   #Remove the failure node
            $newTestCase.RemoveChild($newTestCase.ChildNodes[0]) | Out-Null
        }
        else
        {
            $newTestCase.failure.InnerText = Format-ErrorRecord $result.Reason
        }
        $xml.testsuite.AppendChild($newTestCase) > $null
    }   

    # remove users with undefined name (remove template)
    $xml.testsuite.testcase | Where-Object { $_.Name -eq "" } | ForEach-Object  { [void]$xml.testsuite.RemoveChild($_) }
    # save xml to file
    Write-Host "Path" $ResultFilePath

    $xml.Save($ResultFilePath)

    Remove-Item $templatePath #clean up
}

Debugging Javascript

What’s the easiest way to break into the debugger in JavaScript especially when you have heaps of js files being loaded by a page (SharePoint 2013 & display templates, I’m looking at you)
Apparently this is a very old trick (pre 2006). Just add the debugger command (and enable script debugging if your using IE).

debug

Tweaking the default search display template in SharePoint 2013

Let’s look at what it takes to make a minor tweak to the out of the box search result in SharePoint 2013. Say my requirement is to show the document id in the search result like the sample shown below.

Search Result

For the example above I’m going to create a custom display template for PowerPoint files.

Let’s start by mapping the display templates folder as a local drive. Browse to /_layouts/15/DesignMapDrive.aspx and click on the /_catalogs/masterpage/ link to open the drive. You can then map that as a network drive.

Through explorer browser to the \_catalogs\masterpage\Display Templates\Search folder and copy these two files file to a local drive.

  • Item_PowerPoint.html
  • Item_CommonItem_Body.html

Rename Item_PowerPoint.html to make it your own.

Open up the file and change the <title> node. This is what get’s displayed in SharePoint.

Make the changes highlighted below.

I’m basically updating the title in javascript to show the doc id. You would think this would be enough, unfortunately the render body method doesn’t seem to pick up the updated value. Instead you need to copy the entire div from the Item_CommonItem_Body.html file. Copy the Item_CommonItem_Body div from that file into your customised PowerPoint file and overwrite the line that makes the call to ctx.RenderBody.

DisplayTemplate

Upload your custom html file to Search display templates mapped folder.

Now browse to the Manage Result Types page from Site Collection Administration and make a copy of the Microsoft PowerPoint result type.

From the Actions drop down pick the display template that you just uploaded and your all set.

Things to watch out for when migrating SharePoint 2010 FAST Search to SharePoint 2013

I’m currently working on a Search First migration to SharePoint 2013. This post is a placeholder to document the gotchas and workarounds.

Search Centre Keywords

Our initial plan was for a search-first migration where we would swap out the FAST search service application for an SP2013 search service application. The idea was that we would make no changes to the existing search centres but they would get a better/fast search engine with all the improvements that come in 2013.

Issue: Keywords defined in the SP 2010 Search Centre are ignored by SP2013 Search. The only way this functionality can work is when you use a SP2013 search centre. This is not a problem if you have only one search centre since you can manage the keywords at a farm level but we had a number of search centres with site collection admins needing the ability to manage the keywords for the site they manage.

Workaround: We were forced to create Search Centres in SP 2013 and have the SP 2010 sites use the new search centres.

XSLT to Display Templates

Given that we were on the path to using SP2013 search centres any customisations that were made to the SP2010/FAST search XSL now needs to be re-written as Display Templates. In a way this is better than having to mess with XSL, but this is still something that you need to take into account.

 

Link

XPathTool is a really great online XPath utility. It’s free, doesn’t need to be installed and has more features than a lot of the utilities that you find on CodePlex.

Making SharePoint JSon calls from PowerShell in SharePoint 2013

The Invoke-RestMethod in PowerShell 3 doesn’t send the appropriate header required by SharePoint 2013 to return JSon results. It took me a while to figure out this workaround.

$parameter = "my search text"
$encParam = [System.Web.HttpUtility]::UrlEncode("'$parameter'")  
$url = "http://mysp2013site/_api/search/query?querytext=$encParam"  
$wc = new-object System.Net.WebClient  
$wc.UseDefaultCredentials = $true  
$wc.Headers.Add("Accept", "application/json; odata=verbose")  
$res = $wc.DownloadString($url)  
$res

Mobile Apps: Native or Web?

When building for mobile there isn’t a silver bullet. Instead we have a myriad of compromises to make. If your an enterprise wanting to build apps here are four broad options.

Native code (Objective C for iOS, Java for Android, C#/Xaml for Windows)

Pros:

  • Build the best experience in each platform (Native UI, Performance)
  • Discoverable in app stor

Cons:

  • Cost (3 codebases)
  • Dev skills
  • Publishing to each app store, wait for approvals etc

Native with re-usable code (C# for platforms -> MonoTouch for iOS, Mono for Android, C#/Xaml for Windows) http://xamarin.com

Pros:

  • Build the best experience in each platform (Native UI, Performance)
  • Discover-able in app store
  • Code reuse (except for the presentation layer in each platform the rest of the business logic, web service calls etc are reusable)

Cons:

  • Cost (Cheaper than 100% native but will cost more than plain html)
  • Dev skills (Devs still need to understand the UI APIs for each platform e.g. CocoaTouch, UIKit…
  • Publishing to each app store, wait for approvals (e.g. you find a bug fix it and submit to app store, it will then take 5 business days before the bug fix is available for end users to download).

HTML but deployed natively (PhoneGap, Sencha, etc…)

Pros

  • Javascript (Use frameworks /tools such as jQuery mobile, TypeScripts etc)
  • Costs less to build (one code base across platforms)

Cons:

  • Performance issues with iOS webkit (Only Apple apps and Safari browser can use the hardware accelerated Nitro JavaScript engine, everyone else is forced to use the slower js engine. This is why Facebook ditched HTML5 and wrote a native iOS app). If the apps we’re building are not going to be flashy and don’t rely on animations then this is a non-issue.
  • UI is not native to each OS
  • App updates need to go through approval process for each App Store

HTML only: Basically a web site (ASP.NET MVC or a SharePoint app / application page with responsive layout to adapt to a mobile browser)

Pros:

  • Javascript (Use frameworks /tools such as jQuery mobile, TypeScripts etc)
  • Costs less to build (one code base across platforms)
  • Performance will be better (but not as good as native) since the site runs in Safari and can use hardware acceleration
  • Updates to app is just a matter of pushing update to website (user doesn’t need to upload etc)
  • Option #1 and #2 will anyway need a website to host the webservice

Cons:

  • UI is not native to each OS
  • Discover-ability: No app store. User needs to bookmark app url. Enterprises can work around this by having a single Web App Store that lists all their web apps (ala http://www.apple.com/webapps). Or build a shell native app that acts as a launcher for the web apps.

Need more options/tool choices? See http://en.wikipedia.org/wiki/Mobile_application_development

Another disadvantage with the native options. You need to build and publish a mobile and a tablet version of the app.

My view is that while native apps are the better choice for companies that build and sell services/products, the web option gives the best ROI for enterprises. Even when it comes to product/service companies a strong case can be made for going web only. Ask the guys who built Basecamp.

Creating a BCS Content Source using PowerShell

You can use the following command to create a content source to crawl a Business Data Connectivity Service (BDCS).

$lobSystems = @("LOBSystemName1","LOBSystemNameInstance1") 
New-SPEnterpriseSearchCrawlContentSource -name "My Content Source Name" -searchapplication "My Search Service Application Name" -Type Business -LOBSystemSet $lobSystems

If the LOBSystemName is not correct the content source gets created but the model you want to search is not checked.

To figure out the right values for the LOBSystemName and LOBSystemInstanceName look no further than the bdcm file in your solution. Open the .bdcm file in notepad and use the Name attributes of the LobSystem and LobSystemInstance nodes.