Task Scheduler Managed Wrapper 错误访问被拒绝
Task Scheduler Managed Wrapper error Access denied
我正在创建一个应用程序,它会在每个用户首次登录时创建一个计划任务。我正在使用 NuGet 包 Task Scheduler Managed Wrapper 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 - 它们都将 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);
}
}
我正在创建一个应用程序,它会在每个用户首次登录时创建一个计划任务。我正在使用 NuGet 包 Task Scheduler Managed Wrapper 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 - 它们都将 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);
}
}