locked
invoke-command to execute Exchange commands in the remote environment. RRS feed

  • Question

  • Greetings scripting gurus!  

    All servers below, source and target, are Windows 2012 R2, patched to current, and running Exchange 2016 CU10.  

    I having a problem executing Exchange commands on remote servers.  Importing commands and running locally will not work for this requirement.  Because some commands only run on machines with specific Exchange roles installed, I need the commands to run locally on the remote server.  Kind of like "Turn left right here!"  

    So, I've worked my way through a lot of errors to get to where everything appears to be working correctly, but not the results i need.  The sample code here is only intended to test running an Exchange on the remote server, not in a remote session that returns the result to the server I'm logged into.  Here is the code I'm working with:

    ##########################################
    
    # script block to run the commands.
    $scriptblock = {
    param($server,$credential) ; 
    
    # insurance that there are no other remote sessions running here (which is remote).  
    get-pssession | remove-pssession ;
    
    # create the session.  $server is an fqdn passed to the scriptblock.  
    write-host "creating new pssession" ;
    $fqdn = "$server" ;
    $Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri http://$fqdn/PowerShell/ -Authentication Kerberos -credential $credential ;
    
    # import the session.  
    write-host "import $session" ;
    Import-PSSession $Session -AllowClobber | select moduletype, version, name, exportedcommands  ; 
    
    # display the session to confirm it is an Exchange shell.  
    write-host "get newly imported pssession:" ;
    $session | get-pssession | ft name ;
    
    # try to run an Exchange shell command.
    write-host "test get-exchangeserver cmd:" ;
    $exserver = get-exchangeserver 
    }
    
    # define my remote server.  
    $server = $myserver
    
    # invoke the scriptblock.  
    invoke-command -ScriptBlock $scriptblock -ComputerName $server -ArgumentList $server,$credential
    ###################################
    
    These are the results:
    ##################################################
    [PS] C:\>$scriptblock = {
    >> param($server,$credential) ;
    >>
    >> write-host "this is server myserver" ;
    >>
    >> get-pssession | remove-pssession ;
    >>
    >> write-host "creating new pssession" ;
    >> $fqdn = "$server" ;
    >> $Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri http://$fqdn/PowerShell/ -Authentication Kerberos -credential $credential ;
    >>
    >> write-host "import $session" ;
    >> Import-PSSession $Session -AllowClobber | select moduletype, version, name, exportedcommands  ;
    >>
    >> write-host "get newly imported pssession:" ;
    >> $session | get-pssession | ft name ;
    >>
    >> write-host "test get-exchangeserver cmd:" ;
    >> $exserver = get-exchangeserver
    >> }
    >>
    [PS] C:\>$server = $myserver
    [PS] C:\>invoke-command -ScriptBlock $scriptblock -ComputerName $server -ArgumentList $server,$credential
    this is server myserver
    creating new pssession
    import [PSSession]Session1
    
    
    ModuleType       : Script
    Version          : 1.0
    Name             : tmp_e2yypwrw.1k4
    ExportedCommands : {Set-MailboxRegionalConfiguration, Search-MessageTrackingReport, Get-User, Set-DistributionGroup,
                       Set-User, Get-CalendarNotification, Test-SiteMailbox, Start-AuditAssistant, Set-Mailbox,
                       Get-UMMailboxConfiguration, Get-MailboxUserConfiguration, Set-UserPhoto, Remove-DistributionGroup,
                       Set-MailboxSpellingConfiguration, Get-MessageClassification, Set-MailboxMessageConfiguration...}
    PSComputerName   : myserver
    RunspaceId       : 616d3979-8b8f-43bd-a855-ce1e89dd4c42
    
    get newly imported pssession:
    
    
    Name
    ----
    Session1
    
    
    test get-exchangeserver cmd:
    The term 'get-exchangeserver' is not recognized as the name of a cmdlet, function, script file, or operable program.
    Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
        + CategoryInfo          : ObjectNotFound: (get-exchangeserver:String) [], CommandNotFoundException
        + FullyQualifiedErrorId : CommandNotFoundException
        + PSComputerName        : myserver
    ##########################################################

    After the import completes you can see the imported commands, but when it tries to execute get-exchangeserver it can't find the command...

    All comments and critiques are welcome!  

    TIA.  


    • Edited by daddmac Friday, April 5, 2019 2:26 AM moving code to code block window.
    Thursday, April 4, 2019 8:26 PM

Answers

  • You cannot use Invoke-Command on Exchange and you cannot do cluster management remotely.  You will be restricted by the "second hop restriction".  Look it up.


    \_(ツ)_/

    • Marked as answer by daddmac Friday, April 5, 2019 2:55 AM
    Friday, April 5, 2019 2:37 AM

All replies

  • Please post code only using the code posting tool provided on the icon bar of the post editor (second to last icon). That counts for sample data and console output as well.

    Thanks.


    Live long and prosper!

    (79,108,97,102|%{[char]$_})-join''

    Thursday, April 4, 2019 9:09 PM
  • All servers below, source and target, are Windows 2012 R2, patched to current, and running Exchange 2016 CU10.  

    I having a problem executing Exchange commands on remote servers.  Importing commands and running locally will not work for this requirement.  Because some commands only run on machines with specific Exchange roles installed, I need the commands to run locally on the remote server.  Kind of like "Turn left right here!" 

    You cannot run Exchange commands locally. To do so requires installing RSAT and Exchange shell support.


    \_(ツ)_/

    Thursday, April 4, 2019 9:48 PM
  • You cannot run Exchange commands locally. To do so requires installing RSAT and Exchange shell support.
    Does implicit remoting count as "locally"?  ;-)

    #$Cred = Get-Credential
    $Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri "http://<YourServerNameHere>/powershell/"  # -Credential $Cred
    Import-PSSession -Session $Session

    This way I can run Echange cmdlets locally on my client.   (if you need to use other than the current credentials you should uncomment the $Cred part)


    Live long and prosper!

    (79,108,97,102|%{[char]$_})-join''

    • Edited by BOfH-666 Thursday, April 4, 2019 10:08 PM
    • Proposed as answer by jrv Thursday, April 4, 2019 10:09 PM
    Thursday, April 4, 2019 10:07 PM
  • Thank you BOfH_666, lesson learned!  
    Thursday, April 4, 2019 10:52 PM
  • Hello again!  

    The situation is that I need to put a farm with multiple dags into maintenance, by running a script from a utility server that has the Exchange tools installed.  We tried specifying the node and the dag with suspend-clusternode command, but it appears to choke unless it is running on a server in the dag.  It is possible the problem is with my code, but I believe I followed the syntax correctly:

    Suspend-ClusterNode -name $targetserver.name -cluster $dag 

    So, my solution was to run the code in a remote shell using the remote system's local environment to put its dag into maintenance.  I have scripts running from start-job that create remote sessions to randomly selected machines, to distribute the load, and then import the exchange commands to run in that shell.  So, I thought I could do something similar with invoke-command to run the commands in the remote shell on the remote server.  


    Thursday, April 4, 2019 11:16 PM
  • What does that have to do with Exchange commands?

    https://docs.microsoft.com/en-us/powershell/module/failoverclusters/suspend-clusternode?view=win10-ps

    Both parameters are stings names of cluster and node.


    \_(ツ)_/

    Thursday, April 4, 2019 11:26 PM
  • Please fix your code and post correctly or no one will help you.  Your original post is unreadable.


    \_(ツ)_/

    Thursday, April 4, 2019 11:27 PM
  • I've inserted the code and error into a code.  HTH.
    Friday, April 5, 2019 2:27 AM
  • Thank you for calling that out, and for the link. 

    This command is part of a code block that is mostly comprised of Exchange commands. 

    It is simple enough to load the failover module to expose the *-clusternode commands, but I prefer to keep the code simple by using one script block to do all the work.  To do that, I think I need to open an EMS on the remote server and execute the commands in that shell. 

    If there is a better, or no, way to do this, then I am happy to learn. 

    Friday, April 5, 2019 2:34 AM
  • You cannot use Invoke-Command on Exchange and you cannot do cluster management remotely.  You will be restricted by the "second hop restriction".  Look it up.


    \_(ツ)_/

    • Marked as answer by daddmac Friday, April 5, 2019 2:55 AM
    Friday, April 5, 2019 2:37 AM
  • I was trying to find a way around it.  I read an article about how to do so with a reasonable amount of effort, but have not found it again. 

    I've seen other articles that create complex solutions, but they would not be maintainable for less experienced admins.

    Thank you.

    Friday, April 5, 2019 2:55 AM