简体   繁体   中英

Powershell reboot console issue

I have a login script that reboots PC if it has been on longer than allowed.

I have a PowerShell script that is run during login and executed weekly to check the machine uptime and reboot if it is on > 48 hours. The script allows the user to request an extension so they are not kicked off the machine immediately. I have a 1, 3, 8 hour extension. Only the 1, 3 hour extension work. It appears that if you enter a value greater than 3, it does not accept it. Is there a way to make this "extension" work longer than 3 hours?

<#
.SYNOPSIS
    Script displays an interactive popup that display the reason for having the reboot the computer.
.DESCRIPTION
     The reboot script gives users the option to reboot now or delay the reboot for 1, 3, or 6 hours
.EXAMPLE
    Script executes from the login script
.INPUTS
    N/A
.OUTPUTS
    N/A
.NOTES
    General notes
#>

try {
    Add-Type -AssemblyName PresentationCore, PresentationFramework, WindowsBase, system.windows.forms
} 
catch {}

#Calculate the time since last reboot

$lastBootTime = Get-CimInstance -ClassName Win32_OperatingSystem | Select-Object LastBootUpTime | ForEach-Object { Get-Date -Date $_.LastBootUpTime }
$Time = (Get-Date) - $lastBootTime

#if last reboot is less than 2 days exit the script.
if ($Time.TotalHours -lt 48) {
    exit
}

#if computer has a server os, exit
$version = (Get-CimInstance -ClassName Win32_OperatingSystem).caption

if($version -match "server")
{
    exit
}

<#
 # Set Sync hash
 #>
$Global:hash = [hashtable]::Synchronized(@{})
$Global:hash.Stopwatch = New-Object System.Diagnostics.Stopwatch
$Global:hash.Timer = New-Object System.Windows.Forms.Timer
$Global:hash.Timer.Enabled = $true
$Global:hash.Timer.Interval = 1000


<#
 # Form design XML
 #>
[xml]$xaml = @'
<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Name="window" Height="340" Width="400" Title="Mandatory Reboot"  WindowStartupLocation="CenterScreen" Background="Transparent" AllowsTransparency="True"
ResizeMode="NoResize" ShowInTaskbar="True"  SizeToContent="Height" Topmost="True" WindowStyle="None">
    <Window.Resources>
        <SolidColorBrush x:Key="Brush_ChromeBackground" Color="#FFC8D1E0"/>
        <SolidColorBrush x:Key="Brush_ChromeBorder" Color="#FFA0A0A0"/>
    </Window.Resources>
    <Border x:Name="Border_Chrome"  BorderBrush="{StaticResource Brush_ChromeBorder}" BorderThickness="5"  CornerRadius="10"  Width="Auto" Background="#FFCD3232">
        <Grid Margin="15" >
            <Grid.RowDefinitions>
                <RowDefinition Height="120"></RowDefinition>
                <RowDefinition Height="60"></RowDefinition>
                <RowDefinition Height="60"></RowDefinition>
                <RowDefinition Height="60"></RowDefinition>
            </Grid.RowDefinitions>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="50"></ColumnDefinition>
                <ColumnDefinition Width="*"></ColumnDefinition>
                <ColumnDefinition Width="50"></ColumnDefinition>
            </Grid.ColumnDefinitions>
            <TextBlock TextWrapping="Wrap" Grid.Column="0" Grid.ColumnSpan="3" FontSize="14" Foreground="White">
                <Bold FontSize="16">Mandatory Reboot</Bold><LineBreak/>
                This computer exceeds the maximum allowed uptime. Your computer will be automatically rebooted unless manually restarted or an extension is requested.<LineBreak/>
            </TextBlock>
            <Button Name="RestartNowBtn" Grid.Column="1" Grid.Row="1" Grid.ColumnSpan="3" Width="240" Height="40" HorizontalContentAlignment="Center" HorizontalAlignment="Left">
                <StackPanel Orientation="Horizontal" >
                    <Label Content="Restart Now" FontWeight="Bold"></Label>
                </StackPanel>
            </Button>
            <StackPanel Orientation="Horizontal" Grid.Row="2" Grid.Column="1" Grid.ColumnSpan="3" Margin="5,8" >
                <GroupBox Width="100" Header="Postpone">
                    <ComboBox Name="ScheduleValue" VerticalAlignment="Center" >
                        <ComboBoxItem Name="one" Selector.IsSelected="True">1</ComboBoxItem>
                        <ComboBoxItem Name="three">3</ComboBoxItem>
                        <ComboBoxItem Name="eight">8</ComboBoxItem>
                    </ComboBox>
                </GroupBox>
                <TextBlock Foreground="White" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="10,0" FontWeight="Bold">Hour(s)</TextBlock>
                <Button Content="Request Extension" Name="scheduleBtn" Width="110" FontWeight="Bold"></Button>
            </StackPanel>
            <Grid Grid.Row="3" Grid.ColumnSpan="3" Margin="10">
                <ProgressBar Name="Time" Maximum="100" Value="100"></ProgressBar>
                <TextBlock HorizontalAlignment="Center" VerticalAlignment="Center">Time to Automatic Reboot (All unsaved work will be lost)</TextBlock>
            </Grid>
        </Grid>
    </Border>
</Window>
'@

$Global:hash.window = [Windows.Markup.XamlReader]::Load((New-Object -TypeName System.Xml.XmlNodeReader -ArgumentList $xaml))

#Connect to Control
$xaml.SelectNodes("//*[@Name]") | ForEach-Object -Process { 
    $Global:hash.$($_.Name) = $Global:hash.window.FindName($_.Name)
}

<#
 # Restart Now Button Even Handler
 #>
$Global:hash.RestartNowBtn.Add_Click( {
        #Stop the timer so that the auto reboot dosen't happen
        $Global:hash.Timer.Stop()
        #Force Reboot Now!
        cmd.exe /c shutdown.exe -r -d P:0:0 -t 60 -f
        $Global:hash.window.Close()
    })

<#
 # Schedule Button Click event handler
 #>
$Global:hash.ScheduleBtn.Add_Click( {

        switch ($Global:hash.ScheduleValue.SelectedItem.Name) {
            "one" {
                $rebootTime = (Get-Date).AddHours(1).TimeOfDay.TotalSeconds
            }
            "three" {
                $rebootTime = (Get-Date).AddHours(3).TimeOfDay.TotalSeconds
            }
            "eight" {
                $rebootTime = (Get-Date).AddHours(8).TimeOfDay.TotalSeconds
            }
        }

        $startTime = [Math]::Round(($rebootTime - (Get-Date).TimeOfDay.TotalSeconds), 0)

        #Stop the timer so that the auto reboot dosen't happen
        $Global:hash.Timer.Stop()

        cmd.exe /c shutdown.exe -r -d P:0:0 -t $startTime -f 

        $Global:hash.Window.Close()
    })

<#
 # Form Loaded Event Handler
 #>
$Global:hash.window.Add_Loaded( {

        $Global:hash.Stopwatch.Start()
        $Global:hash.Timer.Add_Tick( {
                [timespan]$secs = $Global:hash.Stopwatch.Elapsed

                if ($secs.TotalSeconds -gt 120) {
                    cmd.exe /c shutdown.exe -r -d P:0:0 -t 60 -f
                    $Global:hash.Timer.Stop()
                    $Global:hash.window.Close()
                    exit
                }

                $Global:hash.Time.Value = (100 - (($secs.TotalSeconds / 120) * 100))
            })

        $Global:hash.Timer.Start()
    })

<#
 # Start the form
 #>
$Global:hash.window.ShowDialog() | Out-Null

I would like to allow the 8 hour extension, but it isn't allowing > 3.

This is a limitation of the shutdown.exe executable. Per the documentation found here:

https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/shutdown

 
 
 
  
  /t <XXX> Sets the time-out period or delay to XXX seconds before a restart or shutdown. This causes a warning to display on the local console. You can specify 0-600 seconds. If you do not use /t, the time-out period is 30 seconds by default.
 
 

If you want to go beyond that you will have to create a pause within PowerShell before you execute shutdown.exe . This could be done by adding a start-sleep within the 8 hour option, sleep for 3 hours, and then specify the maximum 600 second timer.

Edit: Looks like that documentation is out of date, and shutdown now accepts anything up to 10 years (formatted in seconds). Look, the shutdown command just wants a number of seconds. You should be able to just calculate that with seconds x minutes x hours, rather than all the fancy math you're trying. 60 seconds in a minute, and 60 minutes in an hour, so the only thing that changes is the number of hours to delay. Try this:

 $Global:hash.ScheduleBtn.Add_Click( { $startTime = switch ($Global:hash.ScheduleValue.SelectedItem.Name) { "one" { 1*60*60 } "three" { 3*60*60 } "eight" { 8*60*60} } $Global:hash.Timer.Stop() cmd.exe /c shutdown.exe -r -d P:0:0 -t $startTime -f $Global:hash.Window.Close() }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM