Powershell

替換批處理文件的預定powershell過早結束或永遠不會結束

  • August 9, 2018

首先,我將解釋上下文,因為也許我沒有以正確的方式這樣做。

我們有一個使用 Oracle Forms 6i 開發的 ERP(是的,確實很舊)。它有表格和報告。報告具有如此復雜的查詢,當以充足的日期執行時,輸出僅在一個小時或更長時間後可用,因此這些報告安排在任務管理器中。該任務呼叫 .bat,.bat 呼叫 Forms Runtime (a .exe),Forms Runtime 執行一個表單,該表單執行一個報表。我沒有解釋為什麼這一切。關鍵是這些任務是在 Windows XP 中安排的,我想將它們移動到我們的一台伺服器上(我試圖在 Server 2012R2 中完成這項工作)。

經過一些嘗試和研究,我決定從 .bat 腳本轉移到 powershell。我已經讓 ps1 執行,但我有一些問題我不知道如何解決: 1- 呼叫 PS1 腳本的計劃任務執行一秒鐘,並在表單/報告結束執行後結束。2- 計劃任務在表單/報告結束後保持“執行”。

我的 PS1 腳本是這樣的:

param (
   [Parameter(Mandatory=$true)]
   [alias ("form")]
   [string]$formulario = $(throw "-form parametro obligatorio.") 
)

try
{
 BEHAVIOUR 1
   Start-Process -FilePath "C:\orant\BIN\ifrun60.EXE" -WorkingDirectory <SOMEPATH> -ArgumentList "$formulario <oracle_conn_credentials>"
 BEHAVIOUR 2
   Start-Process -FilePath "C:\orant\BIN\ifrun60.EXE" -WorkingDirectory <SOMEPATH> -ArgumentList "$formulario <oracle_conn_credentials>" -Wait


} 
catch
{
   LogWrite "ERROR."
   LogWrite $Error[0]
}

在哪裡:

  • $formulario 是輸入參數,如 \blah\blah\blah.fmx
  • LogWrite 是我用來記錄執行的函式,在這種情況下不需要,因為這個函式已經過全面測試
  • 帶有“行為 1”的行是導致計劃任務過早結束的行。我想這是因為我正在使用 Start-Process 並且這會啟動一個新的獨立執行緒。這把我帶到了下一點:
  • 帶有“行為 2”的行是使計劃任務永無止境的行。與上一行類似,但添加了“-Wait”,因此 powershell 腳本等待程序結束。

在這兩種情況下,我還看到,儘管正確生成了報告,但報告執行時程序永遠不會結束。這可能是腳本沒有結束的原因,但腳本正在執行 Forms Runtime,而 Forms Runtime 是呼叫 Reports Runtime 的原因。在所有報告結束時,Forms Runtime 完成,但 Reports Runtime 和 Powershell 程序都沒有結束。

我希望我已經解釋得足夠清楚了。如果沒有解決方案,任何解決方法都將受到高度讚賞。

**編輯:**好的,我發現了幾件事……首先,我找到了讓 powershell 或多或少像我想要的那樣行事的方法。這是使用Start-Process -PassThru. 它會是這樣的:

$proceso = Start-Process -FilePath "C:\orant\BIN\ifrun60.EXE" -WorkingDirectory <SOMEPATH> -ArgumentList "$formName <oracle_conn_credentials>" -PassThru
$handle = $proceso.Handle
$proceso.WaitForExit();

在閱讀了這個問題的第三個答案後,我得到了這個解決方案: https ://stackoverflow.com/questions/10262231/obtaining-exitcode-using-start-process-and-waitforexit-instead-of-wait 好的,現在我的流程結束了,所以預定的任務也結束了。但是,子程序將永遠執行。報告執行時打開一個控制台,讓您知道報告是否正在執行並顯示已執行報告的日誌。通常,此控制台會被忽略,並在退出報告時關閉視窗(手動,點擊右上角的 X)。但是由於報告是從沒有使用者界面的計劃任務生成的(在任務管理器中,您可以看到它以 session_id = 0 執行,這意味著沒有人機界面),因此無法手動關閉此控制台並且程序會一直保留,直到您將其殺死。所以現在的問題變了:有沒有辦法辨識這個子流程?請記住:任務調度程序執行 powershell 腳本,ps 執行 oracle 表單,oracle forms 執行 oracle 報告。我需要確定這個 oracle 報告過程。

好吧,在另一天尋找如何解決這個問題之後,我想我已經找到了執行所有這些並在不讓孤兒程序的情況下完成的方法。

$process = Start-Process -FilePath "C:\orant\BIN\ifrun60.EXE" -WorkingDirectory <SOMEPATH> -ArgumentList "$formName <oracle_conn_credentials>" -PassThru
$idProcess = $process.Id
$handle = $process.Handle
A ==> $process.WaitForExit();
B ==> $process | Wait-Process
$child = Get-WmiObject win32_process | where {$_.ParentProcessId -eq $idProcess}
Stop-Process -Id $child.ProcessId
Write-Output "Process finished with exit code "  $process.ExitCode

當我通過做這些事情來學習 Powershell 時,我不確定標記為“A”的行和標記為“B”的行之間到底有什麼區別,但兩者似乎都有效。

引用自:https://serverfault.com/questions/925451