【问题标题】:My PowerShell task scheduler script is showing a runtime exception error when running我的 PowerShell 任务计划程序脚本在运行时显示运行时异常错误
【发布时间】:2022-01-08 15:24:26
【问题描述】:

当我运行以下脚本来创建计划任务时,我收到错误

错误类型(HRESULT 异常:0x80020005 (DISP_E_TYPEMISMATCH))

$u = "domain\$env:username" 
$p = "SomePassword"
$UserPass = ConvertTo-SecureString $p -AsPlainText -Force

$TaskName = "ML"
$TaskDescr = "Descriptor"
$TaskCommand = "$pos\$nm"
$TaskStartTime = [datetime]::Now.AddMinutes(5)
$service = new-object -ComObject("Schedule.Service")
$service.Connect()
$rtFr = $service.GetFolder("\")
$TaskDefinition = $service.NewTask(0)
$TaskDefinition.RegistrationInfo.Description = "$TaskDescr"
$TaskDefinition.Settings.Enabled = $true
$TaskDefinition.Settings.AllowDemandStart = $true
$triggers = $TaskDefinition.Triggers
$dd = "T"
$vv = "yyyy-MM-dd"
$xx = "HH:mm:ss"
$pr = "$vv$dd$xx"
$trigger = $triggers.Create(9)
$trigger.StartBoundary = $TaskStartTime.ToString($pr)
$trigger.Enabled = $true
$Action = $TaskDefinition.Actions.Create(0)
$action.Path = "$TaskCommand"
$rtFr.RegisterTaskDefinition("$TaskName",$TaskDefinition,6,$u,$UserPass,5)

【问题讨论】:

  • 很多 COM 对象不能在非交互式会话中使用。老实说:我不明白你为什么要使用 com 对象来创建计划任务,因为 Powershell 有一些内置的 cmdlet 可以做到这一点
  • 发布完整错误会很有帮助。另外,同意 Bluuf,为什么不使用内置的 cmdlet?即:New-ScheduledTask
  • 尝试$trigger.StartBoundary = $TaskStartTime.ToString("o") 使用round-trip specifierStartBoundary 属性需要日期为格式为yyyy-MM-ddTHH:mm:ss(+-)HH:MM 的字符串。见the docs
  • 感谢您的评论,使用 COM 对象是因为内置 cmdlet 在 Windows 7 版本上不可用,我尝试使其工作。
  • 由于 Windows 7 不再受支持(并且已经停止支持很长一段时间了),我真的建议不要使用这个操作系统。除了安全方面,它还使得从人们那里获得帮助变得更加困难(尤其是当代码由于缺少或过时的库而无法工作时)

标签: powershell exception task runtime scheduled-tasks


【解决方案1】:

关于你的脚本有太多话要说,但让我们专注于你的问题:

来自 HRESULT 的异常:0x80020005 (DISP_E_TYPEMISMATCH)

这个错误是由于 $rtFr.RegisterTaskDefinition 参数的密码需要明文而不是加密字符串引起的。所以改变你的脚本如下:

  • 使用 $p 而不是 $UserPass
  • 将触发器类型从 9 更改为 1(原因见下文)
  • 将登录类型从 5 更改为 6(原因见下文)

修改:

# Change these lines
$trigger = $triggers.Create(9)
$rtFr.RegisterTaskDefinition("$TaskName",$TaskDefinition,6,$u,$UserPass,5)

# To this
$trigger = $triggers.Create(1)
$rtFr.RegisterTaskDefinition($TaskName,$TaskDefinition,6,$u,$p,6)

参考: https://docs.microsoft.com/en-us/windows/win32/taskschd/taskfolder-registertaskdefinition https://docs.microsoft.com/en-us/windows/win32/taskschd/triggercollection-create

这足以让您的脚本无错误地执行

...

现在,如果你不将触发器类型从9改为1,你会遇到这个错误:

HRESULT 异常:0x80070005 (E_ACCESSDENIED)

您正在尝试创建将在登录时执行的任务 ($trigger = $triggers.Create(9)),这需要管理权限。因此,您必须从提升的 Powershell 会话(以管理员身份运行)运行脚本

最后,如果你不将登录类型从5改为6,你会遇到这个错误:

(XX,XX):UserId: At :XX char:XX

您正在尝试创建登录类型为 TASK_LOGON_SERVICE_ACCOUNT 的任务,但未指定要使用的服务帐户。此外,您正在传递用户名和密码参数来创建任务,它们应该为空/null。

# Change this line
$rtFr.RegisterTaskDefinition($TaskName,$TaskDefinition,6,$u,$p,6)

# To this
$TaskDefinition.Principal.UserId = "S-1-5-18" # i.e Local System Account
$rtFr.RegisterTaskDefinition($TaskName,$TaskDefinition,6,$null,$null,5)

结论:

所以我不知道您要实现什么,但您必须与所有参数保持一致才能正确执行任务创建。

我建议您使用 SCHTASKS.exe 而不是 COM 对象,它会更简单、更简单,并且在 Windows 7 和更高版本上可用。

【讨论】:

  • Zivkok,感谢您的完整解释,我承认我没有花太多时间来编写这个脚本,也许三十分钟,但你是对的,脚本现在运行良好!我会花时间阅读有关 SCHTASKS.exe 并尝试使用它再次感谢,我真的很感激
  • @dst1ny,不客气,很高兴为您提供帮助 :-)
猜你喜欢
  • 2019-10-31
  • 2020-08-07
  • 2015-07-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-07-27
  • 2019-05-02
  • 1970-01-01
相关资源
最近更新 更多