XmlLists with Psake / Powershell

On a POSH roll here, this time I needed to list out the Include attributes for references in an msbuild file. Let’s take a look at the POSH script equivalent of XmlList:

function xmlList([string]$file, [string]$xpath, [hashtable]$namespaces) { 
    [xml] $fileXml = Get-Content $file 
    $xmlNameTable = new-object System.Xml.NameTable
    $xmlNameSpace = new-object System.Xml.XmlNamespaceManager($xmlNameTable)

    foreach($key in $namespaces.keys)
    {
        $xmlNameSpace.AddNamespace($key, $namespaces.$key);
    }
    $nodes = @()
    $node = $fileXml.SelectNodes($xpath, $xmlNameSpace) 
    $node | ForEach-Object { $nodes += @($_.Value)}
    
    return $nodes
}

Now to use this we can do this:

$namespaces = @{ "xsi" = "http://schemas.microsoft.com/developer/msbuild/2003"}
$xpath = "//xsi:Reference/xsi:HintPath/../@Include"

$nodes = xmlList "$examplesdest_dir\NBehave.Examples.csproj" $xpath $namespaces

And it gives us a list of the references in the msbuild file.

image

XmlPoking vsixmanifests with Psake / Powershell

 

Nant had some very useful XmlPoke and XmlPeek tasks for working with xml files. When manually installing visual studio plug-ins, the vsixmanifest needs to have some fields prodded to work correctly, specifically the InstalledByMsi and Version.

So here’s a POSH version of XmlPoke:

function xmlPoke([string]$file, [string]$xpath, $value, [hashtable]$namespaces) { 
    [xml] $fileXml = Get-Content $file 
    $xmlNameTable = new-object System.Xml.NameTable
    $xmlNameSpace = new-object System.Xml.XmlNamespaceManager($xmlNameTable)

    foreach($key in $namespaces.keys)
    {
        $xmlNameSpace.AddNamespace($key, $namespaces.$key);
    }
    
    $node = $fileXml.SelectSingleNode($xpath, $xmlNameSpace) 
    if ($node) { 
        $node.InnerText = $value 

        $fileXml.Save($file)  
    } 
}

 

And the usage for vsixmanifests is below, you will need to adjust the namespaces based on the xml you are prodding.

$namespaces = @{ "vsx" = "http://schemas.microsoft.com/developer/vsx-schema/2010"}
$xpath = "/vsx:Vsix/vsx:Identifier/vsx:"
xmlPoke "$destination\extension.vsixmanifest" $xpath"InstalledByMsi" "true" $namespaces
xmlPoke "$destination\extension.vsixmanifest" $xpath"Version" $version $namespaces

ILMerging assemblies with Psake / Powershell

 

On NBehave I am migrating the existing build framework from Nant over to Psake, and am thoroughly enjoying the ability to debug and step through my build scripts.

We needed to merge some of our output assemblies before packaging, and this was extremely easy in POSH:

function ilmerge($key, $directory, $name, $assemblies, $extension)
{    
    # Create a new temp directory as we cannot overwrite the main assembly being merged.
    new-item -path $directory -name "temp_merge" -type directory -ErrorAction SilentlyContinue
    
    # Unfortuntately we need to tell ILMerge its merging CLR 4 assemblies.
    if($framework -eq "4.0")
    {
        Exec { tools\ilmerge\ilmerge.exe /keyfile:$key /out:"$directory\temp_merge\$name.$extension" "$directory\$name.$extension" $assemblies /targetplatform:"v4,$env:ProgramFiles\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0" }
    }
    else
    {
        Exec { tools\ilmerge\ilmerge.exe /keyfile:$key /out:"$directory\temp_merge\$name.$extension" "$directory\$name.$extension" $assemblies }
    }
    
    Get-ChildItem "$directory\temp_merge\**" -Include *.dll, *.pdb | Copy-Item -Destination $directory
    Remove-Item "$directory\temp_merge" -Recurse -ErrorAction SilentlyContinue
}

The parameters are straightforward and as you’d expect, here’s an example usage:

$key = "$solution_dir\NBehave.snk"
$directory = "$build_dir\dist\v$framework"
$name = "NBehave.Narrator.Framework"

$assemblies = @("$directory\gherkin.dll", 
                "$directory\NBehave.Spec.Framework.dll", 
                "$directory\Should.Core.dll", 
                "$directory\Should.Fluent.dll")

ilmerge $key $directory $name $assemblies "dll"

 

The extension should be “.dll” or “.exe” depending on what the main artifact your trying to merge is.

Older Posts