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:
Project Overview:
Code Structure:
Additional Notes:
Benefits:
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
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 🙂
New to the site? Take a look at these additional resources:
Ready to join us? You can register here.