在PowerShell中启动分离的后台进程

时间:2014-07-29 19:30:11

标签: windows powershell

我有一个Java程序,我想从PowerShell脚本作为后台进程启动,类似于守护程序在Linux上运行的方式。 PowerShell脚本需要做几件事:

  1. 在后台运行程序作为单独的分离进程,这意味着可以关闭父窗口并继续运行。
  2. 将程序的标准输出和标准错误重定向到文件。
  3. 将后台进程的PID保存到文件中,以便稍后由另一个脚本终止。
  4. 我在Linux上有一个shell脚本,可以像这样启动程序:

    $ java -jar MyProgram.jar >console.out 2>console.err &
    

    我希望使用PowerShell脚本在Windows上复制相同的行为。我尝试使用Start-Process各种选项组合,以及创建System.Diagnostics.ProcessStartInfoSystem.Diagnostics.Process个对象,但到目前为止我没有运气。 PowerShell作为后台进程启动程序,但是当启动PowerShell会话的DOS窗口关闭时,程序突然终止。我希望它在后台启动并独立于启动它的命令窗口。

    输出重定向也很麻烦,因为输出和错误流似乎只能在同一窗口中运行的过程中重定向(例如,使用-NoNewWindow)。

    在PowerShell中这种事情是否可行?

4 个答案:

答案 0 :(得分:18)

使用jobs

Start-Job -ScriptBlock {
  & java -jar MyProgram.jar >console.out 2>console.err
}

另一种选择是Start-Process

Start-Process java -ArgumentList '-jar', 'MyProgram.jar' `
  -RedirectStandardOutput '.\console.out' -RedirectStandardError '.\console.err'

答案 1 :(得分:2)

考虑使用任务调度程序。定义任务并设置它而不需要任何触发器。这将允许您简单地“运行”(手动触发)任务。

您可以使用ScheduledTasks powershell模块设置和/或触发计划任务,也可以使用GUI。

答案 2 :(得分:2)

这是一篇很老的帖子,但是因为我认为它很好,所以可能有助于分享。它是对'java'而不是'javaw'的调用,这可能是你的问题。使用我的JEdit java程序通过powershell启动它,然后自己动手。

var doneTodoIds = todos.filter(todo => todo.completed === true ).map( todo => todo.id).includes(this.state.checkedIds);
var result = arraysIntersect(doneTodoIds, this.state.checkedIds);

您可以将其转换为小功能,然后使用别名,以便在Powershell中轻松启动。

#Requires -Version 3.0
$MyDriveRoot = (Get-Location).Drive.Root
$JEditDir = $($mydriveroot + "jEdit") ;# Should be C:\jEdit or wherever you want. JEdit is a sub-directory.
$jEdit = $($JEditDir + "\jedit.jar" )
$jEditSettings = $($JEditDir + "\settings")
$JEditLogs = $($JEditDir + "\logs")

Start-Process -FilePath javaw -ArgumentList ( '-jar',"$jEdit", '-settings="$JEditSettings"' ) -RedirectStandardOutput "$JEditLogs\console.out" -RedirectStandardError "$JEditLogs\console.err"

答案 3 :(得分:0)

古老的问题,但是由于我有相同的目标,因此我使用了@use的答案来实现它。

这是我的代码:)

$NAME_TASK = "myTask"
$NAME_TASKPATH = "\myPath\"

if ($args[0] -eq "-task") {
  # Code to be run "detached" here...
  Unregister-ScheduledTask -TaskName $NAME_TASK -TaskPath $NAME_TASKPATH -Confirm:$False
  Exit
}

$Task = (Get-ScheduledTask -TaskName $NAME_TASK -TaskPath $NAME_TASKPATH -ErrorAction 'SilentlyContinue')
if ($Task) {
  Write-Host "ERR: Task already in progress"
  Exit 1
}

$A = New-ScheduledTaskAction -Execute "PowerShell.exe" -Argument "-ExecutionPolicy bypass -NoProfile -Command ""$PSCommandPath -task $args"""
Register-ScheduledTask -TaskName $NAME_TASK -TaskPath $NAME_TASKPATH -Action $A | Start-ScheduledTask