Run multiple PowerShell Invoke-Command - powershell

I have been working to automate my SQL patching. I have found that I can run the command below from my central server and it will perform the upgrade on the remote computer. My issue is that I can only run one command at a time until the command comes back with a response. I am trying to figure out how I can run this command against 100 different computers at one time and all the upgrades can be performed at once in parallel and not one by one.
Invoke-Command -computername SQLServer1 -command {D:\DBA\SQLPatching\SQL_2014\SP1\Patch-SQL2014_SP1.bat}
I would just be replacing the -computername parameter with my list of servers being patched.
Does anyone have any suggestions?

Invoke-Command -ComputerName $computers -ScriptBlock {D:\DBA\SQLPatching\SQL_2014\SP1\Patch-SQL2014_SP1.bat }
Assuming that bat file is in D on all the computers. Using invoke-command will run in parallel if you have a list of machines to pass to if.
If you instead used a ForEach $computer in $computers you would have it run one at a time.

Related

Powershell : I am trying to run a script on a remote server. The script is for gathering info of that remote and other servers in the same domain

Editing to be clear with the issue
I am running the below code from a local computer which should run the script Test.ps1 placed on $server at C:\Temp to collect data from $server and other servers.
When i perform this, the script runs but i only get data for the $server and not the others. While if i run the C:\Temp\Test.ps1 script sitting on the $server, i get the desired output for all servers.
I am using this code
$s = New-PSSession -ComputerName $server -Credential $credential
Invoke-Command -Session $s -Command {C:\Temp\Test.ps1}
I am getting the output for the remote server on which the code is placed (localhost for the script), buti am not getting any output for the other servers.
While if I run the script locally on the remote server i get output from all the servers
The script does not have to be on the remote host. PowerShell allows you to run local PS1 scripts on remote computers.
Running Remote Commands
https://learn.microsoft.com/en-us/powershell/scripting/learn/remoting/running-remote-commands?view=powershell-7.1
Run a Script
To run a script on one or many remote computers, use the FilePath
parameter of the Invoke-Command cmdlet. The script must be on or
accessible to your local computer. The results are returned to your
local computer.
For example, the following command runs the DiskCollect.ps1 script on
the remote computers, Server01 and Server02.
Invoke-Command -ComputerName Server01, Server02 -FilePath 'c:\Scripts\DiskCollect.ps1'
As for this...
'My requirement is to run that script from the remote host per
security protocols'
... just use a script block as shown via the same MS Docs link
Run a Remote Command
To run a command on one or more computers, use the Invoke-Command
cmdlet. For example, to run a Get-UICulture command on the Server01
and Server02 remote computers, type:
Invoke-Command -ComputerName Server01, Server02 -ScriptBlock {& .c:\Scripts\DiskCollect.ps1}
Of course, I just removed Get-UICulture cmdlet in the docs command, with a script to use.
It depends on how your remote script uses credentials to access other servers. This should classify as a double hop issue.
If you cannot use CredSPP, you can use Resource-Based Kerberos Constrained Delegation
or use credentials inside the Invoke-Command scriptblock i.e. you can define a credential object on the local computer to be used in the -credentials parameter, and refer to it with $using:cred in your scriptblock.
The article does a good job of summarizing all your options.

Start an executable on a remote station

I have a executable that resides on a remote station that I am trying to run from a central server, but running into issues. I am able to stop the Process on the remote station from the server using
Invoke-Command -ComputerName $name {Stop-Process -Name "ProcessName"
But when I try and run the executable, using
Invoke-Command -ComputerName $Args Start-Process "C:\Process\Process.exe"
it returns an error
This command cannot be run due to the error: The system cannot find the file
I have tried many variations of Invoke-Command, Start-Process, along with specifying the UNC path using the $name variable, but it will not run the executable stored on the remote computer.
You should run it like this:
Invoke-Command -ComputerName $name -ScriptBlock {
Set-Location c:\path\to\exe
FileName.exe /switch 1 /switch 2
}
You don’t need to use Start-Process. Just call the file and it should start execution.

Powershell remote install/app run

I am going to try and install software remotely onto a server and first i am trying to play around with the invoke-command cmdlet in powerhsell. Below is what I have so far
cls
Exit-PSSession
New-PSSession -ComputerName vm912test
Enter-PSSession -ComputerName vm912test -Credential sceris\pmanca
Invoke-Command -Computername vm912test -ScriptBlock {Start-Process "calc.exe" -wait}
Get-PSSession
However when i run this i see no running tasks in task manager. Does anyone know what i am missing? Once i can get this to work i will expand onto trying to remotely install some software first. I have no issues on communicating with the server and i have remote access/admin access on the box.
I updated with some more code but still receiving the same result that nothing is happening.

Installing Windows Features on remote server 2012 using powershell 3.0

I am wondering which is best practice considering both examples will probably work. Using the built in help examples I have written a script to install windows features on remote servers. Here is my code:
$servers = ('server1', 'server2', 'server3', 'server4')
ForEach ($server in $servers) {
Install-WindowsFeature -Name Desktop-Experience -ComputerName $server -IncludeAllSubFeature -IncludeManagementTools -Restart
}
Would the above be preferred OR should I wrap the "Install-WindowsFeature ..." in an "Invoke-Command" block like the following?
Invoke-Command -ComputerName server1, server2, server3, server4 -command {
Install-WindowsFeature -Name Desktop-Experience -ComputerName $server -IncludeAllSubFeature -IncludeManagementTools -Restart
}
Thanks for your insight!
Personally I would use the latter (directly call Install-WindowsFeature -ComputerName $server rather than do a separate Invoke-Command) in this case for the following reasons:
You may be hard-coding the feature names now, but in the future you may want to put those in a variable. If you put them in a variable, you'll have to pass it as a parameter into the Invoke-Command's script block. This is entirely possible, but more work.
By using your own loop, you can write progress messages, logging, etc.
You gain nothing by using Invoke-Command in this case because you're running a single command on the remote computer (as opposed to running multiple commands with -ComputerName parameters vs. running multiple commands inside the script block).

Can you run remote commands without psexec?

I am attempting to run a batch file on several remote machines. It has some registry changes and other commands that I am able to run remotely. I have one command I have not been able to figure out an alternative:
net user USERNAME /PASSWORDREQ:yes
Is there a way to run this command remotely without psexec? I'd rather not distribute my batch file with a dependancy.
Yes, you can enable powershell remoting on the remote computers, and then use the Invoke-Command cmdlet. Example:
Invoke-Command -ComputerName RemoteComputer -Script { param($userName) net use $userName /PASSWORDREQ:yes } -Args "UserNameArgumentValue"