- SolarWinds Server Performance and Configuration Bundle - Tue, Jun 18 2019
- SolarWinds Patch Manager: Updating Windows and third-party software - Tue, Apr 30 2019
- Monitor file changes in Windows with PowerShell and pswatch - Fri, Feb 1 2019
One of the great features of PowerShell is the ability to run commands and scripts remotely on machines. I often find myself either entering an interactive session with Enter-PSSession or using Invoke-Command on multiple machines at once. I am an old PSExec user, and although I do not find much use for it anymore now that PowerShell can do so many things PSExec does (and better), to me it still has had one benefit.
This would be the ability to run remote commands as the SYSTEM account by specifying the ‑s parameter like this:
PSExec.exe –s \\machine whoami
I have searched in the past for solutions that let me do this in PowerShell, but recently one module has made it possible: Invoke-CommandAs. This module aims to address this very problem in PowerShell, and it does so wonderfully. Its creator is Marc Kellerman, whom I met at PowerShell Summit this year.
How it works
For Windows 8/2012+ systems, the command uses the ScheduledTasks module to register and run script blocks on remote systems. For Windows 7/2008, it creates a scheduled task COM object and invokes the code this way since the ScheduledJobs module is not available on these versions of Windows.
This serves two critical functions. For one, it provides a way to solve the PowerShell double-hop problem by running the code "locally" under a scheduled task. In addition, it creates and runs the task under the SYSTEM account, which can be preferable for things such as installing software.
PowerShell remotely as SYSTEM
To show that the remote commands are actually running under the SYSTEM account, I can do a simple test using the whoami command. Note that I specify ‑AsSystem as a parameter, which is not a parameter you can use in Invoke-Command.
Next, we will do something a bit more interesting. Let's use Invoke-CommandAs to install a Chocolatey package remotely as SYSTEM.
C:\> Invoke-CommandAs -ComputerName TestMachine -ScriptBlock { choco install curl y no-progress } -AsSystem -RunElevated Chocolatey v0.10.11 Installing the following packages: curl By installing you accept licenses for the packages. curl v7.62.0 curl package files install completed. Performing other installation steps. Extracting 64-bit C:\ProgramData\chocolatey\lib\curl\tools\curl-7.62.0-win64-mingw.zip to C:\ProgramData\chocolatey\lib\curl\tools... C:\ProgramData\chocolatey\lib\curl\tools ShimGen has successfully created a shim for curl.exe The install of curl was successful. Software installed to 'C:\ProgramData\chocolatey\lib\curl\tools' Chocolatey installed 1/1 packages. See the log for details (C:\ProgramData\chocolatey\logs\chocolatey.log).
As you can see, it works like a charm, returning me the same output I would see if I ran this command locally.
Solving the double-hop issue
There are various ways to get around the PowerShell double-hop issues, which occur when you attempt to access a Server Message Block (SMB) share from a remote session. Invoke-CommandAs does this within the cmdlet. Not only this, but you can also run the scriptblock as a completely different user and pass your local credential object to the remote computer with the ‑As parameter.
Subscribe to 4sysops newsletter!
PS C:\> $Credential = Get-Credential PS C:\> Invoke-CommandAs -ComputerName TestMachine -ScriptBlock {Get-Item \\Server\Test} -As $Credential Directory: Mode LastWriteTime Length Name ---- ------------- ------ ---- d--hs 12/5/2018 2:58 PM Test
Wrap-up
One of the characteristics I enjoy most about the PowerShell community is the number of quality modules created. Chances are if you are looking for a module for a specific circumstance, it is in the PowerShell Gallery. Invoke-CommandAs does exactly that by solving not only running remote commands as SYSTEM but solving the double-hop issue as well.
Thanks for the shoutout!
Nice Article Dan!
I have to download Mark’s module and kick the tires; it looks super useful!
Great article Dan. Thanks for sharing.
If Invoke-CommandAs is not available, where can I get this module?
Thanks…
James
@James
Amazing!
What would be the syntax if you wanted to run a separate powershell script as the logged in user?
Something like this…
Invoke-CommandAs -FilePath C:\Scripts\PowershellScript.ps1 -ComputerName WIN10 -Interactive
But it's looking for argument for that parameter.
I'm trying to run a script that the user interacts with. It seems like no matter what parameters I use, the script does not run interactively with the logged on user. I tried this…
…but notepad still ran as me and not the logged in user.
Have you tried the command on the first line? 🙂 It does not return a property named UserName from remote system. Even when I try the command locally, the UserName is empty.
Furthermore – executing something under user context does not mean that the user will get a GUI of that process…