Automatic Shutdown
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
01-24-2024 06:14 AM - edited 01-24-2024 06:15 AM
This document details the "Automatic Shutdown" project, developed using a PowerShell script running on JumpCloud. The main objective is to automate system shutdown when a computer remains idle for a specific period.
Target Audience:
- JumpCloud administrators
- System administrators interested in managing idle computer shutdown
Project Overview:
- Platform: JumpCloud
- Scripting Language: PowerShell
- Functionality: Detects idle user activity and initiates automatic system shutdown.
- Key Features:
- Idle Time Detection using Win32 API
- Configurable Timeout
- Forced Shutdown
- User Confirmation Prompt
- RunAsCurrentUser Execution
Code Structure:
- Dependency Checks:
- Installs NuGet and RunAsUser PowerShell module if missing.
- Command Block:
- Encapsulates the core shutdown logic within a scriptblock.
- Idle Time Tracking:
- Leverages PInvoke to access Win32 API's GetLastInputInfo function for accurate idle time measurement.
- Shutdown Threshold:
- Sets a configurable idle threshold in seconds ($idleThreshold) to trigger shutdown.
- Continuous Monitoring:
- Employs a while loop to continuously check idle time.
- Shutdown Initiation:
- If idle time exceeds the threshold:
- Initiates shutdown with a 30-second delay using shutdown.exe.
- Displays a confirmation prompt using a WScript.Shell message box.
- If the user confirms (clicks OK), aborts shutdown using shutdown -a.
- If no interaction, proceeds with shutdown using Stop-Computer -Force.
- If idle time exceeds the threshold:
- Execution Context:
- Uses Invoke-AsCurrentUser to execute the scriptblock in the context of the current user, ensuring proper idle time detection.
Additional Notes:
- Testing: Thoroughly test the script in a controlled environment before deployment.
- Timeout Configuration: Adjust the $idleThreshold value to suit your needs.
- Exclusions: Consider adding logic to exclude specific applications or processes from triggering shutdown.
- JumpCloud Integration: Explore options for centralized configuration and reporting through JumpCloud policies and tools.
- Error Handling: Implement error handling and logging for enhanced reliability.
Benefits:
- Energy savings
- Enhanced security
- Improved resource management
- Compliance with organizational policies
Conclusion:
This project demonstrates the value of PowerShell automation for managing idle computer shutdown on JumpCloud. By combining idle time detection, configurable timeouts, user confirmation, and proper execution context, it provides a flexible and effective solution for optimizing resource utilization and security.
Code Highlights:
# If Nuget is not installed, go ahead and install it
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
$PkgProvider = Get-PackageProvider
If ("Nuget" -notin $PkgProvider.Name){
Install-PackageProvider -Name NuGet -Force
}
# If PSModule RunAsUser is not installed, install it
if ( -not (get-installedModule "RunAsUser" -ErrorAction SilentlyContinue)) {
install-module RunAsUser -force
}
$Command = {
#Powershell Command Goes Here - paste your code:
<# testing the accuracy of GetLastInputInfo - testing Idle Time (Done)#>
<# testing the accuracy of GetLastInputInfo - testing Idle Time (Done)#>
Add-Type @'
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
namespace PInvoke.Win32 {
public static class UserInput {
[DllImport("user32.dll", SetLastError=false)]
private static extern bool GetLastInputInfo(ref LASTINPUTINFO plii);
[StructLayout(LayoutKind.Sequential)]
private struct LASTINPUTINFO {
public uint cbSize;
public int dwTime;
}
public static DateTime LastInput {
get {
DateTime bootTime = DateTime.UtcNow.AddMilliseconds(-Environment.TickCount);
DateTime lastInput = bootTime.AddMilliseconds(LastInputTicks);
return lastInput;
}
}
public static TimeSpan IdleTime {
get {
return DateTime.UtcNow.Subtract(LastInput);
}
}
public static int LastInputTicks {
get {
LASTINPUTINFO lii = new LASTINPUTINFO();
lii.cbSize = (uint)Marshal.SizeOf(typeof(LASTINPUTINFO));
GetLastInputInfo(ref lii);
return lii.dwTime;
}
}
}
}
'@
# Set the idle threshold for shutdown (in seconds)
$idleThreshold = 20 # Adjust this value as needed
while ($true) {
$idleTime = [PInvoke.Win32.UserInput]::IdleTime.TotalSeconds
Write-Host ("Idle for: $idleTime seconds")
if ($idleTime -ge $idleThreshold) {
Write-Host "User is idle for $idleThreshold seconds. Initiating shutdown..."
# Initiate shutdown with a delay
Start-Process -FilePath "shutdown" -ArgumentList "-s -t 30" -NoNewWindow -Wait
# Prompt the user to confirm or abort shutdown # Display message box
$confirmation = (New-Object -ComObject WScript.Shell).Popup("If you see this and don't want to shut down the PC, just click OK.", 0, "Shutdown Cancellation", 1)
if ($confirmation -eq 1) {
# User clicked OK, abort shutdown
Write-Host "Shutdown aborted by user."
# Abort the shutdown using shutdown -a
Start-Process -FilePath "shutdown" -ArgumentList "-a" -NoNewWindow -Wait
} else {
# User didn't interact, allow shutdown to proceed
Write-Host "Shutting down..."
# Implement your shutdown logic here
Stop-Computer -Force
}
}
Start-Sleep -Seconds 20 # Check every 20 seconds
}
# end
}
invoke-ascurrentuser -scriptblock $Command
- Labels:
-
General Software
-
Homelabs
-
Windows
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
01-24-2024 09:35 AM
@cali thank you for taking the time to share such a detailed guide with the community! We appreciate you 🙂
![](/skins/images/C210B62239BAF37B0AB0FAEB086BB5F1/responsive_peak/images/icon_anonymous_message.png)
![](/skins/images/C210B62239BAF37B0AB0FAEB086BB5F1/responsive_peak/images/icon_anonymous_message.png)