Scenario
You want to log off users who have been inactive for a specified period of time. By inactive, I mean the user has not used the mouse, keyboard, input device. I have tried a few ways of doing this, but this way was the most successful way for me.What you need
CoreTech Shutdown Tool - Shutdown ToolHidden Powershell Script - Hidden Powershell Script
Exported Scheduled Task - XML File
Powershell Script
These are the files that you will need to deploy this solution...
- HiddenPowerShell.vbs - this will allow you to run a powershell script via a scheduled task on a regular basis without the powershell window popping up.
- InactiveUserLogoff.xml - You can use this to import your scheduled task. I created this by creating a new scheduled task in the task scheduler, and then I exported it to this xml file.
- InactiveUserLogoff.ps1 - The scheduled task kicks off these powershell scripts to detect idle time and determine if they need to launch the shutdown / logoff tool.
- ShutdownTool_NoBack.exe - Shutdown Tool
- ShutdownTool_NoBack.png - Customization image for branding the shutdown tool.
Overview
How this works...We are creating a scheduled task that runs every 5 minutes. That scheduled task kicks off a powershell script that checks the idle time. If the idle time is more than 14 minutes, then the powershell script kicks off the shutdown tool. If it has not been idle for more than 14 minutes, then the powershell script ends and will run again in 5 minutes. [These timers can be modified by modifying the scheduled task / powershell script]
We are using this too with the /l switch to log the user off. Without that switch, it will shut the machine down.
You might be wondering... "Why not just use the Idle trigger in the scheduled task?". Good question... Because it didn't give me the behavior that I was looking for. This method is more complicated, but it gives me more control.
Powershell Script Contents
<#
This script is a modification of the script found here: https://stackoverflow.com/questions/15845508/get-idle-time-of-machine
It will check the idle time of the machine and if it has reached the threshold, it will launch the shutdown tool.
#>
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;
}
}
}
}
'@
# Create Idle Time Variables
# $Last = [PInvoke.Win32.UserInput]::LastInput
$Idle = [PInvoke.Win32.UserInput]::IdleTime
# $LastStr = $Last.ToLocalTime().ToString("MM/dd/yyyy hh:mm tt")
# Create File Variables
# Change the cancel time (in seconds) to change the amount of time a user has to cancel logoff.
$CancelTime = "900"
$FilePath = "C:\ProgramData\ShutdownTool\ShutdownTool_NoBack.exe"
$Parameters = " /l /f /d:'This computer appears to be idle or not in use. If you would like to continue working, press the Abort button above.' /t:$CancelTime"
$Execute = $FilePath + $Parameters
If ($Idle.Minutes -ge 14) {
Invoke-Expression $Execute
}
This script is a modification of the script found here: https://stackoverflow.com/questions/15845508/get-idle-time-of-machine
It will check the idle time of the machine and if it has reached the threshold, it will launch the shutdown tool.
#>
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;
}
}
}
}
'@
# Create Idle Time Variables
# $Last = [PInvoke.Win32.UserInput]::LastInput
$Idle = [PInvoke.Win32.UserInput]::IdleTime
# $LastStr = $Last.ToLocalTime().ToString("MM/dd/yyyy hh:mm tt")
# Create File Variables
# Change the cancel time (in seconds) to change the amount of time a user has to cancel logoff.
$CancelTime = "900"
$FilePath = "C:\ProgramData\ShutdownTool\ShutdownTool_NoBack.exe"
$Parameters = " /l /f /d:'This computer appears to be idle or not in use. If you would like to continue working, press the Abort button above.' /t:$CancelTime"
$Execute = $FilePath + $Parameters
If ($Idle.Minutes -ge 14) {
Invoke-Expression $Execute
}
As you can see, you can modify the amount of time the computer can be idle before the shutdown tool is launched If ($Idle.Minutes -ge 14) just change the 14 to however many minutes you want.
You can also change the amount of time the shutdown tool gives the user to cancel the logoff. Just change the value 900 to the number of seconds you want to give them to cancel the logoff. $CancelTime = "900"
Now that you have the powershell script, you need a scheduled task to kick off the powershell script at your desired interval. Create a scheduled task that has the parameters that you want and then export it to .xml.
IMPORTANT: If this is to work for more than one person (the person who created the scheduled task) you need to use a group that contains the users who might logon to this computer.
The trigger I used is as follows: The task repeats every 5 minutes.
Keep in mind that if the idle time is at 13 minutes when the powershell script checks the idle time, it won't actually attempt the user to logoff until 18 minutes (next time the scheduled task gets kicked off).
In my case the arguments are as follows:
HiddenPowerShell.vbs -ExecutionPolicy Bypass -File C:\ProgramData\ShutdownTool\InactiveUserLogoff_15min.ps1
I copied my folder containing all my shutdown tools to the ProgramData folder. You may decided to put them elsewhere.
SCCM Package
I ended up creating an SCCM package to push this out. I used two bat files - one for copying the shutdown tools to the local drive. The other one creates the scheduled task by importing the .xml file.The sources folder contains the files I mentioned at the beginning of this post. The contents of the bat files are as follows:
Copy Shutdown Tools
SET loc=%~dp0
pushd "%~dp0"
mkdir "C:\ProgramData\ShutdownTool"
takeown /a /f "C:\ProgramData\ShutdownTool"
icacls "C:\ProgramData\ShutdownTool" /Grant Administrators:(F)
icacls "C:\ProgramData\ShutdownTool" /Grant System:(F)
cmd /c Xcopy /E "%~dp0source" "C:\ProgramData\ShutdownTool" /Y
Create Scheduled Task
SET loc=%~dp0Finally, I can create a package with two programs, one for copying the files and the other for creating the scheduled tasks.
pushd "%~dp0"
cmd /c schtasks /Create /XML "%~dp0source\InactiveUserLogoff.xml" /TN "Logoff Inactive User"
I hope that helps.
No comments:
Post a Comment