none
Import-PSSession w/Remote Exchange within Runspaces RRS feed

  • Question

  • Thanks in advance for your help. I'm cross-posting this with the PowerShell forum as the issue seems to span both subjects. I am having difficulty using the Import-PsSession to import a remote Exchange shell session within a runspace. My underlying goal is I want to multi-thread some Exchange-related operations with EWS Managed API. I'm trying to spread these connections among six Exchange servers in our environment. However when I do so results are inconsistent; it's random how many of the six servers will actually return results and which will error out. The error I receive:

    PS>TerminatingError(Import-PSSession): "Data returned by the remote Get-FormatData command is not in the expected format."
    import-pssession : Data returned by the remote Get-FormatData command is not in the expected format.
    At line:12 char:13
    +             import-pssession $session -AllowClobber
    +             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        + CategoryInfo          : InvalidResult: (:) [Import-PSSession], ArgumentException
        + FullyQualifiedErrorId : ErrorMalformedDataFromRemoteCommand,Microsoft.PowerShell.Commands.ImportPSSessionCommand

    I've created the below script (with copious help from other TechNet articles) to produce these errors in hope of figuring out how to fix them. FYI we run Exchange 2016 CU12 on-prem.

      # I didn't write this function either but for the life of me I can't find where it came from to credit the author.
        function Resize-Array ([object[]]$InputObject, [int]$SplitSize)
        {
    	    $length = $InputObject.Length
    	    for ($Index = 0; $Index -lt $length; $Index += $SplitSize)
    	    {
    		    , ($InputObject[$index .. ($index + $splitSize - 1)])
    	    }
        }
    
    $InputObject = (get-aduser -Filter {extensionattribute2 -eq "a"} -ResultSetSize 100).samaccountname
    $bucketsize = 10
    
        # Segregate our list of targets into a set of arrays
        $TargetsArray = resize-array -inputobject $InputObject -SplitSize $bucketsize
    
        # Create the pool of runspaces
        [void][runspacefactory]::CreateRunspacePool()
        # Define initial session state
        $SessionState = [System.Management.Automation.Runspaces.InitialSessionState]::CreateDefault()
        # Define the pool and the max number of runspaces to be active
        $RunspacePool = [runspacefactory]::CreateRunspacePool(1,3)
        # Create a new PS session
        $PowerShell = [powershell]::Create()
        # Assign our runspace pool to this new session and open it.
        $PowerShell.RunspacePool = $RunspacePool
        [void]$RunspacePool.open()
    
        $jobs = new-object system.collections.arraylist
        $servers = get-exchangeserver | where {$_.name -like "dc1*"}
        $counter = 0
        $serverCounter = 0
    
        foreach ($array in $TargetsArray)
            {
            $PS = [powershell]::Create()
            $PS.RunspacePool = $RunspacePool
            [void]$PS.AddScript({
                Param ($target,$server)
                
                start-transcript ($env:USERPROFILE + "\desktop\test\" + $server + ".txt")
    
                $URI = "http://" + $server + "/PowerShell/"
                $session = new-pssession -ConfigurationName Microsoft.Exchange -ConnectionUri $URI -Authentication Kerberos
                import-pssession $session -AllowClobber
    
                foreach ($thing in $target)
                    {
                    [pscustomobject]@{
                    Target = $thing
                    Server = $server
                    Result = (get-mailbox $thing).distinguishedname
                    Errors = $Error
                        }
                    }
                Stop-Transcript
                })
            $PS.AddParameter("Target",$Array).AddParameter("Server",$servers[$serverCounter])
            # Begin execution of this runspace
            $Handle = $PS.BeginInvoke()
            $temp = "" | select PowerShell,Handle
            $temp.PowerShell = $PS
            $temp.Handle = $handle
            [void]$jobs.add($temp)
    
            $ServerCounter++
            # If our ServerCounter is equal to the count of available servers to connect to - we use equal because the count of servers is going to be one more than the index of the array $servers.
            # In other words $servers[4] would be the fifth server in the list because we index upwards from 0.
            if ($ServerCounter -ge ($servers | measure).count)
                {
                # If we've reached the end of the list of servers then start again from the first one.
                $ServerCounter = 0
                }
            }
    
            #Verify completed
        do
            {
            Write-host -ForegroundColor DarkGreen (“Available Runspaces in RunspacePool: {0}” -f $RunspacePool.GetAvailableRunspaces())
            Write-host -ForegroundColor DarkGreen (“Remaining Jobs: {0}” -f @($jobs | Where {$_.handle.iscompleted -ne ‘Completed’}).Count)
            start-sleep 5}
        until (($jobs | Where {$_.handle.iscompleted -ne ‘Completed’}).Count -eq 0)
    
        $return = $jobs | ForEach {
            $_.powershell.EndInvoke($_.handle)
            $_.PowerShell.Dispose()
        }
    
        $jobs.clear()


    Thursday, August 22, 2019 4:00 PM

All replies