Search code examples
powershellpowershell-2.0psexecstart-job

I'm trying to execute an existing script on a remote server and capture the output in a local file


I want to run this on multiple servers(nearly 40-50 servers) parallely

$Username = "user"

$Password = "Password"

$servers = get-content "c:\temp\servers.txt"

$sb = {c:\temp\PsExec.exe -h \\$server -u $Username -p $password cmd.exe /c "echo . | Powershell.exe -executionpolicy bypass -file c:\script.ps1" > "$env:userprofile\Desktop\output.txt"} 

foreach($server in $servers)
{
    start-job -ScriptBlock $sb
}

this code works fine if i remove start-job, but executes one after the other, which takes lot of time.

I cannot use PSsession or invoke-command, since it is restricted in our environment.

This code never exits. It stops at this position:

 + CategoryInfo          : NotSpecified: (:String) [], RemoteException
    + FullyQualifiedErrorId : NativeCommandError
 
PsExec v1.98 - Execute processes remotely
Copyright (C) 2001-2010 Mark Russinovich
Sysinternals - www.sysinternals.com

Solution

  • To Start with you aren't passing any of your variables into the job. What you need is to use the $args variable within the ScriptBlock and then pass the variables you want with -ArgumentList.

    $Password = "Password"
    
    $servers = get-content "c:\temp\servers.txt"
    
    $sb = {
      c:\temp\PsExec.exe -h \\$args[0] -u $args[1] -p $args[2] cmd.exe /c "echo . | Powershell.exe -executionpolicy bypass -file c:\script.ps1" > "$args[3]\Desktop\output.txt"
    } 
    
    foreach($server in $servers)
    {
        start-job -ScriptBlock $sb -ArgumentList $server,$Username,$password,$env:userprofile
    }
    

    I probably didn't need to pass the environment variable, but it seemed like you had a scoping problem with the variables.

    Alternatively you could use a Param Block in the ScriptBlock to name your Variables, which essentially maps positionally the Arguments passed into the named variable.

    $Password = "Password"
    
    $servers = get-content "c:\temp\servers.txt"
    
    $sb = {
      Param ($Server,$UserName,$Password,$UserProfile)
    
      c:\temp\PsExec.exe -h \\$Server -u $UserName -p $Password cmd.exe /c "echo . | Powershell.exe -executionpolicy bypass -file c:\script.ps1" > "$UserProfile\Desktop\output.txt"
    } 
    
    foreach($server in $servers)
    {
        start-job -ScriptBlock $sb -ArgumentList $server,$Username,$password,$env:userprofile
    }
    

    I hope this helps. Cheers, Chris.