Проблема с консолью перезагрузки Powershell

#powershell #reboot #login-script #uptime

#powershell #перезагрузка #сценарий входа в систему #время безотказной работы

Вопрос:

У меня есть сценарий входа в систему, который перезагружает компьютер, если он был включен дольше, чем разрешено.

У меня есть сценарий PowerShell, который запускается при входе в систему и выполняется еженедельно, чтобы проверить время безотказной работы компьютера и перезагрузиться, если оно включено> 48 часов. Сценарий позволяет пользователю запрашивать расширение, чтобы его не выгнали с компьютера немедленно. У меня есть продление на 1, 3, 8 часов. Работает только продление на 1, 3 часа. Похоже, что если вы введете значение больше 3, оно не будет принято. Есть ли способ заставить это «расширение» работать дольше 3 часов?

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

Я хотел бы разрешить продление на 8 часов, но оно не разрешает> 3.

Комментарии:

1. Я проверил, что все 3 части кода «reboot extension» работают правильно, переместив 8 в другие места. Они по-прежнему не позволяют дольше 3 часов? Невозможно запланировать перезагрузку на такой длительный срок? (Я изменяю калькулятор последней перезагрузки на 0 часов при устранении неполадок)

Ответ №1:

Это ограничение shutdown.exe исполняемого файла. Согласно документации, найденной здесь:


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.
 

Если вы хотите выйти за рамки этого, вам нужно будет создать паузу в PowerShell перед выполнением shutdown.exe . Это можно сделать, добавив start-sleep параметр в течение 8 часов, режим ожидания в течение 3 часов, а затем указав максимальный таймер в 600 секунд.

Редактировать: похоже, что эта документация устарела, и завершение работы теперь принимает что-либо до 10 лет (отформатировано в секундах). Посмотрите, команде shutdown требуется всего несколько секунд. Вы должны быть в состоянии просто вычислить это с помощью секунд x минут x часов, а не всей причудливой математики, которую вы пытаетесь. 60 секунд в минуту и 60 минут в час, поэтому единственное, что меняется, — это количество часов для задержки. Попробуйте это:

 $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()
}
 

Комментарии:

1. Спасибо за информацию. Я не очень хорошо разбираюсь в PowerShell, можно ли просто добавить следующее: $ sleept = (Get-Date). Добавить часов (5). Время дня. Общее количество секунд $ Global:хэш. ScheduleBtn. Add_Click( { переключатель ($ Global: хэш. Значение расписания. SelectedItem.Name ) { «один» { $rebootTime = (Get-Date). Добавьте часы (1). Время дня. Всего секунд } «три» { $rebootTime = (Get-Date). Добавьте часы (3). Время дня. Всего секунд } «восемь» { $rebootTime = (Get-Date). Добавьте часы (3). Время дня. Всего секунд. Добавить часы $ время сна }}

2. Я предполагаю, что добавление 8 часов переносит работу на следующий день, и в итоге вы получаете отрицательные числа. Кроме того, я ошибался в отношении ограничения в 600 секунд, которое кажется (похоже, документы MS устарели). Проверьте обновленный ответ.

3. Извините за мой медленный ответ. Я думаю, вы были правы с предыдущим комментарием, если он был «отложен» на период времени, который должен был перейти на следующий день, это не сработало, но это сработало, если это было ранее в тот же день, и не перешло на следующий день. Я изменил код на тот, который вы предоставили, и это устранило проблему. Спасибо за помощь!