【问题标题】:Can't minimize the new Process Window on Process.Start无法最小化 Process.Start 上的新进程窗口
【发布时间】:2020-04-16 06:57:22
【问题描述】:

我需要从我的程序中启动一个 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()

我需要以下几行来获取 Process 的输出以供我使用:

p_p.UseShellExecute = False
p_p.RedirectStandardOutput = True

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

【问题讨论】:

  • WindowState.Minimized,你确定吗?你有Option Strict On吗?您是否尝试过ProcessWindowStyle.Minimized?还有p_p.UseShellExecute = True?或者也许你想隐藏窗口?
  • WindowsStyle 属性的文档包含一个代码示例,显示它被设置为ProcessWindowStyle.Minimized,而不是WindowState.Minimized。始终阅读文档。
  • @Jimi,UseShellExecute 的文档说 “如果将 WindowStyle 设置为 ProcessWindowStyle.HiddenUseShellExecute 必须设置为 true,所以在这种情况下没有问题。
  • @jmcilhinney 自我发布该评论以来,该问题已被编辑。最初,OP 忘记提及他们需要使用RedirectStandardOutput = True。所以我暗示,也许他们可以使用ShellExecute = True 来获得最小化(或隐藏)的效果。现在它不再适用了。但无论如何,您都可以将其最小化。 PInvoking,带有 UI 自动化等。
  • @Jimi:对不起,在这里传递代码是一个错误。我使用 ProcessWindowStyle.Minimized。关于 p_p.UseShellExecute,它必须为 false 才能重定向输出。如果设置为 true,则无法重定向。

标签: java .net vb.net jar process


【解决方案1】:

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

您也可以使用 Window Title 属性,以防它在这里是更好的选择。在这种情况下,用于识别Window的PropertyConditionNameProperty而不是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 毫秒间隔太短或太长,请调整代码。
但是请注意,一旦 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

【讨论】:

  • 那么,如果我理解正确,上面的代码用于调用 setWindowVisualState 函数。是对的?如果是,是否与使用 ShowWindow 功能相同?
  • 此代码旨在异步处理流程 StandardOutput 和 StandardError 以及流程终止(基于事件)。然后,在没有 PInvoking 的情况下最小化新的 Process Window。您也可以使用 Win32 函数来完成最后一项任务,这是肯定的。但是你必须知道什么时候调用它。此处的代码无需特定要求即可完成所有操作。也可以修改为自动检测窗口的打开,无论在某个时间点打开了多少相同的窗口。
  • 我刚刚测试了您的代码,但没有任何反应。黑窗继续正常状态:-(
  • 如果你正确使用了这段代码并且它没有检测到新的窗口,那么窗口类名有可能不是SunAwtFrame。您可以使用 Spy++ 或 Inspect 来确定 Window 类名。或使用 Window Title,如注释中所述。 Inspect 可以在 C:\Program Files (x86)\Windows Kits\10\bin\x64\inspect.exe(或您的系统安装在其中的任何其他光盘)中找到。
  • ConsoleWindowClass?这很奇怪(好吧,至少不是我想的那样)。所以,它不是一个标准的 Win32 窗口,它是一个控制台。无论如何,如果您有兴趣,此代码也适用于标准 Windows。这意味着,您也可以通过.jar 文件从java.exe 创建的标准Win32 窗口中获取StandardOutput
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-08-24
  • 1970-01-01
  • 1970-01-01
  • 2016-10-08
  • 1970-01-01
  • 2021-11-27
  • 1970-01-01
相关资源
最近更新 更多