Import-PSSession fails in script, works in shell - powershell

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)

Related

PowerShell Alias when connected to a remote Exchange Server

I am trying to create a script to connect to my exchange server remotely and create some alias for commonly used commands.
I connect to exchange using:
$Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri http://<ServerFQDN>/PowerShell/ -Authentication Kerberos -Credential $UserCredential
Import-PSSession $Session -DisableNameChecking
If I add to the bottom of this script:
New-Alias -Name "GR" -Value Get-Recipient
I see no error message, but no alias is created. If I run my script to connect to Exchange, and then run the New-Alias command in the terminal, the alias creates as expected.
I assume I am missing something fundamental regarding Sessions or scope, and any help gratefully received.

Why does importing my custom modul show the whole script code?

The Problem:
I have a big custom modul with tons of functions. I import it via my profile.ps1 file like this:
import-module "\\server\path\Filename.psm1"
This worked perfectly in the past.
But since today I added in new code to my profile.ps1 code.
What I changed was that I create a 2nd session to Office 365.
The whole ps1 file looks like this now:
# Log Files
Start-Transcript
# Session leeren
Get-PSSession | Remove-PSSession
#Session auf onPrem
$onpremSession = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri http://onPremServer/powershell
Import-PSSession $onpremSession -Prefix onPremises
#Session auf Cloud
$cloudSession = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri https://outlook.office365.com/powershell-liveid/ -Credential "$env:USERNAME#mycompany.com" -Authentication Basic -AllowRedirection
Import-PSSession $cloudSession -Prefix Cloud
#Modul Import von allen Scripts
import-module "\\server\path\Filename.psm1"
# Show available CMDlets
get-commands
So since today when I start my powershell using this profile.ps, powershell loads in, creates the session and then when it jumps to the import-module line it shows the whole code from my custom modul.
Screenshot:
Why? I already tried to add a -Verbose:$false but that doesn't change anything.
How can I get rid of the whole script block it shows from the custom modul?
I solved it by saving the import-PsSession output into a variable like this: $s = Import-PSSession $onpremSession -Prefix onPremises
This gets rid of the output.

Remote powershell sessions can only be established with interactively entered credentials?

I'm trying to automate a powershell script which gathers data from O365. I've got a special limited user setup with the privileges required on O365 and also with local logon allowed on the server so that I can "run-as" that user (which I do for all the scripts below. I have verified different, expected errors when running as other users).
The script works fine interactively when credentials are set like this and the session opened:
$cred = Get-Credential
$Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri https://ps.outlook.com/powershell -Credential $cred -Authentication Basic –AllowRedirection
However, if I create the credentials file for automation with:
Get-Credential | Export-Clixml -Path C:\batch\${env:USERNAME}_cred.xml
And then access from the script via:
$cred = Import-Clixml -Path C:\batch\${env:USERNAME}_cred.xml
$Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri https://ps.outlook.com/powershell -Credential $cred -Authentication Basic –AllowRedirection
The credential file load appears to succeed. I then get "Access Denied" on the session open, and then of course the rest of the script fails due to the session being null. I'm cutting and pasting the password in all cases (plus have tried many, MANY times including hand typing) so I don't think it's a simple typo issue. Seems more like something I'm fundamentally misunderstanding about powershell. Ultimately I'd like to not just have the credentials automated, but also have it run from task scheduler if there's any special settings above and beyond that I also need.
I don't see anything wrong from your code from PowerShell perspective. I have tested the way you are creating credentials within a company domain and I was able to create new session by importing credential XML file that was created by exporting the credentials the way you did. I then assume it might be MS Exchange related.
I can suggest alternatives for you to try:
# First we need to get the encrypted password:
$TempCred = Get-Credential
# provide credentials to the prompt
# now the encryption to be saved in a file
$TempCred.Password | ConvertFrom-SecureString | Set-Content C:\mypass.txt
This was the encrypted version of your password is saved as a text.
In your automation script you can now do this:
$username = "yourusername"
$password = Get-Content C:\mypass.txt | ConvertTo-SecureString
$cred = New-Object System.Management.Automation.PsCredential($username, $password)
$session = New-PSSession -Credential $cred .....
I am not sure if this works in your case, it worked in my company domain. Once again it worked for me the XML version too. I am just providing alternatives to try if you are not keen to find out as to why the XML way did not work.
I was able to get this working, in my environment at least, by including a call to Import-PSSession:
$Credential = Import-Clixml -Path D:\Modules\O365Credentials.xml
$Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri https://outlook.office365.com/powershell-liveid/ -Credential $Credential -Authentication Basic -AllowRedirection
Import-PSSession $Session -DisableNameChecking
Get-Mailbox
Does the account in question have MFA enabled? If so, you might try this.
This script:
Downloads Exchange Online Remote PowerShell Module
Installs Exchange Online PowerShell Module
Connects Exchange Online PowerShell using MFA
Or, you can perform these manually. More information, including a detailed walk-through, is available here:
https://o365reports.com/2019/04/17/connect-exchange-online-using-mfa/

PowerShell returning a PSSession object

I'm new to PowerShell and trying to write some Exchange Online modular scripts for various tasks. The model I'm working on is to have a control script that calls other parameterised scripts to perform reusable functions.
I've written a connection script, but when I return the PSSession object to my command script I can't import the session, it is somehow getting cast to an object.
How should I be sharing this session around my scripts?
Control script:
$session = .\Connection.ps1 -user admin#mydomain.com
Import-PSSession $session
Connection script (summary):
Param (
[string]$userparam
)
$UserCredential = Get-Credential -userName $userparam
$Exch = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri https://outlook.office365.com/powershell-liveid/ -Credential $UserCredential -Authentication Basic -AllowRedirection
return $Exch
First, this is happening because when you run a script it runs in its own scope. You'll get the return value as an object, but it won't be "live" anymore because the scope in which it was created doesn't exist.
Second, it sounds an awful lot like what you really want is a module. Write these pieces as functions, not scripts, and then make them into a single package by writing them as a module.
Doing so would solve your scope problem as well, but the advantages are many.

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