Need one script to export User, Email, licenses used, MFA type, and Sign in status.

%3CLINGO-SUB%20id%3D%22lingo-sub-3023494%22%20slang%3D%22en-US%22%3ENeed%20one%20script%20to%20export%20User%2C%20Email%2C%20licenses%20used%2C%20MFA%20type%2C%20and%20Sign%20in%20status.%3C%2FLINGO-SUB%3E%3CLINGO-BODY%20id%3D%22lingo-body-3023494%22%20slang%3D%22en-US%22%3E%3CP%3ESo%20let%20me%20first%20say%20thanks%20for%20working%20with%20me%20as%20I%20am%20new%20to%20powershell.%20With%20that%20I%20have%20found%20and%20used%20three%20different%20scripts%20to%20get%20this%20info%20and%20have%20three%20different%20.csv%20files%20that%20I%20can%20then%20combine.%20But%20I%20am%20wanting%20to%20know%20if%20I%20can%20get%20them%20to%20run%20as%20one%20script%20to%20output%20on%20.csv%20to%20save%20time%20as%20I%20have%20to%20do%20this%20twice%20month%20for%20the%20next%2012%20months.%20Each%20script%20pulls%20from%20a%20different%20powershell%20connection%20so%20I%20don't%20know%20if%20this%20will%20work%20as%20I%20haven't%20found%20a%20way%20to%20do%20it.%20This%20environment%20is%20O365%20with%20no%20local%20servers.%3C%2FP%3E%3CP%3E%26nbsp%3B%3C%2FP%3E%3CP%3EThese%20are%20the%20scripts%20I%20have.%3C%2FP%3E%3CP%3ELicenses%20used%3A%3C%2FP%3E%3CPRE%20class%3D%22lia-code-sample%20language-powershell%22%3E%3CCODE%3E%23Using%20this%20script%20administrator%20can%20identify%20all%20licensed%20users%20with%20their%20assigned%20licenses%2C%20services%2C%20and%20its%20status.%0A%0AParam%0A(%0A%20%5BParameter(Mandatory%20%3D%20%24false)%5D%0A%20%20%20%20%5Bstring%5D%24UserNamesFile%0A)%0A%0A%0AFunction%20Get_UsersLicenseInfo%0A%7B%0A%20%20%24LicensePlanWithEnabledService%3D%22%22%0A%20%20%24FriendlyNameOfLicensePlanWithService%3D%22%22%0A%20%20%24upn%3D%24_.userprincipalname%0A%20%20%24Country%3D%24_.Country%0A%20%20if(%5Bstring%5D%24Country%20-eq%20%22%22)%0A%20%20%7B%0A%20%20%20%24Country%3D%22-%22%0A%20%20%7D%0A%20%20Write-Progress%20-Activity%20%22%60n%20%20%20%20%20Exported%20user%20count%3A%24LicensedUserCount%20%22%60n%22Currently%20Processing%3A%24upn%22%0A%20%20%23Get%20all%20asssigned%20SKU%20for%20current%20user%0A%20%20%24Skus%3D%24_.licenses.accountSKUId%0A%20%20%24LicenseCount%3D%24skus.count%0A%20%20%24count%3D0%0A%20%20%23Loop%20through%20each%20SKUid%0A%20%20foreach(%24Sku%20in%20%24Skus)%20%20%23License%20loop%0A%20%20%7B%0A%20%20%20%23Convert%20Skuid%20to%20friendly%20name%0A%20%20%20%24LicenseItem%3D%20%24Sku%20-Split%20%22%3A%22%20%7C%20Select-Object%20-Last%201%0A%20%20%20%24EasyName%3D%24FriendlyNameHash%5B%24LicenseItem%5D%0A%20%20%20if(!(%24EasyName))%0A%20%20%20%7B%24NamePrint%3D%24LicenseItem%7D%0A%20%20%20else%0A%20%20%20%7B%24NamePrint%3D%24EasyName%7D%0A%20%20%20%23Get%20all%20services%20for%20current%20SKUId%0A%20%20%20%24Services%3D%24_.licenses%5B%24count%5D.ServiceStatus%0A%20%20%20if((%24Count%20-gt%200)%20-and%20(%24count%20-lt%20%24LicenseCount))%0A%20%20%20%7B%0A%20%20%20%20%24LicensePlanWithEnabledService%3D%24LicensePlanWithEnabledService%2B%22%2C%22%0A%20%20%20%20%24FriendlyNameOfLicensePlanWithService%3D%24FriendlyNameOfLicensePlanWithService%2B%22%2C%22%0A%20%20%20%7D%0A%20%20%20%24DisabledServiceCount%20%3D%200%0A%20%20%20%24EnabledServiceCount%3D0%0A%20%20%20%24serviceExceptDisabled%3D%22%22%0A%20%20%20%24FriendlyNameOfServiceExceptDisabled%3D%22%22%0A%20%20%20foreach(%24Service%20in%20%24Services)%20%23Service%20loop%0A%20%20%20%7B%0A%20%20%20%20%24flag%3D0%0A%20%20%20%20%24ServiceName%3D%24Service.ServicePlan.ServiceName%0A%20%20%20%20if(%24service.ProvisioningStatus%20-eq%20%22Disabled%22)%0A%20%20%20%20%7B%0A%20%20%20%20%20%24DisabledServiceCount%2B%2B%0A%20%20%20%20%7D%0A%20%20%20%20else%0A%20%20%20%20%7B%0A%20%20%20%20%20%24EnabledServiceCount%2B%2B%0A%20%20%20%20%20if(%24EnabledServiceCount%20-ne%201)%0A%20%20%20%20%20%7B%0A%20%20%20%20%20%20%24serviceExceptDisabled%20%3D%24serviceExceptDisabled%2B%22%2C%22%0A%20%20%20%20%20%7D%0A%20%20%20%20%20%24serviceExceptDisabled%20%3D%24serviceExceptDisabled%2B%24ServiceName%0A%20%20%20%20%20%24flag%3D1%0A%20%20%20%20%7D%0A%20%20%20%20%23Convert%20ServiceName%20to%20friendly%20name%0A%20%20%20%20for(%24i%3D0%3B%24i%20-lt%20%24ServiceArray.length%3B%24i%20%2B%3D2)%0A%20%20%20%20%7B%0A%20%20%20%20%20%24ServiceFriendlyName%20%3D%20%24ServiceName%0A%20%20%20%20%20%24Condition%20%3D%20%24ServiceName%20-Match%20%24ServiceArray%5B%24i%5D%0A%20%20%20%20%20if(%24Condition%20-eq%20%22True%22)%0A%20%20%20%20%20%7B%0A%20%20%20%20%20%20%24ServiceFriendlyName%3D%24ServiceArray%5B%24i%2B1%5D%0A%20%20%20%20%20%20break%0A%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%20%20%20%20if(%24flag%20-eq%201)%0A%20%20%20%20%7B%0A%20%20%20%20%20if(%24EnabledServiceCount%20-ne%201)%0A%20%20%20%20%20%7B%0A%20%20%20%20%20%24FriendlyNameOfServiceExceptDisabled%20%3D%24FriendlyNameOfServiceExceptDisabled%2B%22%2C%22%0A%20%20%20%20%7D%0A%20%20%20%20%24FriendlyNameOfServiceExceptDisabled%20%3D%24FriendlyNameOfServiceExceptDisabled%2B%24ServiceFriendlyName%0A%20%20%20%7D%0A%20%20%20%23Store%20Service%20and%20its%20status%20in%20Hash%20table%0A%20%20%20%24Result%20%3D%20%40%7B'DisplayName'%3D%24_.Displayname%3B'UserPrinciPalName'%3D%24upn%3B'LicensePlan'%3D%24Licenseitem%3B'FriendlyNameofLicensePlan'%3D%24nameprint%3B'ServiceName'%3D%24service.ServicePlan.ServiceName%3B%0A%20%20%20'FriendlyNameofServiceName'%3D%24serviceFriendlyName%3B'ProvisioningStatus'%3D%24service.ProvisioningStatus%7D%0A%20%20%20%20%24Results%20%3D%20New-Object%20PSObject%20-Property%20%24Result%0A%20%20%20%20%24Results%20%7Cselect-object%20DisplayName%2CUserPrinciPalName%2CLicensePlan%2CFriendlyNameofLicensePlan%2CServiceName%2CFriendlyNameofServiceName%2C%0A%20%20%20%20%20%20%20%20ProvisioningStatus%20%7C%20Export-Csv%20-Path%20%24ExportCSV%20-Notype%20-Append%0A%20%20%7D%0A%20%20if(%24Disabledservicecount%20-eq%200)%0A%20%20%7B%0A%20%20%20%24serviceExceptDisabled%20%3D%22All%20services%22%0A%20%20%20%24FriendlyNameOfServiceExceptDisabled%3D%22All%20services%22%0A%20%20%7D%0A%20%20%24LicensePlanWithEnabledService%3D%24LicensePlanWithEnabledService%20%2B%20%24Licenseitem%20%2B%22%5B%22%20%2B%24serviceExceptDisabled%20%2B%22%5D%22%0A%20%20%24FriendlyNameOfLicensePlanWithService%3D%24FriendlyNameOfLicensePlanWithService%2B%20%24NamePrint%20%2B%20%22%5B%22%20%2B%20%24FriendlyNameOfServiceExceptDisabled%20%2B%22%5D%22%0A%20%20%23Increment%20SKUid%20count%0A%20%20%24count%2B%2B%0A%20%7D%0A%20%24Output%3D%40%7B'Displayname'%3D%24_.Displayname%3B'UserPrincipalName'%3D%24upn%3BCountry%3D%24Country%3B'LicensePlanWithEnabledService'%3D%24LicensePlanWithEnabledService%3B%0A%20%20%20%20%20%20'FriendlyNameOfLicensePlanAndEnabledService'%3D%24FriendlyNameOfLicensePlanWithService%7D%0A%20%24Outputs%3D%20New-Object%20PSObject%20-Property%20%24output%0A%20%24Outputs%20%7C%20Select-Object%20Displayname%2Cuserprincipalname%2CCountry%2CLicensePlanWithEnabledService%2CFriendlyNameOfLicensePlanAndEnabledService%20%7C%20Export-Csv%20-path%20%24ExportSimpleCSV%20-NoTypeInformation%20-Append%0A%7D%0A%0A%0AFunction%20main()%0A%7B%0A%20%23Clean%20up%20session%0A%20Get-PSSession%20%7C%20Remove-PSSession%0A%20%23Connect%20AzureAD%20from%20PowerShell%0A%20Connect-MsolService%0A%20%23Set%20output%20file%0A%20%24ExportCSV%3D%22.%5CDetailedO365UserLicenseReport_%24((Get-Date%20-format%20yyyy-MMM-dd-ddd%60%20hh-mm%60%20tt).ToString()).csv%22%0A%20%24ExportSimpleCSV%3D%22.%5CSimpleO365UserLicenseReport_%24((Get-Date%20-format%20yyyy-MMM-dd-ddd%60%20hh-mm%60%20tt).ToString()).csv%22%0A%20%23FriendlyName%20list%20for%20license%20plan%20and%20service%0A%20%24FriendlyNameHash%3DGet-Content%20-Raw%20-Path%20.%5CLicenseFriendlyName.txt%20-ErrorAction%20Stop%20%7C%20ConvertFrom-StringData%0A%20%24ServiceArray%3DGet-Content%20-Path%20.%5CServiceFriendlyName.txt%20-ErrorAction%20Stop%0A%20%23Hash%20table%20declaration%0A%20%24Result%3D%22%22%0A%20%24Results%3D%40()%0A%20%24output%3D%22%22%0A%20%24outputs%3D%40()%0A%20%23Get%20licensed%20user%0A%20%24LicensedUserCount%3D0%0A%0A%20%23Check%20for%20input%20file%2FGet%20users%20from%20input%20file%0A%20if(%5Bstring%5D%24UserNamesFile%20-ne%20%22%22)%0A%20%7B%0A%20%20%23We%20have%20an%20input%20file%2C%20read%20it%20into%20memory%0A%20%20%24UserNames%3D%40()%0A%20%20%24UserNames%3DImport-Csv%20-Header%20%22DisplayName%22%20%24UserNamesFile%0A%20%20%24userNames%0A%20%20foreach(%24item%20in%20%24UserNames)%0A%20%20%7B%0A%20%20%20Get-MsolUser%20-UserPrincipalName%20%24item.displayname%20%7C%20where%7B%24_.islicensed%20-eq%20%22true%22%7D%20%7C%20Foreach%7B%0A%20%20%20Get_UsersLicenseInfo%0A%20%20%20%24LicensedUserCount%2B%2B%7D%0A%20%20%7D%0A%20%7D%0A%0A%20%23Get%20all%20licensed%20users%0A%20else%0A%20%7B%0A%20%20Get-MsolUser%20-All%20%7C%20where%7B%24_.islicensed%20-eq%20%22true%22%7D%20%7C%20Foreach%7B%0A%20%20Get_UsersLicenseInfo%0A%20%20%24LicensedUserCount%2B%2B%7D%0A%20%7D%0A%0A%0A%20%23Open%20output%20file%20after%20execution%0A%20Write-Host%20Detailed%20report%20available%20in%3A%20%24ExportCSV%0A%20Write-host%20Simple%20report%20available%20in%3A%20%24ExportSimpleCSV%0A%20%24Prompt%20%3D%20New-Object%20-ComObject%20wscript.shell%0A%20%24UserInput%20%3D%20%24Prompt.popup(%22Do%20you%20want%20to%20open%20output%20files%3F%22%2C%60%0A%200%2C%22Open%20Files%22%2C4)%0A%20If%20(%24UserInput%20-eq%206)%0A%20%7B%0A%20%20Invoke-Item%20%22%24ExportCSV%22%0A%20%20Invoke-Item%20%22%24ExportSimpleCSV%22%0A%20%7D%0A%7D%0A%20.%20main%3C%2FCODE%3E%3C%2FPRE%3E%3CP%3EMFA%3A%3C%2FP%3E%3CPRE%20class%3D%22lia-code-sample%20language-powershell%22%3E%3CCODE%3EWrite-Host%20%22Finding%20Azure%20Active%20Directory%20Accounts...%22%0A%24Users%20%3D%20Get-MsolUser%20-All%20%7C%20%3F%20%7B%20%24_.UserType%20-ne%20%22Guest%22%20%7D%0A%24Report%20%3D%20%5BSystem.Collections.Generic.List%5BObject%5D%5D%3A%3Anew()%20%23%20Create%20output%20file%0AWrite-Host%20%22Processing%22%20%24Users.Count%20%22accounts...%22%20%0AForEach%20(%24User%20in%20%24Users)%20%7B%0A%20%20%20%20%24MFAEnforced%20%3D%20%24User.StrongAuthenticationRequirements.State%0A%20%20%20%20%24MFAPhone%20%3D%20%24User.StrongAuthenticationUserDetails.PhoneNumber%0A%20%20%20%20%24DefaultMFAMethod%20%3D%20(%24User.StrongAuthenticationMethods%20%7C%20%3F%20%7B%20%24_.IsDefault%20-eq%20%22True%22%20%7D).MethodType%0A%20%20%20%20If%20((%24MFAEnforced%20-eq%20%22Enforced%22)%20-or%20(%24MFAEnforced%20-eq%20%22Enabled%22))%20%7B%0A%20%20%20%20%20%20%20%20Switch%20(%24DefaultMFAMethod)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%22OneWaySMS%22%20%7B%20%24MethodUsed%20%3D%20%22One-way%20SMS%22%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%22TwoWayVoiceMobile%22%20%7B%20%24MethodUsed%20%3D%20%22Phone%20call%20verification%22%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%22PhoneAppOTP%22%20%7B%20%24MethodUsed%20%3D%20%22Hardware%20token%20or%20authenticator%20app%22%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%22PhoneAppNotification%22%20%7B%20%24MethodUsed%20%3D%20%22Authenticator%20app%22%20%7D%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%20%20%20%20Else%20%7B%0A%20%20%20%20%20%20%20%20%24MFAEnforced%20%3D%20%22Not%20Enabled%22%0A%20%20%20%20%20%20%20%20%24MethodUsed%20%3D%20%22MFA%20Not%20Used%22%20%0A%20%20%20%20%7D%0A%20%20%0A%20%20%20%20%24ReportLine%20%3D%20%5BPSCustomObject%5D%20%40%7B%0A%20%20%20%20%20%20%20%20User%20%20%20%20%20%20%20%20%3D%20%24User.UserPrincipalName%0A%20%20%20%20%20%20%20%20Name%20%20%20%20%20%20%20%20%3D%20%24User.DisplayName%0A%20%20%20%20%20%20%20%20MFAUsed%20%20%20%20%20%3D%20%24MFAEnforced%0A%20%20%20%20%20%20%20%20MFAMethod%20%20%20%3D%20%24MethodUsed%20%0A%20%20%20%20%20%20%20%20PhoneNumber%20%3D%20%24MFAPhone%0A%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%0A%20%20%20%20%24Report.Add(%24ReportLine)%20%0A%7D%0A%0AWrite-Host%20%22Report%20is%20in%20c%3A%5Ctemp%5CMFAUsers.CSV%22%0A%24Report%20%7C%20Select%20User%2C%20Name%2C%20MFAUsed%2C%20MFAMethod%2C%20PhoneNumber%20%7C%20Sort%20Name%20%7C%20Out-GridView%0A%24Report%20%7C%20Sort%20Name%20%7C%20Export-CSV%20-NoTypeInformation%20-Encoding%20UTF8%20c%3A%5Ctemp%5CMFAUsers.csv%3C%2FCODE%3E%3C%2FPRE%3E%3CP%3E%26nbsp%3B%3C%2FP%3E%3CP%3ESign%20in%20status%3A%3C%2FP%3E%3CPRE%20class%3D%22lia-code-sample%20language-powershell%22%3E%3CCODE%3E%24Groups%20%3D%20Get-UnifiedGroup%20-ResultSize%205%24Groups%20%7C%20ForEach-Object%20%7B%0A%24group%20%3D%20%24_%0AGet-UnifiedGroupLinks%20-Identity%20%24group.Name%20-LinkType%20Members%20-ResultSize%20Unlimited%20%7C%20ForEach-Object%20%7B%0A%20%20%20%20%20%20New-Object%20-TypeName%20PSObject%20-Property%20%40%7B%0A%20%20%20%20%20%20%20Group%20%3D%20%24group.DisplayName%0A%20%20%20%20%20%20%20Member%20%3D%20%24_.Name%0A%20%20%20%20%20%20%20EmailAddress%20%3D%20%24_.PrimarySMTPAddress%0A%20%20%20%20%20%20%20RecipientType%3D%20%24_.RecipientType%0A%20%20%20%20%20%20%20Status%20%3D%20%24_.SignInStatus%0A%7D%7D%7D%3C%2FCODE%3E%3C%2FPRE%3E%3CP%3E%26nbsp%3B%3C%2FP%3E%3CP%3EOnce%20again%20thanks%20for%20the%20help!%3C%2FP%3E%3C%2FLINGO-BODY%3E%3CLINGO-LABS%20id%3D%22lingo-labs-3023494%22%20slang%3D%22en-US%22%3E%3CLINGO-LABEL%3EAzure%20Active%20Directory%3C%2FLINGO-LABEL%3E%3CLINGO-LABEL%3EWindows%20PowerShell%3C%2FLINGO-LABEL%3E%3C%2FLINGO-LABS%3E
Occasional Contributor

So let me first say thanks for working with me as I am new to powershell. With that I have found and used three different scripts to get this info and have three different .csv files that I can then combine. But I am wanting to know if I can get them to run as one script to output on .csv to save time as I have to do this twice month for the next 12 months. Each script pulls from a different powershell connection so I don't know if this will work as I haven't found a way to do it. This environment is O365 with no local servers.

 

These are the scripts I have.

Licenses used:

#Using this script administrator can identify all licensed users with their assigned licenses, services, and its status.

Param
(
 [Parameter(Mandatory = $false)]
    [string]$UserNamesFile
)


Function Get_UsersLicenseInfo
{
  $LicensePlanWithEnabledService=""
  $FriendlyNameOfLicensePlanWithService=""
  $upn=$_.userprincipalname
  $Country=$_.Country
  if([string]$Country -eq "")
  {
   $Country="-"
  }
  Write-Progress -Activity "`n     Exported user count:$LicensedUserCount "`n"Currently Processing:$upn"
  #Get all asssigned SKU for current user
  $Skus=$_.licenses.accountSKUId
  $LicenseCount=$skus.count
  $count=0
  #Loop through each SKUid
  foreach($Sku in $Skus)  #License loop
  {
   #Convert Skuid to friendly name
   $LicenseItem= $Sku -Split ":" | Select-Object -Last 1
   $EasyName=$FriendlyNameHash[$LicenseItem]
   if(!($EasyName))
   {$NamePrint=$LicenseItem}
   else
   {$NamePrint=$EasyName}
   #Get all services for current SKUId
   $Services=$_.licenses[$count].ServiceStatus
   if(($Count -gt 0) -and ($count -lt $LicenseCount))
   {
    $LicensePlanWithEnabledService=$LicensePlanWithEnabledService+","
    $FriendlyNameOfLicensePlanWithService=$FriendlyNameOfLicensePlanWithService+","
   }
   $DisabledServiceCount = 0
   $EnabledServiceCount=0
   $serviceExceptDisabled=""
   $FriendlyNameOfServiceExceptDisabled=""
   foreach($Service in $Services) #Service loop
   {
    $flag=0
    $ServiceName=$Service.ServicePlan.ServiceName
    if($service.ProvisioningStatus -eq "Disabled")
    {
     $DisabledServiceCount++
    }
    else
    {
     $EnabledServiceCount++
     if($EnabledServiceCount -ne 1)
     {
      $serviceExceptDisabled =$serviceExceptDisabled+","
     }
     $serviceExceptDisabled =$serviceExceptDisabled+$ServiceName
     $flag=1
    }
    #Convert ServiceName to friendly name
    for($i=0;$i -lt $ServiceArray.length;$i +=2)
    {
     $ServiceFriendlyName = $ServiceName
     $Condition = $ServiceName -Match $ServiceArray[$i]
     if($Condition -eq "True")
     {
      $ServiceFriendlyName=$ServiceArray[$i+1]
      break
     }
    }
    if($flag -eq 1)
    {
     if($EnabledServiceCount -ne 1)
     {
     $FriendlyNameOfServiceExceptDisabled =$FriendlyNameOfServiceExceptDisabled+","
    }
    $FriendlyNameOfServiceExceptDisabled =$FriendlyNameOfServiceExceptDisabled+$ServiceFriendlyName
   }
   #Store Service and its status in Hash table
   $Result = @{'DisplayName'=$_.Displayname;'UserPrinciPalName'=$upn;'LicensePlan'=$Licenseitem;'FriendlyNameofLicensePlan'=$nameprint;'ServiceName'=$service.ServicePlan.ServiceName;
   'FriendlyNameofServiceName'=$serviceFriendlyName;'ProvisioningStatus'=$service.ProvisioningStatus}
    $Results = New-Object PSObject -Property $Result
    $Results |select-object DisplayName,UserPrinciPalName,LicensePlan,FriendlyNameofLicensePlan,ServiceName,FriendlyNameofServiceName,
        ProvisioningStatus | Export-Csv -Path $ExportCSV -Notype -Append
  }
  if($Disabledservicecount -eq 0)
  {
   $serviceExceptDisabled ="All services"
   $FriendlyNameOfServiceExceptDisabled="All services"
  }
  $LicensePlanWithEnabledService=$LicensePlanWithEnabledService + $Licenseitem +"[" +$serviceExceptDisabled +"]"
  $FriendlyNameOfLicensePlanWithService=$FriendlyNameOfLicensePlanWithService+ $NamePrint + "[" + $FriendlyNameOfServiceExceptDisabled +"]"
  #Increment SKUid count
  $count++
 }
 $Output=@{'Displayname'=$_.Displayname;'UserPrincipalName'=$upn;Country=$Country;'LicensePlanWithEnabledService'=$LicensePlanWithEnabledService;
      'FriendlyNameOfLicensePlanAndEnabledService'=$FriendlyNameOfLicensePlanWithService}
 $Outputs= New-Object PSObject -Property $output
 $Outputs | Select-Object Displayname,userprincipalname,Country,LicensePlanWithEnabledService,FriendlyNameOfLicensePlanAndEnabledService | Export-Csv -path $ExportSimpleCSV -NoTypeInformation -Append
}


Function main()
{
 #Clean up session
 Get-PSSession | Remove-PSSession
 #Connect AzureAD from PowerShell
 Connect-MsolService
 #Set output file
 $ExportCSV=".\DetailedO365UserLicenseReport_$((Get-Date -format yyyy-MMM-dd-ddd` hh-mm` tt).ToString()).csv"
 $ExportSimpleCSV=".\SimpleO365UserLicenseReport_$((Get-Date -format yyyy-MMM-dd-ddd` hh-mm` tt).ToString()).csv"
 #FriendlyName list for license plan and service
 $FriendlyNameHash=Get-Content -Raw -Path .\LicenseFriendlyName.txt -ErrorAction Stop | ConvertFrom-StringData
 $ServiceArray=Get-Content -Path .\ServiceFriendlyName.txt -ErrorAction Stop
 #Hash table declaration
 $Result=""
 $Results=@()
 $output=""
 $outputs=@()
 #Get licensed user
 $LicensedUserCount=0

 #Check for input file/Get users from input file
 if([string]$UserNamesFile -ne "")
 {
  #We have an input file, read it into memory
  $UserNames=@()
  $UserNames=Import-Csv -Header "DisplayName" $UserNamesFile
  $userNames
  foreach($item in $UserNames)
  {
   Get-MsolUser -UserPrincipalName $item.displayname | where{$_.islicensed -eq "true"} | Foreach{
   Get_UsersLicenseInfo
   $LicensedUserCount++}
  }
 }

 #Get all licensed users
 else
 {
  Get-MsolUser -All | where{$_.islicensed -eq "true"} | Foreach{
  Get_UsersLicenseInfo
  $LicensedUserCount++}
 }


 #Open output file after execution
 Write-Host Detailed report available in: $ExportCSV
 Write-host Simple report available in: $ExportSimpleCSV
 $Prompt = New-Object -ComObject wscript.shell
 $UserInput = $Prompt.popup("Do you want to open output files?",`
 0,"Open Files",4)
 If ($UserInput -eq 6)
 {
  Invoke-Item "$ExportCSV"
  Invoke-Item "$ExportSimpleCSV"
 }
}
 . main

MFA:

Write-Host "Finding Azure Active Directory Accounts..."
$Users = Get-MsolUser -All | ? { $_.UserType -ne "Guest" }
$Report = [System.Collections.Generic.List[Object]]::new() # Create output file
Write-Host "Processing" $Users.Count "accounts..." 
ForEach ($User in $Users) {
    $MFAEnforced = $User.StrongAuthenticationRequirements.State
    $MFAPhone = $User.StrongAuthenticationUserDetails.PhoneNumber
    $DefaultMFAMethod = ($User.StrongAuthenticationMethods | ? { $_.IsDefault -eq "True" }).MethodType
    If (($MFAEnforced -eq "Enforced") -or ($MFAEnforced -eq "Enabled")) {
        Switch ($DefaultMFAMethod) {
            "OneWaySMS" { $MethodUsed = "One-way SMS" }
            "TwoWayVoiceMobile" { $MethodUsed = "Phone call verification" }
            "PhoneAppOTP" { $MethodUsed = "Hardware token or authenticator app" }
            "PhoneAppNotification" { $MethodUsed = "Authenticator app" }
        }
    }
    Else {
        $MFAEnforced = "Not Enabled"
        $MethodUsed = "MFA Not Used" 
    }
  
    $ReportLine = [PSCustomObject] @{
        User        = $User.UserPrincipalName
        Name        = $User.DisplayName
        MFAUsed     = $MFAEnforced
        MFAMethod   = $MethodUsed 
        PhoneNumber = $MFAPhone
    }
                 
    $Report.Add($ReportLine) 
}

Write-Host "Report is in c:\temp\MFAUsers.CSV"
$Report | Select User, Name, MFAUsed, MFAMethod, PhoneNumber | Sort Name | Out-GridView
$Report | Sort Name | Export-CSV -NoTypeInformation -Encoding UTF8 c:\temp\MFAUsers.csv

 

Sign in status:

$Groups = Get-UnifiedGroup -ResultSize 5$Groups | ForEach-Object {
$group = $_
Get-UnifiedGroupLinks -Identity $group.Name -LinkType Members -ResultSize Unlimited | ForEach-Object {
      New-Object -TypeName PSObject -Property @{
       Group = $group.DisplayName
       Member = $_.Name
       EmailAddress = $_.PrimarySMTPAddress
       RecipientType= $_.RecipientType
       Status = $_.SignInStatus
}}}

 

Once again thanks for the help!

2 Replies

@Jallcock 

Okay, its too late for me rn
I dont have a premium plan so I cant test the part with last login and MFA.
Try it and give a feedback:
should look like this. Used the following articles:

https://techcommunity.microsoft.com/t5/azure/manage-licenses-with-powershell-in-azure-active-directo...

https://www.higginson.org/powershell-getting-all-azure-ad-user-ids-last-login-date-and-time/

 

<#
Connect-AzAccount
Connect-AzureAD
Connect-ExcangeONline
Connect-MsolService
Import-Module -Name AzureADPreview
#>

Import-Module -Name AzureADPreview

$AzureADSubscribedSku = "O365_BUSINESS_ESSENTIALS"



Get-AzureAdUser | ForEach { $licensed=$False ; For ($i=0; $i -le ($_.AssignedLicenses | Measure).Count ; $i++)`
{ If( [string]::IsNullOrEmpty( $_.AssignedLicenses[$i].SkuId ) -ne $True) { $licensed=$true } } ; If( $licensed -eq $true)`
{ Write-Host $_.UserPrincipalName, $_.Mail, $_.AssignedLicenses.SkuId, $_.StrongAuthenticationRequirements.State} } | export-csv C:\users\Schnittlauch\desktop\exports.csv -Delimiter ';'




$Cred = Get-Credential
Connect-MsolService -Credential $Cred
Connect-AzureAD -Credential $Cred

$Users = Get-MsolUser -all
$Headers = "DisplayName`tUserPrincipalName`tLicense`tLastLogon" >>C:\Temp\Users.txt
ForEach ($User in $Users)
{
$UPN = $User.UserPrincipalName
$LoginTime = Get-AzureAdAuditSigninLogs -top 1 -filter "userprincipalname eq '$UPN'" | select CreatedDateTime
$NewLine = $User.DisplayName + "`t" + $User.UserPrincipalName + "`t" + $User.Licenses.AccountSkuId + "`t" + $LoginTime.CreatedDateTime
$NewLine >>C:\Temp\Users.txt
}

 

Thanks you are a life saver.

I have tried it but it erroring out. The account need MFA as it was required on all accounts as per the security consultant. I looks like the Connect-AzureAD isn't pulling for MFA and isn't logging.

This is the error.

Get-AzureAdUser : You must call the Connect-AzureAD cmdlet before calling any other cmdlets.
At line:15 char:1
+ Get-AzureAdUser | ForEach { $licensed=$False ; For ($i=0; $i -le ($_. ...
+ ~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [Get-AzureADUser], AadNeedAuthenticationException
+ FullyQualifiedErrorId : Microsoft.Open.Azure.AD.CommonLibrary.AadNeedAuthenticationException,Microsoft.Open.AzureAD16.PowerShell.GetUser

cmdlet Get-Credential at command pipeline position 1
Supply values for the following parameters:
Connect-AzureAD : One or more errors occurred.: AADSTS50076: Due to a configuration change made by your administrator, or because you moved to a new
location, you must use multi-factor authentication to access '00000002-0000-0000-c000-000000000000'.
Trace ID: 826c877b-dcd4-4ceb-96db-0fb64586a300
Correlation ID: 6db0dcc8-5d72-41da-931c-2c8a2f571c81
Timestamp: 2021-12-06 13:31:09Z
At line:24 char:1
+ Connect-AzureAD -Credential $Cred
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : AuthenticationError: (:) [Connect-AzureAD], AadAuthenticationFailedException
+ FullyQualifiedErrorId : Connect-AzureAD,Microsoft.Open.Azure.AD.CommonLibrary.ConnectAzureAD

Connect-AzureAD : One or more errors occurred.
At line:24 char:1
+ Connect-AzureAD -Credential $Cred
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : AuthenticationError: (:) [Connect-AzureAD], AggregateException
+ FullyQualifiedErrorId : Connect-AzureAD,Microsoft.Open.Azure.AD.CommonLibrary.ConnectAzureAD

Connect-AzureAD : AADSTS50076: Due to a configuration change made by your administrator, or because you moved to a new location, you must use
multi-factor authentication to access '00000002-0000-0000-c000-000000000000'.
Trace ID: 826c877b-dcd4-4ceb-96db-0fb64586a300
Correlation ID: 6db0dcc8-5d72-41da-931c-2c8a2f571c81
Timestamp: 2021-12-06 13:31:09Z
At line:24 char:1
+ Connect-AzureAD -Credential $Cred
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : AuthenticationError: (:) [Connect-AzureAD], AdalClaimChallengeException
+ FullyQualifiedErrorId : Connect-AzureAD,Microsoft.Open.Azure.AD.CommonLibrary.ConnectAzureAD

Connect-AzureAD : Response status code does not indicate success: 400 (BadRequest).
At line:24 char:1
+ Connect-AzureAD -Credential $Cred
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : AuthenticationError: (:) [Connect-AzureAD], HttpRequestException
+ FullyQualifiedErrorId : Connect-AzureAD,Microsoft.Open.Azure.AD.CommonLibrary.ConnectAzureAD

Connect-AzureAD : {"error":"interaction_required","error_description":"AADSTS50076: Due to a configuration change made by your administrator, or because
you moved to a new location, you must use multi-factor authentication to access '00000002-0000-0000-c000-000000000000'.\r\nTrace ID:
826c877b-dcd4-4ceb-96db-0fb64586a300\r\nCorrelation ID: 6db0dcc8-5d72-41da-931c-2c8a2f571c81\r\nTimestamp: 2021-12-06
13:31:09Z","error_codes":[50076],"timestamp":"2021-12-06 13:31:09Z","trace_id":"826c877b-dcd4-4ceb-96db-0fb64586a300","correlation_id":"6db0dcc8-5d72-41da
-931c-2c8a2f571c81","error_uri":"https://login.microsoftonline.com/error?code=50076","suberror":"basic_action"}: Unknown error
At line:24 char:1
+ Connect-AzureAD -Credential $Cred
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : AuthenticationError: (:) [Connect-AzureAD], AdalException
+ FullyQualifiedErrorId : Connect-AzureAD,Microsoft.Open.Azure.AD.CommonLibrary.ConnectAzureAD

Connect-AzureAD : One or more errors occurred.: AADSTS50076: Due to a configuration change made by your administrator, or because you moved to a new
location, you must use multi-factor authentication to access '00000002-0000-0000-c000-000000000000'.
Trace ID: 826c877b-dcd4-4ceb-96db-0fb64586a300
Correlation ID: 6db0dcc8-5d72-41da-931c-2c8a2f571c81
Timestamp: 2021-12-06 13:31:09Z
At line:24 char:1
+ Connect-AzureAD -Credential $Cred
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [Connect-AzureAD], AadAuthenticationFailedException
+ FullyQualifiedErrorId : Microsoft.Open.Azure.AD.CommonLibrary.AadAuthenticationFailedException,Microsoft.Open.Azure.AD.CommonLibrary.ConnectAzureAD

Get-AzureAdAuditSigninLogs : You must call the Connect-AzureAD cmdlet before calling any other cmdlets.
At line:31 char:14
+ ... LoginTime = Get-AzureAdAuditSigninLogs -top 1 -filter "userprincipaln ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [Get-AzureADAuditSignInLogs], AadNeedAuthenticationException
+ FullyQualifiedErrorId : Microsoft.Open.Azure.AD.CommonLibrary.AadNeedAuthenticationException,Microsoft.Open.MSGraphBeta.PowerShell.GetAuditSignInLo
gs