Loading a .Net 4.0 Snap-in in PowerShell V2

March 14, 2011

I recently started developing a PowerShell snap-in, and without putting much thought into it, I created a .Net 4.0 project. After getting the initial code ready, I attempted to load the snap-in and got the following error:

This assembly is built by a runtime newer than the currently loaded runtime and cannot be loaded.

After a bit of searching, I found that this was not a PowerShell issue, but a .Net one, and the solution was to add to the PowerShell.exe.config file. The following was needed:

<?xml version="1.0"?>
<configuration>
    <startup useLegacyV2RuntimeActivationPolicy="true">
        <supportedRuntime version="v4.0.30319"/>
        <supportedRuntime version="v2.0.50727"/>
    </startup>
</configuration>

(http://tfl09.blogspot.com/2010/08/using-newer-versions-of-net-with.html)

For PowerShell to work using remoting, the same solution must also be applied to wsmprovhost.exe (http://tfl09.blogspot.com/2010/08/using-later-versions-of-net-framework.html). 

In ultra-lazy fashion, I spent half an hour writing a function to place one of these configuration files for me, which is probably 10 times as long as it would take for me to do it all the times I will need to. However, writing scripts is fun. Smile

function Write-DotNet4Config
{
<#
    .SYNOPSIS
    Function to write .Net 4 configuration files for me so I don't have to remember
    
    .EXAMPLE
    Write-DotNet4Config "$env:SystemRoot\system32\WindowsPowerShell\v1.0\powershell.exe"
    
    Writes a configuration for the given executable if none currently exists.
#>
    [CmdletBinding()]
    param($executable, [switch]$whatif)

    if (-not (test-path $executable)) 
    { 
        Write-Error "Cannot find executable $executable"
        if (-not $whatif.isPresent) { return }
    }
    
    if(test-path "$executable.config") 
    { 
        Write-Error "Path already exists"; 
        if (-not $whatif.isPresent) { return }
    }
    
    $versions = @("v4.0.30319", "v2.0.50727" )
    
    $config = @"
<?xml version="1.0"?>
<configuration>
    <startup useLegacyV2RuntimeActivationPolicy="true">
        $($versions | %{'<supportedRuntime version="{0}"/>' -f $_})
    </startup>
</configuration> 
"@
    Write-Verbose "XML: $config"    
    Write-Verbose "Output file: $executable.config"

    if($whatif.isPresent)
    {
        Write-Host "What if: Writes to file $executable.config"
        Write-Host "What if: Writes xml: $config"
    }
    else
    {
        ([xml]$config).Save("$executable.config")
    }
}