Trying to divide an array by a fixed value causes a conversion error

I have a piece of code which was working OK then I moved a piece of the code to a function in order to simplify the overall structure. I’m now getting a conversion error.

This is the code:

Function Collate_Data_Into_HTML()
    {
    Param(
        $fCustomerVPGs,
        $fActiveAlerts
        )
    	   # Loop through the all customer VPGs and obtain status info.
        Write-Host "$LineHeader Getting Status info for all VPGs." -ForegroundColor Yellow
	    $foutputArray_VPGInfo = @()
	    $fCustomerVPGs | % {

	    $fVPG = $_.VPGName
	    $fVMsCount = $_.VMsCount
	    $fActualRPO = $_.ActualRPO
	    $fLastTest = $_.LastTest
	    $fiStatus = $_.Status
	    $fiSubStatus = $_.SubStatus
        [double]$fProvisionedStorageInMB = 0
	    $fProvisionedStorageInMB = $_.ProvisionedStorageInMB
        
	    $fProvisionedStorageInGB = $fProvisionedStorageInMB /1kb
	    $fProvisionedStorageInGB = [math]::Round($fProvisionedStorageInGB,1)

I get the following error at the line “$fProvisionedStorageInMB = $_.ProvisionedStorageInMB”.

Error: [ Cannot convert the “System.Object” value of type “System.Object” to type “System.Double”. ]

The variables have the following values:
$_.ProvisionedStorageInMB:

1438851
533470
5576093
41549797
42807
244205
1776643
512017
7202102
492230
803842

The variable type is:

$fProvisionedStorageInMB.GetType()

IsPublic IsSerial Name                                     BaseType                                                                                                                                                                                             
-------- -------- ----                                     --------                                                                                                                                                                                             
True     True     Double                                   System.ValueType

$fCustomerVPGs:

OrganizationName       : MyCompany Finance Australia
VpgName                : MYC-PREPROD-PRD-MYCAUDITAPP01
VmsCount               : 1
ActualRPO              : 6
LastTest               : 
Status                 : 1
SubStatus              : 0
ProvisionedStorageInMB : 81923
Zorg                   : @{rel=; href=https://10.0.0.58:9669/v1/zorgs/32e2b5c6-e666-ea46-916f-e35b8e1834b1; type=ZorgApi; identifier=32e2b5c6-e666-ea46-916f-e35b8e1834b1}
VpgIdentifier          : f72f7896-ee99-0123-b3d4-eceb4c503f50

Variable Type:


IsPublic IsSerial Name                                     BaseType                                                                                                                                                                                             
-------- -------- ----                                     --------                                                                                                                                                                                             
True     True     Object[]                                 System.Array

I changed the code to this:

	    $fProvisionedStorageInMB = $_.ProvisionedStorageInMB
	    $fProvisionedStorageInGB = $fProvisionedStorageInMB /1kb

And now I get the error “[ Method invocation failed because [System.Object] does not contain a method named ‘op_Division’. ]” at this line:

$fProvisionedStorageInGB = $fProvisionedStorageInMB /1kb

The variable type here is:
 IsPublic IsSerial Name                                     BaseType                                                                                                                                                                                             
-------- -------- ----                                     --------                                                                                                                                                                                             
True     True     Object[]                                 System.Array

I don’t understand what’s going on?

What I’ve noticed is that when the code is in the main body, this line:

$fCustomerVPGs | % {

…cycles thru all the values one by one so the variable “$_.ProvisionedStorageInMB” only has one value at a time. However, since moving the code to a function, the variable now has multiple values.

For example, I modified the code to this:

	        $fProvisionedStorageInMB = $_.ProvisionedStorageInMBWrite-Host "ProvisionedStorageInMB: $fProvisionedStorageInMB"	        $fProvisionedStorageInGB = $fProvisionedStorageInMB /1kb

And the Write-Host shows the following when I step the code:

ProvisionedStorageInMB: 1438851 533470 5576093 41549798 42807 244205 1776643 512017 7202102 492230 803842 2429852 822601 875526 4313810 2528873 1136643 256005 250882 534474 585804 5593917 153931 841686 1153669 493042 368641 1331202 5989379 3098225 3123205 368816 163846 665604 601433 184323 81921 1127350 409612 1991941 665604 419871 22478034 360320 615944 2528873 164439 1402881 81928 9125613 102411 153931 1274028 972443 3123205 547891 739349 144288 245766 184322 1535946 553291 2429852 368816 384004 144310 5989
379 266251 4313810 13615268 81933 368641 5570570 368823 220216 44688 410849 20481 4834306 1622284 655428 22737 430084 584328 5593917 124405 1331202 11545627 579888 1136643 410388 81923 81921 7419907 1440783 411650 12509 737402 565670 409610 163846 164329 94412 1776643 525190 1422366 188420 133152 41142 379083 2705571 409612 601433 3098225 512017 865282 82036 123078 225284 250882 532572 43334 1482115 512020 3445735 1438851 370100 1353157 824323 822601 841686 81946 410343 215243 5576093 1127350 1991941 2048008 803842 60457 124011 487762 7202102 256005 405906 256002 875526 585804 455684 1372369 840477 470521 165052 81923

It should only have ONE value!?

Before we proceed … please format code, error messages, console output and sample data as code. Do not “quote” them.

That means that you have an array instead of a single element of the type [Double]. Usually we use loops to extract the single elements.

This code expects the input parameter $fCustomerVPGs to be an array of complex objects with the shown properties. Is that the case?

It’s not necessary to do this in two steps. You can devide any number directly by 1KB, 1MB, 1GB, 1TB or 1PB.

It depends how you populate this variable and how you provide the input to your function. If you want to provide the variable as an input to your function you may use the properties of the input objects as single parameters.

Sorry about the formatting, should be OK now.

The main body of the code which calls the function looks like this:

# Get Virtual Protection Group List
	    $VPGsURL = $BaseURL+"vpgs"
	    $VPGsCMD = Invoke-RestMethod -Uri $VPGsURL -TimeoutSec 1000 -Headers $zertSessionHeader -ContentType "application/JSON"
	    $oAllVPGs = $VPGsCMD | Select *
	    $CustomerVPGs  = $oAllVPGs | where {$_.OrganizationName -eq $Zorg} | select OrganizationName,VPGName,VMsCount,ActualRPO,LastTest,Status,Substatus,ProvisionedStorageinMB,Zorg,VpgIdentifier

        $outputArray_VPGInfo = Collate_Data_Into_HTML($CustomerVPGs, $ActiveAlertsFound)

The variable $CustomerVPGs has this as the first record:
Using the command to display the first record:
$CustomerVPGs [0]

OrganizationName       : MyCompany Finance Australia
VpgName                : MYC-PREPROD-PRD-MYCAUDITAPP01
VmsCount               : 1
ActualRPO              : 6
LastTest               : 
Status                 : 1
SubStatus              : 0
ProvisionedStorageInMB : 81923
Zorg                   : @{rel=; href=https://10.0.0.58:9669/v1/zorgs/32e2b5c6-e666-ea46-916f-e35b8e1834b1; type=ZorgApi; identifier=32e2b5c6-e666-ea46-916f-e35b8e1834b1}
VpgIdentifier          : f72f7896-ee99-0123-b3d4-eceb4c503f50

The function looks like this:

Function Collate_Data_Into_HTML()
    {
    Param(
        $fCustomerVPGs2,
        $fActiveAlerts
        )
    	   # Loop through the all customer VPGs and obtain status info.
        Write-Host "$LineHeader Getting Status info for all VPGs." -ForegroundColor Yellow
	    $foutputArray_VPGInfo = @()
	    $fCustomerVPGs2 | ForEach-Object {
	        $fVPG = $_.VPGName
	        $fVMsCount = $_.VMsCount
	        $fActualRPO = $_.ActualRPO
	        $fLastTest = $_.LastTest
	        $fiStatus = $_.Status
	        $fiSubStatus = $_.SubStatus
	        $fProvisionedStorageInMB = $_.ProvisionedStorageInMB
            Write-Host "ProvisionedStorageInMB: $fProvisionedStorageInMB"
	        # $fProvisionedStorageInGB = $fProvisionedStorageInMB /1kb
	        $fProvisionedStorageInGB = [math]::Round($fProvisionedStorageInMB / 1kb,1)
            Write-Host "$LineHeader TEMP- VPG Name: $fVPG"

NOTE: I modified the name of the function variable to “$fCustomerVPGs2” in case there were any weird naming conflicts with the same variable in other functions.

While stepping thru the function code, the variable “$fCustomerVPGs2” contains all the records of the passed variable from the main code. Interestingly, when I try the command “$fCustomerVPGs2[0]” it does not list the first record only, it lists ALL records???

Has this got something to do with how I’m passing the variable “$CustomerVPGs” to the function?

The count property of each variable is interesting:

[DBG]: PS C:\scripts\Zerto>> $CustomerVPGs.count
154

[DBG]: PS C:\scripts\Zerto>> 
[DBG]: PS C:\scripts\Zerto>> $fCustomerVPGs2.count
2

Also this:

[DBG]: PS C:\scripts\Zerto>> $fCustomerVPGs2[1]
True

Why is there a TRUE value as the 2nd item in the fCustomerVPGs2 variable values?

I figured it out, it was the way I was calling the function. I changed the call to the following and it works:
$outputArray_VPGInfo = Collate_Data_Into_HTML -fCustomerVPGs2 $CustomerVPGs -fActiveAlerts $ActiveAlertsFound

Looks like it was my misunderstanding on how to call a function.

Thanks!

Hey hey … great that you’ve found the solution. And thanks for sharing. :+1:t4: :love_you_gesture:t4: