This project has moved and is read-only. For the latest updates, please go here.

TaskEditDialog and Access is Denied

May 29, 2011 at 1:24 AM

I've created a task with this code:

         string taskName = execName;

         // Get the service on the local machine
         using (TaskService ts = new TaskService())
         {
            // Create a new task definition and assign properties
            TaskDefinition td = ts.NewTask();
            td.RegistrationInfo.Description = "My task description";

            // Settings and principles
            td.Settings.DisallowStartIfOnBatteries = false;
            td.Settings.Priority = ProcessPriorityClass.Normal;
            td.Settings.WakeToRun = true;
            td.Principal.GroupId = "Users";

            // Triggers.
            LogonTrigger lt = new LogonTrigger();
            lt.Delay = TimeSpan.FromMinutes(5);
            lt.UserId = String.Empty;
            td.Triggers.Add(lt);

            // Start at 2:30 p.m.
            DailyTrigger dt2 = new DailyTrigger();
            dt2.StartBoundary = DateTime.Today + TimeSpan.FromHours(14.5);
            td.Triggers.Add(dt2);

            // Create an action that will launch the exec whenever the trigger fires
            ExecAction ea1 = new ExecAction();
            ea1.Path = this.execFullPath;
            ea1.Arguments = "-SignatureUpdate";
            ea1.WorkingDirectory = null;
            td.Actions.Add(ea1);

            // Register the task in the root folder
            ts.RootFolder.RegisterTaskDefinition(taskName, td, TaskCreation.CreateOrUpdate, null, null, TaskLogonType.InteractiveToken);

            // Remove the task we just created
            //ts.RootFolder.DeleteTask(taskName);
         }

The task is created and runs OK.

I then attempt to edit the task with the following code but the RegisterTaskDefinition throws Access is Denied?

         DialogResult res;

         // Get the service on the local machine
         using (TaskService ts = new TaskService())
         {
            // Create a new task
            string taskName = name;
            Task t = ts.FindTask(taskName, true);
            if (t == null)
            {
               return;
            }

            // Edit task and re-register if user clicks Ok
            TaskEditDialog editorForm = new TaskEditDialog();
            editorForm.Editable = true;         
            editorForm.Initialize(t);
            res = editorForm.ShowDialog();
            if (res == System.Windows.Forms.DialogResult.OK)
            {
               ts.RootFolder.RegisterTaskDefinition(taskName, editorForm.TaskDefinition);
            }

            // Remove the task we just created
            ts.RootFolder.DeleteTask(taskName);
         }

Thanks,
Ed...

Coordinator
May 29, 2011 at 8:51 PM

Your best bet is to use the RegisterTaskOnAccept property of the TaskEditDialog as it handles an number of conditions instead of trying to re-register it on your own. You can also combine a lot of those same lines into the constructor.

TaskEditDialog editorForm = new TaskEditDialog(t, true, true);
editorForm.ShowDialog();
May 30, 2011 at 12:32 AM

Thank you for taking the time to reply...

I edited my method as you indicated:

TaskEditDialog editorForm = new TaskEditDialog(t, true, true);
editorForm.ShowDialog();
and removed my registrTaskDefination. After editing the task and clicking OK, the "Access is Denied" is returned (0x80070005) after editorFoem.ShowDialog()?
I'm logged on as Administrator. The OS is Win7 x64.
Ed...
Coordinator
May 30, 2011 at 4:17 AM

Remove the line below and see if that helps.

td.Principal.GroupId = "Users";
May 30, 2011 at 6:05 AM

Removing the td.Principal.GroupId = "Users" causes a ComException 0x80070534.

I guess I should explain that the task create code method is in a Custom Actions InstallerClass and is being called in the Installer_Committed callback.

Removing the Principal.GroupId line produces the ComException during the program setup install. (With the GroupId line in, the Task is created with incident or error??)

So, I placed the Task Schedule create code in the main app and called the TaskSchedule create in debug (not install).

The only method run is the Task Create method I Posted above. With and without the td.Principal.GroupId = "Users", an "Access is Denied" 0x80070005 is thrown?

I don't understand enough about the RegisterTaskDefinition method to go further in analysis? I figured that the TaskLogonType.InteractiveToken parm would negate the need for userId and PW to be required since I'm logged in as Administrator.

Ed...

May 30, 2011 at 6:35 AM

OK, I created another project and used the Task Create code you have on your Home page. It works fine.

So I went to my code and removed the LogonTrigger. This is what is causing the ComException in registration?

With the LogonTrigger removed and the td.Principle.GroupId set, a Access is Denied is thrown. I removed the GroupId line as you mentioned. 

I guess I mis-interpret the meaning of this trigger?

I want to run my action after the system starts-up (after a delay).

ed...

Coordinator
May 30, 2011 at 7:01 AM
Edited May 30, 2011 at 4:13 PM

I believe you may be looking for a BootTrigger which will fire just after system startup. You can use the Delay property for that trigger to indicate the time after boot that should lapse before the trigger fires. You are correct, the LogonTrigger must be created with credentials that can access the user credentials of the account logging on.

May 30, 2011 at 4:26 PM

David, this project has got me by the tail :)
I've paired it down trying to make it as simple as possible. In reading the BootTrigger documentation, I don't see that user credentials are required?

This gives me Access is Denied:

using (TaskService ts = new TaskService())
{
     TaskDefinition td = ts.NewTask();
     td.RegistrationInfo.Description = "Testing";
     td.Actions.Add(new ExecAction("notepad.exe, "c:\\test.log", null));

     BootTrigger bt = new BootTrigger();
     bt.Delay = TimeSpan.FromMinutes(5);
     td.Triggers.Add(bt);

     ts.RootFolder.RegisterTaskDefinition(taskName, td);

{

 

 

May 30, 2011 at 8:51 PM

David, I dont' believe that the BootTrigger is going to work in my case since my task has to run after logs on.

I visited this URL: http://msdn.microsoft.com/en-us/library/aa380727(v=VS.85).aspx
for the LogonTrigger which reads:

If you want a task to be triggered when any member of a group logs on to the computer rather than when a specific user logs on, then do not assign a value to the UserId property. Instead, create a logon trigger with an empty UserId property and assign a value to the principal for the task using the GroupId property.

So I tried this:

using (TaskService ts = new TaskService())
{
      TaskDefinition td = ts.NewTask();
      td.RegistrationInfo.Description = "Testing";
      td.Actions.Add(new ExecAction("notepad.exe, "c:\\test.log", null));

      LogonTrigger lt = new LogonTrigger();
      lt.UserId = string.Empty;
      td.Triggers.Add(lt);

      td.Principal.GroupId = "Administrators";

      ts.RootFolder.RegisterTaskDefinition("Test", td);
{

It still produces "Access is Denied".
BTW, the ts.HighestSupportedVersion = 1.3.

ed...

Coordinator
May 31, 2011 at 5:58 AM

I just ran this code with no errors on a Win7 64-bit machine.

using (TaskService ts = new TaskService())
{
   TaskDefinition td = ts.NewTask();
   td.RegistrationInfo.Description = "Does something";
   td.Principal.GroupId = "Administrators";
   td.Triggers.Add(new LogonTrigger { UserId = string.Empty });
   td.Actions.Add(new ExecAction("notepad.exe", "c:\\test.log", null));
   ts.RootFolder.RegisterTaskDefinition("Test", td);
}
May 31, 2011 at 3:39 PM
Edited Jun 1, 2011 at 1:11 AM

Thanks for taking your time.

I created a new VS 2010 project and placed your method there in. The registration doesn't itself throw an error, but it doesn't actually create a task.

Placing a try/catch around the code, catches a "Access is Denied" exception.

I'm going to download a fresh copy of the TaskScheduler zip and replace my orginal copy, clean up the references, and start fresh. Something is weird.

Edit Update: I downloaded the zip package but the error remains.

Ed...

Jun 2, 2011 at 5:26 AM

The only way I can get a LogonTrigger to register is to supply a userId to the trigger which is contrary to the specs?
Win7 x64, VS 2010

    try{
	using (TaskService ts = new TaskService())
	{
	  TaskDefinition td = ts.NewTask();
 	  td.RegistrationInfo.Description = "Does something";
 	  //td.Principal.GroupId = "Administrators";
 	  td.Triggers.Add(new LogonTrigger { UserId = "MyDomain\\My UserId" });
 	  td.Actions.Add(new ExecAction("notepad.exe", "c:\\test.log", null));
 	  ts.RootFolder.RegisterTaskDefinition("Test", td);
	}
       }
    catch(Exception ex)
{
Display ex;
}
Coordinator
Jun 2, 2011 at 6:45 AM

Is there a chance that the current user account is not a member of the Adminstrators group? This would prevent you from being able to create a task with those permissions.

Jun 2, 2011 at 3:09 PM

Well, if I open Local Users and Groups => Groups => Administrators I see my usedID listed in the Administrators Properties. I have 2 desktop and 1 laptop with Win7 x64 which exhibit the same symptom. In any event, the spec states that all that needs be done is provide an empty UserId for the trigger and a groupId for the Principal.GroupId. It doesn't say it has to be an administrator, I believe.

Coordinator
Jun 9, 2011 at 11:43 PM

Determined to be a problem with debugging under Visual Studio while not running as Adminstrator.