Forum Discussion

StefanoC66's avatar
StefanoC66
Iron Contributor
Nov 29, 2024

Remote execution with exchange powershell

I'm trying to extract the primarysmtpaddress of each member of a distribution group from an exchange server in a remote forest.

The bulk of the script is something link this

  $parameters = @{
  ConfigurationName = 'Microsoft.Exchange'
  ConnectionUri     = 'http://srvwex.company.local/powershell'
  Credential        = $sourceCred
  # Authentication    = 'Basic'
  ScriptBlock       = {{(Get-DistributionGroup $args[0] |Get-DistributionGroupMember).PrimarySmtpAddress }}
  ArgumentList = $DG.Alias
   }

  $RemoteMembership=(Invoke-Command @parameters)

but I got the following error 

The syntax is not supported by this runspace. This can occur if the runspace is in no-language mode.
    + CategoryInfo          : ParserError: ({(Get-Distribut...rySmtpAddress }:String) [], ParseException
    + FullyQualifiedErrorId : ScriptsNotAllowed

Running the command 

(Get-DistributionGroup distributiongroup | Get-DistributionGroupMember).PrimarySmtpAddress

locally on the remote exchange server obviously works

Is there a way I can do it ?

thanks

 

 

  • 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 }

  • Mks_1973's avatar
    Mks_1973
    Iron Contributor

    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 }

Resources