powershell session connection cmdlets not work when executed in function - powershell

I get connected to Exchange in the cloud by issuing a series of powershell commands:
$credential = new-object -typename ... -argumentList ...
$session = New-PSSession -configurationName ... -connectionUri ... -credential $credential ...
Import-PSSession $session ...
I can then issue commands to do things I need to do, e.g.,
get-mailbox | ? {$_.aliast -like "*[.]*"} | select alias
alias
-----
john.public
jane.doe
...
However, the cmdlets for obtaining a PSSession are long, and typing them is error-prone even if I could manage to memorize them correctly. So I saved all the three long command lines verbatim in a function:
function get-365session() {
$credential = new-object -typename ... -argumentList ...
$session = New-PSSession -configurationName ... -connectionUri ... -credential $credential ...
Import-PSSession $session ...
}
But it does not work out as expected:
PS> get-365session
ModuleType Version Name ExportedCommands
---------- ------- ---- -----------------
...
PS> get-mailbox
get-mailbox: The term 'get-mailbox' is not recognized as the name of a cmdlt, function, script file, ....
I thought the session was obtained but was gone with the function's "sub-shell" as soon as the function has completed its run. I therefore tried
PS> . get-365session
But it was to no avail.
Hope there is a way and someone can help me out. Many thanks!

You need to import the session in the current scope using Import-Module with the -Global flag.
Your Import-PSSession line should look like
Import-Module (Import-PSSession $session365 -AllowClobber) -Global
Here is a working example:
function Connect-O365{
$o365cred = Get-Credential username#domain.onmicrosoft.com
$session365 = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri "https://outlook.office365.com/powershell-liveid/" -Credential $o365cred -Authentication Basic -AllowRedirection
Import-Module (Import-PSSession $session365 -AllowClobber) -Global
}
Connect-O365
Reference
This technet forum thread from 2012

Local functions and variables are not available in other sessions. However, you can use the following trick to specify your function as a script block:
Invoke-Command -Session $session -ScriptBlock ${Function:My-FunctionName}
The article I linked to above goes into more detail about more advanced use-cases for this, but as your script doesn't seem to require any parameters. Do note that this requires the use of Invoke-Command to run the code in the other session, from the session where the function is defined, so I'm not sure how, if you could, get the function body if you have already done Enter-PSSession and are currently in the remote session.

Related

Accessing credential in the script executing from Invoke-Command

I am trying to execute the following command in PowerShell:
Invoke-Command -ComputerName <computerName> -FilePath script.ps1 -Credential $cred
Using Invoke-Command I am executing a PowerShell script "script.ps1" providing credentials in $cred.
Is there any way I can use the passed variable $cred in the above Invoke-Command, in the script again without asking a user about credentials?
i.e. something like below:
script.ps1:
New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri https://outlook.office365.com/powershell-liveid/ -Credential $cred -Authentication Basic -AllowRedirection
You can have the script accept a credential parameter:
script.ps1:
Param([PSCredential]$Credential)
New-PSSession ... -Credential $Credential
and invoke it while passing $cred as an argument like this:
Invoke-Command -Computer $computer -FilePath script.ps1 -ArgumentList $cred -Credential $cred

Export-PSSession not exporting any cmdlets

I'm trying to export a remote Microsoft Exchange session using Export-PSSession however when I do this none of the Exchange specific cmdlets have been imported when I import the module, only the Exchange specific counters work. This is what I have so far:
$Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri http://my.exchange.server.name.and.domain/PowerShell/ -Authentication Kerberos -Credential administrator
Export-PSSession -Session $Session -OutputModule ExchangeCmdlets -CommandType All -CommandName * -AllowClobber -Force
Import-Module -name ExchangeCmdlets
Get-ExchangeServer
I feel like I'm close but missing something.
You can try -PSSession parameter in Import-Module cmdlet.
Import-Module -PSSession $Session

Import-PSSession fails in script, works in shell

I'm new to Powershell scripting and I'm working on a user management Powershell script, but I have run into a strange error.
The following code works when I run it from the shell, but not when it is run from a script:
$UserCredential = Get-Credential
$Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionURI http://servername/Powershell/ -Authentication Kerberos -Credential $UserCredential -AllowRedirection
Import-PSSession $Session
When I run it in a script with a Param() block on the first line, it fails with the following error:
Import-PSSession: Cannot bind argument to parameter 'Path' becuase it is an empty string.
I can get the Import-PSSession to work if I remove my Param() block, but I'm not sure how to accept command-line arguments for my script otherwise. How can I keep the Param() block (or more generally, accept command-line arguments) and still be able to import the PS session?
I'm using Powershell v2 on a Windows 2008 R2 server trying to connect to a 2010 Exchange server.
Update:
I have a script named ManageUser.ps1 that I run from a Powershell prompt like
.\ManageUser.ps1 -disableUser -username someuser
The script starts like this:
Param(
[switch]$disableUser,
[string]$username
)
$UserCredential = Get-Credential
$Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionURI http://servername/Powershell/ -Authentication Kerberos -Credential $UserCredential -AllowRedirection
Import-PSSession $Session
#more stuff past here...
It is failing on the Import-PSSession command. But, if I remove the whole Param(...), the session import works. I hope this is enough for you to understand it!
Your script works fine on it's own and also when called from within another script:
& 'C:\Scripts\ManageUser.ps1' -disableUser -username "foo"
Get-Mailbox -resultsize 5 | ConvertTo-Csv -NoTypeInformation | Out-File C:\Scripts\mytest.csv
Subsequent runs will get the import error/warning due to not having -allowclobber as mentioned by #SamuelWarren...
In your case (at least when initially writing the question long ago) the error was due to another variable that you haven't mentioned here. It's likely you fixed that after the first run, and then subsequent tests were showing the AllowClobber error.
Also worth noting (for anybody who comes across this in the future) to check the path of the file you are calling. Just because you try to use a relative path .\myfile.ps1 doesn't mean that PowerShell is currently looking in the right directory.
Check: $psscriptroot
Or Split-Path -Path $($global:MyInvocation.MyCommand.Path)

powershell function not working right when used in custom module

My function is simple, it connects you to an Office365 account:
Function Connect-O365 {
[CmdletBinding()]
Param()
$url = "https://ps.outlook.com/powershell"
$O365Credential = Get-Credential -Message "Enter your Office 365 Credentials"
$O365Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri $url -Credential $O365Credential -Authentication Basic -AllowRedirection
Import-PSSession -Session $O365Session -Prefix O365
}
When running from a custom module, the commands from the imported session are not imported, no message is returned back with any errors or anything.
However, if i copy/paste the same function to my powershell profile, or direct to the console, it works perfectly fine, the commands are successfully imported from the session.
Thoughts?
EDIT: My Module I am adding this function to is a simple .psm1 file with only two other unrelated functions in it, nothing too complex either.
modified the last line in my function to:
Import-Module (Import-PSSession -Session $O365Session) -Global -Prefix O365
This resolved my issue, it was that the module was not importing on my Import-Session

Connect Office 365 Exchange Online through Powershell

I am trying to perform some operations on Exchange online(Office 365) through powershell.
First I created a new powershell session and exported the modules to local as "o365", so that on any later operation I no need to use Import-PsSession to download the required modules
$cred = Get-Credential
$s = New-PSSession -ConfigurationName "Microsoft.Exchange" -ConnectionUri "https://ps.outlook.com/powershell/" -Credential $cred -Authentication Basic -AllowRedirection
Export-PsSession -session $s -outputModule o365
Now, I am creating new session and importing the existing module "o365".
$cred = Get-Credential
$s = New-PSSession -ConfigurationName "Microsoft.Exchange" -ConnectionUri "https://ps.outlook.com/powershell/" -Credential $cred -Authentication Basic -AllowRedirection
Import-Module o365
Get-DistributionGroup
While running the command "Get-DistributionGroup", powershell prompts me to enter the office 365 credentials once again. Is it possible to avoid entering the credentials once again? I don't want to use Import-PsSession, since it takes more time.
It's prompting because you're asking it to each time. I would set up $cred by creating a new object.
#Initiate Get-Credential cmdlet and store inputs
$getcred = Get-Credential
$username = $getcred.UserName
$password = $getcred.Password
$cred = new-object -typename System.Management.Automation.PSCredential -argumentlist $username, $password
If you place the above in its own function, you wont have the issue of re-defining the $getcred variable. (That to most is obvious, but thought I'd cover that base)