Show / Hide Table of Contents

Game scripts

Introduction

Custom PowerShell scripts can be assigned via Playnite's UI to game events. This is similar in a way that extensions support hooking into game events, but doesn't require creation of custom extension and can be assigned on multiple levels:

  • Global: executed for every game in a library.
  • Emulator: executed for a specific emulator profile on all games using that profile.
  • Game: executed for a specific game.

This is not the same as script extensions which offer extended functionality and should be used for more complex scenarios.

Note

PowerShell support requires PowerShell 5.1 to be installed on your machine. If you are Windows 7 user, you need to install it manually (Windows 8 and 10 includes it by default). This also means that PowerShell functionality is restricted to 5.1 version. Playnite currently doesn't support newer PowerShell Core runtime (PowerShell versions 6 and newer).

Execution

Scripts are executed in the following order:

global pre -> emulator pre -> game pre -> game post -> emulator post -> global post -> emulator exit -> game exit -> global exit

where:

  • pre - before game is started.
  • post - after game is started running.
  • exit - after game stopped running.

If a game has installation directory set and that directory actually exists, Playnite will set current working directory of a script runtime to that installation directory.

All scripts share the same runtime environment for a single game session. This means that you can share data between them if you declare your variables on global scope, for example $global:testVar = 2.

Note

All scripts are executed synchronously, meaning that Playnite will wait for a script to finish and will block any other execution, including UI since the script runtime runs on main thread.

Startup script is an exception to mentioned execution behavior, see startup script section for more details.

Script variables

Playnite provides some built-in global variables that scripts can use to get more information about current game session.

Variable Description
PlayniteApi Instance of Playnite API.
Game Game library object for current game session.
SourceAction Custom game action used to start a game.
SelectedRomFile ROM file selected when running a game with multiple ROMs assigned.

Startup script

If you need more complex startup and game tracking procedure other then just starting an executable, or default session tracking doesn't work for a specific game, then you can start and manage game session using a script. This is currently available to emulators (custom profiles) and games.

The script should keep running while you want Playnite to detect the game as running. Once the script finishes with execution, Playnite considers the game to stop running and will record game session length based on how long the script was running (adding that time to overall game play time).

Note

Startup scripts run in a separate script runtime and thread compared to other game scripts. Therefore you can't share data with other game/global scripts and you can't directly call any code that must be run on main thread (most UI things)!

Breaking exceptions from startup script are not propagated to UI via error message (like for other game/global scripts) and are only logged into Playnite's log file.

Startup script example

$process = [System.Diagnostics.Process]::Start("game.exe")
$process.WaitForExit()
$process.Dispose()

Reacting to tracking cancellation

You can use $CancelToken.IsCancellationRequested to detect if user cancelled game session manually from Playnite. When cancellation is initiated, Playnite sets mentioned property to true and gives the script 10 seconds to exit gracefully. If the script fails to exit in that time, script's runtime is killed.

# WaitForExit() is synchronous check so it can't be used if you want to support session cancellation
$process = [System.Diagnostics.Process]::Start("game.exe")
while ($true)
{
    # Check if user cancelled game session
    if ($CancelToken.IsCancellationRequested)
    {
        break
    }

    # Check if process is still running
    if (!(Get-Process -Name "game" -EA 0))
    {
        break
    }

    # Sleep for a while to not waste CPU
    Start-Sleep -s 1
}

$process.Dispose()

Startup script variables

Variable Description
PlayniteApi Instance of Playnite API.
Game Game library object for current game session.
IsPlayAction Indicates whether an action was started as play action.

Examples

Starting additional application(s) before game starts and killing it after game exits.

  • Edit game and go to Scripts tab
  • Set first script to start your application using Start-Process cmdlet
Start-Process "c:\somepath\someapp.exe" "-some arguments"
  • Set second script to kill the application using [Stop-Process]https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.management/stop-process?view=powershell-5.1) cmdlet
Stop-Process -Name "someapp"
  • If the application requires elevated rights to start then you need to start Playnite as admin too, otherwise the Stop-Process will fail due to insufficient privileges.
  • If you want to start application minimized and application doesn't have native support for it then add -WindowStyle argument.
Start-Process "c:\somepath\someapp.exe" "-some arguments" -WindowStyle Minimized

Troubleshooting

Application doesn't start

Some applications won't work properly (or even start) when started using working directory outside of their application director. In that case you need to use -WorkingDirectory parameter and specify working directory manually.

Can't shutdown process

You won't be able to use Stop-Process on processes that are started with elevated rights. In that case, you need to use WMI to shutdown a process:

(Get-WmiObject -Class Win32_Process -Filter "name = 'someapp.exe'").Terminate()

Exceptions related to directory not being found

Paths (and strings in general) in various places in PowerShell are handled not as literal strings, but as strings with wildcard patterns. This has unfortunate issue if specific command doesn't allow you to pass literal string via a specific argument (for example -LiteralPath) or has an option to disable wildcard parsing.

This can cause issues if game's installation path contains wildcard pattern characters. For example game installed in d:\[test] game name\ will cause issues to Start-Process cmdlet, because of [ and ] pattern characters. This is because Playnite sets script runtime's working directory to game's installation path and Start-Process tries to parse it before launching a program.

Solution is to either use literal path arguments or use different cmdlet or .NET classes directly. For example to start a process:

# Instead of:
Start-Process "game.exe"

# call .NET class directly:
[System.Diagnostics.Process]::Start("game.exe")

Note: This issue has been fixed in newer versions of PowerShell, but since Playnite has to use older version (5.1) until we switch to newer .NET runtime, you may encounter this issue.

  • Improve this Doc
Back to top Generated by DocFX