Controlling System Power State with Windows PowerShell

What would you do in the event of a complete utility power failure? Would you remote desktop to each key workoad running in your environment and shut it down gracefully? This approach works very well when your infrastructure is relatively small, but eventually the number of servers in your environment will grow to the point that it’s simply no longer practical. This is where PowerShell’s capability of managing the power state of your machines either via WMI calls or through native Cmdlets really becomes valuable. Let’s take a look at how we would shut down or restart machines, both singly and in batch.

First thing’s first, Prepare your infrastructure for controlling system power state with PowerShell

If you’re adhering to best practices of running as a standard user and running a local firewall (Windows Firewall or otherwise) on your machines you will see the following message when attempting to execute a remote shutdown or restart operation.

To correct this issue either temporarily disable the local firewall as part of your script or open ports 135 and 445 on each target server.

Restarting one or multiple machines with Windows PowerShell

Restart the local machine with Windows PowerShell

[ps]Restart-Computer[/ps]

The WMI (PowerShell 1.0) Method:

(Get-WmiObject -Class Win32_OperatingSystem -Computername .).InvokeMethod("Win32Shutdown",2)

Restart a single remote machine

[ps]Restart-Computer –Computername machine[/ps]

The WMI (PowerShell 1.0) Method:

(Get-WmiObject -Class Win32_OperatingSystem -Computername MyMachine).InvokeMethod("Win32Shutdown",2)

Restart multiple remote machines using Windows PowerShell (Method 1) – Providing server names in line

[ps]Restart-Computer –Computername Machine1, Machine2, Machine3[/ps]

Restart multiple remote machines using Windows PowerShell (Method 2) – Defining a variable to hold server names

[ps]$Computers = Get-Content c:ServerList.txt
Restart-Computer –Computername $Computers[/ps]

The WMI (PowerShell 1.0) Method:

(Get-WmiObject -Class Win32_OperatingSystem -Computername Machine 1, Machine 2, Machine 3).InvokeMethod("Win32Shutdown",2)

Run with alternate credentials when performing a remote restart from PowerShell

[ps]$Cred = Get-Credential
$Computers = C:ServerList.txt
Stop-Computer –Computername $Computers –Credential $Cred[/ps]

Shutting down one or multiple machines with Windows PowerShell

While one would imagine the cmdlet to shut down a machine using PowerShell would be Shutdown-Computer it is, in fact, Stop-Computer.

Shut down the local machine using Windows PowerShell

[ps]Stop-Computer[/ps]

The WMI (PowerShell 1.0) Method:

(Get-WmiObject -Class Win32_OperatingSystem -ComputerName .).InvokeMethod("Win32Shutdown",8)

Shut down a single remote machine

[ps]Stop-Computer –Computername machine[/ps]

The WMI (PowerShell 1.0) Method:

(Get-WmiObject -Class Win32_OperatingSystem -ComputerName MyMachine).InvokeMethod("Win32Shutdown",8)

Shut down multiple remote machines using Windows PowerShell (Method 1) – Providing machine names in line

[ps]Stop-Computer –Computername Machine1, Machine2, Machine3[/ps]

The WMI (PowerShell 1.0) Method:

(Get-WmiObject -Class Win32_OperatingSystem -ComputerName Machine 1, Machine 2, Machine 3).InvokeMethod("Win32Shutdown",8)

Shut down multiple remote machines using Windows PowerShell (Method 2) – Defining a variable to hold server names

[ps]$Computers = Get-Content C:ServerList.txt
Stop-Computer – Computername $Computers[/ps]

The WMI (PowerShell 1.0) Method:

$Computers = ServerList.txt
(Get-WmiObject -Class Win32_OperatingSystem -ComputerName $computers).InvokeMethod("Win32Shutdown",8)

Run with alternate credentials when performing a remote shut down from PowerShell

[ps]$Cred = Get-Credential
$Computers = C:ServerList.txt
Restart-Computer –ComputerName $Computers –Credential $Cred[/ps]

A couple real world examples

Example 1

A simple script to write a warning message to the console, play a warning sound effect then shutdown a list of servers as defined in a variable

[ps]
Write-Host -ForegroundColor Green -BackgroundColor Black "Warning
Emergency Shutdown Sequence in progress. Please be advised this will
shutdown critical infrastructure workloads rendering all hosted
services unavailable. Process will begin in 20 seconds."

Start-Sleep -Seconds 10

$sound = new-Object System.Media.SoundPlayer;

$sound.SoundLocation="c:pstestshutdown.wav";

$sound.Play();

Start-Sleep -Seconds 20

Clear-Host

$Computers = Get-Content Servers.txt

foreach ($Computer in $Computers

{try {Stop-Computer -ComputerName $Computers

Write-Host "Shutting down $Computer"

}

catch {

Write-Error "Unable to restart $computer!. n$error[0]"

}

}
[/ps]

Example 2

A script to send an automated Email to an administrator notifying them that the Emergency Shutdown Process has been triggered then proceed shut down a group of machines as defined in a variable. Please note that [System.Net.NetworkCredential] requires the username (in the form of DOMAINusername) and password of a mail enabled user account.

[ps]
Write-Host -ForegroundColor Green -BackgroundColor Black "Warning....Emergency Shutdown Sequence in progress. Please be advised this will shutdown critical infrastructure workloads rendering all hosted services unavailable. Process will begin in 20 seconds.

$ClientCredentials = [System.Net.NetworkCredential]::("DomainUsername goes here" , "Password goes here")

$ClientCredentials = [System.Net.CredentialCache]::DefaultNetworkCredentials

$emailFrom = "From address goes here"

$emailTo = "To address goes here"

$subject = "Email subject goes here"

$body = "Email body goes here"

$smtpServer = "Email server hostname or IP address goes here"

$smtp = new-object Net.Mail.SmtpClient($SmtpServer)

$smtp.Send($emailFrom, $emailTo, $Subject, $Body)

Clear-Host

$Computers = Get-Content Servers.txt

foreach ($Computer in $Computers)

{try {Stop-Computer -ComputerName $Computers

Write-Host "Shutting down $Computer"

}

catch {

Write-Error "Unable to restart $computer!. n$error[0]"

}

}
[/ps]

Note:

If you are attempting to shut down or restart a machine with an active console session (i.e. a user is logged in) you will need to include the -Force paramater. For example,

[ps]Restart-Computer -Computername machine -Force[/ps]

The WMI (PowerShell 1.0) Method:

(Get-WmiObject -Class Win32_OperatingSystem -Computername machine).InvokeMethod("Win32Shutdown",6)

or

[ps]Stop-Computer -Computername machine -Force[/ps]

The WMI (PowerShell 1.0) Method:

(Get-WmiObject -Class Win32_OperatingSystem -Computername Mymachine).InvokeMethod("Win32Shutdown",5)

Using a combination of the Cmdlets detailed above you can create a remarkably simple yet powerful power management solution that’s great both for emergency situations (such as  power failures) or simply restarting multiple servers at the end of a Windows Update cycle.

//J

Leave a Reply

Your email address will not be published. Required fields are marked *