完成后(异步)自动删除PowerShell作业

时间:2014-09-22 19:26:31

标签: powershell jobs cmdlet

我有一个PowerShell cmdlet,我用它来简化与RDP的另一台计算机的连接。

在该cmdlet中,我运行以下操作:

    if ($null -ne $Username -and $null -ne $Password) {
        Start-Process -FilePath "cmdkey.exe" -ArgumentList @("/generic:`"TERMSRV/$ComputerName`"", "/user:`"$Username`"", "/pass:`"$Password`"") -WindowStyle Hidden
    }

    Start-Job -ScriptBlock {
        param($InstallPath, $ComputerName, $Port, $Username, $Password)

        $arguments = @("`"$(Join-Path $InstallPath '\Support Files\MSTSC\Default.rdp')`"")
        if ($null -ne $Port) {
            $arguments += "/v:`"$($ComputerName):$($Port)`""
        } else {
            $arguments += "/v:`"$($ComputerName)`""
        }

        Start-Process -FilePath "mstsc.exe" -ArgumentList $arguments -Wait

        if ($null -ne $Username -and $null -ne $Password) {
            Start-Process -FilePath "cmdkey.exe" -ArgumentList @("/delete:`"TERMSRV/$ComputerName`"") -WindowStyle Hidden
        }
    } -ArgumentList @($InstallPath, $ComputerName, $Port, $Username, $Password)

如您所见,我添加了用于连接远程计算机的凭据,然后启动执行mstsc.exe的作业,等待它完成然后删除凭据。

问题是我必须在删除凭据之前等待mstsc关闭,否则在mstsc有机会建立连接之前它们会被删除,我希望这个cmdlet是自包含的 - 立即将控制权返回给users命令提示所以我可以运行其他命令,同时我也在使用RDP会话,这意味着我不能等待工作完成,因为这意味着我等到我从远程会话断开连接时等待:

| Wait-Job | Remove-Job

我想要做的是能够在完成后删除Job,也许使用某种回调,这样一旦我退出RDP,我就不必手动运行另一个命令来清理作业会话和作业没有处于完成状态(这是我目前正在做的事情,但显然这不是'干净)。

对于完整的cmdlet,您可以在此处查看更多上下文:

https://github.com/paulmarsy/Console/blob/master/AdvancedPowerShellConsole/Exports/Functions/Connect-Remote.ps1

2 个答案:

答案 0 :(得分:1)

所以注册一个预定的工作,在5分钟内运行,这将删除已完成的工作。我很确定你可以这样做:

Register-ScheduledJob -ScriptBlock {param($computername); Wait-Job -Name $ComputerName|remove-job} -Trigger @{Frequency="Once";At=(get-date).AddMinutes(5).ToString("h:MM tt")} -argumentlist $computername

然后,只需在执行Start-Job时为您的连接命名,方法是将-Name $ComputerName附加到命令的末尾。这样,在您启动它的5分钟后,计划任务将启动查找并按名称清除该作业。

答案 1 :(得分:1)

我知道这是一个非常古老的问题...您可以使用 Register-ObjectEvent 来清理作业。作业有一个 StateChanged 事件,该事件有一个 EventSubscriber 参数传递给它,其中包含事件和源作业的详细信息。

这是一个例子。作业完成后,回调将删除自身和源作业。

$job = Start-Job { Start-Sleep -Seconds 2 }
Register-ObjectEvent -InputObject $job -EventName StateChanged -Action {
    Unregister-Event $EventSubscriber.SourceIdentifier
    Remove-Job $EventSubscriber.SourceIdentifier
    Remove-Job -Id $EventSubscriber.SourceObject.Id
} | Out-Null