first load
Some checks failed
Build, Push, Publish / Build & Release (push) Failing after 2s

This commit is contained in:
2025-12-16 04:43:41 -03:00
parent d6c8176c7e
commit fb6ead25ee
12 changed files with 1144 additions and 1 deletions

513
mainscript.ps1 Normal file
View File

@@ -0,0 +1,513 @@
# Set console output encoding to UTF-8 for Latin characters
[console]::OutputEncoding = [System.Text.Encoding]::UTF8
# Specify the output directory for working files, report and other variables
$outputDirectory = (New-Object -ComObject Shell.Application).NameSpace('shell:Downloads').Self.Path
$timestamp = Get-Date -Format "yyyy-MM-dd_HH-mm-ss"
# Read tenant IDs from a text file
$tenantIdsFilePath = ".\tenantIds.txt"
if (-not (Test-Path $tenantIdsFilePath)) {
Write-Host "Tenant IDs file not found. Please create a file named 'tenantIds.txt' with the tenant IDs, one per line."
pause
exit
}
$tenantIds = Get-Content -Path $tenantIdsFilePath
# Prompt the user to select a tenant
Write-Host
Write-Host "Select a Tenant ID to connect:"
for ($i = 0; $i -lt $tenantIds.Count; $i++) {
Write-Host "$($i + 1). $($tenantIds[$i])"
}
$tenantSelection = Read-Host "Enter the number of the Tenant ID you want to connect to"
$selectedTenantId = $tenantIds[$tenantSelection - 1]
# Check if ImportExcel module is installed, if not, ask the user to install it
if (-not (Get-Module -ListAvailable -Name ImportExcel)) {
Write-Host "ImportExcel module is not installed. Please install it using the following command: Install-Module -Name ImportExcel -Force -AllowClobber"
pause
exit
}
# Check if Microsoft Teams module is installed, if not, ask the user to install it
if (-not (Get-Module -ListAvailable -Name MicrosoftTeams)) {
Write-Host "Microsoft Teams module is not installed. Please install it using the following command: Install-Module -Name MicrosoftTeams -Force -AllowClobber"
pause
exit
}
# Check if Microsoft Graph module is installed, if not, ask the user to install it
if (-not (Get-Module -ListAvailable -Name Microsoft.Graph)) {
Write-Host "Microsoft Graph module is not installed. Please install it using the following command: Install-Module -Name Microsoft.Graph -Force -AllowClobber"
pause
exit
}
# Check if Exchange Online module is installed, if not, ask the user to install it
if (-not (Get-Module -ListAvailable -Name ExchangeOnlineManagement)) {
Write-Host "ExchangeOnlineManagement module is not installed. Please install it using the following command: Install-Module -Name ExchangeOnlineManagement -Force -AllowClobber"
pause
exit
}
# Import the required modules
Import-Module Microsoft.Graph.Authentication
Import-Module Microsoft.Graph.Users # Get-MgUser Get-MgUserLicenseDetail
Import-Module Microsoft.Graph.Groups
Import-Module Microsoft.Graph.Teams # Get-MgTeam
Import-Module Microsoft.Graph.Identity.DirectoryManagement # Get-MgDomain
Import-Module MicrosoftTeams # Get-TeamChannel Get-TeamChannelUser
Import-Module ImportExcel # Export-Excel
Import-Module ExchangeOnlineManagement # Get-Mailbox
# Connect to Microsoft Graph
Write-Host
Write-Host "Connecting to Microsoft Graph..."
Connect-MgGraph -TenantId $selectedTenantId -Scopes "User.Read.All Directory.Read.All Group.Read.All Team.ReadBasic.All TeamMember.Read.All ChannelMember.Read.All Domain.Read.All" -NoWelcome
Write-Host
Write-Host "Connected to Microsoft Graph."
# Connect to Microsoft Teams
Write-Host
Write-Host "Connecting to Microsoft Teams..."
Connect-MicrosoftTeams
Write-Host "Connected to Microsoft Teams."
# Connect to Exchange Online
Write-Host
Write-Host "Connecting to Exchange Online..."
Connect-ExchangeOnline -ShowBanner:$false
Write-Host
Write-Host "Connected to Exchange Online."
# Create the output directory if it doesn't exist
if (-not (Test-Path $outputDirectory)) {
New-Item -ItemType Directory -Path $outputDirectory
}
# Export Groups with all columns available
Write-Host
Write-Host "Exporting groups..."
$groups = Get-MgGroup -All
# Export Users with account status and licenses using Graph (temporary)
# Comprehensive license mapping including Visio SKUs
$licenseMap = @{
'a403ebcc-fae0-4ca2-8c8c-7a907fd6c235' = 'Microsoft Fabric (Free)'
'f245ecc8-75af-4f8e-b61f-27d8114de5f3' = 'Microsoft 365 Business Standard'
'3b555118-da6a-4418-894f-7df1e2096870' = 'Microsoft 365 Business Basic'
'f30db892-07e9-47e9-837c-80727f46fd3d' = 'Microsoft Power Automate Free'
'4b9405b0-7788-4568-add1-99614e613b69' = 'Exchange Online (Plan 1)'
'19ec0d23-8335-4cbd-94ac-6050e30712fa' = 'Exchange Online (Plan 2)'
'cdd28e44-67e3-425e-be4c-737fab2899d3' = 'Microsoft 365 Apps for business'
'50509a35-f0bd-4c5e-89ac-22f0e16a00f8' = 'Microsoft Teams Rooms Basic without Audio Conferencing'
'6af4b3d6-14bb-4a2a-960c-6c902aad34f3' = 'Microsoft Teams Rooms Basic'
'e0dfc8b9-9531-4ec8-94b4-9fec23b05fc8' = 'Microsoft Teams Exploratory Dept (unlisted)'
'f8a1db68-be16-40ed-86d5-cb42ce701560' = 'Power BI Pro'
'cbdc14ab-d96c-4c30-b9f4-6ada7cdc1d46' = 'Microsoft 365 Business Premium'
'c1d032e0-5619-4761-9b5c-75b6831e1711' = 'Power BI Premium Per User'
'53818b1b-4a27-454b-8896-0dba576410e6' = 'Planner and Project Plan 3'
'295a8eb0-f78d-45c7-8b5b-1eed5ed02dff' = 'Microsoft Teams Shared Devices'
'c5928f49-12ba-48f7-ada3-0d743a3601d5' = 'Vision Plan 2'
'1f2f344a-700d-42c9-9427-5cea1d5d7ba6' = 'Microsoft Stream Trial'
'52ea0e27-ae73-4983-a08f-13561ebdb823' = 'Teams Premium (for Departments)'
'639dec6b-bb19-468b-871c-c5c441c4b0cb' = 'Microsoft 365 Copilot'
'5b631642-bd26-49fe-bd20-1daaa972ef80' = 'Microsoft Power Apps for Developer'
'beb6439c-caad-48d3-bf46-0c82871e12be' = 'Planner Plan 1'
'3f9f06f5-3c31-472c-985f-62d9c10ec167' = 'Power Pages vTrial for Makers'
}
# Get users and process license information
$usersGraph = Get-MgUser -All -Property `
Id,DisplayName,UserPrincipalName,Mail,AccountEnabled,UserType, `
CreatedDateTime,AssignedLicenses,Department,JobTitle,OfficeLocation, `
UserPrincipalName,ProxyAddresses
$usersGraphReport = $usersGraph | ForEach-Object {
$user = $_
$skuPartNumbers = @()
try {
$licenseDetails = Get-MgUserLicenseDetail -UserId $user.Id
foreach ($license in $licenseDetails) {
$skuPartNumbers += $license.SkuPartNumber
}
} catch {
Write-Warning "Could not get license details for $($user.UserPrincipalName)"
$skuPartNumbers += "Error"
}
[PSCustomObject]@{
Id = $user.Id
DisplayName = $user.DisplayName
UserPrincipalName = $user.UserPrincipalName
Mail = $user.Mail
AccountEnabled = $user.AccountEnabled
UserType = $user.UserType
Licenses = ($user.AssignedLicenses | ForEach-Object {
if ($licenseMap.ContainsKey($_.SkuId)) {
$licenseMap[$_.SkuId]
} else {
$_.SkuId
}
}) -join ", "
LicenseSKUs = ($user.AssignedLicenses.SkuId -join ", ")
SkuPartNumbers = $skuPartNumbers -join ", "
CreatedDateTime = $user.CreatedDateTime
Department = $user.Department
JobTitle = $user.JobTitle
OfficeLocation = $user.OfficeLocation
}
}
$usersGraphReport | Export-Csv -Path "$outputDirectory\UsersGraph.csv" -NoTypeInformation -Encoding UTF8
# Export Shared Mailboxes
Write-Host
Write-Host "Exporting Shared Mailboxes..."
$sharedMailboxes = Get-Mailbox -RecipientTypeDetails SharedMailbox -ResultSize Unlimited | Select-Object DisplayName,PrimarySmtpAddress,ExternalDirectoryObjectId
$sharedMailboxes | Export-Csv -Path "$outputDirectory\SharedMailboxes.csv" -NoTypeInformation -Encoding UTF8
Write-Host "Shared Mailboxes exported to $outputDirectory\SharedMailboxes.csv."
# Get all Teams
$teams = Get-MgTeam -All
# Export Teams using original file name
$teams | Select-Object Id, DisplayName, Description, Visibility | `
Export-Csv -Path "$outputDirectory\Teams.csv" -NoTypeInformation -Encoding UTF8 -Force
Write-Host "Teams exported to $outputDirectory\Teams.csv."
# Export Teams Channels and Memberships
Write-Host
Write-Host "Exporting Teams channels and memberships..."
$teamsChannels = @()
# Loop through Teams
foreach ($team in $teams) {
# Check if Team Id is null or empty
if ([string]::IsNullOrEmpty($team.Id)) {
Write-Host "Skipping team '$($team.DisplayName)' because Id is null or empty."
continue
}
# Get channels for the team
try {
$channels = Get-TeamChannel -GroupId $team.Id
} catch {
Write-Warning "Could not get channels for team $($team.DisplayName): $_"
continue
}
foreach ($channel in $channels) {
$channelMembers = @()
$membershipNote = ""
if ($channel.MembershipType -eq "shared") {
$membershipNote = "Shared channel membership not accessible via Teams module"
Write-Warning "Skipping members of shared channel '$($channel.DisplayName)' in team '$($team.DisplayName)'"
} else {
try {
$channelMembers = Get-TeamChannelUser -GroupId $team.Id -DisplayName $channel.DisplayName
} catch {
$membershipNote = "Error retrieving users: $_"
Write-Warning "Could not get users for channel $($channel.DisplayName) in team $($team.DisplayName): $_"
}
}
if (-not $channelMembers -or $channelMembers.Count -eq 0) {
$teamsChannels += [PSCustomObject]@{
TeamName = $team.DisplayName
TeamId = $team.Id
ChannelName = $channel.DisplayName
ChannelId = $channel.Id
MembershipType = $channel.MembershipType
UserName = ""
Role = ""
Notes = $membershipNote
}
} else {
foreach ($member in $channelMembers) {
$teamsChannels += [PSCustomObject]@{
TeamName = $team.DisplayName
TeamId = $team.Id
ChannelName = $channel.DisplayName
ChannelId = $channel.Id
MembershipType = $channel.MembershipType
UserName = $member.User
Role = $member.Role
Notes = ""
}
}
}
}
}
$teamsChannels | Export-Csv -Path "$outputDirectory\TeamsChannels.csv" -NoTypeInformation -Encoding UTF8 -Force
Write-Host "Teams channels and memberships exported to $outputDirectory\TeamsChannels.csv."
# Wait
Start-Sleep -Seconds 2
# Export Domains
Write-Host
Write-Host "Exporting domains..."
$domains = Get-MgDomain
$domains | Export-Csv -Path "$outputDirectory\Domains.csv" -NoTypeInformation -Encoding UTF8
Write-Host "Domains exported to $outputDirectory\Domains.csv."
# Convert Teams and Groups data to arrays for easier comparison
$teamsArray = $teams | ForEach-Object {
[PSCustomObject]@{
GroupId = $_.GroupId
}
}
$groupsArray = $groups | ForEach-Object {
$aliases = (Get-MgGroup -GroupId $_.Id).ProxyAddresses -join ", "
[PSCustomObject]@{
ObjectId = $_.Id
DisplayName = $_.DisplayName
MailEnabled = $_.MailEnabled
Mail = $_.Mail
SecurityEnabled = $_.SecurityEnabled
SharePointGroup = if ($teamsArray.GroupId -contains $_.Id -or $aliases -match "SPO:") { "Yes" } else { "No" }
Aliases = $aliases
}
}
$groupsArray | Export-Csv -Path "$outputDirectory\Groups.csv" -NoTypeInformation -Encoding UTF8
Write-Host "Groups exported to $outputDirectory\Groups.csv."
# Export Group Memberships to separate CSV files based on SharePoint group status
Write-Host
Write-Host "Exporting group memberships..."
$sharePointMembershipsCsvPath = "$outputDirectory\SharePointMemberships.csv"
$dlMembershipsCsvPath = "$outputDirectory\DLMemberships.csv"
$sharePointMemberships = @()
$dlMemberships = @()
foreach ($group in $groupsArray) {
$owners = Get-MgGroupOwner -GroupId $group.ObjectId
$members = Get-MgGroupMember -GroupId $group.ObjectId
foreach ($owner in $owners) {
$userInfo = $usersGraph | Where-Object { $_.Id -eq $owner.Id }
$membership = [PSCustomObject]@{
GroupName = $group.DisplayName
GroupObjectId = $group.ObjectId
ObjectId = $owner.Id
DisplayName = $userInfo.DisplayName
UserPrincipalName= $userInfo.UserPrincipalName
MembershipStatus = "Owner"
}
if ($group.SharePointGroup -eq "Yes") {
$sharePointMemberships += $membership
} else {
$dlMemberships += $membership
}
}
foreach ($member in $members) {
$userInfo = $usersGraph | Where-Object { $_.Id -eq $member.Id }
$membership = [PSCustomObject]@{
GroupName = $group.DisplayName
GroupObjectId = $group.ObjectId
ObjectId = $member.Id
DisplayName = $userInfo.DisplayName
UserPrincipalName= $userInfo.UserPrincipalName
MembershipStatus = "Member"
}
if ($group.SharePointGroup -eq "Yes") {
$sharePointMemberships += $membership
} else {
$dlMemberships += $membership
}
}
}
$sharePointMemberships | Export-Csv -Path $sharePointMembershipsCsvPath -NoTypeInformation -Encoding UTF8
Write-Host "SharePoint memberships exported to $sharePointMembershipsCsvPath."
$dlMemberships | Export-Csv -Path $dlMembershipsCsvPath -NoTypeInformation -Encoding UTF8
Write-Host "DL memberships exported to $dlMembershipsCsvPath."
# Get all distribution groups
$groups = Get-DistributionGroup -ResultSize Unlimited
# Prepare an array to store results
$dlOwnersCsvPath = "$outputDirectory\DLOwners.csv"
$dlOwners = @()
foreach ($group in $groups) {
foreach ($owner in $group.ManagedBy) {
$ownerRecipient = Get-Recipient -Identity $owner -ErrorAction SilentlyContinue
# Defensive: Only output if we get a valid recipient
if ($ownerRecipient) {
$dlOwners += [PSCustomObject]@{
GroupDisplayName = $group.DisplayName
GroupPrimarySmtp = $group.PrimarySmtpAddress
OwnerDisplayName = $ownerRecipient.DisplayName
OwnerEmail = $ownerRecipient.PrimarySmtpAddress
}
}
}
}
# Export to CSV
$dlOwners | Export-Csv -Path $dlOwnersCsvPath -NoTypeInformation -Encoding UTF8
Write-Host "Distribution list owners exported to $outputDirectory\DLOwners.csv."
# Disconnect from Microsoft Teams (if connected)
try {
Disconnect-MicrosoftTeams -ErrorAction SilentlyContinue
Write-Host "Disconnected from Microsoft Teams." -ForegroundColor Green
} catch {
Write-Host "No active Teams session to disconnect." -ForegroundColor Yellow
}
# Disconnect from Microsoft Graph (if connected)
try {
Disconnect-MgGraph -ErrorAction SilentlyContinue
Write-Host "Disconnected from Microsoft Graph." -ForegroundColor Green
} catch {
Write-Host "No active Graph session to disconnect." -ForegroundColor Yellow
}
# Disconnect from Exchange Online (if connected)
try {
Disconnect-ExchangeOnline -Confirm:$false -ErrorAction SilentlyContinue
Write-Host "Disconnected from Exchange Online." -ForegroundColor Green
} catch {
Write-Host "No active Exchange Online session to disconnect." -ForegroundColor Yellow
}
# Consolidate all CSVs into an Excel file with each CSV in a separate sheet
Write-Host
Write-Host "Consolidating CSVs into an Excel file..."
$excelFilePath = "$outputDirectory\$selectedTenantId-report_$timestamp.xlsx"
$excelSheets = @(
@{Name="Users"; Path="$outputDirectory\UsersGraph.csv"},
@{Name="SharedMailboxes"; Path="$outputDirectory\SharedMailboxes.csv"},
@{Name="Groups"; Path="$outputDirectory\Groups.csv"},
@{Name="SharePointMemberships"; Path="$sharePointMembershipsCsvPath"},
@{Name="DLMemberships"; Path="$dlMembershipsCsvPath"},
@{Name="DLOwners"; Path="$dlOwnersCsvPath"},
@{Name="Teams"; Path="$outputDirectory\Teams.csv"},
@{Name="TeamsChannels"; Path="$outputDirectory\TeamsChannels.csv"},
@{Name="Domains"; Path="$outputDirectory\Domains.csv"}
)
foreach ($sheet in $excelSheets) {
Import-Csv -Path $sheet.Path | Export-Excel -Path $excelFilePath -WorksheetName $sheet.Name -AutoSize -TableName $sheet.Name -TableStyle Light1
}
Write-Host "CSV consolidation complete. Excel file saved to $excelFilePath."
# Wait
Start-Sleep -Seconds 2
# Delete the CSV files after consolidation
foreach ($sheet in $excelSheets) {
Remove-Item -Path $sheet.Path -Force
Write-Host "Deleted $($sheet.Path)"
}
# Clear the prompt
Clear-Host
# Clear the prompt
cls
# Calculate MD5 hash of the Excel file
Write-Host "Calculating MD5 hash of the Excel file..."
Write-Host "File name: $selectedTenantId-report_$timestamp.xlsx"
$md5Hash = Get-FileHash -Path $excelFilePath -Algorithm MD5 | Select-Object -ExpandProperty Hash
Write-Host "MD5 hash of the Excel file: $md5Hash"
Write-Host
# Wait to print info on screen for print screen
Start-Sleep -Seconds 2
# Print screen program
Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName System.Drawing
# Send alt + printscreen to capture the active window
[System.Windows.Forms.SendKeys]::SendWait("%{PRTSC}")
Start-Sleep -Milliseconds 500 # Give clipboard time to update
# Try to get image from clipboard
$image = [System.Windows.Forms.Clipboard]::GetImage()
if ($image -ne $null) {
$bitmap = New-Object System.Drawing.Bitmap $image
$screenshotPath = "$outputDirectory\screenshot_$timestamp.png"
$bitmap.Save($screenshotPath)
Write-Host "Screenshot saved to $screenshotPath"
} else {
Write-Host "No image found in clipboard. Screenshot not saved."
$screenshotPath = $null
}
Write-Host
Start-Sleep -Seconds 2
# Archive the Excel file, the script itself, and the screenshot in a zip file
Write-Host "Archiving the Excel file, the script itself, and the screenshot in a zip file..."
$zipFilePath = "$outputDirectory\$selectedTenantId-report_$timestamp.zip"
$scriptPath = $MyInvocation.MyCommand.Path
Write-Host "$zipFilePath"
Write-Host "$scriptPath"
Write-Host "$excelFilePath"
Write-Host
Start-Sleep -Seconds 2
# Prepare list of files to archive
$filesToArchive = @($excelFilePath, $scriptPath)
if ($screenshotPath) {
$filesToArchive += $screenshotPath
}
Compress-Archive -Path $filesToArchive -DestinationPath $zipFilePath
Write-Host "Files archived to $zipFilePath"
Start-Sleep -Seconds 2
# Delete the Excel file and the screenshot if it exists
Remove-Item -Path $excelFilePath -Force
if ($screenshotPath) {
Remove-Item -Path $screenshotPath -Force
}
Write-Host "Deleted $selectedTenantId-report_$timestamp.xlsx and screenshot (if created)"
Start-Sleep -Seconds 2
# Pause at the end
pause