I'm trying to create a task on Win 2008 R2 to run a batch script (that eventually calls powershell but that's irrelevant for now, I think).
The code is as below. The trouble is, I'm simply unable to get this to work in various combinations. I've tried to debug through it, and I see that it ends up calling the RegisterTaskDefinition method in the ITaskDefinition COM object as follows:
if (v2Folder != null)
return new Task(this.TaskService, v2Folder.RegisterTaskDefinition(Path, definition.v2Def, (int)createType, UserId, password, LogonType, sddl));
I have checked in the debugger that the user name, password and logon type are set correctly (LogonType is set to TaskLogonType.Password, and UserId and Password are valid values which I know work).
The error I get is COMException (18,8) LogonType. The HRESULT seems to be 0x80070534 (I searched around the internet and it seems to be related to the message: "No mapping between account names and security IDs was done").
The MSDN documentation for ITaskDefinition.RegisterTaskDefinition says that the 0x80070534 error occurs when called by the System Account with user paramter = NULL, password = NULL and LogonType = SERVICE_ACCOUNT. But I've checked that the caller is
not the system account (more on this later), and the user is a non-null string containing a DOMAIN\Username.
Now, a little bit more about how and where this code is used:
It is part of a ASP.NET web application that runs under Windows Authentication with ASP.NET Impersonation turned on. I've logged the Exception to the Event log and I see that the identity is indeed being impersonated:
System.Runtime.InteropServices.COMException (0x80070534): (18,8):LogonType:
at Microsoft.Win32.TaskScheduler.V2Interop.ITaskFolder.RegisterTaskDefinition(String Path, ITaskDefinition pDefinition, Int32 flags, Object UserId, Object password, TaskLogonType LogonType, Object sddl)
at Microsoft.Win32.TaskScheduler.TaskFolder.RegisterTaskDefinition(String Path, TaskDefinition definition, TaskCreation createType, String UserId, String password, TaskLogonType LogonType, String sddl) in C:\Users\krishna.nadiminti\Downloads\taskscheduler-68509\TaskService\TaskFolder.cs:line
at ADM.Sharepoint.SiteAdmin.Web.Services.OperationService.CreateOperation(Operation operation) in C:\Users\krishna.nadiminti\Work\...\Services\OperationService.cs:line 136
Win identity Name: MyDOMAIN\MyUserName, SID: S-1-5-21-1078621877-1660878857-569397357-10089, IsSystem: False, ImpersonationLevel: Impersonation
Thread identity: MyDOMAIN\MyUserName
Svc Ctxt identity: MyDOMAIN\MyUserName
My code: (the part that does not work is commented out - but I need that to work) :
var logonDetails = string.Empty;
using (var ts = GetTaskService())
var folder = ts.RootFolder.SubFolders.FirstOrDefault(f => f.Name == FolderName);
if (folder == null)
folder = ts.RootFolder.CreateFolder(FolderName);
var taskNameToGenerate = operation.GetTaskName();
if (folder.Tasks.Count(t => t.Name == taskNameToGenerate) >= 1)
throw new ValidationException(string.Format(ValidationErrorResources.ValidationErrorOperationAlreadyExists, taskNameToGenerate));
var taskDef = ts.NewTask();
taskDef.Settings.Compatibility = TaskCompatibility.V2;
taskDef.Data = SerializeOperation(operation);
taskDef.RegistrationInfo.Source = "Parish Admin Site Tool";
taskDef.RegistrationInfo.Description = "Created by the Parish Admin Site Tool";
var execAction = new ExecAction(GetTaskExecActionCommand(), GetTaskExecActionArgs(operation));
//COMMENTED OUT since this doesn't seem to work: but we need it to run the task with the highest privilege, regardless of whether the user is logged on or not.
//taskDef.Principal.UserId = this.ServiceContext.User.Identity.Name; //commented out
//taskDef.Principal.RunLevel = TaskRunLevel.Highest; //TODO do we need this? on Win7, I get access denied, on Win 2008, COMException
//taskDef.Principal.LogonType = TaskLogonType.Password;
//logonDetails = "LogonType:" + taskDef.Principal.LogonType.ToString();
//logonDetails += "\nUserId:" + taskDef.Principal.UserId;
//logonDetails += "\nRunLevel:" + taskDef.Principal.RunLevel;
//logonDetails += "\nDisplayName:" + taskDef.Principal.DisplayName;
//logonDetails += "\nId:" + taskDef.Principal.Id;
var task = folder.RegisterTaskDefinition(taskNameToGenerate, taskDef);
//var task = folder.RegisterTaskDefinition(taskNameToGenerate, taskDef,
// taskDef.Principal.UserId, operation.PasswordForNonInteractiveUser, TaskLogonType.Password);
var path = task.Path;
operation.GeneratedId = path;
catch (Exception ex) //a bit ugly, but this will do for this simple utility
Any ideas / help, greatly appreciated.