I have created an Azure function under consumption plan, that uses PowerShell, then inside the run.ps1, i added this code, to remove a user from all the groups assigned to the user:-
param($Timer)
Import-Module ExchangeOnlineManagement
Import-Module Microsoft.Graph
# Connect to Microsoft Graph with required delegated scopes
Write-Host "Start"
Connect-MgGraph -Scopes "User.Read.All", "Group.Read.All", "GroupMember.ReadWrite.All", "Directory.Read.All", "Group.ReadWrite.All" -Identity
Write-Host "Connect to Graph"
# Connect to Exchange Online
Connect-ExchangeOnline -Identity
# Target user email
$userEmail = "test@***.onmicrosoft.com"
# --- PART 1: Azure AD + Office 365 Groups ---
$userList = Get-MgUser -Filter "mail eq '$userEmail' or userPrincipalName eq '$userEmail'" -ConsistencyLevel eventual -All -Property Id, DisplayName, UserPrincipalName, Mail
$userObj = $userList | Select-Object -First 1
if (-not $userObj) {
Write-Host "User $userEmail not found in Microsoft Graph. Skipping AAD removal."
} elseif (-not $userObj.Id) {
Write-Host "User objectId missing even after lookup. Skipping AAD removal."
} else {
Write-Host "Found user: $($userObj.DisplayName) ($($userObj.UserPrincipalName))"
$groups = Get-MgUserMemberOf -UserId $userObj.Id -All
$groupsAsOwner = Get-MgUserOwnedObject -UserId $userObj.Id -All
foreach ($group in $groups) {
if ($group.AdditionalProperties.'@odata.type' -ne '#microsoft.graph.group') {
continue
}
$groupId = $group.Id
$groupName = $group.AdditionalProperties.DisplayName
if (-not $groupId) {
Write-Host "Skipping group with empty ID"
continue
}
$fullGroup = Get-MgGroup -GroupId $groupId
if ($fullGroup.GroupTypes -contains "DynamicMembership") {
Write-Host "Skipping dynamic group: ${groupName}"
continue
}
# Remove as MEMBER
try {
Remove-MgGroupMemberByRef -GroupId $groupId -DirectoryObjectId $userObj.Id -ErrorAction Stop
Write-Host "Removed as MEMBER from ${groupName}"
}
catch {
Write-Host "Failed MEMBER removal from ${groupName}: $($_.Exception.Message)"
}}
foreach ($group2 in $groupsAsOwner) {
$groupId2 = $group2.Id
$groupName2 = $group2.AdditionalProperties.DisplayName
# Remove as OWNER
try {
Remove-MgGroupOwnerByRef -GroupId $groupId2 -DirectoryObjectId $userObj.Id -ErrorAction Stop
Write-Host "Removed as OWNER from ${groupName2}"
}
catch {
Write-Host "Failed OWNER removal from ${groupName2}: $($_.Exception.Message)"
}
}
}
# --- PART 2: Exchange Distribution Groups + Mail-enabled Security Groups ---
$dlGroups = Get-DistributionGroup -ResultSize Unlimited
foreach ($dl in $dlGroups) {
try {
# Remove as MEMBER
$members = Get-DistributionGroupMember -Identity $dl.Identity -ResultSize Unlimited
$memberMatch = $members | Where-Object { $_.PrimarySmtpAddress -ieq $userEmail }
if ($memberMatch) {
Remove-DistributionGroupMember -Identity $dl.Identity -Member $userEmail -BypassSecurityGroupManagerCheck -Confirm:$false
Write-Host "Removed as MEMBER from Exchange group: $($dl.DisplayName)"
}
# Remove as OWNER
# $owners = (Get-DistributionGroup -Identity $dl.Identity).ManagedBy
$owners = (Get-DistributionGroup -Identity $dl.Identity).ManagedBy | Foreach-Object { Get-Mailbox $_ }
$ownerMatch = $owners | Where-Object { $_.PrimarySmtpAddress -ieq $userEmail }
if ($ownerMatch) {
Set-DistributionGroup -Identity $dl.Identity -ManagedBy @{ Remove = "$userEmail" }
Write-Host "Removed as OWNER from Exchange group: $($dl.DisplayName)"
}
}
catch {
Write-Host "Failed Exchange removal for group: $($dl.DisplayName) - $($_.Exception.Message)"
}
}
Write-Host "Cleanup script completed."
and we have the following inside the function.json
:-
{
"bindings": [
{
"name": "Timer",
"type": "timerTrigger",
"direction": "in",
"schedule": "0 */5 * * * *"
}
]
}
and the following inside the requirments.psd1
to load the external libraries:-
@{
'ExchangeOnlineManagement' = '3.*'
'Microsoft.Graph' = '2.*'
}
as follow:-

but when i run the script, i got those errors:-
2025-05-08T22:03:06Z [Error] ERROR: The term 'Disable-AzContextAutosave' is not recognized as a name of a cmdlet, function, script file, or executable program.
Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
Exception :
Type : System.Management.Automation.CommandNotFoundException
ErrorRecord :
Exception :
Type : System.Management.Automation.ParentContainsErrorRecordException
Message : The term 'Disable-AzContextAutosave' is not recognized as a name of a cmdlet, function, script file, or executable program.
Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
HResult : -2146233087
TargetObject : Disable-AzContextAutosave
CategoryInfo : ObjectNotFound: (Disable-AzContextAutosave:String) [], ParentContainsErrorRecordException
FullyQualifiedErrorId : CommandNotFoundException
InvocationInfo :
ScriptStackTrace : at <ScriptBlock>, C:\home\site\wwwroot\profile.ps1: line 15
CommandName : Disable-AzContextAutosave
TargetSite :
Name : LookupCommandInfo
DeclaringType : [System.Management.Automation.CommandDiscovery]
MemberType : Method
Module : System.Management.Automation.dll
Message : The term 'Disable-AzContextAutosave' is not recognized as a name of a cmdlet, function, script file, or executable program.
Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
Data : System.Collections.ListDictionaryInternal
Source : System.Management.Automation
HResult : -2146233087
StackTrace :
TargetObject : Disable-AzContextAutosave
CategoryInfo : ObjectNotFound: (Disable-AzContextAutosave:String) [], CommandNotFoundException
FullyQualifiedErrorId : CommandNotFoundException
ScriptName : C:\home\site\wwwroot\profile.ps1
Line : Disable-AzContextAutosave -Scope Process | Out-Null
Statement : Disable-AzContextAutosave
ScriptStackTrace : at <ScriptBlock>, C:\home\site\wwwroot\profile.ps1: line 15
2025-05-08T22:03:06Z [Error] ERROR: The term 'Connect-AzAccount' is not recognized as a name of a cmdlet, function, script file, or executable program.
Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
System.Management.Automation.CommandNotFoundExceptionSystem.Management.Automation.ParentContainsErrorRecordException
Message : The term 'Connect-AzAccount' is not recognized as a name of a cmdlet, function, script file, or executable program.
Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
HResult : -2146233087
TargetObject : Connect-AzAccount
CategoryInfo : ObjectNotFound: (Connect-AzAccount:String) [], ParentContainsErrorRecordException
FullyQualifiedErrorId : CommandNotFoundException
InvocationInfo :
ScriptStackTrace : at <ScriptBlock>, C:\home\site\wwwroot\profile.ps1: line 16
CommandName : Connect-AzAccount
TargetSite :
Name : LookupCommandInfo
DeclaringType : [System.Management.Automation.CommandDiscovery]
MemberType : Method
Module : System.Management.Automation.dll
Message : The term 'Connect-AzAccount' is not recognized as a name of a cmdlet, function, script file, or executable program.
Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
Data : System.Collections.ListDictionaryInternal
Source : System.Management.Automation
HResult : -2146233087
StackTrace :
TargetObject : Connect-AzAccount
CategoryInfo : ObjectNotFound: (Connect-AzAccount:String) [], CommandNotFoundException
FullyQualifiedErrorId : CommandNotFoundException
InvocationInfo :
PositionMessage : At C:\home\site\wwwroot\profile.ps1:16 char:5
+ Connect-AzAccount -Identity
+ ~~~~~~~~~~~~~~~~~
2025-05-08T22:03:06Z [Error] Errors reported while executing profile.ps1. See logs for detailed errors. Profile location: C:\home\site\wwwroot\profile.ps1.
2025-05-08T22:03:07Z [Error] ERROR: The specified module 'ExchangeOnlineManagement' was not loaded because no valid module file was found in any module directory.
Exception :
Type : System.IO.FileNotFoundException
Message : The specified module 'ExchangeOnlineManagement' was not loaded because no valid module file was found in any module directory.
HResult : -2147024894
TargetObject : ExchangeOnlineManagement
CategoryInfo : ResourceUnavailable: (ExchangeOnlineManagement:String) [Import-Module], FileNotFoundException
FullyQualifiedErrorId : Modules_ModuleNotFound,Microsoft.PowerShell.Commands.ImportModuleCommand
InvocationInfo :
MyCommand : Import-Module
ScriptStackTrace : at <ScriptBlock>, C:\home\site\wwwroot\TimerTrigger1\run.ps1: line 2
PipelineIterationInfo :
2025-05-08T22:03:07Z [Error] ERROR: The specified module 'Microsoft.Graph' was not loaded because no valid module file was found in any module directory.
Exception :
Type : System.IO.FileNotFoundException
Message : The specified module 'Microsoft.Graph' was not loaded because no valid module file was found in any module directory.
HResult : -2147024894
TargetObject : Microsoft.Graph
CategoryInfo : ResourceUnavailable: (Microsoft.Graph:String) [Import-Module], FileNotFoundException
FullyQualifiedErrorId : Modules_ModuleNotFound,Microsoft.PowerShell.Commands.ImportModuleCommand
InvocationInfo :
ScriptStackTrace : at <ScriptBlock>, C:\home\site\wwwroot\TimerTrigger1\run.ps1: line 3
PipelineIterationInfo :
2025-05-08T22:03:07Z [Error] ERROR: The term 'Connect-MgGraph' is not recognized as a name of a cmdlet, function, script file, or executable program.
Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
System.Management.Automation.CommandNotFoundException
System.Management.Automation.ParentContainsErrorRecordException
Message : The term 'Connect-MgGraph' is not recognized as a name of a cmdlet, function, script file, or executable program.
Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
HResult : -2146233087
TargetObject : Connect-MgGraph
CategoryInfo : ObjectNotFound: (Connect-MgGraph:String) [], ParentContainsErrorRecordException
FullyQualifiedErrorId : CommandNotFoundException
InvocationInfo :
ScriptStackTrace : at <ScriptBlock>, C:\home\site\wwwroot\TimerTrigger1\run.ps1: line 6
CommandName : Connect-MgGraph
TargetSite :
Name : LookupCommandInfo
DeclaringType : [System.Management.Automation.CommandDiscovery]
MemberType : Method
Module : System.Management.Automation.dll
Message : The term 'Connect-MgGraph' is not recognized as a name of a cmdlet, function, script file, or executable program.
Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
Data : System.Collections.ListDictionaryInternal
Source : System.Management.Automation
HResult : -2146233087
TargetObject : Connect-MgGraph
CategoryInfo : ObjectNotFound: (Connect-MgGraph:String) [], CommandNotFoundException
FullyQualifiedErrorId : CommandNotFoundException
InvocationInfo :
ScriptStackTrace : at <ScriptBlock>, C:\home\site\wwwroot\TimerTrigger1\run.ps1: line 6
2025-05-08T22:03:07Z [Error] ERROR: The term 'Connect-ExchangeOnline' is not recognized as a name of a cmdlet, function, script file, or executable program.
Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
Exception :
Type : System.Management.Automation.CommandNotFoundException
ErrorRecord :
Exception :
Type : System.Management.Automation.ParentContainsErrorRecordException
Message : The term 'Connect-ExchangeOnline' is not recognized as a name of a cmdlet, function, script file, or executable program.
Check the spelling of the name, or if a path was included, verify that the path is correct and try again.C:\home\site\wwwroot\TimerTrigger1\run.ps1: line 9
CommandName : Connect-ExchangeOnline
TargetSite :
Name : LookupCommandInfo
DeclaringType : [System.Management.Automation.CommandDiscovery]
MemberType : Method
Module : System.Management.Automation.dll
Message : The term 'Connect-ExchangeOnline' is not recognized as a name of a cmdlet, function, script file, or executable program.
Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
Data : System.Collections.ListDictionaryInternal
Source : System.Management.Automation
HResult : -2146233087
TargetObject : Connect-ExchangeOnline
CategoryInfo : ObjectNotFound: (Connect-ExchangeOnline:String) [], CommandNotFoundException
FullyQualifiedErrorId : CommandNotFoundExceptionC:\home\site\wwwroot\TimerTrigger1\run.ps1
Line : Connect-ExchangeOnline -Identity
Statement : Connect-ExchangeOnline
PositionMessage : At C:\home\site\wwwroot\TimerTrigger1\run.ps1:9 char:1
+ Connect-ExchangeOnline -Identity
+ ~~~~~~~~~~~~~~~~~~~~~~
PSScriptRoot : C:\home\site\wwwroot\TimerTrigger1
PSCommandPath : C:\home\site\wwwroot\TimerTrigger1\run.ps1
InvocationName : Connect-ExchangeOnline
CommandOrigin : Internal
ScriptStackTrace : at <ScriptBlock>, C:\home\site\wwwroot\TimerTrigger1\run.ps1: line 9
2025-05-08T22:03:07Z [Error] ERROR: The term 'Get-MgUser' is not recognized as a name of a cmdlet, function, script file, or executable program.
Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
Exception :
Type : System.Management.Automation.CommandNotFoundException
ErrorRecord :
Exception :
Type : System.Management.Automation.ParentContainsErrorRecordException
Message : The term 'Get-MgUser' is not recognized as a name of a cmdlet, function, script file, or executable program.
Message : The term 'Get-MgUser' is not recognized as a name of a cmdlet, function, script file, or executable program.
Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
Data : System.Collections.ListDictionaryInternal
Source : System.Management.Automation
HResult : -2146233087
TargetObject : Get-MgUser
CategoryInfo : ObjectNotFound: (Get-MgUser:String) [], CommandNotFoundException
FullyQualifiedErrorId : CommandNotFoundExceptionC:\home\site\wwwroot\TimerTrigger1\run.ps1
Line : $userList = Get-MgUser -Filter "mail eq '$userEmail' or userPrincipalName eq '$userEmail'" -ConsistencyLevel eventual -All -Property Id, DisplayName, UserPrincipalName, Mail
Statement : Get-MgUser
PositionMessage : At
2025-05-08T22:03:07Z [Error] ERROR: The term 'Get-DistributionGroup' is not recognized as a name of a cmdlet, function, script file, or executable program.
HResult : -2146233087
TargetObject : Get-DistributionGroup
CategoryInfo : ObjectNotFound: (Get-DistributionGroup:String) [], ParentContainsErrorRecordException
FullyQualifiedErrorId : CommandNotFoundException
C:\home\site\wwwroot\TimerTrigger1\run.ps1
Line : $dlGroups = Get-DistributionGroup -ResultSize Unlimited
Statement : Get-DistributionGroup
PositionMessage : At C:\home\site\wwwroot\TimerTrigger1\run.ps1:73 char:13
+ $dlGroups = Get-DistributionGroup -ResultSize Unlimited
+ ~~~~~~~~~~~~~~~~~~~~~
PSScriptRoot : C:\home\site\wwwroot\TimerTrigger1
PSCommandPath : C:\home\site\wwwroot\TimerTrigger1\run.ps1
InvocationName : Get-DistributionGroup
CommandOrigin : Internal
ScriptStackTrace : at <ScriptBlock>, C:\home\site\wwwroot\TimerTrigger1\run.ps1: line 73
CommandName : Get-DistributionGroup
TargetSite :
Name : LookupCommandInfo
DeclaringType : [System.Management.Automation.CommandDiscovery]
MemberType : Method
Module : System.Management.Automation.dll
Message : The term 'Get-DistributionGroup' is not recognized as a name of a cmdlet, function, script file, or executable program.
Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
Data : System.Collections.ListDictionaryInternal
Source : System.Management.Automation
HResult : -2146233087
TargetObject : Get-DistributionGroup
CategoryInfo : ObjectNotFound: (Get-DistributionGroup:String) [], CommandNotFoundException
FullyQualifiedErrorId : CommandNotFoundException
C:\home\site\wwwroot\TimerTrigger1\run.ps1
Line : $dlGroups = Get-DistributionGroup -ResultSize Unlimited
Statement : Get-DistributionGroup
PositionMessage : At C:\home\site\wwwroot\TimerTrigger1\run.ps1:73 char:13
+ $dlGroups = Get-DistributionGroup -ResultSize Unlimited
2025-05-08T22:03:08Z [Error] ERROR: The specified module 'ExchangeOnlineManagement' was not loaded because no valid module file was found in any module directory.
Exception :
Type : System.IO.FileNotFoundException
Message : The specified module 'ExchangeOnlineManagement' was not loaded because no valid module file was found in any module directory.
HResult : -2147024894
TargetObject : ExchangeOnlineManagement
CategoryInfo : ResourceUnavailable: (ExchangeOnlineManagement:String) [Import-Module], FileNotFoundException
FullyQualifiedErrorId : Modules_ModuleNotFound,Microsoft.PowerShell.Commands.ImportModuleCommand
InvocationInfo :
ScriptStackTrace : at <ScriptBlock>, C:\home\site\wwwroot\TimerTrigger1\run.ps1: line 2
PipelineIterationInfo :
2025-05-08T22:03:08Z [Error] ERROR: The specified module 'Microsoft.Graph' was not loaded because no valid module file was found in any module directory.
Exception :
Type : System.IO.FileNotFoundException
Message : The specified module 'Microsoft.Graph' was not loaded because no valid module file was found in any module directory.
HResult : -2147024894
TargetObject : Microsoft.Graph
CategoryInfo : ResourceUnavailable: (Microsoft.Graph:String) [Import-Module], FileNotFoundException
FullyQualifiedErrorId : Modules_ModuleNotFound,Microsoft.PowerShell.Commands.ImportModuleCommand
InvocationInfo :
ScriptStackTrace : at <ScriptBlock>, C:\home\site\wwwroot\TimerTrigger1\run.ps1: line 3
PipelineIterationInfo :
2025-05-08T22:03:08Z [Error] ERROR: The term 'Connect-MgGraph' is not recognized as a name of a cmdlet, function, script file, or executable program.
HResult : -2146233087
TargetObject : Connect-MgGraph
CategoryInfo : ObjectNotFound: (Connect-MgGraph:String) [], ParentContainsErrorRecordException
FullyQualifiedErrorId : CommandNotFoundException
ScriptStackTrace : at <ScriptBlock>, C:\home\site\wwwroot\TimerTrigger1\run.ps1: line 6
CommandName : Connect-MgGraph
TargetSite :
Name : LookupCommandInfo
DeclaringType : [System.Management.Automation.CommandDiscovery]
MemberType : Method
Module : System.Management.Automation.dll
Message : The term 'Connect-MgGraph' is not recognized as a name of a cmdlet, function, script file, or executable program.
2025-05-08T22:03:09Z [Error] ERROR: The term 'Connect-ExchangeOnline' is not recognized as a name of a cmdlet, function, script file, or executable program.
HResult : -2146233087
TargetObject : Connect-ExchangeOnline
CategoryInfo : ObjectNotFound: (Connect-ExchangeOnline:String) [], ParentContainsErrorRecordException
FullyQualifiedErrorId : CommandNotFoundException
ScriptStackTrace : at <ScriptBlock>, C:\home\site\wwwroot\TimerTrigger1\run.ps1: line 9
CommandName : Connect-ExchangeOnline
TargetSite :
Name : LookupCommandInfo
DeclaringType : [System.Management.Automation.CommandDiscovery]
MemberType : Method
Module : System.Management.Automation.dll
Message : The term 'Connect-ExchangeOnline' is not recognized as a name of a cmdlet, function, script file, or executable program.
Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
Data : System.Collections.ListDictionaryInternal
Source : System.Management.Automation
StackTrace :
TargetObject : Connect-ExchangeOnline
CategoryInfo : ObjectNotFound: (Connect-ExchangeOnline:String) [], CommandNotFoundException
FullyQualifiedErrorId : CommandNotFoundException
InvocationInfo :
ScriptStackTrace : at <ScriptBlock>, C:\home\site\wwwroot\TimerTrigger1\run.ps1: line 9
2025-05-08T22:03:09Z [Error] ERROR: The term 'Get-MgUser' is not recognized as a name of a cmdlet, function, script file, or executable program.
HResult : -2146233087
InvocationName : Get-MgUser
CommandOrigin : Internal
ScriptStackTrace : at <ScriptBlock>, C:\home\site\wwwroot\TimerTrigger1\run.ps1: line 15
CommandName : Get-MgUser
TargetSite :
Name : LookupCommandInfo
DeclaringType : [System.Management.Automation.CommandDiscovery]
MemberType : Method
Module : System.Management.Automation.dll
Message : The term 'Get-MgUser' is not recognized as a name of a cmdlet, function, script file, or executable program.
TargetObject : Get-MgUser
CategoryInfo : ObjectNotFound: (Get-MgUser:String) [], CommandNotFoundException
FullyQualifiedErrorId : CommandNotFoundException
ScriptStackTrace : at <ScriptBlock>, C:\home\site\wwwroot\TimerTrigger1\run.ps1: line 15
2025-05-08T22:03:09Z [Error] ERROR: The term 'Get-DistributionGroup' is not recognized as a name of a cmdlet, function, script file, or executable program.
Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
System.Management.Automation.CommandNotFoundExceptionSystem.Management.Automation.ParentContainsErrorRecordException
Message : The term 'Get-DistributionGroup' is not recognized as a name of a cmdlet, function, script file, or executable program.
Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
HResult : -2146233087
TargetObject : Get-DistributionGroup
CategoryInfo : ObjectNotFound: (Get-DistributionGroup:String) [], ParentContainsErrorRecordException
FullyQualifiedErrorId : CommandNotFoundException
InvocationInfo :
ScriptStackTrace : at <ScriptBlock>, C:\home\site\wwwroot\TimerTrigger1\run.ps1: line 73
CommandName : Get-DistributionGroup
Module : System.Management.Automation.dll
Message : The term 'Get-DistributionGroup' is not recognized as a name of a cmdlet, function, script file, or executable program.