Dinnertime Gaming Blocker

March 10, 2024

Because you can love gaming a bit too much.

We all love a bit of gaming at my house, myself, my wife and my kids.

The only problem is, when it is time to stop and come off the computer games in time for dinner.

Whether it is Minecraft, Party Animals, Kerbal Space Program or anything else, the kids don’t want to stop.

As parents, we’ve been met with ‘in a minute’ refusals that have found food going cold, and a lot of frustration on our part.

Child being blocked from gaming.

So, what if we give them some warning and then turn the game off?

This post explains how to use Automation and PowerShell specifically to do just that.

Note: There are options within Microsoft family controls, but with the variety of other gaming platforms like Steam, Epic Games and so on, controlling everything through online portals/apps is a bit impractical.

Why PowerShell?

PowerShell is installed by default on every modern Windows machine, and as a family of Windows PC gamers, it is the simplest choice that requires no extra installation.

It allows for scripting and automation of different tasks on the Windows machine, and is also object orientated, giving many advantages of modern programming languages. At the same time, it is simple to get started with.

Script Requirements

For our kids, we wanted to block Minecraft at 5pm, in time for dinner a few minutes later.

We wanted to give them warning of the upcoming block for a few minutes, and then wanted to stop the game running after this time.

We also wanted to make sure that this only ran for their users - we have a Microsoft family setup, and multiple accounts, so would want to only run the gaming blocker for processes on their accounts.

Yes, this is one rule for the grown ups and one for the kids.

How to block gaming

Anything that runs in Windows (or any other OS in fact) will exist as a process, and it is possible to get the running processe with PowerShell. If you know what the process name is, or other characteristics such as where it runs from, you can identify it with a high degree of certainty.

When you know which process you want to control, you can then shut it down.

This is as true when blocking games as it is with other processes.

For example, you can find out if you have the “notepad” application running using this command in a PowerShell window.

get-process -Name notepad

To do the same for Minecraft (or other games) it looks like this.

get-process -name Minecraft.Windows

PowerShell will report an error if there is no process exists, but we’ll handle that in the script.

If you have specific games or processes that should be blocked, the ‘Get-Process’ command and Task Manager are the best way to do this - make sure the game is running, alt-tab out and launch PowerShell / Task Manager to find the process name.

Find Party Animals Process

However, this will only work for uniquely named process games. Some games run under other processes with names also used by other applications - Minecraft Java Edition is the obvious example of this as it runs using the javaw.exe process which is used by other Java apps.

To find other process paths, you will need to dig a bit deeper. As before, use “Get-Process” but this time pipe it to the Select-Object commandlet, and add the option “-ExpandProperty Path”.

get-process -Name <process name> | Select-Object -ExpandProperty Path

For example:

Find Minecraft Java Process.

With the path property identified, you can use this to identify the running process for the game and add it to the processpaths variable in the script.

Which users to block

The blocker script needs to run as the user in order to show notifications, and in order to only affect the child accounts. The PowerShell environment variable $env:username will provide this.

A Windows Scheduled task, set to run at the login of each user, is used to launch the script as a PowerShell process.

If the user who has logged in is named in the script, the PowerShell process will run in the background until cut-off time approaches. If the user is not named, it will simply exit.

The additional user filter is not strictly necessary, but it does stop the child user from switching the user onto the parent’s account and interferring with their activity (unless they edit the script itself).

I Toast Therefore I Am

“Would anyone like any toast?” as the Crapola inc toaster once asked in Red Dwarf. Unlike Dave Lister, our answer is “yes”.

Toast notifications as they are known are the pop-ups that appear next to the taskbar in Windows to let the user know certain things.

If the user (child) is approaching their cutoff time, the script will start to display toast notification messages from the admins (parents), giving them advance warning of the impending block to gaming.

Depending on the game, these may be shown over the top of the gaming UI.

The Script

Param(
    [bool]$whatif = $false,
    [int]$warningstartminutes = 5,
    [DateTime]$dinnertime = "17:00:00",
    $users = @( "demouser","demouser2"),
    $processes = @( "Minecraft.Windows", "PartyAnimals", "RobloxPlayer"  ),
    $processpaths = @( "C:\Users\$env:username\AppData\Local\Packages\Microsoft.4297127D64EC6_8wekyb3d8bbwe\LocalCache\Local\runtime\java-runtime-gamma\windows-x64\java-runtime-gamma\bin\javaw.exe" )
    )
function Stop-Game
{
    # find the game process and kill it
   
   $gameprocesses = get-process -ErrorAction SilentlyContinue | Where-Object {($_.Name -in $processes) -or ($_.Path -in $processpaths) }
   
   if( $gameprocesses )
        {
        foreach( $gameprocess in $gameprocesses )
            {

            $gameprocess | Stop-Process -Force
            Show-Notification -ToastText "Your game has been stopped." -ToastTitle "Time to stop!"
            }
        }
}

function Show-Notification {
    [cmdletbinding()]
    Param (
        [string]
        $ToastTitle,
        [string]
        [parameter(ValueFromPipeline)]
        $ToastText
    )

    [Windows.UI.Notifications.ToastNotificationManager, Windows.UI.Notifications, ContentType = WindowsRuntime] > $null
    $Template = [Windows.UI.Notifications.ToastNotificationManager]::GetTemplateContent([Windows.UI.Notifications.ToastTemplateType]::ToastText02)

    $RawXml = [xml] $Template.GetXml()
    ($RawXml.toast.visual.binding.text|where {$_.id -eq "1"}).AppendChild($RawXml.CreateTextNode($ToastTitle)) > $null
    ($RawXml.toast.visual.binding.text|where {$_.id -eq "2"}).AppendChild($RawXml.CreateTextNode($ToastText)) > $null

    $SerializedXml = New-Object Windows.Data.Xml.Dom.XmlDocument
    $SerializedXml.LoadXml($RawXml.OuterXml)

    $Toast = [Windows.UI.Notifications.ToastNotification]::new($SerializedXml)
    $Toast.Tag = "PowerShell"
    $Toast.Group = "PowerShell"
    $Toast.ExpirationTime = [DateTimeOffset]::Now.AddMinutes(1)

    $Notifier = [Windows.UI.Notifications.ToastNotificationManager]::CreateToastNotifier("Parental Controls")
    $Notifier.Show($Toast);
}
function CheckLoggedInUser
{

    $loggedinuser = $env:username

    if( $users -contains $loggedinuser )
        {
        return $true
        }
    else
        {
        return $false
        }
}

if( CheckLoggedInUser )
    {

    $timeformat = "HH:mm:ss"
    while( $true )
        {
        Start-Sleep -Seconds 60
        
        $timenow = Get-Date -format $timeformat
        $dinnerdatetime = Get-Date -Date $dinnertime -Format $timeformat
        Write-Output "Time is $timenow"

        $warningstart =  Get-Date -date ($dinnertime.AddMinutes( - $warningstartminutes)) -Format $timeformat

        if( ($timenow -gt $warningstart) -and  ($timenow -le $dinnerdatetime) )
            {
            for( $i = 0; $i -lt $warningstartminutes ; $i++ )
                {
                $warncount = $warningstartminutes - $i

                Show-Notification -ToastText "It's nearly Dinnertime. Your game will exit in $warncount minutes." -ToastTitle "Dinnertime soon!"
                Start-Sleep -Seconds 60
                }
            
            }
        else
            {

            if( $timenow -gt $dinnerdatetime )
                {

               
                Stop-Game
                } 
            }
        }
    }
else
    {
    Write-Output "User not in user list"
    exit 
    }
    

Also available on GitHub here..

Setup

Copy the script, or download it from Github, into a folder on the machine you need the blocker to run on.

Note the path and the filename where you have copied/downloaded it to.

Go into Windows Task Scheduler and create a task that is set to trigger at login, and that should run powershell as a script.

The example “DinnertimeGamingBlocker.xml” file which is found on Github, can be imported into Task Scheduler, but may need paths or other details to be customised.

The following video demonstrates the setup and usage.

Create a scheduled task and set it to run when the user is logged on as the the child’s account - demouser in screenshot.

Scheduled task setup step 1.

Under triggers, set the task to run at logon of the specific user.

Scheduled task setup step 2.

In the actions section, select “Start a program”, and enter “powershell.exe” in the “Program/script” field.

In the “Add arguments” field enter “-executionpolicy Bypass -windowstyle hidden -file ‘full-path-to-script-file’”

For example, “-executionpolicy Bypass -windowstyle hidden -file C:\Scripts\DinnertimeGamingBlocker.ps1”

If the blocker script is in a different location, you will need to customise this and if you have spaces in the filepath, the full path should be in quotes - eg ‘C:\Script Files\DinnertimeGamingBlocker.ps1"

Scheduled task setup step 3.

In the conditions section, you may need to turn off the “Only run on AC” options if the PC is a laptop that runs on battery a lot.

Scheduled task setup step 4.

Save the scheduled task, then logoff and logon as the child’s user account.

The script will run in the background until the specified “dinnertime” and will then give the child a warning by toast notification until the 5 minute grace period runs out. After this time, they will be kicked out of the blocked games every 60 seconds.

Impact

With the script running, the kids should get notice of when they are to be kicked out of their game. After the cutoff time, they will no longer receive warnings, and the game process will be killed off after up to 1 minute, effectively stopping them from loading.

Limitations

It is worth noting that the script and approach is not without its limits. To turn off the blocker, the PowerShell process can simply be killed off in Task Manager to override the block. Note the command line options match that of the scheduled task.

You may find that you even want to override the block from time to time - eg dinner is late!

The main limit you will find on this script is if your kids figure out how to kill the PowerShell process.

Mine did - but another option is coming soon.

Further Ideas

The script could be modified to use a config file, covering various blocked / allowed time periods, or even make a call out to a remote endpoint to dynamically set the configuration - a new favourite game is preventing your child getting to the dinner table - just add it to the list.

With the way that the script runs, the one thing I would advise against is logoff / shutdown commands being part of the script as doing so in a login script could make it very difficult to access the user account or computer if something goes wrong.