Using the Exchange Online Management in a native script (After Modify)

I need to perform some mailbox managment when an identity is enabled or disabled. In order to make the decisions that my script needs to make, I have to connect to our Exchange online instance and query the mailbox. The problem is that the script runs fine when I execute it, but when the IQService service account runs it, it receives an error when trying to connect.

Could not load type ‘System.Diagnostics.Metrics.Meter’ from assembly ‘System.Diagnostics.DiagnosticSource, Version=5.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51’.

My server guy and I have tried several different things to get it to work. At one point, I allowed the service account to have interactive logon rights and the server guy logged in as the service account and the script executed as expected, but when the IQService runs the script, it still receives the error above.

This is the sample script we are using to test connectivity. We are using certificate-based authentication.

Import-Module ExchangeOnlineManagement
[string]$certThumb = "b5eb899e122ec5523e251a93b9f7439d80756ade"
[string]$appID = "52c4b0cd-f2f4-472e-97aa-fd86f1621c40"
Connect-ExchangeOnline -Prefix 365 -CertificateThumbprint $certThumb -AppId $appID -Organization "mydomain.onmicrosoft.com" -ErrorAction Stop -ShowProgress $true
Get-365Mailbox -Identity [email protected]
Disconnect-ExchangeOnline -Confirm:$false

The script will fail on the Connect-ExchangeOnline statement when it is run with the IQService. Any thoughts here? On disabling, I need to check to see if the mailbox is on litigation hold (no problem there) and if the mailbox is larger than 50 GB. Both conditions mean that the mailbox will need to continue to have a license assigned. Otherwise, I can remove the license and convert he mailbox to a shared mailbox for a few months until the AD account is deleted.

This seems to be the one of the PS module messed up with other modules or due to incompatible version with PowerShell. Try to cleanup all the modules and install again, or try to run it in different PS version like execute the script in PS7 if you already running in v5 and see whether it fixes the issue.

@BCyr -

What’s really causing the “Could not load type System.Diagnostics.Metrics.Meter’ …” error?

  1. ExchangeOnlineManagement 3.x uses libraries that were compiled for .NET 6 / .NET Standard 2.1.
    The new telemetry classes live in the System.Diagnostics.DiagnosticSource assembly version 8.x, which contains the Meter type.
  2. PowerShell 5.1 (the engine IQService launches by default) is stuck on the .NET Framework 4.8 runtime, where only DiagnosticSource ≤ 5.x is available – that version doesn’t have Meter.
    When the module tries to load the 5.x copy that’s already in the PowerShell 5.1 AppDomain the type can’t be found and you get the exception.
  3. When you (or your server admin) tested interactively you used PowerShell 7 (or at least a console that was loading the right DLL version), so everything worked.
    IQService simply loads the wrong PowerShell host, therefore the wrong .NET runtime.

Reference -


Two dependable ways to fix it

Path When to use Key steps
A. Tell IQService to run the script in PowerShell 7 (recommended – keeps you on the current EXO module and avoids future breakage) You’re allowed to install PowerShell 7.4 LTS (or later) on the IQService host. 1. Install the x64 MSI for PWsh 7.
2. Add one of the following to the native‑rule definition that calls your script: xml <entry key="program" value="pwsh.exe" /> or put #Requires -Version 7.3 on the very first line of the script. IQService 8.3+ automatically launches pwsh when it sees either marker. 3. Restart IQService. 4. Verify with the test script – it should now connect without errors. Refer SailPoint Documentation
B. Pin ExchangeOnlineManagement to an older build that still supports .NET 4.8 You can’t put PWsh 7 on the server, but you can decide which version of the EXO module to load. 1. Uninstall‑Module ExchangeOnlineManagement ‑AllVersions (run once in an elevated console). 2. Install‑Module ExchangeOnlineManagement –RequiredVersion 2.0.5 –Scope AllUsers –Force • 2.0.5 is the last generally reliable build that doesn’t reference System.Diagnostics.Metrics. 3. Add Import‑Module ExchangeOnlineManagement –RequiredVersion 2.0.5 as the first line of the script so the right version is always chosen. 4. Test again under IQService.

Why option A is safer: Microsoft is actively retiring Remote PowerShell, and newer EXO cmdlets (Get‑EXOMailbox*, etc.) only appear in 3.x+. Running them under PowerShell 7 keeps you on the supported path and delivers far better performance in large tenants.


Checklist – common gotchas after the switch

  • Module visibility for the service account
    Install the module with ‑Scope AllUsers or copy it to C:\Program Files\PowerShell\7\Modules so the non‑interactive IQService logon can find it.
  • Certificate permissions
    Make sure the certificate you use for CBA is in LocalMachine\My, and the IQService account has read access to the private key.
  • Suppress progress/UI in background executions:
Connect‑ExchangeOnline `
   -CertificateThumbprint $certThumb `
   -AppId $appId `
   -Organization $tenant `
   -ShowProgress:$false `
   -SkipLoadingFormatData
  • If you stay on PowerShell 5.1 patch the host with the .NET 6 Desktop runtime. That installs the newer DiagnosticSource assemblies into the GAC and also removes the error, but you’re still missing the PowerShell‑7‑only EXO cmdlets. Do this only when you must remain on option B. Microsoft Learn

Putting it all together – sample rule snippet

<!-- SailPoint nativeRule (After‑Provisioning) -->
<Source>powershell</Source>
<entry key="program" value="pwsh.exe"/>

#Requires -Version 7.3
param($plan, $identity)

Import-Module ExchangeOnlineManagement -MinimumVersion 3.6.0

$certThumb = 'b5eb899e122ec5523e251a93b9f7439d80756ade'
$appId     = '52c4b0cd-f2f4-472e-97aa-fd86f1621c40'
$tenant    = 'mydomain.onmicrosoft.com'

Connect-ExchangeOnline -Prefix 365 `
                       -CertificateThumbprint $certThumb `
                       -AppId $appId `
                       -Organization $tenant `
                       -ShowProgress:$false `
                       -SkipLoadingFormatData

$mailbox = Get-365Mailbox -Identity $identity.email
$stats   = Get-365MailboxStatistics -Identity $identity.email

# If the mailbox is >50 GB or on litigation hold keep the license,
# otherwise convert it to a shared mailbox.
if ($stats.TotalItemSize.Value.ToBytes() -gt 50GB -or
    $mailbox.LitigationHoldEnabled) {
    Write-Host "Leaving license intact."
}
else {
    Set-365Mailbox -Identity $identity.email -Type Shared
    Write-Host "Converted to shared mailbox – license can be removed."
}

Disconnect-ExchangeOnline -Confirm:$false

With PowerShell 7 and the current EXO module this rule will execute under IQService the same way it runs in your interactive tests – no more System.Diagnostics.Metrics.Meter error and no interactive UI.

Hope this helps.

1 Like

Thank you, Amit, for that very well-thought-out and thorough answer. The server team upgraded PowerShell and installed the latest EXO module, and once I updated the config for the native script, it all worked great!

This topic was automatically closed 60 days after the last reply. New replies are no longer allowed.