powershellfunctionreturn-valuepscustomobject

Accessing PSCustomObject Properties After Return from Function in PowerShell


I am working on a HealthCheck script that will check if a specific application is installed and verify the version number of the app, and verify id the service for that app is running. For testing purposes I am manually setting the application name (appName) look look for as well as the desired version (appTargetVer) and the service name(appSvc). Once working, I will pull this data from a CSV so I can check multiple apps we feel are critical on each workstation, I set it manually to one specific app for development\testing purposes.

In my script I am passing the the $appName and $appTargetVer to the AppInstallStatus function, determining if the app is installed, checking that the installed version is >= to the appTargetVer, and then saving the desired data to a PSCustomObject. I then return that object in hopes of being able to use that data.

Unfortunately, I am unable to access any of the properties of that returned object. I know the function works as I tested and it does the check properly. But once i assign the function to a variable in order to store the returned object, I can not access any of the object properties.

Testing like this returns good results:

#Test that function working
AppInstallStatus $appName $appTargetVer 

enter image description here

But when I assign to a variable, I can not access any of the properties.

$InstallInfo = AppInstallStatus $appName $appTargetVer 
Write-host "why is there no data in here:  $($InstallInfo.ApplicationName)"

enter image description here

Any assistance you can provided would be greatly appreciated. Ultimately I will be assigning some of the properties from this object, as well as other objects from other functions, to an object that will store all the needed results that can let our techs know that a workstation is missing an app or requires an updates version, etc. I will then output that all to a file that can be stored as evidence. But First I need to be able to access the individual properties of the object before I move on to doing anything else. FYI - I know there are application that will do compliance checking but the boss wants something like this for some silly reason, so I'm stuck cobbling together a script to do what Intune/Tanium/etc should all already be able to do for us.

Here is the full code for this part of the health check:

$appName = "Trend"
$appTargetVer = 14.0
$appSvc = "ntrtscan"



Function AppInstallStatus{
    param(
    $appName,
    $appTargetVer
    )
    
    $AppInstTest =  Get-CimInstance Win32_Product | Where-Object {$_.Name -match $appName} |Select-Object -Property Name,Vendor,Version,Caption


    if($AppInstTest.Name -match $appName){
        $InstallStatus = $true        
        if($AppInstTest.Version -ge $appTargetVer){
            $VerStatus = $true
            $CurVer = $AppInstTest.Version
            }
            else{
                $VerStatus = $false
                }
        }
        else{
            $InstallStatus = $false
            }
    #$AppStatObj = New-Object -TypeName psobject -Property @{
    $AppStatObj = [PSCustomObject]@{            
        AppNameTest=$appName
        AppTargetVerTest=$appTargetVer
        ApplicationName = $AppInstTest.Name
        ApplicationCurrentVer = $AppInstTest.Version
        AppInstallStatus = $InstallStatus
        ApplicationVersionStatus = $VerStatus
        } | Format-List
                    
        return $AppStatObj
}

Function AppService{
    param(
    $appSvc
    )
    
    $AppTest = Get-Service -Name $appSvc
    if($AppTest.Status -match "running"){
        $AppSvcStatus = $true
        }
        else{
            $AppSvcStatus = $false
            }
        
        return $AppSvcStatus
}


#Test that function working
#AppInstallStatus $appName $appTargetVer 

#save to a variable to access individual properties of returned object
$InstallInfo = AppInstallStatus $appName $appTargetVer 
AppService $appSvc

Write-host "why is there no data in here:  $($InstallInfo.ApplicationName)"

Solution

  • Remove | Format-List from your $AppStatObj = [PSCustomObject]@{ ... } | Format-List statement.

    What ... | Format-List outputs (as well as the other Format-* cmdlets) isn't data anymore; it is objects that provide for-display formatting instructions to PowerShell, and they're only useful for that.[1]

    Thus, if you want to output data, for later programmatic processing, never use the output from Format-* calls.

    In your case, output the [pscustomobject] instance as-is; to select a subset of properties from a preexisting object, use Select-Object.

    See this answer for more information.


    [1] Format-* cmdlets output instances of Microsoft.PowerShell.Commands.Internal.Format.* types, with fixed properties that are unrelated to the input objects being formatted by them. Thus, unlike the input object in your case, the formatting object has no .ApplicationName property, and since PowerShell evaluates attempts to access non-existent properties as $null, which in the context of string interpolation turns into the empty string, your Write-Host call output showed nothing after why is there no data in here: