Python调用多行PowerShell单命令报错,求无需.ps1文件的执行方案
解决Python调用PowerShell创建定时任务的引号解析错误
问题重现
尝试在Python中直接执行PowerShell脚本创建定时任务,避免生成.ps1文件,当前代码如下:
import os command='''$jobname = "Recurring PowerShell Task" $script = "w32tm /resync" $action = New-ScheduledTaskAction –Execute "$pshome\powershell.exe" -Argument "$script" $duration = ([timeSpan]::maxvalue) $repeat = (New-TimeSpan -hours 3) $trigger =New-ScheduledTaskTrigger -Once -At (Get-Date).Date -RepetitionInterval $repeat -RepetitionDuration $duration $msg = "Enter the username and password that will run the task"; $credential = $Host.UI.PromptForCredential("Task username and password",$msg,"$env:userdomain\$env:username",$env:userdomain) $username = $credential.UserName $password = $credential.GetNetworkCredential().Password $settings = New-ScheduledTaskSettingsSet -AllowStartIfOnBatteries -DontStopIfGoingOnBatteries -StartWhenAvailable -RunOnlyIfNetworkAvailable -DontStopOnIdleEnd Register-ScheduledTask -TaskName $jobname -Action $action -Trigger $trigger -RunLevel Highest -User $username -Password $password -Settings $settings''' os.system("powershell "+command)
运行后出现错误:
+ $jobname = Recurring PowerShell Task + ~~~~~~~~~ + CategoryInfo : ObjectNotFound: (Recurring:String) [], CommandNotFoundException + FullyQualifiedErrorId : CommandNotFoundException
错误原因
- 引号丢失:通过
os.system传递命令时,cmd.exe会解析外层引号,导致PowerShell脚本中的字符串引号被剥离,PowerShell将Recurring识别为命令而非字符串的一部分,引发找不到命令的错误。 - 符号错误:
New-ScheduledTaskAction后的–Execute使用了中文破折号,PowerShell无法识别该符号,会导致参数解析失败。
解决建议
1. 修正符号错误
将脚本中所有中文破折号–替换为英文短横线-,例如:
$action = New-ScheduledTaskAction -Execute "$pshome\powershell.exe" -Argument "$script"
2. 正确处理引号传递
使用PowerShell的-Command参数包裹整个脚本,并在Python中对引号进行转义,避免被cmd.exe解析丢失。修改os.system调用为:
os.system('powershell -Command "{0}"'.format(command.replace('"', '\\"')))
3. 推荐使用subprocess模块替代os.system
subprocess模块对命令参数的处理更可靠,避免多层解析问题,示例代码:
import subprocess command='''$jobname = "Recurring PowerShell Task" $script = "w32tm /resync" $action = New-ScheduledTaskAction -Execute "$pshome\powershell.exe" -Argument "$script" $duration = ([timeSpan]::maxvalue) $repeat = (New-TimeSpan -hours 3) $trigger =New-ScheduledTaskTrigger -Once -At (Get-Date).Date -RepetitionInterval $repeat -RepetitionDuration $duration $msg = "Enter the username and password that will run the task"; $credential = $Host.UI.PromptForCredential("Task username and password",$msg,"$env:userdomain\$env:username",$env:userdomain) $username = $credential.UserName $password = $credential.GetNetworkCredential().Password $settings = New-ScheduledTaskSettingsSet -AllowStartIfOnBatteries -DontStopIfGoingOnBatteries -StartWhenAvailable -RunOnlyIfNetworkAvailable -DontStopOnIdleEnd Register-ScheduledTask -TaskName $jobname -Action $action -Trigger $trigger -RunLevel Highest -User $username -Password $password -Settings $settings''' subprocess.run(["powershell", "-Command", command], shell=True)
4. 可选:使用Base64编码传递脚本
如果引号转义仍然有问题,可以将PowerShell脚本编码为Base64,通过-EncodedCommand参数执行,彻底避免引号解析问题:
import subprocess import base64 command='''$jobname = "Recurring PowerShell Task" $script = "w32tm /resync" $action = New-ScheduledTaskAction -Execute "$pshome\powershell.exe" -Argument "$script" $duration = ([timeSpan]::maxvalue) $repeat = (New-TimeSpan -hours 3) $trigger =New-ScheduledTaskTrigger -Once -At (Get-Date).Date -RepetitionInterval $repeat -RepetitionDuration $duration $msg = "Enter the username and password that will run the task"; $credential = $Host.UI.PromptForCredential("Task username and password",$msg,"$env:userdomain\$env:username",$env:userdomain) $username = $credential.UserName $password = $credential.GetNetworkCredential().Password $settings = New-ScheduledTaskSettingsSet -AllowStartIfOnBatteries -DontStopIfGoingOnBatteries -StartWhenAvailable -RunOnlyIfNetworkAvailable -DontStopOnIdleEnd Register-ScheduledTask -TaskName $jobname -Action $action -Trigger $trigger -RunLevel Highest -User $username -Password $password -Settings $settings''' # 按PowerShell要求的UTF-16LE编码后转Base64 encoded_command = base64.b64encode(command.encode('utf-16le')).decode('utf-8') subprocess.run(["powershell", "-EncodedCommand", encoded_command])
内容的提问来源于stack exchange,提问作者ripdechains
相关产品推荐
相关产品推荐

