powershellupdatesremote-accessinvoke-commandstart-process

Execute Start-Process Powershell Script on a Remote Computer


I open PowerShell as admin and use the following line of code to run an offline file for windows updates. It works fine

Start-Process 'wusa.exe' -ArgumentList 'C:\Temp\windows10.0-kb5032189-x64_0a3b690ba3fa6cd69a2b0f989f273cfeadba745f.msu' -verb runas

But now I am trying to somehow use this same code to run the file on remote computers. The windows update file has the same name and the exact location on the remote PCs

I came up with this code below which first gets admin credentials and passes it to the the invoke-command. Then the invoke-command runs the Start-Process code.

$Username = 'username123'
$Password = '84fWfghnsf&5Fh'
$pass = ConvertTo-SecureString -AsPlainText $Password -Force
$Cred = New-Object System.Management.Automation.PSCredential -ArgumentList $Username,$pass
Invoke-Command -ComputerName 8HPF31J7V6.domain.local -Credential $Cred -ScriptBlock {Start-Process 'wusa.exe' -ArgumentList 'C:\Temp\windows10.0-kb5032189-x64_0a3b690ba3fa6cd69a2b0f989f273cfeadba745f.msu' -verb runas}

Problem is, when I do this, nothing happens on the remote PC

I also don't get any errors when running

enter image description here

Any ideas on what I am doing wrong, or any other solutions besides this?


Solution

  • Caveat:


    Therefore, with synchronous execution:

    # ... credential construction code ($Cred) omitted
    # Note: If the *current user* is allowed to make remoting calls,
    #       you may not need to construct credentials and don't need the 
    #       -Credential parameter below.
    
    # Note the use of -Wait, removal of -Verb RunAs
    Invoke-Command -ComputerName 8HPF31J7V6.domain.local -Credential $Cred -ScriptBlock {
      Start-Process -Wait wusa.exe -ArgumentList 'C:\Temp\windows10.0-kb5032189-x64_0a3b690ba3fa6cd69a2b0f989f273cfeadba745f.msu'
    }
    

    Read on for an asynchronous alternative. Note that the (Start-Process -PassThru …).ExitCode technique shown below, for reporting the remote process' exit code, can equally be used with the synchronous approach above.


    Asynchronous execution:

    If you don't want the Invoke-Command call to wait for the remotely launched process (wusa.exe) to terminate, you have two options:

    Asynchronous variant with -AsJob, which additionally demonstrates how to report the remote process' exit code:

    # ... credential construction code omitted
    
    # Note the use of -AsJob and the use of -PassThru with Start-Process
    # so as to be able to report the process' exit code.
    $remoteJob = 
      Invoke-Command -AsJob -ComputerName 8HPF31J7V6.domain.local -Credential $Cred -ScriptBlock {
        (
          Start-Process -Wait -PassThru wusa.exe -ArgumentList 'C:\Temp\windows10.0-kb5032189-x64_0a3b690ba3fa6cd69a2b0f989f273cfeadba745f.msu'
        ).ExitCode
      }
    
    # ... perform foreground activity here.
    
    # Now wait for the remote job to complete - which happens when 
    # wusa.exe terminates - and report its exit code.
    $exitCode = 
      $remoteJob | Receive-Job -Wait -AutoRemoveJob