Powershell – How to combine two foreach loops

powershelluser-managementwindows-server-2003workgroup

I've looked at how to combine multiple commands with psexec but none of the methods seems to work. Maybe it's because I'm running the script in PowerShell and not cmd.exe?

I need to create user accounts AND add them to the local Administrators group on non-domain computers (Windows 2003). I've derive the following script (which works) but I'm wondering if there's an easy way to combine the two foreach loops as it has to establish the psexec connection twice for each server.

$username = Read-Host "User name:"
$password = Read-Host "Password:"
$fullname = Read-Host "Full name:"
$computers = Get-Content C:\Tools\scripts\ServerList.txt

foreach ($computer in $computers) {
    psexec \\$computer -u username -p password net user $username $password /add /fullname:""$fullname"" /comment:"Comment"
}

foreach ($computer in $computers) {
    psexec \\$computer -u username -p password net localgroup Administrators $username /add
}

As I mentioned, this is being run in PowerShell. The servers that I'm running it on are Workgroup Windows 2003 Servers without PowerShell installed.

Best Answer

As @CIA said, you can combine the loops by just running psexec twice in one loop.

$username = Read-Host "User name:"
$password = Read-Host "Password:"
$fullname = Read-Host "Full name:"
$computers = Get-Content C:\Tools\scripts\ServerList.txt

foreach ($computer in $computers) {
    psexec \\$computer -u username -p password net user $username $password /add /fullname:""$fullname"" /comment:"Comment"
    psexec \\$computer -u username -p password net localgroup Administrators     
}

But it seems like what you're really asking is how to run both net commands in a single psexec session.

$username = Read-Host "User name:"
$password = Read-Host "Password:"
$fullname = Read-Host "Full name:"
$computers = Get-Content C:\Tools\scripts\ServerList.txt

foreach ($computer in $computers) {
    psexec \\$computer -u username -p password net user $username $password ullname"" /comment:"Comment" ^&^& net localgroup Administrators     
}

You can try it this way, but I'm not sure it will work. The && is escaped using ^ so that it gets passed to psexec instead of being interpreted locally, which would have then run the second net command locally.

Alternative

What you could do instead is not use psexec at all and use PowerShell remoting. It just has to be enabled on each machine you want to remote into. I realize this might be a bit of an undertaking, but it will be worth it since it's way more versatile, and basically, it's the future.

If you're in a domain, you can even use Group Policy to enable PowerShell remoting (full disclosure: this is my article).

If you did that, your code would look like this:

$username = Read-Host "User name:"
$password = Read-Host "Password:"
$fullname = Read-Host "Full name:"
$computers = Get-Content C:\Tools\scripts\ServerList.txt

foreach ($computer in $computers) {
    Invoke-Command -ComputerName $computer -ArgumentList $username,$password,$fullname -ScriptBlock { param($u,$p,$f)
        # Everything in here is executed on the remote computer
        net user $u $p /add /fullname:""$f"" /comment:"Comment"
        net localgroup Administrators     
    }
}