Use PnP PowerShell to Remove members in bulk using a CSV file.
#Connect PnP with same email as $SiteCollAdmin
# Define the log file path
$logFilePath = "Remove-logfile.log"
# Function to log messages
function Log-Message {
param (
[string]$Message
)
$timestamp = Get-Date -Format "yyyy-MM-dd HH:mm"
$logMessage = "$timestamp - $Message"
$logMessage | Add-Content -Path $logFilePath
}
# Define the function to process and add members to the site
function Remove-SiteMembers {
param (
[string]$SiteUrl,
[string]$Members
)
try {
# Connect to the SharePoint Online site
Connect-PnPOnline -Url $SiteUrl -Interactive -ClientId xxxxx-xxxxxx......
Log-Message "Connected to site: $SiteUrl"
# Get site details and check if it's a Teams site (Microsoft 365 Group)
$site = Get-PnPSite -Includes GroupId
if ($site.GroupId -ne [Guid]::Empty) {
# If GroupId is not empty, it's a Teams site
Log-Message "Site $SiteUrl is a Teams site (Microsoft 365 Group)"
# Split the members by semicolon
$memberList = $Members -split ";"
# Loop through each member and add them to the Microsoft 365 Group
foreach ($userEmail in $memberList) {
$userEmail = $userEmail.Trim() # Ensure no extra spaces around the emails
try {
Remove-PnPMicrosoft365GroupMember -Identity $site.GroupId -User $userEmail -ErrorAction Stop
Log-Message "Removed $userEmail to Microsoft 365 Group for site $SiteUrl"
}
catch {
Log-Message "Failed to remove $userEmail to Microsoft 365 Group for site $SiteUrl. Error: $_"
Write-Warning "Failed to remove $userEmail to Microsoft 365 Group for site $SiteUrl"
}
}
} else {
# If it's a regular SharePoint site
Log-Message "Site $SiteUrl is a regular SharePoint site"
# Get the associated member group
$membersGroup = Get-PnPGroup -AssociatedMemberGroup
# Split the members by semicolon
$memberList = $Members -split ";"
# Loop through each member and add them to the SharePoint group
foreach ($userEmail in $memberList) {
$userEmail = $userEmail.Trim() # Ensure no extra spaces around the emails
try {
Remove-PnPGroupMember -LoginName $userEmail -Group $membersGroup.Id -ErrorAction Stop
Log-Message "Removed $userEmail to SharePoint group $($membersGroup.Title) on site $SiteUrl"
}
catch {
Log-Message "Failed to remove $userEmail to SharePoint group $($membersGroup.Title) on site $SiteUrl. Error: $_"
Write-Warning "Failed to remove $userEmail to SharePoint group $($membersGroup.Title) on site $SiteUrl"
}
}
}
}
catch {
Log-Message "Failed to remove members to site: $SiteUrl. Error: $_"
Write-Warning "Failed to remove members to site: $SiteUrl"
}
}
# Path to your CSV file
$csvPath = "Sites.csv"
# Import the CSV file and store it as an array of sites
$sites = Import-Csv -Path $csvPath
# Total number of sites
$totalSites = $sites.Count
# Initialize a counter for processed sites
$processedCount = 0
# Loop through each site URL in the CSV file and process the members
for ($i = 0; $i -lt $totalSites; $i++) {
$site = $sites[$i]
$SiteUrl = $site.URL
$Members = $site.Members
# Print progress update
$processedCount = $i + 1
$percentComplete = [math]::Round(($processedCount / $totalSites) * 100, 2)
Write-Host "Processing site $processedCount of $totalSites ($percentComplete% complete): $SiteUrl"
Log-Message "Processing site $processedCount of $totalSites ($percentComplete% complete): $SiteUrl"
# Define the site collection admin (for example purposes, replace as needed)
$SiteCollAdmin = "admin email"
try {
# Set the site collection admin
Set-PnPTenantSite -Url $SiteUrl -Owners $SiteCollAdmin -ErrorAction Stop
Log-Message "Set site collection admin for site: $SiteUrl"
# Call the Remove-SiteMembers function to add members
Remove-SiteMembers -SiteUrl $SiteUrl -Members $Members
# Remove the site collection admin
Remove-PnPSiteCollectionAdmin -Owners $SiteCollAdmin
Log-Message "Removed site collection admin for site: $SiteUrl"
}
catch {
Log-Message "Failed to set or remove admin for site: $SiteUrl. Error: $_"
Write-Warning "Failed to set or remove admin for site: $SiteUrl"
}
# Optionally add a short delay between iterations (to avoid throttling)
Start-Sleep -Seconds 1
}
# Final message after all sites are processed
Write-Host "Completed processing $processedCount out of $totalSites sites."
Log-Message "Completed processing $processedCount out of $totalSites sites."