System shutdown and system logout based on idle time

Muhammad Umair 0 Reputation points
2025-01-07T09:27:33.3666667+00:00

Hi Team,

We are implementing the ISO 27001 policy for Clear desk and clear screen as documented on below

Clear desk policy according to ISO 27001 - What does it mean?

The policy has three main points :

  1. lock the system
  2. log out the system
  3. shutdown the system

We are able to implement point 1 however facing challenges for logging out users from workstation and then shutting down the systems. What we want is to apply this as idle time based. after 2 hrs logout the system and after 3 hrs shutdown the system.

We don't want to use the idle timeout setting through task scheduler as its deprecated and may stop at any time. Have gone through several other areas but is not able to find a proper solution.

Our devices are hybrid managed (AD and Intune) and open to implement any solution from GPO, Intune or PowerShell script. Please assist how we can do it??

Active Directory
Active Directory
A set of directory-based technologies included in Windows Server.
6,821 questions
Windows 11
Windows 11
A Microsoft operating system designed for productivity, creativity, and ease of use.
10,532 questions
Microsoft Intune
Microsoft Intune
A Microsoft cloud-based management solution that offers mobile device management, mobile application management, and PC management capabilities.
5,470 questions
0 comments No comments
{count} votes

4 answers

Sort by: Most helpful
  1. Crystal-MSFT 51,221 Reputation points Microsoft Vendor
    2025-01-16T05:36:43.14+00:00

    @Muhammad Umair, Thanks for the reply and share your working script. To help others who have the same issue, here, please let me write a brief summary for our issue.

    Issue:

    Need policy or script to shut down the systems after idle 3 hours

    Resolution:

    User's imageUser's imageUser's image

    Thanks for your time and have a nice day!


    If the answer is helpful, please click "Accept Answer" and kindly upvote it. If you have extra questions about this answer, please click "Comment".

    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.

    1 person found this answer helpful.

  2. Crystal-MSFT 51,221 Reputation points Microsoft Vendor
    2025-01-08T01:42:01.89+00:00

    @Muhammad Umair, Thanks for posting in Q&A. Besides Zafer's suggestion, here are some other suggestions from Intune for you.

    We can set "Max Inactivity Time Device Lock" in Settings Catalog policy to set the maximum amount of time (in minutes) allowed after the device is idle that will cause the device to become PIN or password locked.

    https://www.anoopcnair.com/set-automatic-lock-screen-for-inactive-device-intune/#:~:text=In%20Configuration%20settings%2C%20click%20Add%20settings%20to%20browse,the%20below%20settings%2C%20Max%20Inactivity%20Time%20Device%20Lock.

    Note: Non-Microsoft link, just for the reference.

    For log out or shutdown setting, I don't find built in policy in Intune to do this. You can do it via PowerShell script or Task scheduler to accomplish this.

    Hope the above information can help.


    If the answer is helpful, please click "Accept Answer" and kindly upvote it. If you have extra questions about this answer, please click "Comment".

    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.


  3. Zafer KAYA 20 Reputation points MVP
    2025-01-07T11:21:15.5233333+00:00

    sing PowerShell for Idle Timeout Actions

    We will create a script to:

    • Log out users after 2 hours of idle time.
    • Shut down the system after 3 hours of idle time.

    Key Steps:

    1. Detect Idle Time: Use the Get-LastInputInfo function (via P/Invoke in PowerShell) to calculate user idle time.
    2. Perform Actions:
      • Log out users with shutdown.exe /l.
      • Shut down the system with shutdown.exe /s. Using PowerShell for Idle Timeout Actions We will create a script to:
      • Log out users after 2 hours of idle time.
      • Shut down the system after 3 hours of idle time.
      Key Steps:
      1. Detect Idle Time: Use the Get-LastInputInfo function (via P/Invoke in PowerShell) to calculate user idle time.
      2. Perform Actions:
        • Log out users with shutdown.exe /l.
        • Shut down the system with shutdown.exe /s.
    3. Define idle timeout thresholds in seconds

      $logoutIdleTime = 7200 # 2 hours $shutdownIdleTime = 10800 # 3 hours

      Import user32.dll for idle time detection

      Add-Type @" using System; using System.Runtime.InteropServices; public class IdleTimeFinder {
      [DllImport("user32.dll")]
      
      public static extern bool GetLastInputInfo(ref LASTINPUTINFO plii);
      
      [StructLayout(LayoutKind.Sequential)]
      
      public struct LASTINPUTINFO {
      
          public uint cbSize;
      
          public uint dwTime;
      
      }
      
      public static uint GetIdleTime() {
      
          LASTINPUTINFO lii = new LASTINPUTINFO();
      
          lii.cbSize = (uint)System.Runtime.InteropServices.Marshal.SizeOf(lii);
      
          GetLastInputInfo(ref lii);
      
          return ((uint)Environment.TickCount - lii.dwTime) / 1000; // Idle time in seconds
      
      }
      
      } "@

      Main loop

      while ($true) {
      # Get idle time
      
      $idleTime = [IdleTimeFinder]::GetIdleTime()
      
      # Perform logout if idle time exceeds logout threshold
      
      if ($idleTime -ge $logoutIdleTime -and $idleTime -lt $shutdownIdleTime) {
      
          Write-Output "Idle time exceeds logout threshold. Logging out user..."
      
          shutdown.exe /l
      
          break
      
      }
      
      # Perform shutdown if idle time exceeds shutdown threshold
      
      if ($idleTime -ge $shutdownIdleTime) {
      
          Write-Output "Idle time exceeds shutdown threshold. Shutting down system..."
      
          shutdown.exe /s /t 0
      
          break
      
      }
      
      # Sleep for 1 minute before checking again
      
      Start-Sleep -Seconds 60
      
      }

    Deploying the Script

    1. Package the Script as a PowerShell Policy:
      • Save the script as IdleTimeoutScript.ps1.
      • Go to Microsoft Intune > Devices > Scripts > Add Script.
      • Upload the script and assign it to the necessary user/device groups.
      • Configure the script to run in the system context.
    2. Set Execution Frequency:
      • Use Proactive Remediation in Intune (under Reports > Endpoint Analytics) to run the script at periodic intervals.
    3. Using GPO

    Create a GPO:

      - Open **Group Policy Management**.
      
            - Create or edit a GPO and navigate to **Computer Configuration > Policies > Administrative Templates > System > Scripts**.
            
                  - Add the PowerShell script to **Startup Scripts**.
                  
    
    1. Link the GPO:
      • Link the GPO to the required Organizational Unit (OU) containing the hybrid devices.
    0 comments No comments

  4. Muhammad Umair 0 Reputation points
    2025-01-16T05:16:18.6+00:00

    Hi All/Crystal-MSFT/Zafer KAYA ,

    We were able to make it work by using the below script

    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;
    
            }
    
        }
    
    }
    

    }

    '@

    for ($i = 0; $i -lt 545000; $i++) {

    $Last = [PInvoke.Win32.UserInput]::LastInput
    
    $Idle = [PInvoke.Win32.UserInput]::IdleTime
    
    $LastStr = $Last.ToLocalTime().ToString("MM/dd/yyyy hh:mm tt")
    
     Write-Host ("`nTest " + $i)
    
     Write-Host ("   Last user keyboard/mouse input: " + $LastStr)
    
     Write-Host ("   Idle for " + $Idle.Days + " days, " + $Idle.Hours + " hours, " + $Idle.Minutes + " minutes, " + $Idle.Seconds + " seconds.")
    
    # Check if idle time exceeds 3 hours (10,800 seconds)
    
    if ($Idle.TotalSeconds -gt 10800) {
    
        Write-Host "Idle time exceeded 3 Hours seconds. Initiating shutdown..."
    
        Start-Process -FilePath "shutdown.exe" -ArgumentList "/s /t 900" -NoNewWindow
    
        break
    
    }
    
    # Random sleep to simulate repeated checks
    
    Start-Sleep -Seconds (Get-Random -Minimum 1 -Maximum 900)
    

    }

    0 comments No comments

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.