Per-User Services in Windows: Info & Configuration
It’s a little-known fact that Windows comes with per-user services, background processes that complement the well-known per-machine system services. This article explains what per-user services are, how to create your own, and which configuration options there are.
What Are Per-User Services?
A per-user service is a background process that is started automatically when a user logs on and stopped when the user logs off. Per-user services are run in user context (with the user’s account) as part of the user session. This contrasts with system services that are typically started when the machine is booted, and which run in session 0 with special service accounts such as Local Service
or Network Service
.
Why Implement Per-User Services?
Some applications need access to data that is only available in user context or in a user session. Other programs need a background process to complement their application window’s functionality. Traditional solutions rely on Explorer to auto-start processes via the registry (HKCU\Software\Microsoft\Windows\CurrentVersion\Run
) or the start menu (%USERPROFILE%\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup
), to name two popular locations. Per-user services provide an alternative that does not depend on Explorer.
Implementation Details
Requirements
Per-user services are supported on Windows 10 as well as Windows Server 2016 or newer. Windows Server requires Desktop Experience to be installed.
Parent Process of Per-User Services
Per-user services are managed by Service Control Manager (SCM). Their parent process is services.exe
.
Templates and Instances
Per-user services are configured via template entries in the service configuration registry key (see below). As the name implies, templates are used as blueprints to create per-user services.
Per-User Service Instance Creation and Deletion
When a user logs on, SCM creates (and starts) per-user service instances on the fly from their respective templates. When a user logs off, per-user service instances are stopped and deleted.
Per-User Service Instance Naming
For each service or driver, a registry entry in the service configuration registry key is required. Since two adjacent registry keys cannot have the same name, SCM needs a scheme to provide individual names to per-user service instances. It does so by appending the logon session’s LUID to the template service’s name. Example:
- Per-user service template:
WpnUserService
- Per-user service instance:
WpnUserService_1080e4
Listing Per-User Service Templates
Many tools and commands, including PowerShell’s Get-Service
, omit per-user service templates, returning only instances. To list templates you need to iterate the registry. Here’s a PowerShell snippet for that:
Get-ChildItem "HKLM:\SYSTEM\CurrentControlSet\Services" | ForEach-Object { Get-ItemProperty $_.pspath } | Where-Object {$_.Type -eq 80 -or $_.Type -eq 96} | Format-Table PSChildName, Type, UserServiceFlags
The output looks like this:
PSChildName Type UserServiceFlags
----------- ---- ----------------
AarSvc 96 3
BcastDVRUserService 96
BluetoothUserService 96
CaptureService 96 3
cbdhsvc 96 3
CDPUserSvc 96 3
ConsentUxUserSvc 96 3
CredentialEnrollmentManagerUserSvc 80
DeviceAssociationBrokerSvc 96 3
DevicePickerUserSvc 96 3
DevicesFlowUserSvc 96 3
LxssManagerUser 96 3
MessagingService 96
OneSyncSvc 96
PimIndexMaintenanceSvc 96 3
PrintWorkflowUserSvc 96
UdkUserSvc 96 3
UnistoreSvc 96 3
UserDataSvc 96 3
WpnUserService 96 3
Note that Type
is printed as a decimal value (80
corresponds to 0x50
and 96
to 0x60
).
Configuring Per-User Services: Registry Settings
Just like system services, per-user services are configured via the subkeys of HKLM\SYSTEM\CurrentControlSet\Services
.
Type
SCM uses the Type
value to differentiate between per-user services on the one hand and system services and drivers on the other, all of which are configured via the same registry location.
Templates
Per-user service templates have one of the following numbers as Type
value:
- 0x50: individual process (
SERVICE_USER_OWN_PROCESS
) - 0x60: shared process (
SERVICE_USER_SHARE_PROCESS
)
Instances
Per-user service instances have one of the following numbers as Type
value:
- 0xd0: individual process (
SERVICE_USER_OWN_PROCESS
+SERVICE_USERSERVICE_INSTANCE
+0x10
) - 0xe0: shared process (
SERVICE_USER_SHARE_PROCESS
+SERVICE_USERSERVICE_INSTANCE
+0x10
)
Before you ask: I do not know what the meaning of the 0x10
constant is.
When querying all services with a command like sc queryex
some per-user services show a Type
of 0xf0
, even though the Type
stored in the service’s registry key is 0xe0
. The reason for this is unclear.
UserServiceFlags
To prevent the creation (and subsequent start) of per-user service instances at logon add the following registry value to a per-user service’s template registry key:
- Value name:
UserServiceFlags
- Value type:
REG_DWORD
- Value name:
0
To revert to the default behavior, delete the UserServiceFlags
value or set it to its default of 3
.
Creating Per-User Services
To create your own per-user service, specify one of the following as the dwServiceType
parameter in the call to CreateService
:
SERVICE_USER_OWN_PROCESS
(0x50
)SERVICE_USER_SHARE_PROCESS
(0x60
)
Per-User Services in Windows 10
Microsoft’s documentation lists various per-user services, but it does not seem to be up to date. At the time of writing this article, the doc’s timestamp read 2017-09-14.
I found the following per-user service templates on my workstation running Windows 10 2009 (20H2):
Key name | Display name |
AarSvc | Agent Activation Runtime |
BcastDVRUserService | GameDVR and Broadcast User Service |
BluetoothUserService | Bluetooth User Support Service |
CaptureService | CaptureService |
cbdhsvc | Clipboard User Service |
CDPUserSvc | Connected Devices Platform User Service |
ConsentUxUserSvc | ConsentUX |
CredentialEnrollmentManagerUserSvc | CredentialEnrollmentManagerUserSvc |
DeviceAssociationBrokerSvc | DeviceAssociationBroker |
DevicePickerUserSvc | DevicePicker |
DevicesFlowUserSvc | DevicesFlow |
LxssManagerUser | LxssManagerUser |
MessagingService | MessagingService |
OneSyncSvc | Sync Host |
PimIndexMaintenanceSvc | Contact Data |
PrintWorkflowUserSvc | PrintWorkflow |
UdkUserSvc | Udk User Service |
UnistoreSvc | User Data Storage |
UserDataSvc | User Data Access |
WpnUserService | Windows Push Notifications User Service |
Questions
I do not have answers to all my questions regarding per-user services. For the sake of completeness, I am listing the open questions here.
User Interactivity
Can per-user services interact with the user? Do they have access to the desktop, can they create windows?
As you may remember, Microsoft moved system services to session 0 for security purposes starting with Vista. The old practice of bundling background code with UI logic in a single system service has been severely restricted. Developers are encouraged to split their code into two components: a system service for the background code and a separate executable for the UI logic. This is where per-user services fit in perfectly. They provide the “missing link” that, up until Windows 10, had to be substituted with one of the per-user auto-start mechanisms.
Therefore I postulate – without having this tested – that per-user services can indeed interact with the user.
Further Reading
Microsoft’s documentation on per-user services can be found here.
4 Comments
Always great postings Helge. Use of CreateService and HKLM imply that one must be an admin to create a per-user service. My gut says this is unfortunate. Compare to RUN= entries where user privilege is enough for getting into HKCU space, albeit with the shell as parent when execute. If no shell, that wont’ work, so … this is the inspiration for per-user services? Good research, thanks for the article.
Installing a per-user service is a machine-wide operation, it affects all users. Therefore it makes sense to require admin rights in my opinion.
The same is true when manipulating
HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Run
.Just in order to avoid someone wasting time on this: Per-user service is running under a user’s context and behave like a regular user process. But it has a restricted DACL compared to a regular process. It allows the user to have full access or Administrators to have PROCESS_QUERY_INFOMATION and PROCESS_QUERY_LIMITED_INFORMATION only by default. The SYSTEM account can’t open the service process and the OpenProcess call will return ERROR_ACCESS_DENIED unless you manually manipulate the DACL of the process or you have SeDebugPrivilege.
I think your math was slightly off. 0x10 is SERVICE_WIN32_OWN_PROCESS. The difference between SERVICE_WIN32_OWN(SHARE)_PROCESS and SERVICE_USER_OWN(SHARE)_PROCESS is just 0x40 so:
SERVICE_USER_OWN_PROCESS == SERVICE_WIN32_OWN_PROCESS (0x10) + 0x40 == 0x50
SERVICE_USER_SHARE_PROCESS == SERVICE_WIN32_SHARE_PROCESS (0x20) + 0x40 == 0x60
SERVICE_USERSERVICE_INSTANCE == 0x80