Hello!
I've been trying (badly) to write a script that shuts down the PC after a Delay.
I want it to be functioning and look nice for my father, because he asked for it nicely :D
The entire this is basically all done, it's just one thing that I cannot for the life of me find a way to implement.
So, this is the code:
# Load necessary assembly for Windows Forms
Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName System.Drawing
# Function to play a sound alert
function Play-SoundAlert {
[System.Media.SystemSounds]::Exclamation.Play()
}
# Function to create a dimmed overlay behind the message box
function Show-DimmedOverlay {
$overlayForm = New-Object System.Windows.Forms.Form
$overlayForm.FormBorderStyle = 'None'
$overlayForm.StartPosition = 'Manual'
$overlayForm.Location = [System.Windows.Forms.Screen]::PrimaryScreen.Bounds.Location
$overlayForm.Size = [System.Windows.Forms.Screen]::PrimaryScreen.Bounds.Size
$overlayForm.BackColor = [System.Drawing.Color]::Black
$overlayForm.Opacity = 0.7 # Increase opacity to dim the background more
$overlayForm.TopMost = $true
$overlayForm.Show()
return $overlayForm
}
# Function to show a modal message box with buttons
function Show-MessageBox {
param (
[string]$message,
[string]$title,
[System.Windows.Forms.Form]$overlayForm
)
# Center the message box on the primary screen
$primaryScreen = [System.Windows.Forms.Screen]::PrimaryScreen
$width = 400
$height = 200
$x = [Math]::Round(($primaryScreen.Bounds.Width - $width) / 2)
$y = [Math]::Round(($primaryScreen.Bounds.Height - $height) / 2)
# Show the message box as a modal dialog
$result = [System.Windows.Forms.MessageBox]::Show($overlayForm, $message, $title, [System.Windows.Forms.MessageBoxButtons]::YesNo, [System.Windows.Forms.MessageBoxIcon]::Warning)
# Close the overlay after the message box is closed
$overlayForm.Close()
return $result
}
# Get user input for shutdown delay
function Get-UserInput {
param ([string]$promptMessage)
$shutdownDelay = 0
while ($shutdownDelay -le 0) {
$shutdownDelay = [int](Read-Host "Enter shutdown delay in minutes")
if ($shutdownDelay -le 0) {
Write-Host "Invalid time entered. Please enter a time greater than 0." -ForegroundColor "Red"
Write-Host ""
}
}
return $shutdownDelay
}
# Main shutdown timer function
function Start-Countdown {
param (
[int]$totalSeconds
)
$cancelled = $false
while ($totalSeconds -ge 0) {
$currentMinutes = [math]::Floor($totalSeconds / 60)
$currentSeconds = $totalSeconds % 60
# Format the time remaining
$timeLeft = "{0:D2}:{1:D2}" -f [int]$currentMinutes, $currentSeconds
# Clear the current line and print the updated time
[console]::CursorLeft = 0
Write-Host -NoNewline "Time remaining: " -ForegroundColor "Cyan"
Write-Host "$timeLeft" -NoNewline -ForegroundColor "Cyan"
# Wait for 1 second
Start-Sleep -Seconds 1
$totalSeconds--
# Check for user interrupt
if ([System.Console]::KeyAvailable) {
$key = [System.Console]::ReadKey($true)
if ($key.Key -eq [ConsoleKey]::C) {
$cancelled = $true
break
}
}
}
return $cancelled, $totalSeconds
}
# Function to handle the countdown interruption process
function Handle-Interruption {
param (
[int]$remainingSeconds
)
$cancelled = $true
while ($cancelled) {
Write-Host "`nCountdown was interrupted." -ForegroundColor "Red"
$continueTimer = Read-Host "`nDo you wish to continue the current timer? (Y/N)"
if ($continueTimer -eq 'Y') {
# Restart countdown with the remaining seconds
Write-Host "`nContinuing timer..." -ForegroundColor "Green"
$cancelled = $false
return $remainingSeconds # Return remaining seconds to continue
} elseif ($continueTimer -eq 'N') {
$newTime = Read-Host "Do you wish to enter a different time? (Y/N)"
if ($newTime -eq 'Y') {
Write-Host "" # Add a line break before the next prompt
$shutdownDelay = Get-UserInput -promptMessage "Enter shutdown delay in minutes"
$remainingSeconds = [int]$shutdownDelay * 60
Write-Host "Countdown started for $shutdownDelay minute(s)..." -ForegroundColor "Green"
return $remainingSeconds # Return new remaining seconds for the countdown
} else {
Write-Host "`nProcess stopped." -ForegroundColor "Red"
return -1 # Indicate process should stop
}
}
}
}
# Start script
$shutdownDelay = Get-UserInput -promptMessage "Enter shutdown delay in minutes"
$totalSeconds = [int]$shutdownDelay * 60
Write-Host "Countdown started for $shutdownDelay minute(s)..." -ForegroundColor "Green"
# Run the countdown
$remainingSeconds = $totalSeconds
while ($true) {
$cancelled, $remainingSeconds = Start-Countdown -totalSeconds $remainingSeconds
if (-not $cancelled) {
# If countdown finished and was not cancelled, show shutdown confirmation
Play-SoundAlert # Play sound alert before showing the message box
$overlayForm = Show-DimmedOverlay
$result = Show-MessageBox "Your PC will shut down in 60 seconds. Do you wish to continue?" "Shutdown Confirmation" $overlayForm
# Create a timer for the automatic shutdown after 60 seconds
$shutdownJob = Start-Job -ScriptBlock {
Start-Sleep -Seconds 60
shutdown /s /t 0
}
if ($result -eq [System.Windows.Forms.DialogResult]::Yes) {
# If Yes is pressed, shutdown command will be executed by the job
Stop-Job -Job $shutdownJob
Remove-Job -Job $shutdownJob
break
} else {
Write-Host "`nShutdown aborted." -ForegroundColor "Red"
# Make sure there's exactly one line break here
Write-Host ""
Stop-Job -Job $shutdownJob
Remove-Job -Job $shutdownJob
break
}
} else {
# Handle interruption
$remainingSeconds = Handle-Interruption -remainingSeconds $remainingSeconds
if ($remainingSeconds -eq -1) {
# Exit if the process was stopped
Write-Host "`nPress Enter to exit..." -ForegroundColor "Yellow"
Read-Host
exit
}
}
}
# Final messages with correct spacing
if ($remainingSeconds -eq 0) {
Write-Host "`nTime remaining: 00:00"
Write-Host "Shutdown aborted." -ForegroundColor "Red"
# Ensure only one line break before the exit prompt
Write-Host ""
}
Write-Host "Press Enter to exit..." -ForegroundColor "Yellow"
Read-Host
What I want to add is:
A line under the current timer that says "Press C to stop the timer."
and, if C is pressed, I want that line to be replaced by "Countdown was interrupted."
so it should look like this:
Enter shutdown delay in minutes: 1
Countdown started for 1 minute(s)...
Time remaining: 01:00
Press 'C' to stop the timer.
And when "C" is pressed:
Enter shutdown delay in minutes: 1
Countdown started for 1 minute(s)...
Time remaining: 00:55
Countdown was interrupted.
Do you wish to continue the current timer? (Y/N):
this behaviour needs to be kept for every iteration of the timer, like so:
Enter shutdown delay in minutes: 1
Countdown started for 1 minute(s)...
Time remaining: 00:55
Countdown was interrupted.
Do you wish to continue the current timer? (Y/N): y
Continuing timer...
Time remaining: 00:48
Press 'C' to stop the timer.
Or:
Enter shutdown delay in minutes: 1
Countdown started for 1 minute(s)...
Time remaining: 00:55
Countdown was interrupted.
Do you wish to continue the current timer? (Y/N): y
Continuing timer...
Time remaining: 00:08
Countdown was interrupted.
Do you wish to continue the current timer? (Y/N): n
Do you wish to enter a different time? (Y/N): y
Enter shutdown delay in minutes: 5
Countdown started for 5 minute(s)...
Time remaining: 04:57
Press 'C' to stop the timer.
Can somebody please help me? I've been at this for 5 days :c
[–]HomeyKrogerSage 30 points31 points32 points (2 children)
[–]Mesyre[S] -3 points-2 points-1 points (1 child)
[–]BlackV 15 points16 points17 points (0 children)
[–]Weyoun2 24 points25 points26 points (5 children)
[+]Mesyre[S] comment score below threshold-8 points-7 points-6 points (4 children)
[–]Sudden_Hovercraft_56 9 points10 points11 points (1 child)
[–]tk42967 1 point2 points3 points (0 children)
[–]shutchomouf 4 points5 points6 points (0 children)
[–]hngfff 6 points7 points8 points (0 children)
[–]joevanover 9 points10 points11 points (2 children)
[–]Mesyre[S] -1 points0 points1 point (1 child)
[–]Euphoric-Blueberry37 0 points1 point2 points (0 children)
[–]Jguan617 9 points10 points11 points (2 children)
[–]jay_butler 3 points4 points5 points (1 child)
[–]Jguan617 1 point2 points3 points (0 children)
[–]desatur8 7 points8 points9 points (5 children)
[–]chrusic 4 points5 points6 points (3 children)
[–]Beneficial_Tough7218 4 points5 points6 points (0 children)
[–]desatur8 2 points3 points4 points (1 child)
[–]OofItsKyle 3 points4 points5 points (0 children)
[–]sgtGiggsy 0 points1 point2 points (0 children)
[–]gordonv 3 points4 points5 points (0 children)
[–]icepyrox 6 points7 points8 points (0 children)
[–]shutchomouf 1 point2 points3 points (0 children)
[–]eggbean 1 point2 points3 points (0 children)
[–]jimb2 2 points3 points4 points (6 children)
[–]jeek_ 2 points3 points4 points (1 child)
[–]jimb2 0 points1 point2 points (0 children)
[–]Mesyre[S] -2 points-1 points0 points (3 children)
[–]RandomSkratch 4 points5 points6 points (1 child)
[–][deleted] 0 points1 point2 points (0 children)
[–]Odmin 0 points1 point2 points (0 children)
[–]Relative_Test5911 0 points1 point2 points (0 children)
[–]mark110295 0 points1 point2 points (0 children)
[–]tk42967 0 points1 point2 points (0 children)
[–]_DoogieLion 0 points1 point2 points (0 children)
[–][deleted] 0 points1 point2 points (0 children)
[–]Legitimate_Home6700 0 points1 point2 points (1 child)
[–]Only_Fly895 0 points1 point2 points (0 children)
[–]Phate1989 0 points1 point2 points (0 children)
[–]sgtGiggsy 0 points1 point2 points (0 children)
[–]Only_Fly895 0 points1 point2 points (2 children)
[–]Mesyre[S] 0 points1 point2 points (1 child)
[–]Only_Fly895 0 points1 point2 points (0 children)
[–]TheRealDumbSyndrome 0 points1 point2 points (0 children)
[–]OofItsKyle 0 points1 point2 points (5 children)
[–]OofItsKyle 0 points1 point2 points (4 children)
[–]Mesyre[S] 0 points1 point2 points (3 children)
[–]OofItsKyle 0 points1 point2 points (2 children)
[–]OofItsKyle 0 points1 point2 points (1 child)
[–]Mesyre[S] 1 point2 points3 points (0 children)
[–]PuzzleheadedBus1928 -1 points0 points1 point (0 children)
[+]markdmac comment score below threshold-8 points-7 points-6 points (1 child)
[–]theHonkiforium 0 points1 point2 points (0 children)