Forum Discussion
Remote execution with exchange powershell
- Nov 30, 2024
The error indicates that the remote runspace is configured with NoLanguage mode, which restricts executing PowerShell scripts or complex expressions like ScriptBlock
Instead of using Invoke-Command directly, establish a PowerShell remote session to the Exchange server using New-PSSession and execute your commands within that session.# Create a remote session
$Session = New-PSSession -ConfigurationName Microsoft.Exchange `
-ConnectionUri http://srvwex.company.local/powershell `
-Credential $sourceCred# Import the session
Import-PSSession $Session -DisableNameChecking# Fetch the primary SMTP addresses of members in the distribution group
$DistributionGroup = "YourDistributionGroupAlias" # Replace with your DG alias
$Members = Get-DistributionGroupMember -Identity $DistributionGroup | Select-Object PrimarySmtpAddress# Display the result
$Members# Remove the session after use
Remove-PSSession $Session
If you must use Invoke-Command, avoid using nested ScriptBlocks or complex expressions. Run each command in a simpler format, passing arguments directly:# Parameters for Invoke-Command
$parameters = @{
ConfigurationName = 'Microsoft.Exchange'
ConnectionUri = 'http://srvwex.company.local/powershell'
Credential = $sourceCred
ScriptBlock = {
param($DG)
Get-DistributionGroupMember -Identity $DG | Select-Object -ExpandProperty PrimarySmtpAddress
}
ArgumentList = $DG.Alias
}# Execute the command
$RemoteMembership = Invoke-Command @parameters# Display results
$RemoteMembershipImplicit remoting imports remote Exchange commands into your local session without needing to switch contexts repeatedly.
# Create and import remote session
$Session = New-PSSession -ConfigurationName Microsoft.Exchange `
-ConnectionUri http://srvwex.company.local/powershell `
-Credential $sourceCredImport-PSSession $Session -Prefix Remote
# Use the imported remote commands
$DG = "YourDistributionGroupAlias"
$Members = Get-RemoteDistributionGroupMember -Identity $DG | Select-Object PrimarySmtpAddress# Display results
$Members# Remove session
Remove-PSSession $Session
On the remote Exchange server, check the language mode of the session (if having admin privileges on exchange server) :Get-PSSessionConfiguration -Name Microsoft.Exchange
Update it to FullLanguage mode (not recommended in production environments unless necessary):
Set-PSSessionConfiguration -Name Microsoft.Exchange -LanguageMode FullLanguage
Restart the WinRM service on the remote server: Restart-Service WinRM
If modifying the remote runspace isn't an option, create a proxy script to execute the desired command locally on the remote Exchange server and return the results. Save the script on the remote server and invoke it remotely:Save the following script on the remote server:
# Proxy script on remote Exchange server
param([string]$DGAlias)
Get-DistributionGroup $DGAlias | Get-DistributionGroupMember | Select-Object PrimarySmtpAddress
Invoke the script remotely:
Invoke-Command -ComputerName srvwex.company.local `
-Credential $sourceCred `
-ScriptBlock { & "C:\Scripts\Get-DGMembers.ps1" -DGAlias $using:DG }
The error indicates that the remote runspace is configured with NoLanguage mode, which restricts executing PowerShell scripts or complex expressions like ScriptBlock
Instead of using Invoke-Command directly, establish a PowerShell remote session to the Exchange server using New-PSSession and execute your commands within that session.
# Create a remote session
$Session = New-PSSession -ConfigurationName Microsoft.Exchange `
-ConnectionUri http://srvwex.company.local/powershell `
-Credential $sourceCred
# Import the session
Import-PSSession $Session -DisableNameChecking
# Fetch the primary SMTP addresses of members in the distribution group
$DistributionGroup = "YourDistributionGroupAlias" # Replace with your DG alias
$Members = Get-DistributionGroupMember -Identity $DistributionGroup | Select-Object PrimarySmtpAddress
# Display the result
$Members
# Remove the session after use
Remove-PSSession $Session
If you must use Invoke-Command, avoid using nested ScriptBlocks or complex expressions. Run each command in a simpler format, passing arguments directly:
# Parameters for Invoke-Command
$parameters = @{
ConfigurationName = 'Microsoft.Exchange'
ConnectionUri = 'http://srvwex.company.local/powershell'
Credential = $sourceCred
ScriptBlock = {
param($DG)
Get-DistributionGroupMember -Identity $DG | Select-Object -ExpandProperty PrimarySmtpAddress
}
ArgumentList = $DG.Alias
}
# Execute the command
$RemoteMembership = Invoke-Command @parameters
# Display results
$RemoteMembership
Implicit remoting imports remote Exchange commands into your local session without needing to switch contexts repeatedly.
# Create and import remote session
$Session = New-PSSession -ConfigurationName Microsoft.Exchange `
-ConnectionUri http://srvwex.company.local/powershell `
-Credential $sourceCred
Import-PSSession $Session -Prefix Remote
# Use the imported remote commands
$DG = "YourDistributionGroupAlias"
$Members = Get-RemoteDistributionGroupMember -Identity $DG | Select-Object PrimarySmtpAddress
# Display results
$Members
# Remove session
Remove-PSSession $Session
On the remote Exchange server, check the language mode of the session (if having admin privileges on exchange server) :
Get-PSSessionConfiguration -Name Microsoft.Exchange
Update it to FullLanguage mode (not recommended in production environments unless necessary):
Set-PSSessionConfiguration -Name Microsoft.Exchange -LanguageMode FullLanguage
Restart the WinRM service on the remote server: Restart-Service WinRM
If modifying the remote runspace isn't an option, create a proxy script to execute the desired command locally on the remote Exchange server and return the results. Save the script on the remote server and invoke it remotely:
Save the following script on the remote server:
# Proxy script on remote Exchange server
param([string]$DGAlias)
Get-DistributionGroup $DGAlias | Get-DistributionGroupMember | Select-Object PrimarySmtpAddress
Invoke the script remotely:
Invoke-Command -ComputerName srvwex.company.local `
-Credential $sourceCred `
-ScriptBlock { & "C:\Scripts\Get-DGMembers.ps1" -DGAlias $using:DG }