Назад | Перейти на главную страницу

Запланированный Powershell для замены командного файла заканчивается слишком рано или никогда не заканчивается

Сначала я объясню контекст, потому что, возможно, я делаю это неправильно.

У нас есть ERP, разработанная с использованием Oracle Forms 6i (да, действительно старая). Имеет формы и отчеты. Отчеты содержат такие сложные запросы, что при запуске с достаточными датами вывод становится доступен только через час или более, поэтому эти отчеты планируются в диспетчере задач. Задача вызывает .bat, .bat вызывает Forms Runtime (.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]
}

Куда:

В обеих ситуациях я также видел, что процесс выполнения отчетов никогда не заканчивается, хотя отчеты создаются правильно. Это может быть причиной того, что скрипт не завершается, но скрипт запускает среду выполнения форм, а среда выполнения форм вызывает среду выполнения отчетов. К моменту завершения всех отчетов среда выполнения форм завершается, но не завершаются ни среда выполнения отчетов, ни процессы 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/obading-exitcode-using-start-process-and-waitforexit-instead-of-wait Хорошо, теперь мой процесс завершается, поэтому запланированная задача также завершается. НО, подпроцесс остается работать вечно. Среда выполнения отчетов открывает консоль, которая позволяет узнать, запущен ли отчет, и показывает журнал выполненных отчетов. Обычно эта консоль игнорируется и ее окно закрывается при выходе из отчета (вручную, щелчком в правом верхнем углу X). Но поскольку отчет создается из запланированной задачи без пользовательского интерфейса (в диспетчере задач вы можете видеть, что он запускается с session_id = 0, что означает отсутствие человеческого интерфейса), эта консоль не может быть закрыта вручную, и процесс остается, пока вы его не убьете. Итак, теперь вопрос изменился: есть ли способ идентифицировать этот подпроцесс? Помните: планировщик задач запускает сценарий PowerShell, ps запускает формы oracle, а формы oracle запускает отчеты oracle. Мне нужно идентифицировать этот процесс отчетов оракула. Имейте в виду, что я планирую запустить это с несколькими формами / отчетами, и что может быть 2 экземпляра этого, работающих одновременно с одним и тем же пользователем.

Что ж, после еще одного дня поиска того, как решить эту проблему, я думаю, что нашел способ запустить все это и закончить, не допуская сиротских процессов.

$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», но обе, похоже, работают.