Learn about Windows PowerShell
Summary: Microsoft Scripting Guy Ed Wilson discusses how to manage remote Windows PowerShell sessions.
Hey, Scripting Guy! I can see where being able to run a command on a remote computer might be kind of cool. But more often than not, I need to actually sit at the console of the remote computer. For this, I have been using remote desktop protocol (RDP) to display the remote desktop. I then open Windows PowerShell and do my work. It is okay, but a bit slow. I am wondering if there is a better way to do things?
Microsoft Scripting Guy Ed Wilson here. Well things are certainly getting exciting. It is now official—there is a Windows PowerShell Users group in Pittsburgh, Pennsylvania, in the United States. The first meeting is on December 13, 2011, from 6:00 P.M. until 8:00 P.M., and the Scripting Wife and I have been invited to the first meeting. Mark your calendars! If you are within driving range (or even a short flight), you do not want to miss this exciting presentation. The meeting will be held at the Microsoft office in downtown Pittsburgh. I will be speaking about Windows PowerShell best practices (and the Scripting Wife will be there signing autographs, and being nice and fun to talk to). Make sure you go to the PowerShell Community Groups and join the Pittsburgh PowerShell Users Group, and register for the meeting. This will allow the president of the group, Ken McFerron, to know how much food to order for the meeting.
CH, the first thing I do when working with remoting is use the Get-Credential cmdlet to store a credential object in a variable. This allows for a great deal of flexibility, and permits me to try various commands without the need to constantly type the user name and password. The command here prompts for the password for the administrator account of the Contoso domain:
$cred = Get-Credential -Credential contoso\administrator
If all I need to do is to run a few Windows PowerShell commands on the remote computer, I will go ahead and directly enter into a Windows PowerShell session. To do this, I use the Enter-PSSession cmdlet and specify both the remote computer name as well as the credentials to use. Here is the command I use to enter into a remote Windows PowerShell session:
Enter-PSSession -ComputerName syddc01 -Credential $cred
In the following figure, I store credentials in a variable, enter a remote Windows PowerShell session, and use the hostname.exe command to determine the name of the computer to which I am connected.
After I enter a remote Windows PowerShell session, I can use the Windows PowerShell cmdlets without worrying about firewall issues, remote credentials, or anything. The cmdlets work as if I were sitting at the Windows PowerShell console. For example, I can use Get-Process or Get-Service directly without specifying computername parameters. This is great because neither Get-Process nor Get-Service exposes a credential parameter, so it is more complicated to run the commands with alternate credentials.
In the following figure, I am connected to the remote server, SydDc01. I first examine the explorer process. Next, I look for services that contain the letters WMI. Next, I look for services that contain the letters ws. I then exit the remote session, and run the same commands on the local host. The great thing is the remote session, and the local session share the same Windows PowerShell command history. Therefore, I can simply up-arrow to retrieve the previous commands.
I can even enter a remote Windows PowerShell session on another computer, and still use the same history of commands. This makes it really convenient to run the same commands on multiple computers.
To see if there are any Windows PowerShell sessions running, I use the Get-PSSession cmdlet. This is the syntax:
One of the things I like to do is to store a session. This allows me to enter and leave the remote Windows PowerShell session without worrying about overhead. To do this I use the Get-Credential cmdlet to obtain a credential object to use with the remote computer for creating a remote Windows PowerShell session. I then store the credential object in a variable. Syntax for this command is shown here:
$cred = Get-Credential
Next, I use the New-PSSession cmdlet to create a new session to a remote machine. I specify a name for the session, and the computername of the remote computer. For credentials, I use the credentials I stored in the $cred variable. I store the returned PSSession object in a variable:
$syddc01 = New-PSSession -Name syddc01 -ComputerName syddc01 -Credential $cred
Now that I have a PSSession stored in a variable, I can use the Enter-PSSession cmdlet to enter into a remote Windows PowerShell session. Here is the command I use to enter the PSSession stored in the $syddc01 variable:
I can now work in the Windows PowerShell remote console as if I were working on my local computer. I can use the Get-Service cmdlet to return information about the bits service. I can also use wildcard characters with Get-Service to display information about every service that matches a wildcard pattern. I can then exit the Windows PowerShell session by using the exit command. Next, I can use the same commands on my local computer, and then return to the remote session by again using the Enter-PSSession cmdlet. I can again exit the session, and run commands locally. These commands are shown here:
Get-Service -name bits
Get-Service -Name *ii*
The commands and associated output are shown in the following figure.
After I am finished with my remote work, I remove the PSSession; removing unused PSSessions frees up resources. The easy way to remove a PSSession is to pipe the results of Get-Session to Remove-PSSession. This command is shown here:
Get-PSSession | Remove-PSSession
CH, that is all there is to reusing a Windows PowerShell remote session. Join me tomorrow as I talk about more cool Windows PowerShell stuff.
I invite you to follow me on Twitter and Facebook. If you have any questions, send email to me at firstname.lastname@example.org, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.
Ed Wilson, Microsoft Scripting Guy
PS remoting really rocks!
It is something that you have to become used to.
It's easy and very efficient!
But, if you haven't been working with remote machines on a regular basis, it might be a little bit confusing ... and you may not always be aware of "WHERE you are" :-)
So: Be careful!
You may need to RDP onto the remote machine and run PowerShell as Administrator and then run "winrm quickconfig" before the above commands will work.
I love remoting! To make things easier for me, I store an encrypted password as a file and read it in when as part of my profile.
$Password = Get-Content C:\Users\jspatton\cred.txt |ConvertTo-SecureString
$Credentials = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList "Domain\Administrator", $Password
Awesome post Ed!
So, if I am using a computer that is part of Domain A, let's say...and I want to run active directory cmdlets against a trusted domain called Domain B, let's say.....how do I specify the domain in a cmdlet so I can administer Domain B?
This is an amazing post... Thanks a bunch...
This is a wonderful post so useful.
Great guide, its helped a lot thanks.I wonder if you can help though. Once connected to the remote session I am trying to run a batch job from a unc path and even though I am an administrator, i am getting access denied.Syntax:$cred = get-cred # I supply a domain admin account$x=new-pssession -computername x -credential $credenter-pssession $x -credential $cred[x]: PS c:\> set-location \\somew2k8server\c$Result:Set-Location : Access is denied + CategoryInfo : PermissionDenied: (\\somew2k8server\c$:String) [Set-Location], UnauthorizedAccessException + FullyQualifiedErrorId : ItemExistsUnauthorizedAccessError,Microsoft.PowerShell.Commands.SetLocationCommand Set-Location : Cannot find path '\\somew2k8server\c$' because it does not exist. + CategoryInfo : ObjectNotFound: (\\somew2k8server\c$:String) [Set-Location], ItemNotFoundException + FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.SetLocationCommand
@CPThis is known as a 'double hop' and cannot be done unless you enable CredSSP delegation on that server you using for the possession. You can either look at using Delegated Administration or use the Enable-CredSSP cmdlet to set this up. Some links below for assistance.http://blogs.technet.com/b/heyscriptingguy/archive/2013/04/04/enabling-multihop-remoting.aspxhttp://blogs.technet.com/b/askds/archive/2012/08/02/windows-powershell-remoting-and-delegating-user-credentials.aspx