Не удается свернуть новое окно процесса в Process.Start - PullRequest
1 голос
/ 16 апреля 2020

Мне нужно запустить процесс java .jar из моей программы.
После запуска я получаю вывод и обрабатываю его.

Для этого я использую следующий код:

Dim p_Process As New Process()
Dim p_p As New ProcessStartInfo
p_p.FileName = "java.exe"
p_p.Arguments = "-jar myjar.jar"

p_p.WorkingDirectory = apppath & "\myFolder"

p_p.UseShellExecute = False
p_p.RedirectStandardOutput = True
p_p.WindowStyle = ProcessWindowStyle.Minimized
AddHandler p_Process.OutputDataReceived, AddressOf manageContent

p_Process.StartInfo = p_p
p_Process.Start()
p_Process.BeginOutputReadLine()

Мне нужны следующие строки, чтобы получить вывод Процесса для моего использования:

p_p.UseShellExecute = False
p_p.RedirectStandardOutput = True

Все работает, но окно не свернуто.
Как свернуть окно?

1 Ответ

1 голос
/ 16 апреля 2020

Возможный подход - минимизировать окно, генерируемое Java.exe, когда оно появляется, используя UI Automation.
Когда процесс запущен, файл Jar выполняется и создается новое окно. Это окно имеет специфицированное c имя класса, SunAwtFrame: это значение можно использовать для идентификации окна, затем получить доступ к элементу автоматизации пользовательского интерфейса WindowPattern и вызвать его SetWindowVisualState () способ свернуть окно.

Вы также можете использовать свойство «Заголовок окна», если его здесь лучше. В этом случае PropertyCondition для идентификации окна - это NameProperty вместо ClassNameProperty :

window = AutomationElement.RootElement.FindFirst(TreeScope.Children, New PropertyCondition(
    AutomationElement.NameProperty, "[The Window Title]"))

Конечно, Процесс отлично функционирует.

Здесь я реализовал его, используя асинхронный вариант, перенаправляя StandardOutput и StandardError, а также включая и подписываясь на событие Exited, устанавливая [Process].EnableRaisingEvents = True.
События Exited уведомляют, когда Процесс закрыт, а также удаляет объект Process.


Код здесь использует секундомер, чтобы дождаться появления окна Process ', так как Process.WaitForInputIdle() может быть не получить его правильно и завершить слишком рано.
Отрегулируйте код, если 3000 миллисекунды слишком короткий или слишком длинный интервал.
Обратите внимание, однако, что как только появляется окно, While l oop завершается.

Для этого кода требуется ссылка на сборки UIAutomationClient и UIAutomationTypes.

Imports System.Windows.Automation

Dim proc As New Process()
Dim psInfo As New ProcessStartInfo() With {
    .FileName = "java.exe",
    .Arguments = "-jar YourJarFile.jar",
    .WorkingDirectory = "[Your Jar File Path]",
    .UseShellExecute = False,
    .RedirectStandardOutput = True,
    .RedirectStandardError = True
}

proc.EnableRaisingEvents = True
proc.StartInfo = psInfo

AddHandler proc.OutputDataReceived,
    Sub(o, ev)
        Console.WriteLine(ev.Data?.ToString())
    End Sub
AddHandler proc.ErrorDataReceived,
    Sub(o, ev)
        Console.WriteLine(ev.Data?.ToString())
    End Sub
AddHandler proc.Exited,
    Sub(o, ev)
        Console.WriteLine("Process Exited")
        proc?.Dispose()
    End Sub

proc.Start()
proc.BeginOutputReadLine()

Dim window As AutomationElement = Nothing
Dim sw1 As Stopwatch = New Stopwatch()
sw1.Start()
While True
    window = AutomationElement.RootElement.FindFirst(
        TreeScope.Children, New PropertyCondition(
        AutomationElement.ClassNameProperty, "SunAwtFrame"))
    If window IsNot Nothing OrElse sw1.ElapsedMilliseconds > 3000 Then Exit While
End While
sw1.Stop()

If window IsNot Nothing Then
    DirectCast(window.GetCurrentPattern(WindowPattern.Pattern), WindowPattern).
        SetWindowVisualState(WindowVisualState.Minimized)
End If
...