Skip to content

Instantly share code, notes, and snippets.

@tresf
Last active August 18, 2024 17:51
Show Gist options
  • Save tresf/ff91bd29f1f6846c13bf6f8bc255ab55 to your computer and use it in GitHub Desktop.
Save tresf/ff91bd29f1f6846c13bf6f8bc255ab55 to your computer and use it in GitHub Desktop.

Batch QZ Tray Session Stealer

Custom session stealer for Windows fast user switching

For a pure PowerShell solution, see here instead: https://gist.github.com/tresf/4e19e15ad38354af6732ee701c990102

Problem

  • QZ Tray is a singleton application, so only one instance can run at a time.
  • Windows fast-user switching feature leaves applications running when a new user signs onto a shared workstation
  • QZ Tray can "steal" the instance, however this is retroactive and places a burden on the user

Solution

  • A solution is to detect that a user switch has occured and start QZ Tray on the new desktop automatically

Limitations

  • This should ONLY be run on shared workstations with one user at a time. Terminal Server environments should instead leverage a dedicated print-server solution.
  • Company Branded builds must replace "QZ Tray", "qz-tray" and "qz" in each file with the name of your respective application.

Steps

  1. Copy start_if_active.bat to C:\Program Files\QZ Tray\
  2. Import Steal QZ Tray At Login.xml to Task Scheduler
    • If the new entry does not immediately appear after saving, Action -> Refresh
  3. Test fast-user switching
@ECHO OFF
REM Author: tres@qz.io
FOR /F "skip=1" %%g IN ('WMIC COMPUTERSYSTEM GET USERNAME') DO (IF NOT DEFINED LOGGED_USER SET LOGGED_USER=%%g)
REM Note: "": =%"" will Remove spaces from WMIC output when comparing
IF /I "%LOGGED_USER: =%" == "%USERDOMAIN%\%USERNAME%" (
"%~dp0qz-tray.exe" --steal
SET MSG=[start_if_active.bat] %DATE% %TIME% SUCCESS: "%USERDOMAIN%\%USERNAME%" is active, starting "%~dp0qz-tray.exe"
COLOR 0A
) ELSE (
SET MSG=[start_if_active.bat] %DATE% %TIME% SKIPPED: "%USERDOMAIN%\%USERNAME%" is NOT active, skipping "%~dp0qz-tray.exe"
COLOR 0C
)
ECHO %MSG%
ECHO %MSG% >> %APPDATA%\qz\task-scheduler.log
REM PAUSE
<?xml version="1.0" encoding="UTF-16"?>
<Task version="1.2" xmlns="http://schemas.microsoft.com/windows/2004/02/mit/task">
<RegistrationInfo>
<Date>2022-12-13T12:29:01.6615572</Date>
<Author>tres@qz.io</Author>
<URI>\Steal QZ Tray at Login</URI>
</RegistrationInfo>
<Triggers>
<EventTrigger>
<Enabled>true</Enabled>
<Subscription>&lt;QueryList&gt;&lt;Query Id="0" Path="Security"&gt;&lt;Select Path="Security"&gt;*[EventData[ (Data[@Name='LogonType']=2) and (Data[@Name='ElevatedToken']='%%1843')]] and *[System[(EventID=4624)]]&lt;/Select&gt;&lt;/Query&gt;&lt;/QueryList&gt;</Subscription>
</EventTrigger>
</Triggers>
<Principals>
<Principal id="Author">
<GroupId>S-1-5-32-545</GroupId>
<RunLevel>LeastPrivilege</RunLevel>
</Principal>
</Principals>
<Settings>
<MultipleInstancesPolicy>StopExisting</MultipleInstancesPolicy>
<DisallowStartIfOnBatteries>false</DisallowStartIfOnBatteries>
<StopIfGoingOnBatteries>false</StopIfGoingOnBatteries>
<AllowHardTerminate>true</AllowHardTerminate>
<StartWhenAvailable>false</StartWhenAvailable>
<RunOnlyIfNetworkAvailable>false</RunOnlyIfNetworkAvailable>
<IdleSettings>
<StopOnIdleEnd>false</StopOnIdleEnd>
<RestartOnIdle>false</RestartOnIdle>
</IdleSettings>
<AllowStartOnDemand>true</AllowStartOnDemand>
<Enabled>true</Enabled>
<Hidden>false</Hidden>
<RunOnlyIfIdle>false</RunOnlyIfIdle>
<WakeToRun>false</WakeToRun>
<ExecutionTimeLimit>PT0S</ExecutionTimeLimit>
<Priority>7</Priority>
</Settings>
<Actions Context="Author">
<Exec>
<Command>cmd.exe</Command>
<Arguments>/c start_if_active.bat</Arguments>
<WorkingDirectory>%PROGRAMFILES%\QZ Tray\</WorkingDirectory>
</Exec>
</Actions>
</Task>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment