In my previous article, we discussed how to use PsExec. As promised, today we will discuss the various use cases in which you can use PsExec and PowerShell together, working as a team.
Avatar
Latest posts by Surender Kumar (see all)

How to run PowerShell commands remotely with PsExec

First, let's discuss how to run PowerShell commands on remote computers with the help of PsExec. This ability of PsExec might not be useful for people working in domain environments since they can use PowerShell remoting. However, it is still worth discussing as not everyone works in a domain. There are many small organizations that are still operating in a workgroup environment.

To run a PowerShell command on a remote computer with PsExec, you need to use the -command parameter, as shown in the following example:

psexec.exe \\webserver Powershell -command Get-Service w3svc

Since the -command parameter is the default for PowerShell, you can even skip typing it and just type the command itself, as shown in the following screenshot:

Running a single PowerShell command on a remote computer with PsExec

Running a single PowerShell command on a remote computer with PsExec

This command starts the PowerShell process on a remote web server. Then, the PowerShell process in turn runs the Get-Service command specified as a parameter. The command actually gets the status of the worldwide web publishing service on the remote webserver, and PsExec brings the result to your local computer.

There are situations in which you might want to run multiple PowerShell commands on remote computers. If you have even a small amount of experience with PowerShell, you probably know that a quick way to run multiple PowerShell commands is to separate them using a semicolon (;). Unfortunately, this will not work straight with PsExec, but we can use the call operator or ampersand (&) to do the job for us. The following example shows how to do this:

psexec.exe \\webserver powershell "&{start-service wuauserv; get-service wuauserv}"

This command starts the Windows Update service on the remote webserver, and then shows the status of the service. The call operator (&) causes PowerShell to treat the string following it as a command. The commands will work if you omit the braces, but I prefer adding them for readability. Note that the call operator itself needs to be enclosed in quotes. The following screenshot shows the command in action:

Running multiple PowerShell commands on a remote computer with PsExec

Running multiple PowerShell commands on a remote computer with PsExec

Using this technique, you can run multiple PowerShell commands with PsExec on multiple remote computers.

Run a PowerShell script remotely using PsExec

PowerShell remoting is great since it allows system admins to run commands on remote computers. But PsExec can help you take PowerShell remoting to the next level, since it enables you to run PowerShell scripts on multiple remote computers. The following command shows how to execute a PowerShell script on a remote computer:

psexec -s \\webserver Powershell -ExecutionPolicy Bypass -File \\192.168.0.3\scripts$\Get-CompInfo.ps1

This command executes a PowerShell script (Get-CompInfo.ps1) on a remote web server; the script itself is stored in a network share. The -ExecutionPolicy Bypass parameter allows the PowerShell script to execute even if the execution policy on that computer is set to Restricted mode. To run the script on multiple computers, you can either use a file (with entries in the format @computer.txt) or specify a list of comma-separated computer names, as discussed in the How to use PsExec guide.

A quick note on PowerShell execution policy—it is a security measure that controls how PowerShell scripts are handled by the computer. When in Restricted mode, it doesn't allow execution of any PowerShell scripts.

Running a PowerShell script on a remote computer with PsExec

Running a PowerShell script on a remote computer with PsExec

The screenshot shows that the current execution policy on the remote webserver is Restricted, but the script was still executed anyway. Note that the command needs to be run carefully; order matters here with regard to the parameters. If you specify the -File parameter first and the -ExecutionPolicy parameter later on, the command won't work. See the following screenshot for reference:

PowerShell error The file cannot be loaded because running scripts is disabled on this system

PowerShell error The file cannot be loaded because running scripts is disabled on this system

You will see a different error depending on the execution policy set on the remote computer. In Windows client operating systems (Windows 10, Windows 11, etc.), the default execution policy is Restricted, and in Windows Server operating systems (Server 2016, Server 2019, etc.), the default execution policy is RemoteSigned.

This error occurs because the PowerShell process (which is launched by PsExec on remote computers) complies with the execution policy before actually executing the script you specified using the -File parameter. Since you specified the script with the first parameter, it is blocked in the first place and the -ExecutionPolicy Bypass parameter isn't even considered. I hope this makes sense.

Run PsExec via PowerShell script

To use PsExec in a PowerShell script, we can again use the call operator or ampersand (&). See the following PowerShell script for an example:

$Computers = Get-Content D:\MyScripts\Computers.txt
foreach ($Computer in $Computers) {
    if (!(Test-Connection -ComputerName $Computer -Count 2 -Quiet)) {
        Write-Host "The $Computer is not reachable..."
    } else {
        Write-Host "Installing software on $Computer..."
        &\\192.168.0.254\Share$\PSTools\psexec -s -h -f \\$Computer -c \\192.168.0.254\Share$\Scripts\install.bat
    }
} 

This is a simple PowerShell script that I use to perform unattended deployment of a few applications in my environment. The interesting thing is in the line number 7. Look how the call operator or ampersand (&) character is used to call PsExec from a remote share. This technique is particularly useful if you don't want to install PsExec on all computers. If you have PsExec set up on all computers, you can specify the complete local path to the PsExec executable.

Have a look at the following screenshot:

Running PsExec within a PowerShell script on multiple remote computers

Running PsExec within a PowerShell script on multiple remote computers

I intentionally executed this script in PowerShell ISE since it shows some detailed information (in the section marked in red) that you won't see in the regular PowerShell console.

If you get error code 1619 while doing a package installation using PsExec, make sure the installation package is accessible on the remote computer. See the following screenshot as an example:

This installation package could not be opened - error code 1619

This installation package could not be opened - error code 1619

The installation package might not be accessible by the user you specified in the script, or you haven't specified the alternate user at all. If you don't specify the alternate user with PsExec, your currently logged-in user is impersonated, and it won't have access to network resources. In this situation, you need to use the -u switch with PsExec to specify an alternate user that has sufficient access to the network share containing the installation package.

Usage examples with PsExec and PowerShell

In this section, I will cover a few use cases in which you can use PsExec and PowerShell together.

Access to highly restricted objects

We know that there are certain objects in Windows that are accessible to highly privileged users only (such as NT AUTHORITY\System). The HKEY_LOCAL_MACHINE\SYSTEM and HKEY_LOCAL_MACHINE\SAM subkeys are good examples of such objects. If you try to access these objects with PowerShell alone, you will get an error stating, "Requested registry access is not allowed," as shown in the screenshot.

Invoke-Command -ComputerName webserver -ScriptBlock {Get-ChildItem -Path "HKLM:\SECURITY"}
Registry Error- Requested registry access is not allowed

Registry Error- Requested registry access is not allowed

To get around this access problem, you could use PsExec and PowerShell together, as shown in the following command:

psexec \\webserver -s powershell -command "Get-ChildItem -Path 'HKLM:\SECURITY'"
Accessing the restricted registry subkeys using the PsExec System switch

Accessing the restricted registry subkeys using the PsExec System switch

Enable PowerShell remoting on all computers

We all know that PowerShell remoting requires manual configuration on remote computer(s) before you can start using it. In these cases, PsExec proves to be really useful. The following command enables PowerShell remoting on all the computers using the domain_computers.txt file that we created earlier:

psexec @domain_computers.txt -s -h powershell -command Enable-PSRemoting -Force
Enable PowerShell remoting using PsExec

Enable PowerShell remoting using PsExec

Change the service start mode on all computers

Every organization has a different requirement when it comes to setting up Windows services. Some organizations prefer disabling unnecessary services and setting up the service startup mode. The following command is a mix of PsExec and PowerShell to set the startup mode of the Windows Update service to auto on all domain computers:

psexec "\\$((get-adcomputer -filter *).name -join ',')" -s -h sc config wuauserv start=auto

Note that the command must be executed in the PowerShell console instead of the regular command prompt. The "\\$((get-adcomputer -filter *).name -join ',')" part uses PowerShell to dynamically build the computer names in a comma-separated list by pulling all computers from AD. It then feeds the list to PsExec to run whatever process you want to run.

Change the start mode of a service using PsExec and PowerShell on all computers

Change the start mode of a service using PsExec and PowerShell on all computers

Conclusion

These are just a few examples of use cases where you can use PsExec and PowerShell together. Once you start using them yourself, you will realize that the potential is unlimited. You will be able to accomplish things that are hard to achieve with a single tool alone. You can remotely manage services, manage software, troubleshoot problems, perform security assessments, perform penetration testing, and much more.

Subscribe to 4sysops newsletter!

Also read: PsExec vs. the PowerShell remoting cmdlets Invoke-Command and Enter-PSSession

avatar
7 Comments
  1. Avatar
    Darren 2 years ago

    But how can one use Psexec to execute a PowerShell script on a Windows server, and inject domain username/password (eg. Create-FailoverCluster that requires permissions to create AD computer object)?

    The user invoking the PowerShell script is NT AUTHORITY\SYSTEM (from an Azure DevOps automated pipeline), but need the PS1 file to run with domain credentials. I can get the username and password to the script, but seems that it is not allowed to elevate the creds.

    Any advice?

    • Avatar Author

      The -h switch of PsExec takes care of elevation problems. By the way, if nothing else works, you could use regular PowerShell remoting command like this:

      Invoke-Command -ComputerName remoteServer -FilePath D:\Scripts\yourScript.ps1 -Credential domain\admin

  2. Avatar
    julio 7 months ago

    Hello.. I am trying make work a .ps1 file (Pop-Up or Balloon Tip Notification from PowerShell) unsuccefully, any comment about it? or better said I think I do it work…….but do not show nothing on screen (remote device) (file tested ok in Both devices)

    PSExec -s -i 3 -d \\JA-LAP -u cmd /c Powershell -ExecutionPolicy Bypass -File ‘\\\\PSTest.ps1’
    -Show cmd and closed inmediatly but no Pop-up any Notification

    Do any comment ?

  3. Avatar
    julio 7 months ago

    Hello.. I am trying make work a .ps1 file (Pop-Up or Balloon Tip Notification from PowerShell) unsuccefully, any comment about it? or better said I think I do it work…….but do not show nothing on screen (remote device) (file tested ok in Both devices)

    PSExec -s -i 3 -d \\ -u cmd /c Powershell -ExecutionPolicy Bypass -File ‘\\\\PSTest.ps1’
    -Show cmd and closed inmediatly but no Pop-up any Notification

    Do any comment ?

    This code in case you needed !!
    https://dotnet-helpers.com/powershell/creating-a-balloon-tip-notification-using-powershell/

  4. Avatar
    julio 7 months ago

    This code in case you need it !!
    https://dotnet-helpers.com/powershell/creating-a-balloon-tip-notification-using-powershell/

    *Note: When I used Angle Bracket in your post do not show them property.
    -File \sharedfolder\pathtofile\PSTest.ps1

    THY.

    avatar
  5. Avatar

    Julio – there’s no need to call cmd from your psexec. Also, you’re trying to run two contradictory switches: -i (interactive) and -d (non-interactive).. that’s more than likely going to fail.

    try it like this:
    psexec -s -i 3 -h \\ powershell -executionpolicy bypass -file \pstest.ps1

    The pstest.ps1 file has to be local to the system (the system account can’t access network resources).

    David F.

    avatar
  6. Avatar

    Just noticed the angle brackets got deleted from my post.. but it looks like we had the same thoughts..

    \\machinename and the full path to the .ps1 file.

    PSExec is going to start in System32 by default if I remember correctly.

    David F.

Leave a reply

Please enclose code in pre tags: <pre></pre>

Your email address will not be published. Required fields are marked *

*

© 4sysops 2006 - 2023

CONTACT US

Please ask IT administration questions in the forums. Any other messages are welcome.

Sending

Log in with your credentials

or    

Forgot your details?

Create Account