Java Can';t最小化进程上的新进程窗口。启动

Java Can';t最小化进程上的新进程窗口。启动,java,.net,vb.net,jar,process,Java,.net,Vb.net,Jar,Process,我需要从我的程序启动一个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 = Fals

我需要从我的程序启动一个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
一切正常,但窗口未最小化。

如何最小化窗口?

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

您也可以使用窗口标题属性,以防它是一个更好的选择。在这种情况下,用于标识窗口的是,而不是:

当然,这一过程功能完善

在这里,我使用异步变量实现了它,重定向StandardOutput和StandardError,还启用和订阅退出的
事件,设置
[Process]。EnableRaisingEvents=True

退出的
事件在流程关闭时发出通知,并处理流程对象


这里的代码使用秒表等待进程的窗口显示,因为
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

WindowState.Minimized
,您确定吗?您是否有对
严格要求的
选项?您是否尝试过
ProcessWindowsStyle.Minimized
?和
p_p.UseShellExecute=True
?或者您想隐藏窗口吗?
windowstyle
属性的文档包含一个代码示例,显示它被设置为
ProcessWindowStyle.Minimized
,而不是
WindowState.Minimized
。始终阅读文档。@Jimi,
UseShellExecute
的文档中说“如果将
WindowsStyle
设置为
ProcessWindowsStyle.Hidden
UseShellExecute
必须设置为
true
”,因此在这种情况下没有问题。@jmchinney自从我发表评论以来,这个问题已经被编辑过了。OP最初忘记提到他们需要使用
RedirectStandardOutput=True
。所以我暗示,也许他们可以使用
ShellExecute=True
来最小化(或隐藏)效果。现在它不再适用了。但是你可以把它最小化。PInvoking、UI自动化等@Jimi:对不起,在这里传递代码是个错误。我使用ProcessWindowStyle.Minimized。关于p_p.UseShellExecute,它必须为false才能重定向输出。如果设置为true,则无法重定向。然后,如果我理解正确,上述代码用于调用SetWindowVisualSState函数。是吗?如果是,则与是否使用ShowWindow功能相同?此代码旨在异步(基于事件)处理流程StandardOutput和StandardError以及流程终止。然后,最小化新的进程窗口而不出现PInvoking。当然,您也可以使用Win32函数来完成最后一项任务。但你必须知道什么时候打电话。这里的代码没有特定的要求。它也可以被修改为自动检测窗口的打开,无论在一个时间点打开多少个相同的窗口。我刚刚测试了你的代码,但什么都没有发生。黑色窗口在正常状态下继续:-(如果您正确使用了此代码,但它没有检测到新窗口,则窗口类名称可能不是
SunAwtFrame
。您可以使用Spy++或
Inspect
确定窗口类名称。或者使用窗口标题,如注释中所述。
Inspect
可在
C:\Program Files(x86)中找到。)\Windows Kits\10\bin\x64\inspect.exe
(或安装系统的任何其他光盘)。
控制台Windows类
?这很奇怪(至少不是我想的那样)。因此,它不是一个标准的Win32窗口,而是一个控制台。无论如何,如果您感兴趣,此代码也适用于标准窗口。这意味着,您也可以通过
.jar
文件从
java.exe
创建的标准Win32窗口中获取
StandardOutput
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