首页 > 解决方案 > 无法最小化 Process.Start 上的新进程窗口

问题描述

我需要.jar从我的程序中启动一个 java 进程。
一旦开始,我得到输出并处理它。

为此,我使用以下代码:

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()

我需要以下几行才能获得 Process 的输出以供我使用:

p_p.UseShellExecute = False
p_p.RedirectStandardOutput = True

一切正常,但窗口没有最小化。
如何最小化窗口?

标签: java.netvb.netjarprocess

解决方案


一种可能的方法是最小化由 生成的窗口Java.exe,当它出现时,使用 UI 自动化。
当进程启动时,Jar文件被执行并创建一个新窗口。这个窗口有一个特定的类名,SunAwtFrame:这个值可以用来标识窗口,然后访问 UI 自动化元素的WindowPattern并调用它的SetWindowVisualState()方法来最小化窗口。

您还可以使用 Window Title 属性,以防它在这里是更好的选择。在这种情况下,标识 Window的PropertyCondition是NameProperty而不是ClassNameProperty

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

当然,该过程是完美的功能。

在这里,我使用异步变体实现了它,重定向 StandardOutput 和 StandardError,同时启用和订阅Exited事件,设置[Process].EnableRaisingEvents = True.
ExitedProcess 关闭时,事件会通知并处理 Process 对象。


此处的代码使用 StopWatch 来等待“进程”窗口出现,因为它Process.WaitForInputIdle()可能无法正确完成并且过早完成。
如果3000毫秒间隔太短或太长,请调整代码。
但是请注意,一旦 Window 出现,While循环就会退出。

此代码需要对UIAutomationClientUIAutomationTypes程序集的引用。

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

推荐阅读