Programmatically trigger the autoenrollment process for the logged-in user

Assume the following scenario:

  • You write a script or an application that should trigger the autoenrollment process for the currently logged in user.
  • You will find out that the scheduled task cannot be executed.
  • The error message reads:
The user account does not have permissions to run this task.

Autoenrollment is the term used to describe automatic certificate application in the Windows ecosystem. In this way, systems that are members of an Active Directory forest can automatically request and renew certificates from an Enterprise Certification Authority integrated into Active Directory. For more information, see the article "Basics of manual and automatic Certificate Enrollment via Lightweight Directory Access Protocol (LDAP) and Remote Procedure Call / Distributed Common Object Model (RPC/DCOM)„.

The Auto Enrollment process is started via predefined scheduled tasks (under "Microsoft" - "Windows" - "CertificateServicesClient").

Besides the automatic triggers, it can be executed for example with the following command line command:

certutil -pulse -user

If you take a look at the Task Scheduler, you can see that this command seems to execute the scheduled task "UserTask".

However, if you try to start the "UserTask" manually, you get the error message that it cannot be stared due to missing rights.

The same picture results when called via Windows PowerShell with the "Start-ScheduledTask" Command:

Get-ScheduledTask -TaskName UserTask | Start-ScheduledTask
Start-ScheduledTask : Access is denied.
At line:1 char:40
+ Get-ScheduledTask -TaskName UserTask | Start-ScheduledTask
+                                        ~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : PermissionDenied: (PS_ScheduledTask:Root/Microsoft/...S_ScheduledTask) [Start-ScheduledTask], CimException
+ FullyQualifiedErrorId : HRESULT 0x80070005,Start-ScheduledTask

The problem seems to be that the "UserTask" is configured to be executed with the "INTERACTIVE" principal.

If you analyze the certutil.exe (for example with the API Monitor by Rohitab Batra), one recognizes that here apparently the TaskScheduler class is called.

This is a COM object ("Schedule.Service") that can be addressed via C# and PowerShell, among others. This has a RunEx method, which is started with the flag TASK_RUN_AS_SELF can be called, which results in the task being executed with the identity of the currently logged-in user.

Example code

Windows PowerShell

Here is a working example code:

New-Variable -Option Constant -Name TaskRunFlags -Value @{
    TASK_RUN_NO_FLAGS = 0
    TASK_RUN_AS_SELF = 1
    TASK_RUN_IGNORE_CONSTRAINTS = 2
    TASK_RUN_USE_SESSION_ID = 3
    TASK_RUN_USER_SID = 4
}
$TaskScheduler = New-Object -ComObject("Schedule.Service")
$TaskScheduler.Connect()
$UserTask = $TaskScheduler.GetFolder("Microsoft\Windows\CertificateServicesClient").GetTask("UserTask")
$UserTask.RunEx(
    $null,
    $TaskRunFlags.TASK_RUN_AS_SELF,
    0,
    $null
)

C#

A sample code for C# might look like the following:

using TaskScheduler;

var Scheduler = new TaskScheduler.TaskScheduler();
Scheduler.Connect();
var UserTask = Scheduler.GetFolder("Microsoft\Windows\CertificateServicesClient").GetTask("UserTask");

UserTask.RunEx(
    null,
    (int)_TASK_RUN_FLAGS.TASK_RUN_AS_SELF,
    0,
    null
    );

A reference to the TaskScheduler COM object must be configured in the Visual Studio project.

Related links:

en_USEnglish