PS Custom object property key/value instead of string

Hi All,

I made this function (see very bottom) to use in a script to get some info about disks. However some properties appear as a key/value pair instead of just the value, the problem is only for the bitlocker information. Some properties are ok and I can’t figure out why

When I use [string]($blv | Select-Object -ExpandProperty volumestatus) this works as intended ie.
I get just the text I need when using for example $data.Volumestatus. Other properties from other sources, for example Get-CimInstance work fine.

\> $data = Get-DiskInfo -ComputerName TESTPC
\> $data.VolumeStatus
FullyEncrypted

\> $data.volumetype

Value
-----
OperatingSystem

\> $data.MountPoint
C:

function Get-DiskInfo {
    [CmdletBinding()]
    param (
        # Parameter help description
        [Parameter(Mandatory)]
        [string[]]
        $ComputerName,

        # Parameter help description
        [Parameter()]
        [pscredential]
        $Credential,

        [string]$ErrorLogFilePath = "c:\temp\EncryptDrives.log"
    )
        
    begin {}
        
    process {

        foreach ($item in $computername) {

            try {
                $Params = @{} 
                if ($Credential) { 
                    $Params['Credential'] = $Credential
                } 
                
                invoke-command @params -ComputerName $item -ScriptBlock { 

                    $tpm = get-tpm

                    # Just gets Local fixed disks
                    $Params = @{
                        ClassName   = "win32_logicaldisk"
                        Filter      = "drivetype=3"
                        ErrorAction = "Stop"
                    }
                    $disks = Get-CimInstance @Params

                    foreach ($disk in $disks) {

                        $blv = Get-BitLockerVolume -MountPoint $($disk.DeviceID) 
                        $obj = [PSCustomObject]@{
                            MountPoint       = $disk.DeviceID
                            DriveType        = $disk.DriveType
                            VolumeName       = $disk.VolumeName
                            VolumeStatus     = [string]($blv | Select-Object -ExpandProperty  volumestatus)
                            ProtectionStatus = ($blv | Select-Object -ExpandProperty  ProtectionStatus)
                            VolumeType       = $blv.VolumeType
                            computername     = $env:computername
                            tpmEnabled       = $tpm.tpmEnabled
                        } #PSCustomObject
                        Write-Output $obj

                    } #foreach

                } #Invoke-command

            }
            catch {
                $item | Out-File $ErrorLogFilePath -Append
                Write-Error "Error:$_"
            }  # try/catch
                
        } #foreach
 
    } #PROCESS
        
    end {}

} #function Get-DiskInfo

$data = Get-DiskInfo -ComputerName TESTPC

In the custom object I have tried different ways of assigning the property with the $blv variable.

Thanks in advance

In general …

[string]($blv | Select-Object -ExpandProperty volumestatus)

produces the same output like

$blv.volumestatus

If you want to force the output type to be a flat string you could use the .toString() method if there is one.

So instead of

VolumeStatus     = [string]($blv | Select-Object -ExpandProperty  volumestatus)

you do

VolumeStatus     = $blv.volumestatus.toString()

The other option would be to access the subproperty of the output by its name …

$data.volumetype.Value

:man_shrugging:t3:

Hey adrimus,

@Olaf has some suggestions that will probably work. As to why, I think it has something to do with serialization of the data. I’m not an expert on serialization though, but I think I understand your confusion. Locally, the BitLocker commands work and you don’t need to access the value subproperty as it just returns the data. Remotely, though it does the deserialized output when used with that custom object so it doesn’t fully serialize back, causing the data to output differently than normal.

Interesting side point that worked for me without modifying the custom object returned was calling the invoke-command and just putting Get-BitlockerVolume in it and letting it return. on its own and assigning that output a var:

$blv = invoke-command  -ComputerName $item -ScriptBlock { Get-BitLockerVolume -MountPoint C:}

The only downside to that approach is the need for two invoke-command calls since ur also getting the TPM. Not sure I’d suggest that over what Olaf mentioned but figured I’d share!

Thank you, yes I think it’s something to do with serialization like you mentioned