Access is denied when Registering a new task - HRESULT: 0x80070005 (E_ACCESSDENIED)

Topics: Errors
May 29, 2016 at 10:08 PM
I'm trying to register a task for a local user who does not have administrator rights to his/her machine. The task registration code below is wrapped as part of a console application and the application is made to Run As administrator (not necessarily).

When the Administrator credentials are passed in during the Run As procedure, the task gets registered under the Admin's account rather than the local user's.
I would want the task to be registered under the user's account and also, this being a domain user, I cannot ask for his/her credentials. If the console application is simply double-clicked by the local user, I get the Access is Denied error. Although, task registration works fine when the local user is added to the Administrator group. But this is again not a feasible solution while the program gets deployed.

Below is the code that I'm currently running as Admin to register the task for a local user.
Could someone guide me as to what's the right way to register the said task under these circumstances?
if (!taskExists)
    {
        //This task was never installed. So install.
        TaskDefinition td = ts.NewTask();
        td.RegistrationInfo.Description = "MFT Console Application";
        // Run Task whether user logged on or not
        td.Principal.LogonType = TaskLogonType.S4U;
        // Run as Administrator
        td.Principal.RunLevel = TaskRunLevel.Highest;
        td.Principal.UserId = System.Security.Principal.WindowsIdentity.GetCurrent().Name;

        TimeTrigger trigger = new TimeTrigger();
        trigger.StartBoundary = DateTime.Now;
        trigger.Repetition.Interval = TimeSpan.FromMinutes(30);
        td.Triggers.Add(trigger);

        td.Actions.Add(new ExecAction(System.Reflection.Assembly.GetExecutingAssembly().Location, null, null));
        TaskService.Instance.RootFolder.RegisterTaskDefinition("MFT Console Application", td);
    }
Coordinator
May 30, 2016 at 5:07 PM

This is your answer, but got lost:

Answering my own question, I was able to finally achieve this using the bare minimum settings.
Moving the Prinicpal properties assignments and placing them instead inside the parameter call of RegisterTaskDefinition and removing the RunLevel parameter did the trick. I was trying to enable the Run with highest Privilege option using a local user account.

Below is the final code for the sake of completeness:
//This task was never installed. So install.
TaskDefinition td = ts.NewTask();
td.RegistrationInfo.Description = "MFT Console Application";

TimeTrigger trigger = new TimeTrigger();
trigger.StartBoundary = DateTime.Now;
trigger.Repetition.Interval = TimeSpan.FromMinutes(30);
td.Triggers.Add(trigger);

td.Actions.Add(new ExecAction(System.Reflection.Assembly.GetExecutingAssembly().Location, null, null));

ts.RootFolder.RegisterTaskDefinition("MFT Console Application", td, TaskCreation.CreateOrUpdate,
   System.Security.Principal.WindowsIdentity.GetCurrent().Name, null, TaskLogonType.S4U);
Marked as answer by dahall on 5/30/2016 at 10:07 AM
May 30, 2016 at 8:01 PM
Yes. That's correct. I somehow missed it the last time I tried to respond.
So just for an FYI in case somebody hits this roadblock, if you plan to use the S4U logon type, you will need to pass the credentials of an Administrator while registering the task or the user himself needs to be part of the local administrator group.

My user for whom I'm trying to register this task for is a normal user without any such priveleges.

Below is a correction to the above response for registering the task.
ts.RootFolder.RegisterTaskDefinition("MFT Console Application", td, TaskCreation.CreateOrUpdate,
   System.Security.Principal.WindowsIdentity.GetCurrent().Name, null, __TaskLogonType.None__);
Marked as answer by dahall on 5/31/2016 at 7:32 AM