Мне нужно запустить 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
ManRas 16 Апр 2020 в 09:57

1 ответ

Лучший ответ

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

Вы также можете использовать свойство Window Title, если это лучший выбор здесь. В этом случае PropertyCondition для идентификации Окно вместо этого является NameProperty из ClassNameProperty:

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

Конечно, процесс полностью функционален.

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


В приведенном здесь коде используется секундомер, чтобы дождаться появления окна процесса, поскольку Process.WaitForInputIdle() может быть неправильно и завершен слишком рано.
Измените код, если 3000 миллисекунды являются слишком коротким или слишком длинным интервалом.
Обратите внимание, однако, что как только появляется окно, цикл While завершается.

Этот код требует ссылки на сборки 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
1
Jimi 16 Апр 2020 в 16:29