Search code examples
powershellremote-serverwinrm

How to run script against windows servers WinRM


I am trying to run a script that searches/downloads/installs windows updates on remote computers using WinRM. I am running this script as a domain user with Admin access. However, I get an ACCESS Denied error.

Now, I have the script copied over to the remote servers but I am unable to view output to see whether the script is running or not.

OUTPUT I want to see: enter image description here

# Continue running on other servers on error
$ErrorActionPreference = "Continue"

# Server list
$servers = Get-Content "C:\Users\admin\Desktop\vm-nonprod.txt"

# Logs
$log = "C:\Users\admin\Desktop\log-nonprod.txt"

# Path to script on server list
$scriptpath = "C:\Patch.ps1"

$results = @()

foreach ($server in $servers) {

    try {

        $Credential = Import-CliXml -Path "C:\Users\admin\Desktop\admin.Cred"

        #New-PSSession -ComputerName $server -Credential $Credential
        Invoke-Command -ComputerName $server -Credential $Credential -ScriptBlock {$scriptpath} -ArgumentList "Y" | Out-File -FilePath C:\Users\admin\Desktop\WinPatch.txt
        #Invoke-Command -ComputerName $server -Credential hhq\admin -FilePath "C:\Users\admin\Documents\Patch.ps1"
        #Copy-Item -Path C:\Users\admin\Documents\Patch.ps1 -Destination 'C:\' -ToSession (New-PSSession –ComputerName $server -Credential $Credential)
    }
    catch {
        Write-Output ("Error running script on remote host: " + $server)
    }
}

$results | Export-Csv -NoTypeInformation $log

Solution

  • There's a few issues here.

    1. Does the script exist on the server?
      Sounds like yes, you have Patch.ps1 in C:\ on each $server
    2. The scriptblock does not run the script - just prints the variable.
      To run it, change {$scriptpath} to {. $scriptpath} or {& $scriptpath}
    3. The variable $scriptpath is not in the scriptblock scope - you will have to pass it in the -ArgumentList

      Change: {$scriptpath} -ArgumentList "Y"
      ____To: {param($p); . $p} -ArgumentList $scriptpath

    4. The argument "Y" is being passed to the scriptbock, not the script. The scriptblock is not looking for it, so this value is being lost.
      Assume you want it to be passed to the script - this needs to be done in the scriptblock:
      {$scriptpath "Y"}

    5. I would recommend getting rid of Out-File until you are happy with the output in the console.


    Putting it all together:

    -ScriptBlock {$scriptpath} -ArgumentList "Y" | Out-File -FilePath C:\Users\admin\Desktop\WinPatch.txt
    
    -ScriptBlock {param($p); . $p "Y"} -ArgumentList $scriptpath