Scenario: Windows service with Powershell host embedded into it. Single runspace is allocated at startup. Multi-dll solution.
Requirement: Need to access .NET classes inside running service. From a local Powershell instance using
Enter-PSHostProcess -Name MyService
...gives me exactly what I want since I can access the .NET classes.
[MyNameSpace.MyClass]::CallStaticFunction()
Question: How can this Powershell behavior be made available to remote endpoints using Enter-PSSession to a custom endpoint? From the Register-PSSessionConfiguration we can specify a dll but this will spawn up a process and won't connect to a running instance. Not interested in writing proxy via HTTPS, or named pipes, but using the native functionality offered in Powershell for .NET support.
Is it possible to extend this via PSSessions? Or would we just have to first do Enter-PSSession or Invoke-Command?
Reviewing the sources it appears that Enter-PSHostProcess and Enter-PSSession are very independent mechanisms. Enter-PSHostProcess communicates via named pipes, while Enter-PSSession uses WinRM (which is effectively uses http(s) over ports 5985/5986. I don't think you need either Enter-PSSession or Invoke-Command if you want interactive access to a local service process through Enter-PSHostProcess.
You may have already done this, but to try this out I started up both Powershell.exe and Powershell_ise.exe, then from the former used this command to connect to the later:
get-process Powershell_ise | Enter-PSHostProcess
and the prompt changed to include the PID of the ISE. Just to be sure static methods worked as you are expecting, I killed the ISE from the Powershell.exe command line using the command:
[System.Environment]::exit(0)
Powershell creates the named pipe this connects to using the default security descriptor for the thread, which typically allows access only to LocalSystem, Administrators, and the account the process is running under. My test worked because both processes were running under the same account (I didn't need administrator priv.)
To be clear however, Enter-PSHostProcess makes no provision for connecting to processes on another machine. It might be possible to double-hop, connecting to the machine first using Enter-PSSession, then connecting to the process using Enter-PSHostProcess.
Related
Can I supply a version of powershell to be used on the target machine while ps remoting.
May be my question is not proper or not possible to answer but if any body having idea please help me.
I am trying to do a remoting using powershell on a machine where powershell 2.0 3.0 and 4.0 versions are available , but I want to use the version 4.0 only (on target machine)
is it possible?
Thanks
Gyan
Yes, there is a way to connect to a specific version of Powershell on a remote machine. It does require changes to be made on the remote machine though.
When you use Powershell remoting to make a connection, you are always connecting to a specific profile on the other end. Typically this profile is called Microsoft.Powershell, but other products create their own endpoints, like Exchange for example.
You can create your own profiles, called session configurations, setting various settings, including the Powershell version.
The way to do this is to first create a session configuration file using New-PSSessionConfigurationFile and then register it on the target machine using Register-PSSessionConfiguration.
The version can be sepcified in both places (the value in Register-PSSessionConfiguration takes precedence) but only needs to be specified in one place.
Once you've got the session you want on the target machine, use New-PSSession with the -ConfigurationName parameter to create the session, and use Invoke-Command with the -Session parameter to pass the result of New-PSSession.
I have a test bed in my lab consisting of a windows server 2008 running powershell 2.0. I am using that server to manage 50 clients that are connected wired and wireless with the server. I am running windows Active Directory on the server and all the clients are in the domain I created and I am using the AD to push different policies. I have a lot of basic scripts running (shutting down all interfaces on the clients, shutting down clients, fetching logs from clients etc.). But there is one Task in particular that is extremely important for my setup and I am facing a lot of issues with it. Here are the details:
I want to start some applications like windows media player or a VLC player on all the clients through a script. The script will be run on the server and it should try and establish connection with all the clients and bring up the UI.
What has been tried?
Method 1:
New-Pssession -computername -credential
Enter Pssession -id
(brings up the prompt on the remote machine)
start-process wmplayer.exe
Everything runs correctly. A process gets created on the client, but I do not see the UI.
Method 2:
I created a batch file on the remote machine that runs the wmplayer.exe. It works fine and brings up the UI if executed manually from the client, but again if triggered remotely it only creates a process and does not bring up the UI.
Am I missing something while running the commands? Do I need to configure something more to get the UI up and running?
I'm trying to deploy a windows service to remote machine with a parameter being used at service start-up.
I have two issues:
How to actually use the Invoke-WmiMethod (powershell) to pass service with parameters
Starting a service on Windows Server 2012 with a parameter.
ad1) I am publishing service currently like this:
Invoke-WmiMethod -class Win32_process -name Create -ArgumentList ("C:\PathToService\ServiceExecutable.exe install") -ComputerName RemoteComputer.local
This is done in this way as this is self-installable/uninstallable service. What I tried so far is getting the service object after installing the service like this
$(Get-Service -ComputerName RemoteComputer.local -Name ServiceName)
but failed to see how I could attach/modify the startup parameters on it.
ad2) This one completely baffles me;
This is a normal Service dialog since I can remember. Whatever you put into the start parameters should be passed to the service as args.
This just doesn't happen for me on Windows Server 2012 only!.
If I run it under Windows 8 - all is well.
If I run it in a console - all is well.
If I run it under Windows Server 2012 through service manager - logs show it fails to get the args.
Does not make any difference if I use different accounts (network, admin,...).
I would recommend using a local app.config instead.
That way you can specify all configuration you need, without needing to resort to startup parameters.
I have the following batch script on a Windows 2008 R2 server:
#echo off
djoin.exe /provision /domain my.domain.com /machine test /savefile savefile.txt
echo %ERRORLEVEL%
If I run the script on the server itself, either through command prompt or PowerShell, it works perfectly fine and returns "0".
The problem is that I need to execute it from a remote computer, so I do the following (an example just for testing):
Invoke-Command -ComputerName remotehost -ScriptBlock {.\script.cmd}
The output is "-1073740940", which is probably error code C0000374, which could have something to do with heap corruption.
This seems to be a problem with the djoin command itself. I can comment out djoin and run other binaries, like ping, with no issues using the same Invoke-Command.
Keeping in mind that the script works perfectly fine when executed from PowerShell on the target computer, what issues could the act of remoting be introducing?
In both cases, the script is executed with the same privileges using my account, which is a member of Domain Admins. I doubt that it's a permissions issue and have no idea where else to look.
[edit]
Gave up on the whole thing. This is either a bug in djoin or some obscure problem in the interaction between djoin and PS remoting.
I managed to run djoin directly on the client, using 'runas /netonly ...' to provide domain credentials. It's a very messy solution (and I have yet to figure out how to get the exit status of a process started by runas), but gets the job done.
This is almost certainly a classic "double-hop" authentication issue. Remember that when you use PowerShell Remoting you're using up one of those hops. Anything you execute on that remote machine that accesses a third remote machine is unlikely to work if it requires authentication.
To get around that, you can use an authentication method which allows you to Delegate Credentials such as CredSSP. It's a bit more involved than simply changing your authentication type as you have to make changes on the client side and the server side of the transaction. Refer to this blog post on MSDN, PowerShell Remoting and the “Double-Hop” Problem and this "Hey, Scripting Guy!" post, Enable PowerShell "Second-Hop" Functionality with CredSSP.
I've recently upgraded a number of servers from 2003 to 2008R2. Since the upgrade I've started to see the following error:
[servername] Connecting to remote server failed with the following error message : The WSMan service could not launch a host process to process the given request. Make sure the WSMan provider host server and proxy are properly registered. For more information, see the about_Remote_Troubleshooting Help topic.
The error is seemingly random. The script will work and then fail. The command to create the session is in a loop (create session, remove session) and is called numerous times as part of a set of deployment scripts. When the script fails, it fails at different points.
I've checked the event log on the local workstation (win7) destination server (win2008R2) but there are no errors that I can see.
This is the lines that randomly fails:
$session = New-PSSession -ComputerName $serverName -Credential $credential
I did not see this issue on Win2003. The scripts have not changed. I'm assuming the problem is on the destination server but cannot find any errors or logs to look at. It will work once and then fail so my deployment scripts will sometimes succeed and then fail at different points.
Any guidance on tracking down this problem would be much appreciated.
You can get this error when trying to connect to localhost with an account that's not an administrator.
It used to be possible to use accounts that weren't an administrator, but a Windows Update in January 2019 disabled the functionality for security reasons. From the patch notes:
By default, PowerShell remoting only works with administrator accounts, but can be configured to work with non-administrator accounts. Starting with this release, you cannot configure PowerShell remote endpoints to work with non-administrator accounts. When attempting to use a non-administrator account, the following error will appear:“New-PSSession: [computerName] Connecting to remote server localhost failed with the following error message: The WSMan service could not launch a host process to process the given request. Make sure the WSMan provider host server and proxy are properly registered. For more information, see the about_Remote_Troubleshooting Help topic.”
You need to be setting the WSMan TrustedHosts. If you want, you can set it to everything using wildcards (*).
You can do it via PowerShell: Set-Item WSMan:\localhost\Client\TrustedHosts -Value *.
Keep in mind that you also need to enable the Windows Remote service. Use the native winrm qc command for this. Enable-PSRemoting -Force might do it as well.
You can also use the PSExec Tools from Sysinternals. Keep in mind that these tools will likely be blocked by your EndPoint Security, so don't forget to white list it.
Is there a specific reason you migrate your old OSes to a newer, but still EOL OS? You can do a lot via PowerShell in 2008R2, but it's still pretty limited. IMO, Using PowerShell is best starting from 2012R2 and onwards.
Are you hitting the number of processes limit by creating pssessions that are crashing and leaving processes open?
Default limit is 15. I'd agree with the above comment and not use sessions, instead use invoke-command like:
invoke-command -scriptblock $scriptBlock -ArgumentList $args -computername $compName -Credential $encodedRemoteCredentials
to Check your limit:
PS C:\aws> ls WSMan:\localhost\Shell
WSManConfig: Microsoft.WSMan.Management\WSMan::localhost\Shell
Name Value
---- ----
MaxProcessesPerShell 15
As a quick and dirty test - next time your pssession version of your script fails, increase the maxProcessesPerShell limit using set-item cmdlet to 50 and retry. If the script no longer fails, you know that's the issue (and should consider moving to invoke-command!).