I have a very simple powershell script that has a different behaviour depending on if I execute the script locally or remotely through a Invoke-Command / Enter-PSSession . Other scripts work fine. I'm wondering what is different about the environment of a remote session vs. a local session that would cause this difference.
Assuming the remote endpoint is set up to use your credentials, the remote session may have a different set of modules available (or different versions), there may be a profile script configured to run for the remote session and the environment is likely to be different. Also note that remote endpoints can be configured to limit access to commands (including applications) as well as restrict the language mode. A script could also walk various variables and functions to limit their visibility as well. If you look at session state you can see some of the properties that can be tweaked when configuring a remoting endpoint e.g.:
PS> $ExecutionContext.SessionState
Drive : System.Management.Automation.DriveManagementIntrinsics
Provider : System.Management.Automation.CmdletProviderManagementIntrinsics
Path : System.Management.Automation.PathIntrinsics
PSVariable : System.Management.Automation.PSVariableIntrinsics
LanguageMode : FullLanguage
UseFullLanguageModeInDebugger : False
Scripts : {*}
Applications : {*}
Module :
InvokeProvider : System.Management.Automation.ProviderIntrinsics
InvokeCommand : System.Management.Automation.CommandInvocationIntrinsics
See this article for more info on constrained endpoints. All that said, it is likely you're using the default endpoint which is usually not constrained. Another difference could be bitness. For instance, you could be running in an x86 shell but connecting to a 64-bit endpoint or vice-versa. If you need to connect to a 32-bit endpoint try the following:
PS> $s = New-PSSession -cn localhost -ConfigurationName microsoft.powershell32
PS> icm -Session $s { [IntPtr]::Size }
4
PS> Remove-PSSession $s
Related
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.
I have a question regarding multihopping in a windows environment.
Let's say I have a schedule running on Server A (Central Scheduler) which executes a command on Server B. This script contains a call to save files on a remote filer (UNC path, Server C). Hop 1 (from A to B) works well, hop 2 (from B to C) fails.
I already tested to save the files locally on server B, that works flawlessly.
I think there's a problem with the second hop. I remember reading something like this on a forum a while ago, but can't remember a solution.
In detail, the command looks like this:
$session = New-PSSession -computer ComputerName
$templatepath = "\\filerpath\"
Invoke-Command -Session $session -Scriptblock { powershell ovpmutil cfg pol dnl $Using:templatepath /p \BSH }
To clarify: Powershell gives me an "Access denied" when performing the second hop. I already enabled Credential delegation as described here:
Enabling Multihop Remoting
Any help is appreciated. Thanks in advance
The solution is a real pain in the backside if you ask me but here it is...
On the originating server (A):
Set-Item WSMAN:\localhost\client\auth\credssp -value $true
On the intermediate server (B):
Set-Item WSMAN:\localhost\client\auth\credssp -value $true
Open Group Policy editor on server A, navigate to:
Computer Configuration > Administrative Templates > System > Credentials Delegation
Enable these options:
Allow delegating fresh credentials
Allow delegating fresh credentials with NTLM-only server authentication
Both policies need to have server B added to the allowed list, wildcards are allowed. Note that if you use RDP from server A you'll also need to add TERMSRV/*
When running Invoke-Command from server A, include the -Authentication CredSSP param.
Note that if saving SecureStrings somewhere for the credential to connect to server C, you'll want to either use a fixed encryption (specify byte array) or plain text and convert it.
I am trying to execute some PowerShell code in a remote computer using the following:
$session = New-PSSession -Credential "myDomain\myUserName" -ComputerName "remoteCompName"
$result = Invoke-Command -Session $session -ScriptBlock {
New-Item -type file C:\test10.txt
}
I am prompted to enter my password in a GUI. I do that. It then errors out with:
New-PSSession : One or more computer names are not valid. If you are
trying to pass a URI, use the -ConnectionUri parameter, or pass URI
objects instead of strings.
I replaced the computer name with the FQDN. Still no luck. What is going on here?
There are other questions on stackoverflow on executing PowerShell scripts on remote machines of course but none address this error.
BTW, the machine is part of the domain and is running.
Additional info added later [EDIT]
Things to know:
The machine is part of the domain and is running.
I checked if PS remoting is enabled. It was.
I checked if WinRM is running. It is.
The remote machine is a VM and it is a 2012 R2.
Here is what I've tried:
I replaced the computer name with the FQDN. Still no luck.
I removed the credential parameter
I tried another remote machine (also a VM)
I tried another source machine, i.e. the machine I am running the command from)
Thanks!
-Rohan.
When I use a remote machine with a name that is just alphanumeric (no underscores, dashes, etc.), it works! The name of all machines I tried before had leading '_' in them. That was the cause of the error. (The answer was suggested by Rhys W Edwards on the Windows PowerShell TechNet forum, which is within Windows Server forums).
Just put your ComputerName to braces like this {Remote_Computer_Name}
I'm doing a pilot effort to use the new EventSource (Microsoft.Diagnostics.Tracing.EventSource from nuget) and its new support for ETW channels in order to write to the windows event log. The code is in place, and it writes properly to my workstations event log. I'm thrilled.
Now comes the difficult part. The application that's taking advantage of this capability is a web service, and we deploy it with webdeploy as part of a build-deploy-test system. Because usage of ETW channels requires static registration of provider manifests via wevtutil.exe. The EventSource documentation states that this is best done as part of an installer, but this seems a bit out of webdeploy's capabilities.
Our aim is that we would be able to automatically uninstall the manifest resident on the target server immediately before executing the webdeploy package, and then to import the new manifest after the webdeploy sync has completed. We're not set on this, but it seems like the most sensible way.
For that reason, it seems like maybe this is something that powershell remoting might be able to solve, but it's not an area I know much about.
Has anyone done something like this? Is there a better or simpler way?
There are only a few requirements here. A) the remote machine must have PowerShell remoting enable which also means it must have PowerShell 2.0 or higher B) the script running on the local machine must be able to run as administrator and the credentials used must have admin privileges on the remote machine. If you can meet those requirements then this should be cake.
On the remote machine you need to execute two commands to enable remoting:
Set-ExecutionPolicy RemoteSigned
Enable-PSRemoting -Force
Then on the local machine from an elevated prompt you should be able to execute something like this from a script:
# these two paths assume these files have been copied to the remote computer and to a directory
# in which the service account has privileges to read i.e. not under a userprofile dir.
$etwDllPath = c:\somepath\myassembly.mysourcename.etwManifest.dll
$etwManPath = c:\somepath\myassembly.mysourcename.etwManifest.man
$s = New-PSSession -ComputerName <remoteComputerName>
Invoke-Command -Session $s {param($man) wevtutil.exe um $man} -arg $etwManPath
Invoke-Command -Session $s {param($man,$dll) wevutil.exe im $man /rf:$dll /mf:$dll} -arg $etwManPath, $etwDllPath
Remove-PSSession $s
If you can avoid a remote path with spaces, try to. It will make this easier. :-)
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.