任务调度程序托管包装器错误访问被拒绝



我正在创建一个应用程序,该应用程序为第一个登录的每个用户创建计划的任务。我正在使用Nuget软件包任务调度程序托管包装器2.5.21。当EXE在登录上运行时,会发生访问拒绝错误。当手动运行EXE作为管理员时,会创建计划的任务。我该如何克服这个问题?

string installPath = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location);
using (TaskService ts = new TaskService())
{
    TaskDefinition td = ts.NewTask();
    td.Actions.Add(new ExecAction("MyExe.exe", null, installPath));
    td.Triggers.Add(new SessionStateChangeTrigger
    {
        StateChange = TaskSessionStateChangeType.SessionUnlock,
        UserId = Environment.UserName
    });
    td.Principal.RunLevel = TaskRunLevel.Highest;
    td.Principal.LogonType = TaskLogonType.InteractiveToken;
    ts.RootFolder.RegisterTaskDefinition("task_" + Environment.UserName, td);
}

对于非管理或非高级用户,每个触发类型都有一组限制。例如。您不能只为自己添加Onlogon触发触发器。看起来您也无法添加SessionStateChangeTrigger

这是根据作者对我问题的回答的工作示例:https://github.com/dahall/taskscheduler/issues/58

var td = ts.NewTask();
td.Actions.Add("notepad", null, null);
td.Triggers.Add(new LogonTrigger { UserId = WindowsIdentity.GetCurrent().Name });
ts.RootFolder.RegisterTaskDefinition("Test", td);

注意:如果您正在使用UAC下的管理员使用TaskRunLevel.Highest创建任务,那么只有在高程之后才有可能(否则这将是一个巨大的漏洞,使UAC无用)

注意:如果要为启动应用程序的每个用户创建任务,则必须将用户SID包含在任务名称中。即使用户会重命名,也可以保证这是唯一的。否则将拒绝访问,因为其他用户已经创建了相同的任务(他在其中拥有更多的权利)。考虑Dropbox,OneDrive,googledrive -Thery都将SID添加到任务名称中。

这就是我最终完成的方式(包括Highest版本的不同任务名称和正常一个:

private static void CreateTask(string path, string taskFolder, bool highest)
{
    var sid = WindowsIdentity.GetCurrent().User.Value;
    var userId = WindowsIdentity.GetCurrent().Name;
    using (var ts = new TaskService())
    {
        var td = ts.NewTask();
        if (highest)
        {
            td.Principal.RunLevel = TaskRunLevel.Highest;
        }
        td.Actions.Add(path, "/a", null);
        td.Triggers.Add(new LogonTrigger { UserId = userId, });
        ts.RootFolder.RegisterTaskDefinition(taskFolder + "MyApp Task-" + sid + (highest ? "h" : ""), td);
    }
}

最新更新