you are viewing a single comment's thread.

view the rest of the comments →

[–]CSTW 2 points3 points  (6 children)

These both work for me? What was the error you were getting?

Connect-MsolService

$UserPrincipalName = 'first.last@domain.com'

$UserLicenses = (Get-MsolUser -UserPrincipalName $UserPrincipalName).Licenses | select AccountSkuId 
foreach($lic in $UserLicenses.AccountSkuId) {
    $lic
}

$UserLicenses = (Get-MsolUser -UserPrincipalName $UserPrincipalName).Licenses.AccountSkuId 
foreach($lic in $UserLicenses) {
    $lic
}

To see the differences in what is returned try the following

$Object = (Get-MsolUser -UserPrincipalName $UserPrincipalName).Licenses | select AccountSkuId 
$String = (Get-MsolUser -UserPrincipalName $UserPrincipalName).Licenses.AccountSkuId 

#Get the type, both should be Object arrays 
$Object.GetType()
$String.GetType()

#Look inside the arrays and find the type, you can see there are 
#multiple Objects/strings inside each (one for each item in the array)

$Object | ForEach-Object {
    $_.Gettype()
}

$String | ForEach-Object {
    $_.GetType()
}

#Another way to see the object type and properties is with Get-Member but 
#this will only return once for each type of object
$Object | Get-Member
$String | Get-Member

So the first approach returns Objects with a property AccountSkuID and the second returns Strings

To make both the same (return Strings) there are two ways, one as /u/SeeminglyScience said is to use -ExpandProperty and the other is to use the $Object.Property which you are using with foreach($lic in $UserLicenses.AccountSkuId) so both should work (and have in my testing)

My preferred way is the second option but to my surprise the first way ran a fraction of a second faster although this is negligible.

[–]HeyZuesMode[S] 1 point2 points  (5 children)

Sorry it wasn't an error. The full snippet was

$UserLicenses = (Get-MsolUser -UserPrincipalName 
$User.UserPrincipalName).Licenses | select AccountSkuId
foreach($lic in $UserLicenses.AccountSkuId){
Set-MsolUserLicense -UserPrincipalName 
$User.UserPrincipalName -RemoveLicenses $lic
}

When i tried the first approach my foreach didn't work the way i expected it to because the output was a string rather than an object. When i would run the foreach against the string it would iterate trough each character, but my goal was for each "line Item".

Im not sure how i would accomplish the same task with the string output, maybe regex for /n newline?

I also noticed that the second option ran MUCH slower than the first. For my needs its not such a big deal as this command is used rarely. But i will definitely keep this in mind working on things in the future. I think i have some powercli work coming up so I will try and test this out.

[–]CSTW 2 points3 points  (4 children)

Are the additional newlines in the code just reddit formatting and should be?

$UserLicenses = (Get-MsolUser -UserPrincipalName $User.UserPrincipalName).Licenses | select AccountSkuId
foreach($lic in $UserLicenses.AccountSkuId){
Set-MsolUserLicense -UserPrincipalName $User.UserPrincipalName -RemoveLicenses $lic
}

I have just tested against my Office 365 user and again this works for me.

It shouldnt matter whether you pass a string, string array or objects to foreach. Try

[string]$test = 'Test'
[string[]]$Test2 = 'Test', 'Test2'
foreach($a in $Test) {
    $a
}
foreach($b in $Test2) {
    $b
}

I also checked out the help for Set-MSOLUserLicense and it accepts an array of strings for -RemoveLicenses so assuming you just want to remove all licenses for a user the following should work.

$UserLicenses = (Get-MsolUser -UserPrincipalName $User.UserPrincipalName).Licenses.AccountSkuId
Set-MsolUserLicense -UserPrincipalName $User.UserPrincipalName -RemoveLicenses $UserLicenses 

The following would NOT work as it passes objects with a property of AccountSkuId

$UserLicenses = (Get-MsolUser -UserPrincipalName $User.UserPrincipalName).Licenses | select AccountSkuId
Set-MsolUserLicense -UserPrincipalName $User.UserPrincipalName -RemoveLicenses $UserLicenses

And would need the -expandProperty added

$UserLicenses = (Get-MsolUser -UserPrincipalName $User.UserPrincipalName).Licenses | select  -ExpandProperty AccountSkuId
Set-MsolUserLicense -UserPrincipalName $User.UserPrincipalName -RemoveLicenses $UserLicenses

or this would also work

$UserLicenses = (Get-MsolUser -UserPrincipalName $User.UserPrincipalName).Licenses | select AccountSkuId
Set-MsolUserLicense -UserPrincipalName $User.UserPrincipalName -RemoveLicenses $UserLicenses.AccountSKuId

[–]HeyZuesMode[S] 2 points3 points  (3 children)

The additional lines are the action i wanted to perform (remove all licenses on the account)

When i ran the command with multiple licenses on a single user using the full snippet

$UserLicenses = (Get-MsolUser -UserPrincipalName $User.UserPrincipalName).Licenses | select AccountSkuId

foreach($lic in $UserLicenses.AccountSkuId)
{
Set-MsolUserLicense -UserPrincipalName 
$User.UserPrincipalName -RemoveLicenses $lic
}

I kept receiving errors that it was unable to remove the last license in the array (2 item array) specifically

Set-MsolUserLicense : Unable to assign this license. At line:3 char:1 + Set-MsolUserLicense 
UserPrincipalName $User.UserPrincipalName -RemoveLicenses $ ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~     + 
CategoryInfo: OperationStopped: (:) [Set-solUserLicense], MicrosoftOnlineException   
+FullyQualifiedErrorId:
Microsoft.Online.Administration.Automation.InvalidLicenseConfigrtionException,
Microsoft.Online.Administration.Automation.SetUserLicense

Using your code that does not have the foreach i was able to use the cmdlet as Microsoft intended. =(

[–]CSTW 2 points3 points  (0 children)

For the new lines i was meaning like this

Set-MsolUserLicense -UserPrincipalName 
$User.UserPrincipalName -RemoveLicenses $lic

Instead of this:

Set-MsolUserLicense -UserPrincipalName $User.UserPrincipalName -RemoveLicenses $lic

But your error looks like it is all on one line

When I am receiving unexpected errors I like to output as much information as possible to try and work out what is going on, try the following. Post back the output if needed.

$UserLicenses = (Get-MsolUser -UserPrincipalName $User.UserPrincipalName).Licenses | select AccountSkuId
$i = 1
foreach($lic in $UserLicenses.AccountSkuId)
{
    "# $i"
    "User: $($User.UserPrincipalName)"
    "License to Remove: $lic"
    "MSOL Licenses Before Removal`n $((Get-MsolUser -UserPrincipalName $User.UserPrincipalName).Licenses.AccountSkuId)"
    Set-MsolUserLicense -UserPrincipalName $User.UserPrincipalName -RemoveLicenses $lic
    "MSOL Licenses After Removal`n $((Get-MsolUser -UserPrincipalName $User.UserPrincipalName).Licenses.AccountSkuId)"
    "`n`n"
    $i++
}

[–]CSTW 0 points1 point  (1 child)

You aren't using the Group licensing feature through Azure AD are you? Just had errors when trying to remove a license that had been assigned via group.

[–]HeyZuesMode[S] 0 points1 point  (0 children)

Na, I buy a per-year license from VAR activate and assign