Configure PowerShell Remoting and Use Remote Commands

Configure PowerShell Remoting and Use Remote Commands

  • Comments 11
  • Likes

Summary: Learn how to configure Windows PowerShell remoting, store credentials, and use remote commands.

 

Hey, Scripting Guy! QuestionHey, Scripting Guy! I keep hearing about Windows PowerShell remoting. But I do not really know what Windows PowerShell remoting is. For example, I can use the Get-WMIObject to work with remote computers. Is that remoting? If so, what is the big deal? I could do that in Windows PowerShell 1.0. Is this just a bunch of typical marketing hype, or is there something that actually works here and I am missing it?

—GB

 

Hey, Scripting Guy! AnswerHello GB,

Microsoft Scripting Guy Ed Wilson here. GB, I hate to tell you, but you are missing the boat. There is a common misconception about what Windows PowerShell remoting really is. There are several ways to run a command on a remote computer:

  1. Windows Management Instrumentation (WMI) can target a remote computer via the computername parameter. The Get-WMiObject cmdlet also allows for alternate credentials.
  2. The computername cmdlets (not including the Get-WmiObject cmdlet). There are a lot of cmdlets that have a computername parameter. These cmdlets permit making a connection to a remote computer and retrieving information from them. However, not all of these cmdlets have a credential parameter and therefore they must run with administrator rights on the remote computer. In addition, in many cases these cmdlets require specific holes open in the firewall, and even certain services running on the remote machine before they will work properly. To find the cmdlets that have a computername parameter, use the following Windows PowerShell command:

    get-command -CommandType cmdlet | where { $_.definition -match 'computername'}
  3. Some computername cmdlets do permit the use of alternative credentials. These cmdlets allow you to run a command against a remote machine, and to specify the context in which to run the command. This solves the problem of supplying alternative credentials. To find these cmdlets, use the following Windows PowerShell command (gcm is an alias for the Get-Command cmdlet, and ? is an alias for the Where-Object cmdlet; the command is a single command, and I did not include any line continuation;it has wrapped in the output here, but would appear on a single line in the Windows PowerShell console):

    gcm -CommandType cmdlet | ? { $_.definition -match 'computername' -AND $_.definition -match 'credential'}
  4. True, Windows PowerShell remoting is the other way to run a Windows PowerShell command on a remote computer. Windows PowerShell remoting uses Windows Remote Management (WinRM) as the underlying technology, and is therefore firewall friendly. WinRM is Microsoft’s implementation of the WS-Management Protocol that allows hardware and operating systems from different vendors to interoperate. It is industry standard, and extremely powerful.

The first thing to do is to enable and configure Windows PowerShell remoting. To do this, use the Enable-PSRemoting cmdlet. Enable Windows PowerShell remoting on all machines that will communicate. If this only involves a couple computers, using the Enable-PSRemoting cmdlet works fine. But if you need to turn on Windows PowerShell remoting on an entire organizational unit, domain, or forest, it is better to use Group Policy. Unfortunately, there are myriad Group Policy settings from which to choose, and I like the convenience of the Enable-PSRemoting cmdlet. Therefore, I use a script that calls the Enable-PSRemoting cmdlet with Group Policy and assign it as a logon script. I discuss this technique in the Enable PowerShell Remoting to Enable Running Commands blog post.

After it is configured, I like to use the Invoke-Command cmdlet to ensure that Windows PowerShell remoting works properly. By running a simple command such as hostname.exe, I ensure that Windows PowerShell remoting works, and confirm the actual location that ran the command. Here is the syntax:

invoke-command -cn syddc01 -credential contoso\administrator -scriptblock {hostname}

After I have run that command, I know everything works. Now, I like to store my credentials in a variable to make it easier to run remote commands. To do this, I use the Get-Credential cmdlet. Here is the command I use:

$cred = Get-credential contoso\administrator

When the command runs, the following dialog box is displayed.

Image of dialog box displayed when command is run

After I have a credential object stored in the $cred variable, I use it to invoke a remote command. These commands are shown here:

$cred = Get-Credential contoso\administrator

invoke-command -cn syddc01 -cred $cred -script {hostname}

Now, I want to use the Invoke-Command cmdlet to run the Get-Process cmdlet on a remote computer and use alternate credentials. The syntax for this command is shown here (this command uses the cn computername alias for Invoke-Command, the credentials stored in the $cred variable, and the gps alias for the Get-Process cmdlet):

Invoke-Command -cn syddc01 -Credential $cred -ScriptBlock {gps}

The command and associated output are shown in the following figure.

Image of command and associated output

GB, that is all there is to getting Windows PowerShell remoting up and running, and storing credentials in a credential object to simplify running remote commands. Join me tomorrow when I will talk about creating remote Windows PowerShell sessions.

I invite you to follow me on Twitter and Facebook. If you have any questions, send email to me at scripter@microsoft.com, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.

Ed Wilson, Microsoft Scripting Guy

 

 

 

Your comment has been posted.   Close
Thank you, your comment requires moderation so it may take a while to appear.   Close
Leave a Comment
  • Hi Ed,

    remoting support in powershell is one of the major advantages it offers for administration of remote machines. It nearly makes me forget about psexec.exe ( part of the Sysinternals suite )

    There is one tradeoff: We can't work interactivly on remote machines via PS remoting!

    This feature has been considered a security risk and so it is not available in powershell, which sometimes is the only reason to fall back on psexec ...

    Klaus.

  • PowerShell remoting supports an interactive remoting (so called 1:1 remoting) with the Enter-PSSession cmdlet. The Enter-PSSession cmdlet starts an interactive session with a single remote computer. During the session, the commands that you type run on the remote computer, just as though you were typing directly on the remote computer.

  • Dear Aleksandar,

    you are right ... and I am right :-)

    It depends on the meaning of the word "interactive", I'm afraid!

    Well, if you enter a pssession, you are in fact "on/in the remote system" and you can work interactive ... true!

    But you won't see a GUI on the remote machine!

    That's what I meant because I have to start interactive (=~ GUI) programs remotely and it makes no sense to do so, without the graphical interface ... even if some of the programs would begin automatically to do their work, I couldn't see any progress and can't pause/resume - interact them without their controls :-(

    Klaus.

  • I cant seem to find anything about enabling remote access on remote machines. If I want to enable\configure powershell remote access on remote machines, how would I do that (if I couldnt use group policy, but the machines are all on the same domain, and users are local administrators on their machines)?

  • Can you point me to a blog in which you have perhaps talked about using Powershell to retrieve some information from a Unix server?

  • Mr. Scripting Guy,

    When u run the following command:

    Invoke-Command -cn syddc01 -Credential $cred -ScriptBlock {gps}

    You get the output from the remote server.

    When I do the same thing, regardless of the command or script that I try to run on the remote server, all I get is the command/script outputted and nothing else. Am I doing something wrong?

    PS C:\Users\pekelly> Invoke-Command -ComputerName test003 -cred $cred -ScriptBlock {"gps"}

    gps

    PS C:\Users\pekelly>

    PS C:\Users\pekelly> Invoke-Command -ComputerName test003 -cred $cred -ScriptBlock {"c:\test.bat"}

    c:\test.bat

    PS C:\Users\pekelly>  

    Thanks,

    Pete

  • @Peter - I already answered that. Taks the quotes off of the command.

    Commands wil lnot execute is conteined in quotes.  Quotes tell POwerSHell to jsut output the contents to teh shell as a string after evaluating any tokens in teh string.  This:

    $x='Some Text'

    "Get-Process  $x"

    Will output:

    Get-Process Some Text

    Go to a prompt and try it.

    Same thing inside of a script block.

    $sb={"Get-Process  $x"}

    icm $sb

    This will produce the same output.

    Do not put quotes aroung executable statements at the commandline or in a scriptblock.

  • Thanks JRV!! That was a big help!

    Peter

  • HI Peter.  I usually don't answer questions on Ed's forum but this one had just come up more than once in two days.  Glad it helped and sorry for the typos.  You can't edit after clicking 'Post' and I keep forgetting that.

  • The following remote command with parameters works if I hard-code the parameters as strings. By work, I mean that the batch script on the remote server can see the parms.

    Invoke-Command -ComputerName server123 -cred $Creds {param($p1, $p2, $p3)  c:\RunScript.bat "abc" "def" "ghi"}

    But if I turn the strings into variables($p1 $p2 $p3) then the remote batch script sees no parameters.

    $p1="abc"

    $p2="def"

    $p3="ghi"

    Invoke-Command -ComputerName server123 -cred $Creds {param($p1, $p2, $p3)  c:\Script.bat $p1 $p2 $p3}

    Any ideas???

    Thanks,

    Peter

  • Found my answer. Something like this works:

    Invoke-Command -ComputerName server123 -cred $Creds -Script { param($Module, $Build,  $soapuiProject) c:\TestAutomation\RunSoapUIScript.bat $Module, $Build,  $soapuiProject } -Args $Module, $Build,  $soapuiProject