用powershell调度任务

scheduling task with powershell

我正在尝试在远程计算机上安排任务,我成功地在远程计算机上安排了一个任务,但它没有执行。就像我想在某个触发时间下载文件一样。 在我的任务调度程序中,它显示任务已成功完成,但我没有看到任何文件已下载。

 $ComputerName = "win12"
 $cr=Get-Credential $ComputerName\administrator    
 $Session = New-PSSession -ComputerName $ComputerName -Credential $cr

 Invoke-Command -Session $Session -ScriptBlock {       
     $start = (Get-Date).AddMinutes(1).ToString("HH:mm:ss")
    [string]$Result = schtasks /create /tn "kk" /tr "powershell.exe (New-Object System.Net.WebClient).DownloadFile('http://server12/vdir/OracleXE.exe','C:\abc.exe')" /sc once /st $start /ru "administrator" /rp "passw0rd@12" 
     $Result += schtasks /run /tn "kk"

    $Result

}

即使触发时间已过或我将任务强制到 运行,文件仍未下载。当我 运行 单独命令时,它可以很好地下载文件,但不能使用任务调度程序。

您似乎对 kerberos 双跳委派有疑问。我的建议:

  1. 创建一个 ps1 文件并安排脚本文件
  2. 在调用命令中设置并使用 CredSSP 进行身份验证
  3. 可能是计划作业比计划任务更适合这种情况。

问题在于 powershell 和 schtasks 如何处理引号。由于 /tr 命令需要用双引号括起来,因此在命令内部需要双引号的地方使用单引号。这些又被转换为双引号。这与 powershell.exe 不兼容,因为它反过来无法解释命令中的双引号。

到目前为止我发现的唯一解决方法是将命令转换为 Base64,这样可以保留命令的确切格式,然后使用 -encodedCommand 参数将其传递给 powershell.exe

$ComputerName = "win12"
$cr=Get-Credential $ComputerName\administrator    
$Session = New-PSSession -ComputerName $ComputerName -Credential $cr

$command = "(New-Object System.Net.WebClient).DownloadFile('http://server12/vdir/OracleXE.exe','C:\abc.exe')"
$bytes = [System.Text.Encoding]::Unicode.GetBytes($command)
$encodedCommand = [Convert]::ToBase64String($bytes)

Invoke-Command -Session $Session -ScriptBlock {       
    $start = (Get-Date).AddMinutes(1).ToString("HH:mm:ss")
    [string]$Result = schtasks /create /tn "kk" /tr "powershell.exe -encodedCommand $encodedCommand" /sc once /st $start /ru "administrator" /rp "passw0rd@12" 
    $Result += schtasks /run /tn "kk"

    $Result
}

更新:
另一种可能不那么复杂但需要 PowerShell 3.0 的方法是使用计划作业。

$ComputerName = "win12"
$cr=Get-Credential $ComputerName\administrator    
$Session = New-PSSession -ComputerName $ComputerName -Credential $cr

$command = {(New-Object System.Net.WebClient).DownloadFile(
    'http://server12/vdir/OracleXE.exe','C:\abc.exe')}

Invoke-Command -Session $Session -ScriptBlock {
  Register-ScheduledJob -Name kk -ScriptBlock $command;
  (get-scheduledjob kk).Run() }
}