PowerShell Tip: Do all your Microsoft Teams have owners?

PowerShell Tip: Do all your Microsoft Teams have owners?

In many organisations where governance around the creation of Microsoft Teams is currently not in place. You may come across Teams where the owner may have left the organisation but the Team is still active. So using PowerShell we can find which Teams have or do not have owners.

Prerequistes

Microsoft Teams Module needs to be installed

Install-Module MicrosoftTeams

PowerShell Script

The following script will obtain all the required information and export to CSV.

$availableTeams = Get-Team
  $teams = @()
  foreach($team in $availableTeams)
  {
 
    Write-host "Discovered the following team:"  -NoNewline
    Write-host $team.DisplayName -ForegroundColor Yellow
    $users = Get-TeamUser -GroupId $team.GroupId
    $channel = Get-TeamChannel -GroupId $Team.GroupId
    $owners = @($users | Where-Object {$_.Role -eq 'owner'})
    $members = @($users | Where-Object {$_.Role -eq 'member'}).Length
    $guests = @($users | Where-Object {$_.Role -eq 'guest'}).Length

    Write-Host "Number of Owners =",($owners.count),"| Number of Members =",($members.count),"| Number of Guests =",($guests.count)

    $teamObject = New-Object -TypeName PSObject
    $teamObject | Add-Member -MemberType $NoteProperty -Name DisplayName -Value $team.DisplayName
    $teamObject | Add-Member -MemberType $NoteProperty -Name GroupID -Value $team.GroupId
    $teamObject | Add-Member -MemberType $NoteProperty -Name Alias -Value $team.MailNickName
    $teamObject | Add-Member -Membertype $noteproperty -Name "TeamVisibility" -Value $Team.Visibility
    $teamObject | Add-Member -Membertype $noteproperty -Name "TeamArchived" -Value $Team.Archived
    $teamObject | Add-Member -Membertype $noteproperty -Name "TeamOwners" -Value ($owners).Count
    $teamObject | Add-Member -Membertype $noteproperty -Name "TeamMembers" -Value ($members).Count
    $teamObject | Add-Member -Membertype $noteproperty -Name "TeamGuests" -Value ($guests).Count
    $teamObject | Add-Member -Membertype $noteproperty -Name "TeamOverallUserCount" -Value $users.Count
    $teamObject | Add-Member -Membertype $noteproperty -Name "TeamChannelCount" -Value $channel.Count


    if($owners.Count -eq 1)
    {
      $teamObject | Add-Member -MemberType $NoteProperty -Name 'Owner' -Value $owners[0].User
    }

    write-host ' Analysis Completed' -BackgroundColor DarkGreen
    $teams += $teamObject
  }

  $teams | Export-Csv -Path $env:USERPROFILE\desktop\Get-MicrosoftTeamOwnerInfo.csv
  write-host "Output exported to: $env:USERPROFILE\desktop\Get-MicrosoftTeamOwnerInfo.csv" -BackgroundColor DarkGreen
}

Regards,
The Author – Blogabout.Cloud

PowerShell Tip: Obtaining the ImmutableID from your Active Directory Objects on-prem and in the cloud

PowerShell Tip: Obtaining the ImmutableID from your Active Directory Objects on-prem and in the cloud

When working with Azure Active Directory Connect you may experience issues with account duplicating due to the ImmutableID not matching. If it does happen its is a pain to resolve as you have to;

Desynchronize the affected accounts
Delete from the Deleted Users OU in Azure Active Directory
Obtain the on-premises ImmutableID
Obtain the cloud ImmutableID
Compare the IDs
Set the cloud ID with the on-premises ID

Now wouldnt it be easier if someone had a bunch of PowerShell commands to help you get the ImmutableID. This is where I come in

Obtaining ImmutableID from on-premises Active Directory Object

The following PowerShell script extracts all the ImmutableID’s from every single Active Directory User Object and store in a CSV file on your desktop.

$reportoutput=@()
$users = Get-ADUser -Filter * -Properties *
$users | Foreach-Object {

    $user = $_
    $immutableid = "[System.Convert]::ToBase64String($user.ObjectGUID.tobytearray())"
    $userid = $user | select @{Name='Access Rights';Expression={[string]::join(', ', $immutableid)}}

    $report = New-Object -TypeName PSObject
    $report | Add-Member -MemberType NoteProperty -Name 'UserPrincipalName' -Value $user.UserPrincipalName
    $report | Add-Member -MemberType NoteProperty -Name 'SamAccountName' -Value $user.samaccountname
    $report | Add-Member -MemberType NoteProperty -Name 'ImmutableID' -Value $immutableid
    $reportoutput += $report
}
 # Report
$reportoutput | Export-Csv -Path $env:USERPROFILE\desktop\ImmutableID4AD.csv -NoTypeInformation -Encoding UTF8 }

Obtaining ImmutableID from Azure Active Directory Object

The following PowerShell script extracts all the ImmutableID’s from every single Azure Active Directory User Object and store in a CSV file on your desktop.

$reportoutput=@()
$users = Get-AzureADUser -All $true
$users | Foreach-Object {

    $user = $_

    $report = New-Object -TypeName PSObject
    $report | Add-Member -MemberType NoteProperty -Name 'UserPrincipalName' -Value $user.UserPrincipalName
    $report | Add-Member -MemberType NoteProperty -Name 'SamAccountName' -Value $user.samaccountname
    $report | Add-Member -MemberType NoteProperty -Name 'ImmutableID' -Value $user.immutableid
    $report | Add-Member -MemberType NoteProperty -Name 'DisplayName' -Value $user.displayname
    $reportoutput += $report
}
 # Report
$reportoutput | Export-Csv -Path $env:USERPROFILE\onedrive\desktop\ImmutableID4AAD.csv -NoTypeInformation -Encoding UTF8 }

Recommendation

When I have had to compare the two exports at scale for an entire environment, it can be a complete nightmare but the ImportExcel module was brilliant in getting the data merged into a single sheet.

https://www.powershellgallery.com/packages/ImportExcel/7.1.1

Regards
The Author – Blogabout.Cloud

Quick Tips: How do I restore a deleted Microsoft Teams Team using PowerShell.

Quick Tips: How do I restore a deleted Microsoft Teams Team using PowerShell.

Sometimes accidents happen and things get deleted by mistake but what do you do if you delete a Microsoft Team by mistake?

When the team is deleted, it is held in the “recycle bin” for 30 days until it is permanently deleted. The following is the process of restoring a deleted team in Microsoft Teams.

  • Once Team is deleted, option to recover it exists for up to 30 days
  • All of it including (Channels, files, tabs, etc.) will reappear as it was before
  • Restore can take up to 4 hours
  • To restore, from exchange admin center, select recipients, then groups
  • Locate the group (only if soft deleted)
  • Select the group and choose restore

This is where my favourite Microsoft tool comes into action, PowerShell

Prerequisites

AzureAD Module is installed
Global Admin to your Azure AD Tenant

Process

Launch PowerShell as an administrator


1
Connect-AzureAD

When a team is created in Microsoft Teams, it creates an Office 365 group. In order to restore the group you will need to obtain the Id using the following cmdlet


1
Get-AzureADMSDeletedGroup

1
Restore-ADMSDeletedDirectoryObject –ID <objectID>

As mentioned above the restore could take up to 4 hours to complete.

Regards
The Author – Blogabout.Cloud
           

2010 Service Release – Intune in a half shell, Shell Power!!

2010 Service Release – Intune in a half shell, Shell Power!!

The 2010 Service Release has since a number of updates as shown below;

SectionItemLink
App ManagementApps that require enrollment are hidden when enrollment is set to unavailableLink
Improvements to iOS Company Portal privacy message customizationLink
Android app protection policies (MAM) on COPE devicesLink
Max Company Portal version age for Android devicesLink
Mac LOB apps will be supported as managed apps on macOS 11 and higherLink
Enable Outlook S/MIME emails to be always signed or encryptedLink
Device ConfigurationUse the Connect Automatically setting on Android Enterprise basic Wi-Fi profilesLink
New user experience and new Enable direct download setting on macOS devices using associated domainsLink
New lockout password settings on macOS devicesLink
Required password type default setting is changing on Android Enterprise devicesLink
Device enrollmentIntune support for provisioning Azure Active Directory shared devicesLink
Device SecurityApp protection policy support on Android and iOS/iPadOS for additional partnersLink
Endpoint Manager Security tasks include details about misconfigured settings from Microsoft Defender ATP TVMLink
Endpoint security Firewall policies for tenant attached devicesLink
Expanded settings to manage hardware device installation through block and allow listsLink
Improvements to endpoint security Firewall rulesLink
Use Microsoft Defender for Endpoint in compliance policies for iOSLink
Security Experience profiles for Endpoint Security Antivirus policy now have tri-state optionsLink
Updated version of the Edge security baselineLink
Monitor and troubleshootNew Windows 10 feature update failures reportLink
Updates to Antivirus reportsLink
Updated Help and Support for Microsoft Endpoint ManagerLink
ScriptsCollect custom device or user properties using shell scripts on managed MacsLink

But what I wanted to pick up on is the new PowerShell elements within this service release as its something I regular do within my own Windows 10 deployments.

These are really cool additions.

View PowerShell scripts in the Intune Troubleshooting pane

You can now view your assigned PowerShell scripts in the Troubleshooting pane. PowerShell scripts provide Windows 10 client communication with Intune to run enterprise management tasks, such as advanced device configuration and troubleshooting. For more information, see Use PowerShell scripts on Windows 10 devices in Intune.

Win32 app support for Workplace join (WPJ) devices

Existing Win32 apps are supported for Workplace join (WPJ) devices. PowerShell scripts, which are not officially supported on WPJ devices, can be deployed to WPJ devices. Specifically, device context PowerShell scripts work on WPJ devices, but user context PowerShell scripts are ignored by design. User context scripts will be ignored on WPJ devices and will not be reported to the Microsoft Endpoint Manager console. For more information about PowerShell, see Use PowerShell scripts on Windows 10 devices in Intune.

Regards,
The Author – Blogabout.Cloud

Using PowerShell to view the Current Status of Microsoft 365 with Office 365 Service Communications API

Using PowerShell to view the Current Status of Microsoft 365 with Office 365 Service Communications API

With Office 365 Service Communications API you can pull the required Current Status using PowerShell providing you have completed the prerequisites below.

Screenshot

Prerequisites

  • PowerShell script
  • TenantID
  • ClientID
  • ClientSecret

The TenantID, ClientID and ClientSecret are obtained from your Application but please do remember you need to have a copy of the ClientSecret as once you move away from the secret. You wont be able to see it again.

The Script


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
Clear-Host
 <#Information
 
    Author: thewatchernode
    Contact: author@blogabout.cloud
    Published: 30th Ocotber 2020

    .DESCRIPTION
    Tool to gather Microsoft 365 Health Status.

    # IMPORTANT
    Office 365 Service Communications API needs to be configured with your Tenant. http://www.blogabout.cloud/2020/10/1884/

    Version Changes            
   
    : 0.1 Initial Script Build
    : 1.0 Initial Build Release
     
    Credit:
     

    .EXAMPLE
    .\Get-Microsoft365Status.ps1

    Description
    -----------
    Runs script with default values.


    .INPUTS
    None. You cannot pipe objects to this script.
#>
 #region To be configured by the script runner

# Objects
$tenantId = ''
$client_id = ''
$client_secret = ''
#endregion

Function Get-M365Status {
# Construct URI for OAuth Token
$uri = "https://login.microsoftonline.com/$tenantId/oauth2/v2.0/token"

# Construct Body for OAuth Token
$body = @{
    client_id     = $client_id
    scope         = "https://manage.office.com/.default"
    client_secret = $client_secret
    grant_type    = "client_credentials"
}

# Get OAuth 2.0 Token
$tokenRequest = try {

    Invoke-RestMethod -Method Post -Uri $uri -ContentType "application/x-www-form-urlencoded" -Body $body -ErrorAction Stop

}
catch [System.Net.WebException] {

    Write-Warning "Exception was caught: $($_.Exception.Message)"
   
}

$token = $tokenRequest.access_token

# Get Office 365 Status
$m365status = try {

    Invoke-RestMethod -Method Get -Uri "https://manage.office.com/api/v1.0/$tenantid/ServiceComms/CurrentStatus" -ContentType "application/json" -Headers @{Authorization = "Bearer $token"} -ErrorAction Stop

}
catch [System.Net.WebException] {

    Write-Warning "Exception was caught: $($_.Exception.Message)"
   
}

# List service overview status
$m365status.Value | Format-Table WorkloadDisplayName, StatusDisplayName, Status, IncidentIds
}
Write-host 'Version information - You are running script version 1.5' -ForegroundColor $White -BackgroundColor $DarkGray
  @'
  ┌─────────────────────────────────────────────────────────────┐
           Gather the status of Microsoft 365 Service Health

               Follow @thewatchernode on Twitter                              
  └─────────────────────────────────────────────────────────────┘
'@
Start-Transcript -Path $InstallDir\M365Status_Log.txt
Get-M365Status
Stop-Transcript

Download

https://github.com/TheWatcherNode/blogaboutcloud/blob/master/Get-Microsoft365Status.ps1

Regards
The Author – Blogabout.Cloud

How to uninstall PowerShell modules with dependencies within a script.

How to uninstall PowerShell modules with dependencies within a script.

PowerShell module can sometimes become a nightmare if there are dependencies on other modules. I have been recently looking at my AzureADPreview which had one dependency for;

– Microsoft365DSC module

If you run the standard uninstall-module -name AzureADPreview you will receive an error stating the module cannot be uninstalled due to the dependency of the other module as shown below;

If you run install-module AzureADPreview you are likely to receive a duplicate install of the same module which will potential cause issues later down the line.

So,

The following function has made this possible.

Function Uninstall-AllModules
{
[CmdletBinding(SupportsShouldProcess)]
param (
[Parameter(Mandatory = $true)]
[string]
$TargetModule,
[Parameter(Mandatory = $false)]
[string]
$Version,
[switch]
$Force
)

$AllModules = @()

‘Creating list of dependencies…’
$target = Find-Module $TargetModule
$target.Dependencies | ForEach-Object {
$AllModules += New-Object -TypeName psobject -Property @{ name = $_.name}
}
$AllModules += New-Object -TypeName psobject -Property @{ name = $TargetModule}

$cnt = 1;
foreach ($module in $AllModules)
{
Write-Host (“[$cnt] – ” + ‘Uninstalling {0} version’ -f $module.name);
$cnt++;
try
{
if ($PSCmdlet.ShouldProcess($module.name, ‘Uninstall’))
{
Uninstall-Module -Name $module.name -Force:$Force -ErrorAction Stop;
};
}
catch
{
Write-Host (“`t” + $_.Exception.Message)
}
}
}

## – Example using -WhatIf parameter:
Uninstall-AllModules -TargetModule AzureAD -Force

Regards,
The Author – Blogabout.Cloud

Using Endpoint Analytics (Preview) | Let’s see if we can Proactive remediate installed PowerShell Modules.

Using Endpoint Analytics (Preview) | Let’s see if we can Proactive remediate installed PowerShell Modules.

If you have followed my blog for some time now you will know how much I bang on about keeping your PowerShell modules up to date. Its been a while since I have looked at Microsoft Endpoint Manager and recently discovered Endpoint Analytics.

Which got me thinking about how I could automatically remediate out of date installed PowerShell modules.

Detection Script

As you can see from below, I have created a PowerShell which allows me to detect PowerShell modules that are not up to date. The detection scripts works on the basis of comparing the install version vs. cloud version available from the PowerShell Gallery. If matching versions are found it will move on to the next module installed until;

1. All PowerShell modules installed are matched to the Cloud Version.
or
2. A module is found where a latest version is available.

I am using an Array to pull Get-InstalledModules into Foreach Loop.

Remediation Script

The remediation script works in the same way as the detection script but if a new module is found. The script will remove the legacy version then install the latest version from the PowerShell Gallery.

So all this sound simple enough, lets put it to work.

So how does this look in Microsoft Endpoint Manager?

Browse to http://endpoint.microsoft.com

Select Reports from the left hand menu and select Endpoint Analytics as shown below.

Select Proactive Remediation

So as you can see already from the screen shot below, I have already create a script package to address my Windows 10 Virtual Machines with out of date PowerShell modules. It has identified 3 machines with issues and this issue has recurred 3 times. Which I would accept as I installed a number of old modules to demonstrate this process.

So how do we create our Script Package simple!! First of all you will need the scripts from my Github https://github.com/TheWatcherNode/Proactive-Remediation then follow this simple video.

Log Checking

All the PowerShell script are executed by the Intune Management Extension

– C:\ProgramData\Microsoft\IntuneManagementExtension\Logs

All scripts executed against the device are stored in the following location;

– C:\Windows\IMECache\HealthScripts

Negative side

As you may have 10s or 100s of modules installed I don’t believe Proactive Remediate is fully geared up my script currently. I need a bit more work to really make fully compliant in how Proactive Remediate works.

https://github.com/TheWatcherNode/blogaboutcloud/blob/master/Get-InstalledModulesUpdate.ps1

Conclusion

I was able to successful remediate my PowerShell modules but not 100% happy how it display back into the Endpoint Portal can see a lot of value in Proactive Remediation and I accept this area to grow when more and more Consultants start writing scripts to detect and remediate issues.

Regards
The Author – Blogabout.Cloud

Bye Bye Skype for Business Connector.

Bye Bye Skype for Business Connector.

As Microsoft starts to contine to wind down Skype for Business Online, there is no longer a need to install the seperate module using the .exe file for the Skype Connector. The module has been in beta release of the Microsoft Teams module which has now been published to general availability (GA).

Update your MicrosoftTeam module to version 1.1.6 and you will find the cmdlet “New-CSOnlineSession” available to use. To make life easier, check out my Get-InstalledModulesUpdate.ps1 from my GitHub. This PS1 file will look at all installed modules on your client machine and update according.

Here is the current versioning information for MicrosoftTeams module.

DateVersionUpdates
September 20201.1.6Skype for Business Online Connector integration
September 20201.1.5-previewSkype for Business Online Connector integration
July 20201.1.4Added group policy assignment cmdlets
June 20201.1.3-previewSkype for Business Online Connector integrationGet-Team optimizationsEnhanced reliability
June 20201.0.7Added Cmdlet preloading.Net Framework optimizations
April 20201.0.6Authenticode and assembly signingAdded Get-CsPolicyPackageAdded Get-CsUserPolicyPackageAdded Get-CsUserPolicyPackageRecommendationAdded Grant-CsUserPolicyPackageAdded New-CsBatchPolicyPackageAssignmentOperationAdded Set-TeamArchivedStateAdded Set-TeamPictureRemoved Get-TeamHelp
March 20201.0.5Added New-CsBatchPolicyAssignmentOperation
Feb 20201.0.4Get-Team optimizations

Regards
The Author – Blogabout.Cloud

When was the last time you updated your PowerShell modules?

When was the last time you updated your PowerShell modules?

So how often do you check for PowerShell updates? My guess would be not at all as its hard to keep up to date to ensure you have the latest and greatest module available.

So as an example I have two module installed on my client device which I have updated for a while.

Check out my Get-InstalledModuleUpdate script available on Github aimed to help in this situation. It puts all the installed module into an array and check for the latest versions available on the PowerShell Galley.

https://github.com/TheWatcherNode/blogaboutcloud/blob/master/Get-InstalledModulesUpdate.ps1

Regards
The Author – Blogabout.Cloud

Changing the Channel on Microsoft Apps for Enterprise using PowerShell

Changing the Channel on Microsoft Apps for Enterprise using PowerShell

Hello,

In this video I demonstrate how to change the Channel on Microsoft Apps for Enterprise using a PowerShell script that I created.

Or you could do this manually using the following commands;


1
2
3
4
5
6
7
8
9
10
11
12
#region Channel Names
  $CurrentPreview = 'CurrentPreview'
  $Current = 'Current'
  $MonthlyEnterprise = 'MonthlyEnterprise'
  $SemiAnnual = 'SemiAnnual'
  $SemiAnnualPreview = 'SemiAnnualPreview'
#endregion

$path = 'HKLM:\Software\Policies\Microsoft\office\16.0\common\officeupdate\'
$updatebranch = 'updatebranch'

Set-ItemProperty -Path $path -Name $updatebranch -Value "Insert Channel Name"

Regards
The Author – Blogabout.Cloud