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.
6 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
Trying to solve SystemSettings.exe faults (Overrun/Stack-Based Buffer) with anything [excluding reinstalling OS + tons of SW and/or “inplace upgrade”] found in web without any positive result I came to the conclusion that probably crashes came from *missing* services – they are invisible in Services page or in any software that shows services.
When I’ve tuned my OS I’ve disabled creation of per user services by applying UserServiceFlags=0 to registry (not by Group Policy, just directly to registry – it’s simpliest way).
As normal tune to minimize resource consumption I’ve disabled some MS’s services and machine works as a lightning (24/32 cores) but… in some moment I’ve found that I can’t open Settings -> Network & Inretnet – it crashes SystemSettings.exe. Then I tried to enter any submenu in Settings and found that Settings -> Devices are silently crashing too, Settings -> Focus Assist crashing SystemSettings.exe… Then I’ve found full list of Win URI commands (ms-settings:* and so on) – part of them are crashing (ms-settings:quiethours, ms-settings:quietmomentsscheduled, ms-settings:quietmomentspresentation, ms-settings:quietmomentsgame, ms-settings:bluetooth, ms-settings:network, ms-settings:network-status, ms-settings:datausage, ms-settings:sync – leads to error window says SystemSettings.exe Buffer Overrun, and about 20-25 URI’s lead to silent close/crash).
My deep digging shows me that setting UserServiceFlags=0 to 19’s found TEMPLATES not just disabling creation of per user service but totally disables them, they are not started in any context, not user, not system. Digging more (and your post too) shows that per user services are created from templates, and if creation is blocked by UserServiceFlags=0 then service will never born.
But closing eyes to “security” if I don’t want to services be recreated each logon and if I want to make some per user services exist permanently I’m thinking in changing Type from Template User_Share_Process (0x60) to Type=Win32_Share_Process… (0x20) – for example, WpnUserService -> UserServiceFlags=3 fixes part of the SystemSettings.exe crashes – Network & Internet settings opened successfully, DevicesFlowUserSvc or DevicePickerUserSvc -> UserServiceFlags=3 (I can’t say now concretely which is) fixes Settings -> Devices.
Why I’m thinking of that? Because I have a lot enough incidents when there was shutdowns/powerdowns/bsods and user profiles/registry was totally broken (without fresh enough backups or even with backups but they are not helped). If I can make such processes permanent then system will not (probably) rewrite user registry files each logon and because of write lock of that files when incident happens again then registry files will be (probably) the same as before logon and will not be broken.
Second moment is that per user services is a “per user” services, so for each user system creates users own processes. But if machine is used by one user at a time or only one user at all then there will be no problem if the “per user” service “converted” to system wide service will exist.
So I’m thinking about trying to change Type for needed per user services templates to change them from 0x60 to 0x20, other per user services that have no use and have no impact on system and not lead to any crashes to leave in UserServiceFlags=0 state.
Any thougts about that?
Fwiw your untested postulate that “…per-user services can indeed interact with the user”, was very helpful and seems to be correct.
My service code (see below) can run as a console app for debugging or as a service. When I configured it us sc.exe as an ordinary service it ran perfectly, but when run as a per user service it failed generating Event ID 7009 A timeout was reached (60000 milliseconds) while waiting for the service to connect. Environment.UserInteractive is clearly true and once I took out the test for an interactive environment the per user service started and functioned perfectly. I wouldn’t have made the connection between the service failure and that bit of code without that comment.
public static void Main(string[] args)
{
Poller_Service service = new Poller_Service();
if (Environment.UserInteractive)
{
service.RunAsConsole(args);
}
else
{
ServiceBase[] servicesToRun;
servicesToRun = new ServiceBase[]
{
service
};
ServiceBase.Run(servicesToRun);
}
}