Проблема с консолью перезагрузки Powershell - PullRequest
1 голос
/ 16 апреля 2019

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

У меня есть сценарий 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 Ответ

1 голос
/ 16 апреля 2019

Это ограничение исполняемого файла 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 лет (в формате в секундах).Смотри, команда выключения просто хочет количество секунд.Вы должны быть в состоянии просто рассчитать это с секундами 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()
}
...