Wednesday, June 18, 2014

Cannot load Windows PowerShell snap-in microsoft.windowsazure.serviceruntime

There are some issues that simply lose interest due to not being pertinent enough, I believe I have found one.
  
 
And I can see from searching that I am not alone here.
 
The thing that is going on is that I am using startup tasks in a Worker Role to install an MSI and configure it.
 
When the script being executed by my startup task attempts to: add-pssnapin microsoft.windowsazure.serviceruntime

I receive the error:
add-pssnapin : Cannot load Windows PowerShell snap-in microsoft.windowsazure.serviceruntime because of the following error: The Windows PowerShell snap-in module
 
F:\plugins\RemoteAccess\Microsoft.WindowsAzure.ServiceRuntime.Commands.dll does not have the required Windows PowerShell snap-in strong name Microsoft.WindowsAzure.ServiceRuntime.Commands, Version=1.0.0.0, Culture=neutral,
 
 
The work around that has been posted is to edit the registry key for the DLL, because the version is wrong.
My impression of this workaround is this:  "So, now I have to script a work around for an MSFT provided DLL because no one is updating the DLL registration for the snap-in in MSFT provided Gallery Images in Azure."
 
Mind you, these are developers, and if a workaround can be done in code - my experience has been that the issue is ignored after the workaround exists.

A workaround is great, but there are caveats to all of the workarounds posted thus far;
  • if I update the registry key with the incorrect version number, it still won’t load.  
  • I have to get the right version number and fix the registry entry.
  • And edit both the Assembly Name string and the version string.
Each posted workaround that I can find through search is a point version, and a point version edit.  A lasting workaround (since it seems like this bug is not going to get fixed anytime soon) is to dynamically deal with any version of the DLL and strong name enforcement in the OS.
I always preface that my solution might not be the most elegant thing that a developer comes up with, but I hope that folks can follow it and understand what I did.
 
# Get the current execution path
$exPath = Split-Path -parent $MyInvocation.MyCommand.Definition
$exPath # Echo for logging

######################################################################################
### Before we can load the service runtime, we must fix the broken registry information for the DLL
### and the version must be right, or it will continue to be broken.

$runtimeDllReg = Get-Item HKLM:\SOFTWARE\Microsoft\PowerShell\1\PowerShellSnapIns\Microsoft.WindowsAzure.ServiceRuntime
$runtimeDll = Get-Item $runtimeDllReg.GetValue('ModuleName')

$exportPath = $expath + "\AzureServiceRuntime.reg"

& $env:SystemRoot\System32\regedt32.exe /E $exportPath 'HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\PowerShell\1\PowerShellSnapIns\Microsoft.WindowsAzure.ServiceRuntime'

# This is because the wait does not wait until regedit actually completes.

Do {

Start-Sleep 10

$regFile = Get-Item -Path $exportPath -ErrorAction SilentlyContinue

} Until ($regFile.Exists)

$runtimeRegFile Get-Content -Path $exportPath
$newRuntimeRegFile = @()

foreach ($e in $runtimeRegFile) {
     switch -wildcard ($e) {
          "*1.0.0.0*" { $e = $e -replace "1.0.0.0", ($runtimeDll.VersionInfo.FileMajorPart.ToString() + '.' + $runtimeDll.VersionInfo.FileMinorPart.ToString() + '.0.0') }
     }
     $newRuntimeRegFile += $e
}

Set-Content -Value $newRuntimeRegFile -Path $exportPath -Force

Start-Sleep 2

& $env:SystemRoot\System32\regedt32.exe /S $exportPath

Start-Sleep 2

# Load the necessary PowerShell modules for configuration and management Web and Work Roles
 
 
add-pssnapin microsoft.windowsazure.serviceruntime

# Take the VM Instance offline with Azure, or else Azure will keep attempting to start the script
 
 
Set-RoleInstanceStatus -Busy

You might wonder why I am using regedit.exe instead of the PowerShell cmdlets to set the value. What I found is that I kept running into permissions issues. And using regedit to export and import is a way around that.

No comments: