onsdag den 9. marts 2011

Microsoft implements the world’s most stupid error

So I'm working a bit more on my PowerShell class, trying to do some work on remote machines. I add the option to supply a host, username and password and want’s to connect using WSManConnectionInfo. I end up with a ton of weird errors but can’t really figure out what is making all those errors, so desperate as I am, I end up using New-PSSession and Enter-PSSession. ( I should have just sticked with following the error)

I still get errors but now from the Runspace saying its not supported. Digging around on Google I find out I need to implement IHostSupportsInteractiveSession to my PSHost. Well that wasn’t to hard, I add

Imports System.Management.Automation.Host
Public Class CloudPowerShellHost
    Inherits PSHost
    Implements IHostSupportsInteractiveSession

and smack in

Public ReadOnly Property IsRunspacePushed() As Boolean
    Get
        Return Me.pushedRunspace IsNot Nothing
    End Get
End Property

Private pushedRunspace As System.Management.Automation.Runspaces.Runspace = Nothing
Private myRunSpace As System.Management.Automation.Runspaces.Runspace = Nothing

Public Sub PopRunspace() Implements System.Management.Automation.Host.IHostSupportsInteractiveSession.PopRunspace
    myRunSpace = Me.pushedRunspace
    Me.pushedRunspace = Nothing
End Sub

Public Sub PushRunspace(ByVal runspace__1 As System.Management.Automation.Runspaces.Runspace) Implements System.Management.Automation.Host.IHostSupportsInteractiveSession.PushRunspace
    Me.pushedRunspace = Runspace
    myRunSpace = runspace__1
End Sub

Public ReadOnly Property Runspace As System.Management.Automation.Runspaces.Runspace Implements System.Management.Automation.Host.IHostSupportsInteractiveSession.Runspace
    Get
        Return Me.myRunSpace
    End Get
End Property

Public ReadOnly Property IsRunspacePushed1 As Boolean Implements System.Management.Automation.Host.IHostSupportsInteractiveSession.IsRunspacePushed
    Get
        Return Me.pushedRunspace IsNot Nothing
    End Get
End Property

Public Sub SetRunspace(ByVal runspace As System.Management.Automation.Runspaces.Runspace)
    Me.myRunSpace = runspace
End Sub

At the end of the class and I’m good to go. Still after this I’m still getting tons of errors, so I start walking back the stack seeing what I missed. Turns out I forgot some error handling in a function I use, that saved all variables in a runspace, and it is my enumeration of variables that fails.

System.InvalidCastException: Unable to cast object of type 'System.Management.Automation.PSCustomObject' to type 'System.Management.Automation.PSVariable'.

I’m doing something like this

Dim o As System.Management.Automation.PSVariable
Try
    o = ps.BaseObject
Catch ex As Exception
    Throw ex
End Try

I loop all the PSObjects from doing a get-variable so I inspect the PS object and; WTF???

image

image

The BaseObject is “kind of empty” not really sure what it is, but the main object is a variable, so no sweat, I smack in

Dim o As System.Management.Automation.PSVariable
Try
    o = ps.BaseObject
Catch ex As Exception
    Try
        o = ps
    Catch ex2 As Exception
        Throw ex2
    End Try
End Try

and the result is a new exception

System.InvalidCastException: Unable to cast object of type 'System.Management.Automation.PSVariable' to type 'System.Management.Automation.PSVariable'.

LOL of all the world’s most lame error messages that has GOT to be the one.

Screw it. after playing around with a TON of different good/stupid/desperate/brilliant hacks I remember that I used SessionStateProxy.PSVariable.GetValue() when fetching single variables, so I try this approach instead, and it work’s .. Its ugly, I know, but what the hell am I/we suppose to do in a weird situation like this ?

Dim PSVar As System.Management.Automation.PSVariable
Try
    If host.IsRunspacePushed Then
        newPSVariableName = ps.Members("name").Value
        newPSVariableValue = ps.Members("value").Value
        newPSVariable = New PSVariable(newPSVariableName)

        PSVar = newPSVariable
        newPSVariable.Value = newPSVariableValue
    Else
        newPSVariable = ps.BaseObject
        PSVar = newPSVariable
        newPSVariableName = newPSVariable.Name
        newPSVariableValue = newPSVariable.Value
    End If
    If newPSVariableValue Is Nothing Then
    ElseIf InStr(newPSVariableValue.GetType.FullName, "System.Management.Automation") > 0 Then

        If newPSVariableValue.GetType.FullName = "System.Management.Automation.PSObject" Then
            Dim tmpPSObject As PSObject = newPSVariableValue
            newPSVariableValue = tmpPSObject.BaseObject
        Else
            newPSVariableValue = Nothing
        End If
    End If

    If newPSVariableValue Is Nothing Then
        newPSVariable = New PSVariable(newPSVariableName)
        newPSVariable.Value = newPSVariableValue
        PSVar = newPSVariable
    End If

Ingen kommentarer:

Send en kommentar