Get-LoggedOnUser returns incorrect IsCurrentSession when executed via Scheduled Task as SYSTEM on VDI Multi-Session Host

I’m using Get-LoggedOnUser from the PSAppDeployToolkit to retrieve the active user session on a VDI multi-session host (Windows 11 Enterprise multi-session). My goal is to configure user-specific HKCU:\Software\Policies registry values from a script running under the SYSTEM context — for which direct SID-based access via PSADT is ideal.

When I execute the script manually using PsExec as SYSTEM, Get-LoggedOnUser correctly identifies the currently logged-in user and sets IsCurrentSession = $true for the active session. I can then use the returned SID to write to the appropriate HKCU hive under HKEY_USERS.

However, when the exact same script is executed via a Scheduled Task triggered at logon, running as NT AUTHORITY\SYSTEM, Get-LoggedOnUser still returns the correct list of users and sessions, but none of them have IsCurrentSession = $true, even though one of them should.

This leads to the script aborting, since it cannot determine the current user context via the toolkit logic.

I’ve ensured that:

  • The Scheduled Task is configured to run as SYSTEM
  • The trigger is “At logon”
  • The script is not restricted to a specific user
  • A delay of 30–60 seconds has been tested as well

The only difference between the working (PsExec) and failing (Scheduled Task) executions is the mechanism of launch. On identical hosts, one detects the current session correctly and the other does not.

Questions:

  1. What could explain the discrepancy in IsCurrentSession detection between PsExec-as-SYSTEM and Scheduled Task-as-SYSTEM executions?
  2. Is there any timing or session initialization consideration I’m missing in multi-session environments like Azure Virtual Desktop or Windows 11 multi-session?
  3. Is there a known workaround to reliably detect the current interactive session from a Scheduled Task running as SYSTEM?

Any insight would be greatly appreciated. Thanks in advance!

Run as ScheduledTask:

Run manually with Powershell (psexec -i -s)

Follow-up / Additional Information:

After further testing, I’ve identified a crucial detail that likely explains the behavior difference I’m seeing:

When I run my script manually using psexec -i -s, Get-LoggedOnUser successfully detects the session and correctly sets IsCurrentSession = $true for the actively logged-on user. However, when I trigger the same logic via a Scheduled Taskrunning as SYSTEM on logon of any user, the same function does not return any user with IsCurrentSession = $true.

The key difference appears to be the lack of an interactive session context when the Scheduled Task is triggered. Since it’s not explicitly attached to the interactive session (unlike with psexec -i), Get-LoggedOnUser doesn’t link the SYSTEM process to the user session that triggered the logon event.


What I’m trying to achieve:

I’m on a multi-user environment (Windows 11 multi-session / AVD) and want to:

  1. Trigger a SYSTEM-level Scheduled Task each time any user logs in.
  2. From that SYSTEM context, determine which user just logged in (i.e., the session that triggered the task).
  3. Use the user’s SID to write registry keys under their HKCU path via HKEY_USERS<SID>, e.g., to set policies.

What I’m looking for:

An effective and reliable way to identify the just-logged-on user in a multi-session environment from a Scheduled Task running as SYSTEM.

This is important because in environments with multiple concurrently logged-on users (e.g., AVD), Get-LoggedOnUserreturns all sessions, and I need to pinpoint the one that just triggered the logon event, in order to target that specific user’s registry hive.

Any ideas or best practices around correlating the Scheduled Task trigger to the correct user session in such a setup would be greatly appreciated!

Is this in 4.0.x, or in 4.1.0-rc1? If it’s the former, all this code’s been rewritten so please try the rc1 release and let us know how you go.

3 Likes

Tested with PSADT 4.1.0-rc1 on AVD multi-session .

When triggered by a Scheduled Task running as SYSTEM at user logon, Get-ADTLoggedOnUser and Get-ADTRunAsActiveUser do not return the user who just logged in — they return an arbitrary session.

Is this scenario officially supported in 4.1.0-rc1?

If not, what’s the recommended way to detect the just-logged-on user from a SYSTEM context?

You’ll probably have to get all users via Get-ADTLoggedOnUser and sort them by LogonTime.

2 Likes

I’ve added this commit to hopefully address the issue: - Revise `Get-ADTRunAsActiveUser` to return the most recent active se… · PSAppDeployToolkit/PSAppDeployToolkit@bb7b96d · GitHub

You can download a build containing this commit from here: - Revise `Get-ADTRunAsActiveUser` to return the most recent active se… · PSAppDeployToolkit/PSAppDeployToolkit@bb7b96d · GitHub

The reason IsCurrentSession is true when using psexec -i is because you’re forcing the SYSTEM running process to be interactive in your session, which is what ServiceUI does. Therefore even though it’s a process with a different owner, it becomes true. When you’re running via the Task Scheduler, you’re on proper session 0, so this will never evaluate to true and you should have no expectation that it ever will.

The commit above gets all valid, active users, sorts descendingly on LogonTime, then returns the first user. It seems to fit the bill for what you’re after, and is probably the best we can do for 4.1.0 until we include further rework around the new client/server process on multi-user desktop environments.

2 Likes

First of all, thank you so much for the incredibly quick response and targeted fix – this commit is hugely appreciated and aligns exactly with what I’ve been struggling with in a multi-session environment!

One follow-up question:

In high-load AVD scenarios, especially during logon storms, we sometimes see multiple users logging in at nearly the same time – occasionally up to 8+ users within the same second. Does the updated Get-ADTRunAsActiveUser logic compare LogonTime with high enough precision (e.g., milliseconds) to reliably detect the true most recent session?

Also, I’m really looking forward to seeing the future rework around the new client/server process for multi-user desktop environments. That direction makes PSADT an even more powerful tool for use in modern VDI and multi-session scenarios.

I’m glad the committed change has been able to hit the mark!

Regarding the follow-up question, WTS returns the LogonTime as a FILETIME object. FILETIME is a 64-bit integer value comprised of 100 nanosecond ticks since 1601-01-01T00:00:00. There is no greater time precision in Windows than FILETIME so what WTS gives us is the best you’re going to get. You can see where we convert the FILETIME value into a System.DateTime object here: PSAppDeployToolkit/src/PSADT/PSADT/TerminalServices/SessionManager.cs at e7695fc8e74454b1556576cce869abc82d095dcb · PSAppDeployToolkit/PSAppDeployToolkit · GitHub

As for the next steps regarding multi-session operating systems, I’ve opened #1536 to track this. This is going to require a lot of internal discussion around what we think as a team is best, however my thoughts are we’ll have the client/server process display to all active users, with each user’s dialog showing the processes they need to close (users of 4.1.0 will only see the processes they can close also, its just we can’t display the client/server stuff to more than a single user presently).

On the back of that, you’d have a majority percentage you can set to trigger the installation (i.e. 67% of users have closed their processes, but Johnny hasn’t responded in 300 seconds because he’s flirting with Sally and not looking at his screen, therefore his processes close automatically and installation proceeds). Obviously a lower percentage gets things going quicker, but if you were to set it to 100%, you could never guarantee 100% response rate from users, etc.

1 Like

Thanks again for the in-depth discussion and for enabling us to thoroughly test the changes – everything looked good during initial validation.

However, after repeated use in real-world scenarios with multiple active sessions on a multi-session OS, we encountered a specific issue: Get-ADTRunAsActiveUser consistently fails when more than one user is logged in simultaneously. This behavior has only been observed under concurrent user sessions in a multi-session environment.

Just wanted to flag this edge case, as it seems tied directly to the multi-user context and might be relevant for the ongoing discussions around multi-session support and the future direction of client/server interaction.

Let me know if any additional logging or data would be helpful to further isolate the issue.

Grab the latest dev build, it’s been resolved in a post-rc2 commit: Workflow runs · PSAppDeployToolkit/PSAppDeployToolkit · GitHub

1 Like

@George, commented on the wrong thread?

2 Likes

Thanks for that hint. It Works :slight_smile:

1 Like

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.