简体   繁体   中英

Can't minimize the new Process Window on Process.Start

I need to start a java .jar process from my program.
Once started, I get the output and I process it.

For this, I use the following code:

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

I need the following lines in order to get the output of the Process for my use:

p_p.UseShellExecute = False
p_p.RedirectStandardOutput = True

All is working, but the window is not minimized.
How to minimize the window?

A possible approach is to minimize the Window generated by Java.exe , when it shows up, using UI Automation.
When the Process is started, the Jar file is executed and a new Window is created. This Window has a specific class name, SunAwtFrame : this value can be used to identify the window, then access the UI Automation Element's WindowPattern and call its SetWindowVisualState() method to minimize the Window.

You can also use the Window Title property, in case its a better choice here. In this case, the PropertyCondition to identify the Window is the NameProperty instead of the ClassNameProperty :

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

Of course, the Process is perfectly functional.

Here, I've implemented it using the asynchronous variant, redirecting StandardOutput and StandardError, also enabling and subscribing to the Exited event, setting [Process].EnableRaisingEvents = True .
The Exited events notifies when the Process is closed and also disposes of the Process object.


The code here uses a StopWatch to wait for the Process' Window to show up, since Process.WaitForInputIdle() may not be get it right and complete too soon.
Adjust the code if 3000 milliseconds is a too short or too long interval.
Note, however, that as soon as the Window shows up, the While loop is exited.

This code requires a reference to the UIAutomationClient and UIAutomationTypes assemblies.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM