Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Deserialized Object type issues - specifically with Powershell 5 classes and Import-CliXml

I'm having issues with Powershell 5 classes and object types when reimporting deserialized objects using the Import-CliXml command.

I have an object of type Computer and I wish to store this as xml and then reimport this next time the script is run

class Computer 
{
    $Private:hostname
    $Private:ipAddress

    Computer([String] $hostname, [String] $ipAddress)
    {
        $this.hostname = $hostname
        $this.ipAddress = $ipAddress
    }
    static [Computer] reserialize([PSObject] $deserializedComputer)
    {
        return [Computer]::new($deserializedComputer.hostname, $deserializedComputer.ipAddress)
    }
}

I export and import the object using the following:

$computer = [Computer]::new("test-machine", "192.168.1.2")
$computer | Export-CliXml C:\Powershell\exportTest.xml
$deserializedComputer = Import-CliXml C:\Powershell\exportTest.xml

I understand that when this object is reimported that it is deserialized and is basically just a data container (of type [Deserialized.Computer]). I'm trying to figure out how to type check this object before I try and reserialize it using my reserialize method.

For example if I try and cast $deserializedComputer it tells me that:

Cannot convert value "Computer" to type "Computer". Error: "Cannot convert the "Computer" value of type "Deserialized.Computer" to type 
"Computer"."

I understand why this can't be casted, I'm just using the error message to point out that the object has knowledge that it's of type [Deserialized.Computer]

I can find nothing returned from $deserializedComputer.getMember() that indicates that it is of type [Deserialized.Computer], the only information I can find is that it's of type [PSObject], how can I type check that this object is indeed of type [Deserialized.Computer]?

I should add that type [Deserialized.Computer] doesn't exist at run-time so I can't use this directly in my code, otherwise I would simply use:

$deserializedComputer.getType() -eq [Deserialized.Computer]
like image 326
Dan Hampshire Avatar asked Jan 23 '17 13:01

Dan Hampshire


1 Answers

Use (Hint: gm is the alias for Get-Member)

$type = $deserializedComputer | gm | Select -Property TypeName -First 1

then you should be able to access the value like

$type.TypeName

You can also type check to ensure that it is a Computer by using

$deserializedComputer.ToString()

Or if you want another way use

[type]$deserializedComputer.ToString()

Edit:

You can check it by using the following

# you can also use $deserializedComputer.ToString() -eq [Computer].ToString()
if ([type]$deserializedComputer.ToString() -eq [Computer])
{

}

Your Full class would look something like:

class Computer 
{
    $Private:hostname
    $Private:ipAddress

    Computer(){}

    Computer([String] $hostname, [String] $ipAddress)
    {
        $this.hostname = $hostname
        $this.ipAddress = $ipAddress
    }
    static [Computer] reserialize([PSObject] $deserializedComputer)
    {
    # you can also use $deserializedComputer.ToString() -eq [Computer].ToString()
    if ([type]$deserializedComputer.ToString() -eq [Computer])
    {
       return [Computer]::new($deserializedComputer.hostname, $deserializedComputer.ipAddress)
    }
    return [Computer]::new()
    }
}

And Exporting/Importing

$filePath = "C:\Powershell\exportTest.xml"

$computer = [Computer]::new("test-machine", "192.168.1.2")
$computer | Export-CliXml $filePath
$deserializedComputer = Import-CliXml $filePath

And Reserialize method

[Computer]::reserialize($deserializedComputer)
like image 132
Patrick Mcvay Avatar answered Sep 27 '22 18:09

Patrick Mcvay