Проблемы Start-Process-wait с Autodesk Revit

Я наблюдаю какое-то странное поведение с тестом, который работает уже много лет. Тест предназначен для Autodesk Revit, который может использовать файлы журнала для автоматизации задач и регистрации времени. Эталонный тест будет считывать файл XML для серии модульных файлов журналов, которые могут обрабатываться в различных последовательностях в зависимости от того, какие функции Revit необходимо протестировать. В результате Revit запускается с разными журналами и закрывается по завершении каждого журнала для повторного запуска со следующим журналом. Я использовал Start-Process с опцией -wait в таком цикле...

$exitCode = (Start-Process -FilePath:$executable -argumentList:"`"$journalFile`"" -wait -errorAction:stop -PassThru).ExitCode

Что происходит в последнее время, так это ОЧЕНЬ длинные паузы между завершением журнала и закрытием Revit и возвращением управления в PowerShell, чтобы можно было запустить следующий журнал. Например, иногда 3-5 минут, что становится проблемой, когда нужно обработать 10 разных журнальных файлов. Кажется, это происходит только в Windows 10, но я еще не смог проверить, ограничено ли это конкретной сборкой или все Windows 10 ведут себя таким образом.

Я нашел несколько ссылок на то, что Start-Process -wait проблематичен, поэтому я начал искать альтернативы.

Сначала я попробовал...

$process = Start-Process -FilePath:$executable -argumentList:"`"$journalFile`""
Wait-Process $process

Но это, похоже, не ждет. Revit запускается несколько раз параллельно, и, поскольку каждый журнал иногда зависит от файлов, созданных в предыдущих, это не удается. Итак, я нашел ссылку на использование [System.Diagnostics.ProcessStartInfo] вот так...

$processInfo = New-Object System.Diagnostics.ProcessStartInfo
$processInfo.RedirectStandardError = $true
$processInfo.RedirectStandardOutput = $true
$processInfo.UseShellExecute = $false
$process = New-Object System.Diagnostics.Process

с этим в петле...

$processInfo.FileName = $executable
$processInfo.Arguments = "`"$journalFile`""
$process.StartInfo = $processInfo
[Void]$process.Start()
$process.WaitForExit()
exitCode = $process.ExitCode

Кажется, это решает проблему ожидания, но приводит к тому, что Revit не может обработать один конкретный журнал всегда в одном и том же месте. Но это не имеет смысла, так как я предполагаю, что Revit может не знать, как он был запущен.

Есть ли у кого-нибудь какие-либо предложения о том, что я могу делать неправильно с любым из этих подходов, или с третьим вариантом, который я должен попробовать? И есть ли у кого-нибудь достоверная информация о том, что не так с Start-Process -wait?


person Gordon    schedule 14.07.2020    source источник


Ответы (1)


Если у вас не работает параметр -Wait Start-Process (у меня нет информации о том, почему могут возникать длительные задержки), вы действительно можете работать с System.Diagnostics.Process, возвращаемый Start-Process и представляющий вновь созданный процесс, при условии, что вы использовали переключатель -PassThru:

# Simple example (Windows): launch Notepad asynchronously,
# and, thanks to -PassThru, return a System.Diagnostics.Process describing 
# the newly created process.
$ps = Start-Process -PassThru Notepad

Если вы хотите использовать Wait-Process чтобы дождаться завершения процесса, у вас есть два варианта синтаксиса:

$ps | Wait-Process

or

Wait-Process $ps.ID  # parameter -ID implied

Обратите внимание, что Wait-Process $ps не работает, потому что он пытается привязаться к параметру -Name, в результате чего $ps.ToString() используется как (бесполезное) значение.

Однако вы также можете напрямую использовать метод .WaitForExit() типа Process:

$ps.WaitForExit()

После завершения процесса вы можете запросить его свойство .ExitCode, чтобы получить его код выхода.

person mklement0    schedule 14.07.2020
comment
Это трюк, который мне был нужен. Есть ли аргумент за или против .WaitForExit() против Wait-Process $ps.ID? Я пробовал оба, и они оба, кажется, работают хорошо. Все еще нужно попробовать оба в Windows 7/PS2.0, так как некоторые Архитекторы все еще используют его. - person Gordon; 14.07.2020
comment
@Gordon: эти два подхода взаимозаменяемы, хотя, как правило, моя рекомендация заключается в том, чтобы придерживаться собственных функций PowerShell (если только вы не вынуждены использовать другие подходы по причинам производительности). Здесь это не является реальной проблемой, но из-за динамического разрешения перегрузок вызовы методов могут непреднамеренно изменить свое поведение между версиями PowerShell, если базовые типы .NET вводят новые перегрузки. Что касается непосредственного сравнения производительности: при первом вызове вызов Wait-Process может быть быстрее, потому что вызовы методов компилируются JIT - я сомневаюсь, что это имеет значение здесь. - person mklement0; 14.07.2020
comment
Тьфу, какой облом, что методы .NET нельзя доверять от версии к версии. Это может дать информацию о некоторых решениях, которые мне нужно принять в другом проекте, поскольку я по умолчанию тяготел к .NET из соображений производительности. Я думаю, если я хочу зависеть от .NET, мне, вероятно, нужно перейти на C # и скомпилировать EXE. - person Gordon; 14.07.2020
comment
@Gordon: Безусловно: это редко, но случается; яркий пример см. в нижней части этого ответа. Если вы тщательно применяете явное приведение аргументов, чтобы убедиться, что передается точный ожидаемый тип, вы можете защититься от таких проблем. - person mklement0; 14.07.2020