Can you help me make this better?

Hey everyone -

Let me preface this with - this script works. It accomplishes what I want it to do - but I feel like there has to be a better way to program it. I know I can turn it into an advanced function with some parameters - I may do that. I am looking to eliminate the intermediate steps that I used to get at the information I am after - due to nesting objects.

I’ve added some comments on where I think the script should be better/cleaner/more direct - looking for advice.

Thanks
Steve

# sku we are looking for
$sku = 'ENTERPRISEPACK'
# service we are looking for
$Service = 'MCOSTANDARD'

# ----- I would love to be able to filter licensed users that match the SKU I am after
$allusers = Get-MsolUser -All | Where-Object {$_.islicensed -eq $true}

foreach ($user in $allusers)
{
    #  because I couldn't initially filter on sku, I grab the sku of the user here
    $skus = $user.Licenses | Select-Object -ExpandProperty accountsku | Select-Object -ExpandProperty SkuPartNumber
    # check to see if the sku matches
    if ($sku -in $skus)
    {
        # we have an ENTERPRISEPACK
        # find the enterprisepack and get the service status
        #
        # these next 3 lines are all intermediate steps because I couldn't 
        # wrap my head around a more direct path of getting there
        #
        $licenses = $user.Licenses
        $e3License = $licenses | Where-Object {$_.AccountSkuId -match $sku}
        $ServiceStatus = $e3License.ServiceStatus

        foreach ($s in $ServiceStatus)
        {
            if ($s.serviceplan.ServiceName -eq $Service)
            {
                $prop = @{
                    DisplayName        = $user.DisplayName
                    Service            = $s.serviceplan.ServiceName
                    ProvisioningStatus = $s.provisioningstatus
                }

                $obj = New-Object -TypeName psobject -Property $prop
                Write-Output $obj
            }
        }
    }
}

With some modifications, you can have below code. using [PSCustomObject] and by avoiding few Select-Object cmdlet. This can be even a one liner, but it breaks readability.

# sku we are looking for
$sku = 'ENTERPRISEPACK'
# service we are looking for
$Service = 'MCOSTANDARD'

# ----- I would love to be able to filter licensed users that match the SKU I am after
$allusers = Get-MsolUser -All | Where-Object {($_.islicensed -eq $true) -and ($sku -in $_.Licenses.accountsku.kuPartNumber)}

foreach ($user in $allusers){
    $user.Licenses | Where-Object {$_.AccountSkuId -match $sku} | ForEach-Object -Process {
        if ($_.serviceplan.ServiceName -eq $Service){        
            [PSCustomObect]@{
                DisplayName        = $user.DisplayName
                Service            = $s.serviceplan.ServiceName
                ProvisioningStatus = $s.provisioningstatus
            }
        }
    }    
}

PS: I just modified and not tested.

Thank you @kvprasoon – I tend to not use ForEach-Object in favor if a foreach() loop - which leads me to forget that sometimes it is really useful.

I had to add 1 additional select statement before the ForEach-Object statement, and tweak the properties of the PSCustomObject - but that did the trick. That would be a pretty cool one-liner - but I would have no idea what the heck it did next time I look at it :slight_smile:

Final Version:

# sku we are looking for
$sku = 'ENTERPRISEPACK'
# service we are looking for
$Service = 'MCOSTANDARD'

# ----- I would love to be able to filter licensed users that match the SKU I am after
$allusers = Get-MsolUser -All | Where-Object {($_.islicensed -eq $true) -and ($sku -in $_.licenses.accountsku.SkuPartNumber)}

foreach ($user in $allusers)
{
    $user.Licenses | Where-Object {$_.AccountSkuId -match $sku} | Select-Object -ExpandProperty servicestatus | ForEach-Object -Process {
        if ($_.serviceplan.ServiceName -eq $Service)
        {
            [PSCustomObject]@{
                DisplayName        = $user.DisplayName
                Service            = $_.serviceplan.ServiceName
                ProvisioningStatus = $_.provisioningstatus
            }
        }
    }
}