PowerShell Stopping and Starting Windows Services on Remote Computer - powershell

I have a very basic PowerShell that accepts a list of Windows Server and Services on them and then stops the Services
Get-Service -ComputerName machine1 -Name service1 -ErrorAction Stop | Stop-Service -WarningAction SilentlyContinue
Although I had explicitly mentioned -ErrorAction as Stop, in a case if one of the Server is not reachable, the Powershell doesn't come back. How do I change this behaviour at least in a way to stop processing after a certain amount of time as "n" secs which again can be passed thru parameter?

Incorporating both comments, we end up with following
Enclose the current script in a Test-Connection that allows you to first verify if a computer is actually reachable:
if (Test-Connection -ComputerName machine1 -Quiet)
{
all your current code
}

Related

Is there a way to warn remote computer of pending restart AND have my script wait for the restart to complete?

I'm looking to combine the "You will be logged off in x minutes" functionality of 'shutdown.exe", and the "-Wait -For PowerShell" functionality of the Restart-Computer cmdlet.
I have a script that requires a remote computer to restart. I'd like to warn the user of the remote computer that their computer will restart in 5 minutes. I would also like my script to wait until the restart completes before continuing forward.
Shutdown.exe has a great warning system and delay built in, but no great way to have the script wait for the reboot to complete. I've tried a loop that waits until Test-Connection is $true, but of course a computer returns a ping before it can accept PowerShell commands like Invoke-Command. I could slap a Start-Sleep on the end, but the time between ping and PowerShell accepting commands varies per computer.
Restart-Computer has a great "wait for PowerShell" feature, but there's no way to warn the user of the remote computer that their computer is about to restart. I've tried running the commands below, but the restart-computer cmdlet will throw an error if there's already a shutdown in progress.
shutdown /r /t 300 /m \\computer $system
restart-computer -computername $system -Force -Wait -For PowerShell -Timeout 300 -Delay 2
You can try just sending the message just before your call to Restart-Computer using the msg command:
msg * /SERVER:$system /TIME:300 "Computer will be restarted in 5 minutes."
restart-computer -computername $system -Force -Wait -For PowerShell -Delay 2
I won't say this is a complete answer to your question, but instead of Test-NetConnection (which only tests ping/TCP as you mentioned), use Test-WSMan which will test the protocol over which PowerShell Remoting operates (note other protocols are possible, but you're likely just using this one in your environment).

PowerShell won't terminate hung process

I have a scenario where a process is stuck every single Monday morning because of an Oracle database so I tried creating a PowerShell script to run every Monday but regardless of getting an error or not, the process remains.
The line I'm attempting to use for the "kill" is:
Get-Process -Name ez0* -ComputerName $server | Stop-Process -Force
Tried doing this locally as well without the -ComputerName.
I'm not getting any errors from this line with or without the -Force it just executes and moves on.
Just doing Get-Process works and I can see it but I can't end it with PowerShell. After many attempts I remotely logged on to the server and just right-clicked the process and chose "End task" which worked just fine.
It is an odd process because it's one out of initial 8 (based on cores) and when you stop the service, all but one of the processes is removed save for the one that is hung.
Try using:
$termproc = (get-wmiobject -ComputerName $server -Class Win32_Process -Filter "name like 'ez0%'"
$termproc.terminate()
You could also just do the below if you don't want to check the processes in the variable first.
(get-wmiobject -ComputerName $server -Class Win32_Process -Filter "name like 'ez0%'").terminate()
Thanks, Tim.

Powershell: waiting for changed directory

To make it short, I want to connect to a server that is running Virtual Machines and then get a List of all installed machines, the command I use for this is:
Invoke-Command -ScriptBlock {enter-pssession -ComputerName <name>}; Invoke-Command -ScriptBlock {Get-VM} | select-Object -Property name
This line contains two commands at first:
Invoke-Command -ScriptBlock {enter-pssession -ComputerName <name>};
this part connects to the server, and then:
Invoke-Command -ScriptBlock {Get-VM} | select-Object -Property name
This command gets a list of the VMs currently on the server and returns specific properties of these servers.
However, because the connection needs a short time until it is set up, the "get-vm" command is still set in the previous direction and results in an error report.
I want to know if there is a way to wait for ether a command to be finished or for a change in the directory, without having an extra loop running for this time, or waiting for a hard set time.
I don't know why are you trying to do what you are trying to do, what you should do is:
Invoke-Command -SessionName (or -ComputerName) -ScriptBlock {Get-VM | Select-Object -Property name}

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).

Remote Machine not executing program

Here is what I have so far:
$source1="C:\Folder\Files\IPList.txt"
Get-Content $source1 |
Where-Object {-not(gwmi win32_process -ComputerName $_ -filter "name='Program.exe'")} |
Foreach-Object {Invoke-Command -ComputerName $_ -ScriptBlock {"C:\Program Files\Folder\Folder\Program.exe"}}
When I run this in ISE everything comes back as normal and says it has run correctly. However, when I look at my remote machine nothing has been executed. The Process Program.exe is not running and there for the exe should be launched. I am running this from a server to hit about 50 remote machines. Once it goes through all 50, I will loop it and have it do it again, then continue the process in an infinite loop.
What am I missing for the program to start remotely? By the way I am running this script on Server 2008 R2 and it is hitting Windows 7 machines.
Edit
I am wondering since I can see the process firing off, is this an issue with Windows 7? I know Microsoft changed things and a service cannot fire off an application in the User space. Do you think this would be part of the same problem?
Try adding the call (&) operator to the ScriptBlock:
$source1="C:\Folder\Files\IPList.txt"
Get-Content $source1 |
Where-Object {-not(gwmi win32_process -ComputerName $_ -filter "name='Program.exe'")} |
Foreach-Object {Invoke-Command -ComputerName $_ -ScriptBlock {& "C:\Program Files\Folder\Folder\Program.exe"}}
Here's a good article on the various methods available to you: http://social.technet.microsoft.com/wiki/contents/articles/7703.powershell-running-executables.aspx
In your current syntax, the command your passing is just a string! This is what is happening on the remote end:
PS C:\> "C:\Program Files\Console2\Console.exe"
C:\Program Files\Console2\Console.exe
Powershell is echoing your string!
I am going to quote Oliver Lipkau as mentioned here: Source
If you need to start a process on a remote computer that keeps running after the script finished, use this function:
Function New-Process ([string]$computername, [string]$name) {
([WMICLASS]"\\$computername\ROOT\CIMV2:win32_process").Create($name)
}