Powershell Remoting Profiles - powershell

How do I use a function in my profile on the remote machine when using Enter-PSSession on my local machine to open a remote PowerShell session.

By JonZ and x0n:
When you use pssessions with the default session configurations, no profile scripts run.
When starting a remote interactive session with Enter-PSSession, a remote profile is loaded. Additionally, only the machine-level profile in $pshome is loaded.
If you want a session to be preconfigured (to load custom functions, snap-ins, modules, etc.), add a profile script to a new sessionconfiguration (for initialize them in the startup script of the remote session configuration).
The Register-PSSessionConfiguration cmdlet creates and registers a new session configuration on the local computer. Use Get-PSSessionConfiguration to view existing session configurations. Both Get-PSSessionConfiguration and Register-PSSessionConfiguration require elevated rights (start PowerShell with the “Run as Administrator” option).
In the target computer, where profile.ps1 contains all your functions:
Register-PSSessionConfiguration -Name WithProfile -StartupScript $PsHome\Profile.ps1
To use this preconfigured session you would type, from the local computer:
Enter-PSSession -ComputerName $computername -ConfigurationName WithProfile
or
Enter-PSSession -ComputerName $computername -ConfigurationName WithProfile -Credential youradminuser#yourtargetdomain
(where $computername is the hostname of the remote server where you registered the pssessionconfiguration).
A good source on PowerShell remoting is the Administrator's Guide to Powershell Remoting.
References:
Powershell Remoting: Use Functions loaded in Powershell remote Profile?
http://jrich523.wordpress.com/2010/07/21/update-creating-a-profile-for-a-remote-session/
Understanding and Using PowerShell Profiles
http://blogs.technet.com/b/heyscriptingguy/archive/2013/01/04/understanding-and-using-powershell-profiles.aspx
About_Profiles (Microsoft Docs)
https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_profiles
The six different Windows PowerShell profile paths and use
Current User, Current Host - console
$Home[My ]Documents\WindowsPowerShell\Profile.ps1
Current User, All Hosts
$Home[My ]Documents\Profile.ps1
All Users, Current Host - console
$PsHome\Microsoft.PowerShell_profile.ps1
All Users, All Hosts
$PsHome\Profile.ps1
Current user, Current Host - ISE
$Home[My ]Documents\WindowsPowerShell\Microsoft.PowerShellISE_profile.ps1
All users, Current Host - ISE
$PsHome\Microsoft.PowerShellISE_profile.ps1
Windows PowerShell Profiles
http://msdn.microsoft.com/en-us/library/bb613488%28VS.85%29.aspx
This profile applies to all users and all shells.
%windir%\system32\WindowsPowerShell\v1.0\profile.ps1
This profile applies to all users, but only to the Microsoft.PowerShell shell.
%windir%\system32\WindowsPowerShell\v1.0\ Microsoft.PowerShell_profile.ps1
This profile applies only to the current user, but affects all shells.
%UserProfile%\My Documents\WindowsPowerShell\profile.ps1
This profile applies only to the current user and the Microsoft.PowerShell shell.
%UserProfile%\My Documents\WindowsPowerShell\Microsoft.PowerShell_profile.ps1
PowerShell Core Profiles
https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_profiles
This profile applies to all users and all hosts.
$env:ProgramFiles\PowerShell\6\profile.ps1
This profile applies to all users, but only to the current host.
$env:ProgramFiles\PowerShell\6\Microsoft.PowerShell_profile.ps1
This profile applies only to the current user, but affects all hosts.
$env:USERPROFILE\Documents\PowerShell\profile.ps1
This profile applies only to the current user and the Microsoft.PowerShell shell.
$env:USERPROFILE\Documents\PowerShell\Microsoft.PowerShell_profile.ps1

Jason,
In my case, I wanted to have my Powershell Profile follow me when I remoted into another computer.
I have created a wrapper function Remote that takes a computername, creates a session, loads your profile into the session, and uses enter-pssession.
Here is the code below:
function Remote($computername){
if(!$Global:credential){
$Global:credential = Get-Credential
}
$session = New-PSSession -ComputerName $computername -Credential $credential
Invoke-Command -FilePath $profile -Session $session
Enter-PSSession -Session $session
}
You could modify the Invoke-Command -FilePath parameter to take any file of your liking.

take a look at this
http://jrich523.wordpress.com/2010/07/08/creating-a-profile-for-a-remote-session/
its a work around for creating a remote profile.

You can't. When starting a remote interactive session with enter-pssession, a remote profile is loaded. Additionally, only the machine-level profile in $pshome is loaded. If you want remote functions available you'll have to initialize them in the startup script of the remote session configuration. Have a look at get/set-pssessionconfiguration on the remote server.

There is another way to use a profile on a remote session:
Copy the chosen profile to the remote server(s) in your documents folder. For example:
Copy-Item -Path $profile.CurrentUserAllHosts -Destination \\computername\C$\Users\MyAccountName\Documents
Enter the PSSession
Enter-PSSession -ComputerName ComputerName
Dot source your profile
. .\Profile.ps1
Drawbacks of this solution:
you must copy once your profile to all the computers where you want to have a profile
you must dot source the profile every time you enter a PSSession
Advantages of this solution:
There is no need of function and you just enter a PSSession like you always do
You do not alter all users' profile by changing the default session configuration
(Thanks to Jeffery Hicks for the tip about the dot sourcing)

Related

how to get winrm to use powershell 7 for remote sessions by default

With the release of powershell 7, seems like it is time to move past ps 5.1 so I have installed in on a couple of servers to give it a go.
However I when I create a session to these servers from my pc with ps7 I am always running ps5.1 on the remote machine.
Invoke-Command -ComputerName name -ScriptBlock {
Write-Host $env:COMPUTERNAME
$PSVersionTable.PsVersion
}
Which outputs 5.1.17763.316. Any ideas how to get the remote session to use version 7.0.0 preferably by default?
Update
making some progress with this, so though I would share.
On the remote machine in powershell 7 run the following command
Enable-PSRemoting
This will create some PsSessionConfigurations which you can see with the following command..
Get-PSSessionConfiguration
Now you can do the following to create sessions from powershell 7
Invoke-Command -ComputerName ServerName -ScriptBlock { $PsVersionTable.PSVersion } -ConfigurationName Powershell.7
$session = New-PSSession ServerName -ConfigurationName Powershell.7
Invoke-Command -Session $session -ScriptBlock { $PsVersionTable.PSVersion }
This now uses ps 7 on the remote session, happy days. Now how to make this happen by default...? From this github issue :
set the default microsoft.powershell endpoint to any PowerShell they
choose
Which I think is what I want to do so switched back to ps 5.1 and tried this command:
Get-PSSessionConfiguration -Name microsoft.powershell | Set-PSSessionConfiguration -PSVersion 7.0
Only to get the following output:
Set-PSSessionConfiguration : Cannot bind parameter 'PSVersion' to the
target. Exception setting "PSVersion": "The value 7.0 is not valid for
the PSVersion parameter. The available values are 2.0, 3.0, 4.0, 5.0,
5.1."
though I would try this in ps7 so switched back by running pwsh and ran the same command again to get he following...
Write-Error: No session configuration matches criteria
"microsoft.powershell".
So still not quite sure how to make ps7 the default... :(
Note:
It is the remoting client that determines what remoting endpoint (session configuration) to connect to on the server machine - see below.
Therefore, your own attempt,
# WRONG
Get-PSSessionConfiguration -Name microsoft.powershell |
Set-PSSessionConfiguration -PSVersion 7.0
is ineffective, because Set-PSSessionConfiguration modifies endpoint configurations on the server machine, it doesn't control the client's behavior.
Note that the fundamental prerequisite is that PowerShell remoting must be enabled on the server machine, which can be achieved either by opting to do so during installation via the MSI GUI installer, or by running Enable-PSRemoting - with admin privileges - later.Tip of the hat to Lars Fosdal.
Doing so from PowerShell (Core) creates the standard session configuration(s) named PowerShell.<version> that clients can opt to connect to - see below.
To list all configurations defined on a server, run Get-PSSessionConfiguration with admin privileges.
On a client machine, you can set a default for what session configuration defined on the server (remote machine) to connect to, via the $PSSessionConfigurationName preference variable.
E.g., to target PowerShell 7 by default:
# When remoting, default to running PowerShell Core v7.x on the
# the target machines:
$PSSessionConfigurationName = 'PowerShell.7'
If you add the above to your $PROFILE file, future sessions will target PowerShell 7 by default.
See this answer for more information, which also shows how to target a given server configuration in the context of individual commands.
Note: Changing what endpoint PowerShell [Core] targets by default - which as of 7.2 is still Window PowerShell - is being considered: see GitHub issue #11616.

Powershell "screen" - keep the processes running even the connection is dropped?

I'm using enter-pssession to run scripts on remote servers. So I can login remotely to the servers. Run commands interactively, close the powershell console and later I can reattach the session and check the commands outputs.
Is there a Linux screen like functionality in powershell? I cannot use Windows remote desktop to connect the servers.
You can use Invoke-Command with -InDisconnectedSession, it will start session in asynchronous mode. After you can connect to this session, take data from it, etc. You can read more about this here.
You can create session, disconnect from session, connect back to it.
May be useful for you: New-PSSessionOption with -IdleTimeout.
-IdleTimeout:
Determines how long the session stays open if the remote computer does not receive any communication from the local computer. This includes the heartbeat signal. When the interval expires, the session closes. MSDN Link
I have recently run into double-hop issues with using PSSessions. What I did to work around that is to create a Session Configuration on the remote server that uses the -RunAs parameter to set the credentials that I need the commands on the remote server to be executed as. Then you connect to that session configuration on the remote server, and things should work as expected.
$MyCreds = Get-Credential ''
Invoke-Command -ScriptBlock {
Set-PSSessionConfiguration -Name "My Remote Config" -RunAsCredential $using:MyCreds -Force
} -ComputerName Server01
Then once the session configuration exists I can start a session using that config, and the whole double hop issue is null and void.
Now, mind you I do add some additional security, so that other people cannot use my session config, since that config has my credentials cached on the server (encrypted), and if they used that config they could do whatever they wanted as me. So to accomplish that I get my domain account SID, generate a SDDL line, and restrict access to the Session Config to only my account.
$Searcher = [adsisearcher]"(&(sAMAccountName=$($Creds.UserName.Split('\')[1]))(objectClass=user))"
$Results=$Searcher.FindOne().GetDirectoryEntry()
$MySID = new-object System.Security.Principal.SecurityIdentifier($Results.objectSid.value,0)|% value
$SDDL = "O:NSG:BAD:P(A;;GR;;;BA)(A;;GR;;;IU)(A;;GA;;;$MySID)S:P(AU;FA;GA;;;WD)(AU;SA;GXGW;;;WD)"
$FQDN = $Server.ServerName,$Server.Forest -join '.'
$MySessionName = "DoubleHop-{0}" -f $MyCreds.UserName.Split('\')[1]
Invoke-Command -ScriptBlock {
Register-PSSessionConfiguration -Name $using:MySessionName -RunAsCredential $using:MyCreds -Force -SecurityDescriptorSddl $using:SDDL
} -ComputerName $FQDN -ea 4

When powershell is "runas" different user (different domain as well), get that user's domain, and not the logged in user's (on localhost) domain

I know how to get the domain of the user that you are logged into on windows. That's not the problem.
You can do that with $env:USERDOMAIN (and various other ways...)
My situation:
I'm logged into windows as D1Username under DomainOne.
I run cmd and do: runas /user:DomainTwo\D2Username /netonly powershell
In this powershell session, I have the permissions of D2Username, obviously.
When I do $env:USERDOMAIN, I get DomainOne, when (I would think) I should be getting DomainTwo.
What can I do, if anything, to get the domain of the user that is being logged into via "runas"?
I don't have the resources to test this atm., but isn't this exactly what the /netonly parameter is for?
/netonly : Indicates that the user information specified is for
remote access only.
Source: Runas # TechNet
$env:USERDOMAIN is a local variable/run inside a local process, so it should report the domain of your local user. However, if you check the variable while remoting another computer, the runas credentials should be used for the network authentication (and because of that the remote session) and it would hopefully return DomainTwo. Try:
Invoke-Command { $env:USERDOMAIN } -ComputerName computer2.domainone.com
Removing the /netonly from the runas-command should give you the desired output.

New-MailboxExportRequest don't work in remote PSsession

i often use the New-MailboxExportRequest 's command on an exchange server in powershell console, like this one :
Add-PSSnapin Microsoft.Exchange.Management.PowerShell.E2010;
New-MailboxExportRequest -Mailbox jadrego –filepath \\computer1\c$\test.pst -verbose
it works correctly. But if I run those commands in PS remote session like this one :
I use the same User (Domain Admin, Exchange Admin)
Invoke-Command -ComputerName vdiv03 -ScriptBlock {
Add-PSSnapin Microsoft.Exchange.Management.PowerShell.E2010;
New-MailboxExportRequest -Mailbox jadrego –filepath \\computer1\c$\test.pst
}
I obtain this error :
failed to comunicate with mailbox database
with -verbose
Loading the snapin like that isn't supported in Exchange 2010.
IMHO, you'd be much better off just leveraging the native remoting built into Exchange for management tasks.
$ExchangeServer = <exchange serer name>
$SessionParams =
#{
ConfigurationName = 'Microsoft.Exchange'
ConnectionURI = "http://$ExchangeServer/powershell/"
Authentication = 'Kerberos'
# Credential = $Creds
}
$Session = New-PSSession #SessionParams
Invoke-command -ScriptBlock {New-MailboxExportRequest -Mailbox jadrego –filepath \\computer1\c$\test.pst} -Session $Session
Remove-PSSession $Session
Set $ExchangeServer to the name of one of your Exchange 2010 servers. The account will need to be a member of the necessary RBAC role for the function you're performing, and you can uncomment the Credential parameter and provide alternate credentials for the session if you need to.
This will also elimnatat the need to have the management tools installed on the computer that's running the script, and the associated headaches of keeping it patched to the same level as what's on the servers.
If you're working interactively, or running a script that uses many Exchange cmdlets you can add the session creation to your profile, and do an Import-PSSession and you'll have proxy functions for the Exchange cmdlets available locally that you can use the same as if you'd loaded the snapin.
Import-PSSsession $Session
Some caveates to be aware of:
When you use implicit remoting like this, the account of the credentiaals used to establish the session will determine what capablilities you will have. What appear to be Exchange cmdlets added to the local session are actually proxy functions ( you can verify this using Get-Command). This set of proxy functions is created dynamically by Exchange when you initially establish the session and will be customized according to the RBAC roles the account making the connection belongs to. If it doesn't have permissions to perform given functions you will not get the proxy functions for those cmdlets, or functions may not have parameters for those functions.
The results you get back will not be the same as the same as the native objects returned if you used an EMS shell, or loaded the snapin. They will be deserialized objects, which means they may be missing methods and will lose some fidelity compared to the native objects. There will be very few instances where this will be an issue, or cannot by worked around.
Also be aware that when you use implicit remoting, updates are made under the authority of an Exchange system account, not your credentials. When you use the snapin, your account must have permission to update the Exchange properties stored in AD directly, and those changes will be logged in Windows audit logs (if enabled) as having been made by that account. When you use implicit remoting they will be recorded as being done by the Exchange service account. Exchange will record the details of the actual user account that made the request in it's admin audit log, and you can use Search-AdminAuditLog to find out when changes were made, and by who even if Windows audit logging is not enabled. If you use the snapin directly and do not have AD audit logging enabled you will lose that audit trail.

Powershell 3.0: Using my local profile and modules in remote PSSessions

I need my local $profile located on my local PC to be loaded automatically when I PSRemote into other computers. My $profile also imports a few local modules (available only on my local PC). So, I need my $profile to be enhanced so that my modules can be still be imported (regardless where my $profile is loaded).
I spent a lot of time trying to get this to work; but see a lot of inconsistent information posted (probably because the differences between PS2 and PS3). Everything I tried, resulted in some kind of error.
I was hoping someone would help me with a dummy-proof working example of how to do this. The only thing that actually works is a basic: enter-pssession -ComputerName RemoteServerName. I did try to at least get my local profile to load in a remote session (see below), but that didn't work either; let alone loading the modules imported in the profile file.
Register-PSSessionConfiguration -Name MyLocalProfile -StartupScript $Profile
Enter-PSSession -ComputerName REMOTESERVERNAME -ConfigurationName 'MyLocalProfile'
Gives error:
Enter-PSSession : Connecting to remote server REMOTESERVERNAME failed with the following error message : The WS-Management service cannot process the request. Cannot find the MyLocalProfile session configuration in the WSMan: drive on the REMOTESERVERNAME computer.
I even tried:
Register-PSSessionConfiguration -Name MyLocalProfile `
-StartupScript \\MYLocalPC\profile$\Microsoft.PowerShell_profile.ps1
But, but it still produced the same error. Not sure why it should be this hard to do something that most people would most likely want to happen by default.
Short answer: You're doing it incorrectly, and it's impossible to do it that way.
Long Answer:
From the Enter-PSSession page on MSDN, a line stands out:
The session configuration for a session is located on the remote computer. If the specified session configuration does not exist on the remote computer, the command fails.
Therefor you will have to Invoke-Command the Register-PSSessionConfiguration before creating the new session.