Author Posts

August 13, 2018 at 4:55 pm

I'm trying to write a function that will connect me to Exchange Online PowerShell. I will then put this function in a module file (.psm1) that will load up each time I open PowerShell. I have found other functions that are supposed to do this very thing, however when I try them and call the function, it does not retain the open session with Exchange Online. After the cmdlets finish, it shows output that would indicate a successful import (showing ModuleType, Version, Name, and ExportedCommands) but none of the imported cmdlets are available. I'm thinking it might be an issue with the scope of the function but I don't know how to remedy that.

I am using PS version 5.1 on a Windows 10 machine. Below is the function used.

function Connect-ExchangeOnlinePowershell

        # Param1 help description
    Write-Output  "Connecting to Exchange Online Powershell..."
    $exchangeSession = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri `
    -Credential (Get-Credential -UserName $Username -Message "Enter the password for $Username") -Authentication "Basic" -AllowRedirection
    Write-Output  "Importing Exchange Online Powershell session..."
    Import-PSSession $exchangeSession -AllowClobber -DisableNameChecking

August 13, 2018 at 5:02 pm

Well, not an “issue.” Magazines have issues :). Yes, this problem is caused by scope. Once the function ends, variables within it are out of scope and they vanish.

The correct pattern would be for your function to output the session object (as opposed to outputting status messages, which is what Write-Verbose should be used for). You then capture that output in a variable:

$mysession = Connect-ExchangeOnlinePowerShell

That session can then be fed, via input parameter, to any other functions or commands you write or use, and they can use the session that way.

August 13, 2018 at 6:42 pm

Here is an approach you might want to look at, which is what you are after and provides a menu for it.

Connect to Office 365/Exchange Services

PowerShell script defining functions to connect to Office 365 online services or Exchange On-Premises. Makes it easy to connect to different Office 365 services using the same credentials.

An article on the topic


August 13, 2018 at 7:45 pm

Thanks Don and postanote, you hit on both uses I am looking for.

I'd like to be able to call the function within other functions in the module, therefore reducing repeat code. Creating the New-PSSession then returning it from the function Connect-ExchangeOnlinePowershell would solve this.

I'd also like to be able to call the function in an interactive environment to connect quickly for testing, without needing to recall each of the New-PSSession parameters and arguments. It looks like in order to do this I will need to set the scope of the function to global:Connect-ExchangeOnlinePowershell so that it remains in the shell until close. Does it sound like I am understanding that correctly?

Could this be done with one function? I am thinking the function could be made global and a switch could be used. If the switch is present the function would call import-pssession internally and then because the function is global the session would be available in the interactive setting. If the switch is not there, the session would be created but instead of importing it, the session would be returned to be used by other functions/commands.

August 13, 2018 at 9:13 pm

Yeah, you've got it.

My broad approach to this kind of thing is to define a module-level variable, which I export, named something like $DJO365SessionPreference. I then capture my new session into that, and I make the value in that variable the default for other functions' -O365Session parameter.

August 15, 2018 at 5:14 pm

So I have adjusted the function to be global in scope but now I am finding it is not being automatically imported. I have edited $PSModulePath to include the directory where the module is saved. I have the module manifest file set to export all functions. All the other functions are imported automatically and will work fine. The global functions do not show up until I import manually with Import-Module. What other step do I need to take to have the global functions imported automatically?

function global:Connect-ExchangeOnline

        # The default user is ****. Change the user by including this parameter.

        # To use this function to create an interactive connection with Exchange Online Powershell, include this switch

    $exchangeSession = New-PSSession -ConfigurationName Microsoft.Exchange `
                            -ConnectionUri `
                            -Credential (Get-AdminCredentials $Admin) `
                            -Authentication "Basic" `

        Write-Verbose  "Connecting to Exchange Online Powershell..."
        Write-Verbose "Importing Exchange Online Powershell session..."
        Import-PSSession $exchangeSession
        Return $exchangeSession

August 16, 2018 at 4:12 pm

I think my problem from my previous post was in using a wildcard to specify FunctionsToExport with the Update-ModuleManifest cmdlet. Explicitly stating the functions to export seems to have fixed it.

Using the code above, calling Import-PSSession (Connect-ExchangeOnline) works successfully, I get the session commands I expect (Get-Mailbox, etc). However, calling Connect-ExchangeOnline -Interactive does not. It appears (with verbose output) that it imports all the commands, but they are not available in the local session.

Any thoughts on why -Interactive is not working?