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
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
}
}
}
}