Powershell: Imported modules that were exported seem to be broken

Created on 12 Feb 2019  路  10Comments  路  Source: PowerShell/PowerShell


Exporting a module locally (such as Office 365 remote powershell) and then re-importing it results in the cmdlets in that module being broken (on Mac/Linux, haven't tested Windows). The error they return is below. If I just connect to the Office 365 powershell session directly without exporting it, it works fine. So it seems to be something with the re-imported module that breaks it?

Steps to reproduce

$Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri "https://outlook.office365.com/powershell-liveid/" -Credential (Get-Credential) -Authentication Basic -AllowRedirection -Name TestTenant
Export-PSSession $Session -OutputModule "path_to_module" -AllowClobber
Import-Module TestTenant -DisableNameChecking -Global

Expected behavior

The imported module should work.

Actual behavior

PS /Users/rfoust> Get-Mailbox
Creating a new session for implicit remoting of "Get-Mailbox" command...
Exception calling "GetSteppablePipeline" with "1" argument(s): "The expression after '&' in
a pipeline element produced an object that was not valid. It must result in a command name, a script
block, or a CommandInfo object."
At /Users/rfoust/.local/share/powershell/Modules/TestTenant/TestTenant.psm1:18294 char:13
+             $steppablePipeline = $scriptCmd.GetSteppablePipeline($myI ...
+             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo          : NotSpecified: (:) [], ParentContainsErrorRecordException
+ FullyQualifiedErrorId : CmdletInvocationException

Environment data

Name                           Value
----                           -----
PSVersion                      6.1.2
PSEdition                      Core
GitCommitId                    6.1.2
OS                             Darwin 18.2.0 Darwin Kernel Version 18.2.0: Thu Dec 20 20:46:53 PST 2018; root:xnu-4903.241.1~1/RELEASE_X86_64
Platform                       Unix
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0...}
PSRemotingProtocolVersion      2.3
SerializationVersion           1.1.0.1
WSManStackVersion              3.0
Issue-Question

All 10 comments

I believe you need to do the below get them imported properly (or at least I have has this in one of my scripts for a long long time as part of an older office 365 connection script that I had as part of a module that for that imported in my profile)

#Connect-EXOSession#
Function Connect-EXOSession {
<#
.Synopsis
   Short description
.DESCRIPTION
   Long description
.EXAMPLE
   Example of how to use this cmdlet
.EXAMPLE
   Another example of how to use this cmdlet
#>
param (
    [Parameter(Mandatory=$true)][PSCredential]$EXOCredential

     )
$Global:Session = New-PSSession -ConfigurationName Microsoft.Exchange `
                    -ConnectionUri https://ps.outlook.com/powershell/ `
                    -Credential $EXOCredential -Authentication Basic `
                    -AllowRedirection -Name EXOSession -WarningAction SilentlyContinue 
Import-Module (Import-PSSession -Session $Global:Session -Verbose:$false -DisableNameChecking -AllowClobber) -Global -DisableNameChecking
}

I then called these lines in my profile


Function Connect-MyEXOSession { 
Import-Module GitHub:\kilasuit\PoshFunctions\Modules\Connect-EXOSession\Connect-EXOSession.psd1 ; 
$MYO365cred = Get-bCredential -Credential MyO365UserName -Store # as using BetterCredentials Module
Connect-EXOSession -EXOCredential $MYO365cred
}

Connect-MyEXOSession 

Thanks @kilasuit for the suggestion. Yes, I am able to get it to work if I don't export the module. But what I do on regular Windows Powershell is export the module so that I can update the line in the .psm1 file that asks for credentials to use a global variable that already has the credential. This way, the module with automatically re-authenticate without prompting when the session dies. I'm trying to replicate that behavior in PS Core.

This is the line in the .psm1 that is triggering the exception. $myInvocation.CommandOrigin is "Runspace".

$steppablePipeline = $scriptCmd.GetSteppablePipeline($myInvocation.CommandOrigin)

@rfoust I don't know enough an the technical side in this case to know why that regression exists, but in the meantime you can apply such a modification on the in-memory module, and then remove and reload it.

@vexx32 Interesting idea, I didn't realize it was possible to modify an in-memory module. Can you elaborate on how I would do that or point me in the right direction? Thanks!

The basic method I'd probably tackle it from is like this:

# usually these are temp_* for an imported PSSession
$Module = Get-Module -Name $ModuleName 

# single-quotes! Variable names need to be intact
$ModuleScript = [scriptblock]::Create($Module.Definition -replace '<credential_line>','$global:Creds') 

# Create new module from modified script block
$New = New-Module -Name NewModuleName -ScriptBlock $ModuleScript

# remove original copy of the module from the session
Remove-Module $Module.Name 

# import the new module
$New | Import-Module 

This might run into the same issue, but... it's worth a shot nonetheless. 馃槃

@vexx32 Oh wow, doing it that way never occurred to me. Mind blown. :) It worked on a quick test! I still need to put that logic in my wrapper function and see how it behaves after the session breaks. But looks promising so far, thanks!

It'd be really cool if doing the Export-PSSession how you were handling it supported a -Credential parameter so you could just pass them in and have it work, but that's probably a separate issue/request.

Let me know how you get on, I'm curious to see if it behaves as expected. 馃槃

@vexx32 So when I remove the existing pssession, I get the same error. So this caused me to do a little more tracing and long story short, the original problem I have is being caused because New-PSSessionOption does not exist in PS Core (on mac/linux?). Not sure why.

But anyway, since that cmdlet doesn't exist, it is causing the New-PSSession command to bomb out somewhere when it is called this way in the .psm1 file:

Set-PSImplicitRemotingSession `
            -CreatedByModule $true `
            -PSSession (
                $(
                & $script:NewPSSession `
                    -connectionUri 'https://outlook.office365.com/powershell-liveid/' -ConfigurationName 'Microsoft.Exchange' `
                    -SessionOption (Get-PSImplicitRemotingSessionOption) `
                    -Credential ( $host.UI.PromptForCredential( 'PowerShell Credential Request', 'Enter your credentials for https://outlook.office365.com/powershell-liveid/.', '[email protected]', 'outlook.office365.com' ) ) `
                     `
                    -Authentication Basic `
                    -AllowRedirection `
                    -Verbose `
                )
            )

Specifically, the -SessionOption line is where it dies. So if I go back to my original code, I can just strip out that line to resolve all my problems.

But I guess this bug still technically exists, and the question is why is that cmdlet not there? According to the docs, it should be:

https://docs.microsoft.com/en-us/powershell/module/Microsoft.PowerShell.Core/New-PSSessionOption?view=powershell-6

Also just for anyone reading along, to save ya some time, the -SessionOption parameter calls Get-PSImplicitRemotingSessionOption which is this:

function Get-PSImplicitRemotingSessionOption
{
    if ($null -ne $PSSessionOptionOverride)
    {
        return $PSSessionOptionOverride
    }
    else
    {
        return $(& $script:NewPSSessionOption -Culture 'en-US' -UICulture 'en-US' -CancelTimeOut 60000 -IdleTimeOut -1 -OpenTimeOut 180000 -OperationTimeOut 180000 -MaximumReceivedObjectSize 209715200 -MaximumRedirection 5 -ProxyAccessType None -ProxyAuthentication Negotiate )
    }
}

and $script:NewPSSessionOption is this:

$script:NewPSSessionOption = $executionContext.InvokeCommand.GetCommand('New-PSSessionOption', [System.Management.Automation.CommandTypes]::Cmdlet)

This is all auto-generated when the module is exported.

Was this page helpful?
0 / 5 - 0 ratings