JohnLBevan
JohnLBevan

Reputation: 24420

Should I ever include a reboot command in my BoxStarter script?

Question

Is there ever a reason to include if (Test-PendingReboot) { Invoke-Reboot } in a BoxStarter script when $Boxstarter.RebootOk=$true is declared?

Background

I've recently discovered BoxStarter and noticed that a number of scripts out there include the following code: if (Test-PendingReboot) { Invoke-Reboot }. This includes those scripts with the following options: $Boxstarter.RebootOk=$true and $Boxstarter.AutoLogin=$true; i.e. those which are allowed to reboot and continue as required.

On the BoxStarter site the following statement is made:

Boxstarter intercepts all Chocolatey install commands and checks for pending reboots. If a pending reboot is detected, Boxstarter will reboot the machine and automatically log the user back on and resume the installation.

NB: I understand that Invoke-Reboot may sometimes be required after making changes which would not update the PendingReboot flag; e.g. for certain registry changes to take effect; my question purely relates to the use of this command when wrapped in the if (Test-PendingReboot) statement.

Update: Also asked on Google Groups: https://groups.google.com/forum/#!topic/boxstarter/D0kiRqJyiCY

Upvotes: 4

Views: 2552

Answers (2)

dragon788
dragon788

Reputation: 3911

I've only found one case where this was actually required, and like Gary mentioned, I wrapped it in some logic to avoid rolling continuous reboots.

We ran into the case where "freshly minted" servers had some pending file renames that even with multiple restarts NEVER actually went away, so if we ran Boxstarter we ended up having to kill the cmd window as quickly as possible if we could log in between infinite reboots.

The resulting script can be run from a gist via Install-BoxstarterPackage -DisableReboots <gistUrl> to clean up any files you put into $badFile (which you could make a list).

The one caveat to this script is it requires interactive prompting for the login credential. You could use a plain text password and assemble a credential if you trust your systems and network, I assume the worst.

Apologies that this seems to break the syntax highlighter.

Import-Module $env:appdata\Boxstarter\Boxstarter.Common

$badSpoolReg = '\??\C:\Windows\system32\spool\PRTPROCS\x64\1_hpcpp130.dll'
$badSpoolFile = 'C:\Windows\system32\spool\PRTPROCS\x64\1_hpcpp130.dll'

# Next bits taken from the 'Get-PendingReboot' module on the Script Gallery.
$Computer = $env:COMPUTERNAME
$HKLM = [UInt32] "0x80000002"
$WMI_Reg = [WMIClass] "\\$Computer\root\default:StdRegProv" 

## Query PendingFileRenameOperations from the registry 
$RegSubKeySM = $WMI_Reg.GetMultiStringValue($HKLM,"SYSTEM\CurrentControlSet\Control\Session Manager\","PendingFileRenameOperations") 
#$RegSubKeySM # Debug print of the list if you want to run by hand

$RegValuePFRO = $RegSubKeySM.sValue | where { $_ } # Ignore empty values
#$RegValuePFRO # Debug print of the list if you want to run by hand

# Credential is required for Create-BoxstarterTask
# Create-BoxstarterTask required to call Invoke-FromTask
# see https://github.com/mwrock/boxstarter/issues/121  
$cred = Get-Credential
Create-BoxstarterTask $cred

# Perhaps could be improved using set membership comparison?
# like (if $badSpoolReg in $RegValuePFRO.Values?)
foreach ($path in $RegValuePFRO) {
    if ($path -contains $badSpoolReg) {
        write-output "Bogey on my six!"
        Get-Service spooler | stop-service
        Invoke-FromTask "rm -fo $badSpoolFile" # Files in "protected" paths require extra work to remove
        $Boxstarter.RebootOk = $true # Need to enable this to allow Invoke-Reboot to work
        Write-output "Took out the bogey, resetting system state"
        Invoke-Reboot # Manually called but within a fairly good gate
    } else {
        write-output "No bogeys sighted Captain!"
    }
}
Remove-BoxstarterTask

Upvotes: 1

Gary Ewan Park
Gary Ewan Park

Reputation: 18981

Personally, I would never do this, no. I rely on Boxstarter looking after this for me, as internally it is doing the same check, so doing it in addition in my script is duplication of effort.

There are times when, as you mention, you know that a reboot is required for some external reason, so I would directly call Invoke-Reboot, but this would always be surrounded by some guard clause to prevent it happening each time, as I always want my scripts to be repeatable.

Upvotes: 2

Related Questions