9

First post so please don't hurt me. I've searched around but can't seem to find a way to do what I want. I've made a script that copies a folder I have to numerous computers at \$computer\c$. In these folders is a batch file that runs an .exe. What I want to do is have Powershell pull from the same computers.txt that I used to copy the folder and then use psexec to run the batch file. I could do this all manually but scripting it seems to be a problem, here's what I thought would work but apparently not.

    $computers = gc "C:\scripts\computers.txt"

foreach ($computer in $computers) {
if (test-Connection -Cn $computer -quiet) {
    cd C:\pstools
    psexec \\%computer cmd
    C:\Folder\install.bat"
} else {
    "$computer is not online"
}

}

noz3r0
  • 315
  • 3
  • 4
  • 16

4 Answers4

12

Ok, let's take it from the top then.

$computers = gc "C:\scripts\computers.txt"

That loads the contents of the "computers.txt" file into the variable $computers. Simple enough, no issues there.

Next we have a ForEach loop. It splits up the contents of $computers and processes each line (presumably the name of a computer) as $computer against all the code within the curly braces.

foreach ($computer in $computers) {

That loop starts up with a standard If-Then statement. If (condition) then {do stuff}. In this case it is testing to see if the $computer is available on the network. If it is, then it attempts to run PSExec on it. If it isn't online it runs the Else clause, we'll get to that in a second.

if (test-Connection -Cn $computer -quiet) {

Then it changes directory. Kind of pointless, but ok, whatever. You could have just called it explicitly, such as C:\PSTools\PSExec.exe <arguments> and saved a line, but there's really no harm done.

cd C:\pstools

Then you are calling PSExec, though there's a little syntax error here. It should be $computer and not %computer. Also, it should just have the command you want to execute, not cmd and the command on a second line. You may have better results if you use the Call operator (&) to make powershell realize that it's trying to execute something and not run a cmdlet or function or what not.

& psexec \\$computer C:\Folder\install.bat

After that is the Else clause that says if the computer isn't online to write the string "$computer is not online" followed by closing braces for the Else clause and the ForEach loop.

} else {
    "$computer is not online"
}


}

Edit: Ok, your finished script should look something like this (enclosed target in quotes in case there are spaces in the path):

$computers = gc "C:\scripts\computers.txt"

foreach ($computer in $computers) {
    if (test-Connection -Cn $computer -quiet) {
        & C:\pstools\psexec.exe \\$computer "C:\folder\install.bat"
    } else {
        "$computer is not online"
    }
}
TheMadTechnician
  • 34,906
  • 3
  • 42
  • 56
  • Ok I see how I could shrink that down a bit. Thanks for the full break down. My issue now is that I can't get the Psexec function to work correctly and I'm not sure what I'm doing wrong. If I were doing this manually I would open up a command prompt and type 'psexec \\hostname cmd' then I would be in that machines command prompt, from which I could just navigate to the folder I want and run the batch file. – noz3r0 Apr 16 '14 at 21:09
  • Are you sure that it is failing? PSExec will throw an error if you run it in the PowerShell ISE, and still function. There is a reason for it, and it has to do with how PSExec outputs data, and some of it is output to the standard output stream, and some of it is output to the error stream. Regardless, are you sure that it is not working? – TheMadTechnician Apr 16 '14 at 21:26
  • I see you tossed an edit up there, my final script wasn't like what you had, I'll give that a go in the morning and let you know. It seems like it should work though. Thank you for your diligence. – noz3r0 Apr 16 '14 at 23:28
  • Hey that did it. Thanks for your help and patience. I tried to toss some upvotes your way but apparently I can't do that. Is there a way to mark this as "Answered?" – noz3r0 Apr 17 '14 at 12:01
  • on the left side there should be an option to mark the question as answered next to my answer, just below the Mark Up and Mark Down thing. – TheMadTechnician Apr 17 '14 at 15:13
7

I realize this question is from 2014, and this answer will not directly address the question the user asked. But for people who come across this question these days, I want to throw out there that you don't need to use PSExec if you're using PowerShell*. Since you're already in PowerShell, just use Invoke-Command.

Syntax would be

Invoke-Command -ComputerName $Computer -ScriptBlock { C:\Folder\install.bat }

It's really that easy.

*Requires PowerShell remoting to be enabled on the target server. << Some people are using PSExec to enable PSRemoting by running winrm quickconfig... So it's still a valid question and the two things "PSExec" and "PSRemoting" are different.

Community
  • 1
  • 1
Benjamin Hubbard
  • 2,797
  • 22
  • 28
  • 3
    This is a gross over-simplification. If install.bat needs to double-hop, this won't work. – Reuben Tanner Sep 06 '16 at 19:32
  • 2
    "*PowerShell remoting" is a significant difference, especially for a production env which might not be configured to support it. *By default* Win2016/Win10 and earlier have PSExec remoting enabled and WinRM disabled. – Zephan Schroeder Jul 17 '19 at 00:22
2

Give this a try. You had a % where you wanted a $. Also the cmd.exe call is unnecessary.

    $computers = gc "C:\scripts\computers.txt"

foreach ($computer in $computers) {
if (test-Connection -Cn $computer -quiet) {
    cd C:\pstools
    psexec \\$computer "C:\Folder\install.bat"
} else {
    "$computer is not online"
}

}
Spamwich
  • 121
  • 2
  • False alarm. It won't run psexec like that, says its not a valid cmdlet. Is there a command to run executables? – noz3r0 Apr 16 '14 at 20:57
0

use & (call) operator , &psexec \$computer "C:\Folder\install.bat"

Craig Hill
  • 61
  • 3