diff --git a/Find Teams Meetings Attended By a Specific User/GetUserSpecificTeamsMeetingsReport.ps1 b/Find Teams Meetings Attended By a Specific User/GetUserSpecificTeamsMeetingsReport.ps1 new file mode 100644 index 0000000..e104366 --- /dev/null +++ b/Find Teams Meetings Attended By a Specific User/GetUserSpecificTeamsMeetingsReport.ps1 @@ -0,0 +1,239 @@ +<# +============================================================================================= + +Name : Find the Teams Meetings Attended by a Specific User Using PowerShell +Version : 1.0 +website : o365reports.com + +----------------- +Script Highlights +----------------- +1. The script exports user specific Teams meeting report. +2. The script retrieves user specific Teams meeting data for 180 days, by default. +3. Allows you to obtain audit Teams meeting attended by specific user for a custom period. +4. The script can be executed with an MFA enabled account too. +5. It exports audit results to CSV file format in the working directory. +6. Automatically installs the Exchange Online module (if not installed already) upon your confirmation. +7. The script is scheduler friendly. +8. The script supports certificate-based authentication. + +For detailed Script execution: https://o365reports.com/2024/05/22/find-the-teams-meetings-attended-by-a-specific-user-using-powershell/ +============================================================================================ +\#> + +param ( + [Parameter(Mandatory = $false)] + [string]$userUPN, + [Nullable[DateTime]]$StartDate, + [Nullable[DateTime]]$EndDate, + [string]$UserName, + [string]$Password, + [string]$ClientId, + [string]$CertificateThumbprint, + [string]$Organization +) + +Function Connect_Module { + + # Checking availability of Exchange Online module and installing module + $ExchangeModule = Get-Module ExchangeOnlineManagement -ListAvailable + if($ExchangeModule.count -eq 0) + { + Write-Host ExchangeOnline module is not available -ForegroundColor Yellow + $confirm = Read-Host Do you want to Install ExchangeOnline module? [Y] Yes [N] No + if($confirm -match "[Yy]") + { + Write-Host "Installing ExchangeOnline module ..." + Install-Module ExchangeOnlineManagement -Repository PSGallery -AllowClobber -Force -Scope CurrentUser + Import-Module ExchangeOnlineManagement + } + else + { + Write-Host "ExchangeOnline Module is required. To Install ExchangeOnline module use 'Install-Module ExchangeOnlineManagement' cmdlet." + Exit + } + } + + #Connecting to Exchange Online + Write-Host "`nConnecting Exchange Online module ..." -ForegroundColor Yellow + if(($UserName -ne "") -and ($Password -ne "")) { + $SecuredPassword = ConvertTo-SecureString -AsPlainText $Password -Force + $Credential = New-Object System.Management.Automation.PSCredential $UserName,$SecuredPassword + Connect-ExchangeOnline -Credential $Credential + } + elseif($Organization -ne "" -and $ClientId -ne "" -and $CertificateThumbprint -ne "") { + Connect-ExchangeOnline -AppId $ClientId -CertificateThumbprint $CertificateThumbprint -Organization $Organization -ShowBanner:$false + } + else { + Connect-ExchangeOnline + } +} + +#Verify user UPN is present +if($userUPN -eq "") { + Write-Host User Principal Name is Required! -Foregroundcolor Yellow + $userUPN = Read-Host Enter User UPN +} + +$MaxStartDate=((Get-Date).AddDays(-180)).Date + +#Getting Teams meeting attendance report for past 180 days +if(($StartDate -eq $null) -and ($EndDate -eq $null)) { + $EndDate=(Get-Date) #.Date + $StartDate=$MaxStartDate +} + +#Getting start date to generate Teams meetings attendance report +While($true) { + if ($StartDate -eq $null) { + $StartDate = Read-Host Enter start time for report generation '(Eg:MM/DD/YYYY)' + } + Try { + $Date=[DateTime]$StartDate + if($Date -ge $MaxStartDate) { + break + } + else { + Write-Host `nAudit can be retrieved only for past 180 days. Please select a date after $MaxStartDate -ForegroundColor Red + return + } + } + Catch { + Write-Host `nNot a valid date -ForegroundColor Red + } +} + +#Getting end date for teams attendance report +While($true) { + if ($EndDate -eq $null) { + $EndDate = Read-Host Enter End time for report generation '(Eg: MM/DD/YYYY)' + } + Try { + $Date=[DateTime]$EndDate + if($EndDate -lt ($StartDate)) + { + Write-Host End time should be later than start time -ForegroundColor Red + return + } + break + } + Catch { + Write-Host `nNot a valid date -ForegroundColor Red + } +} + +#get file dir +$outputFilePath = $PSScriptRoot +$OutputCSV = "$outputFilePath\TeamsMeetingSpecificUserAttendanceReport_$((Get-Date -format yyyy-MMM-dd-ddd` hh-mm` tt).ToString()).csv" +$IntervalTimeInMinutes = 1440 #$IntervalTimeInMinutes=Read-Host Enter interval time period '(in minutes)' +$CurrentStart = $StartDate +$CurrentEnd = $CurrentStart.AddMinutes($IntervalTimeInMinutes) + +#Check whether CurrentEnd exceeds EndDate +if($CurrentEnd -gt $EndDate) { + $CurrentEnd = $EndDate +} + +if($CurrentStart -eq $CurrentEnd) { + Write-Host Start and end time are same.Please enter different time range -ForegroundColor Red + Exit +} + +Connect_Module + +$CurrentResultCount = 0 +$ResultCount = 0 +Write-Host `nGenerating Teams meeting attendance report from $StartDate to $EndDate... +$ProcessedAuditCount = 0 +$OutputEvents = 0 +$ExportResult = "" +$ExportResults = @() +$RetriveOperation = "MeetingParticipantDetail" +while($true) { + #Getting Teams meeting participants report for the given time range + Search-UnifiedAuditLog -StartDate $CurrentStart -EndDate $CurrentEnd -Operations $RetriveOperation -SessionId s -SessionCommand ReturnLargeSet -ResultSize 5000 | ForEach-Object { + $ResultCount++ + $ProcessedAuditCount++ + Write-Progress -Activity "`n Retrieving Team meeting attended by user : $userUPN ..."`n" Processed audit record count: $ProcessedAuditCount" + $AuditData=$_.AuditData | ConvertFrom-Json + $MeetingID=$AuditData.MeetingDetailId + $CreatedBy=$_.UserIDs + $AttendeesInfo=($AuditData.Attendees) + $AttendeesType=$AttendeesInfo.RecipientType + $Attendees=$AttendeesInfo.DisplayName + $AttendeesUPN=$AttendeesInfo.UPN + $JoinTime=(Get-Date($AuditData.JoinTime)).ToLocalTime() #Get-Date($AuditData.JoinTime) Uncomment to view the Activity Time in UTC + $LeaveTime=(Get-Date($AuditData.LeaveTime)).ToLocalTime() + $Duration = $JoinTime - $LeaveTime + $DurationinSeconds = ($Duration).TotalSeconds + $TimeSpanDuration = [timespan]::fromseconds($DurationinSeconds) + $AttendedDuration = ("{0:hh\:mm\:ss}" -f $TimeSpanDuration) + + if($AttendeesUPN -eq $userUPN) { + #Export result to csv + $OutputEvents++ + $ExportResult=@{'Meeting id'=$MeetingID;'Created By'=$CreatedBy;'Attendee'=$Attendees;'Attendee UPN' = $AttendeesUPN;'Attendee Type'=$AttendeesType;'Joined Time'=$JoinTime;'Left Time'=$LeaveTime;'Duration' = $AttendedDuration} + $ExportResults= New-Object PSObject -Property $ExportResult + $ExportResults | Select-Object 'Meeting id','Created By','Attendee','Attendee UPN','Attendee Type','Joined Time','Left Time','Duration' | Export-Csv -Path $OutputCSV -NoTypeInformation -Append + } + } + + $currentResultCount=$currentResultCount+$ResultCount + + if($CurrentResultCount -ge 50000) { + Write-Host Retrieved max record for current range.Proceeding further may cause data loss or rerun the script with reduced time interval. -ForegroundColor Red + $Confirm=Read-Host `nAre you sure you want to continue? [Y] Yes [N] No + if($Confirm -match "[Y]") { + Write-Host Proceeding audit log collection with data loss + [DateTime]$CurrentStart=$CurrentEnd + [DateTime]$CurrentEnd=$CurrentStart.AddMinutes($IntervalTimeInMinutes) + $CurrentResultCount=0 + if($CurrentEnd -gt $EndDate) { + $CurrentEnd=$EndDate + } + } + else { + Write-Host Please rerun the script with reduced time interval -ForegroundColor Red + Exit + } + } + + if($ResultCount -lt 5000) { + if($CurrentEnd -eq $EndDate) { + break + } + $CurrentStart=$CurrentEnd + if($CurrentStart -gt (Get-Date)) { + break + } + $CurrentEnd=$CurrentStart.AddMinutes($IntervalTimeInMinutes) + $CurrentResultCount=0 + if($CurrentEnd -gt $EndDate) { + $CurrentEnd=$EndDate + } + } + + $ResultCount=0 +} + +#Open output file after execution +if($OutputEvents -eq 0) { + Write-Host No records found +} +else { + Write-Host `nThe Teams meeting attendance report contains $OutputEvents audit records -ForegroundColor Green + if((Test-Path -Path $OutputCSV) -eq "True") { + Write-Host `n "The output file available in: " -NoNewline -ForegroundColor Yellow; Write-Host "$OutputCSV" + Write-Host `n~~ Script prepared by AdminDroid Community ~~`n -ForegroundColor Green + Write-Host "~~ Check out " -NoNewline -ForegroundColor Green; Write-Host "admindroid.com" -ForegroundColor Yellow -NoNewline; + Write-Host " to get access to 1800+ Microsoft 365 reports. ~~" -ForegroundColor Green `n`n + $Prompt = New-Object -ComObject wscript.shell + $UserInput = $Prompt.popup("Do you want to open output file?",0,"Open Output File",4) + If ($UserInput -eq 6) { + Invoke-Item "$OutputCSV" + } + } +} + +#Disconnect Exchange Online session +Disconnect-ExchangeOnline -Confirm:$false -InformationAction Ignore -ErrorAction SilentlyContinue \ No newline at end of file