Uzyskaj dane wyjściowe ciągu Java z języka VBA

Nov 25 2020

Muszę uzyskać ciąg wyjściowy funkcji Java do mojego projektu VBA. Jako szybki przykład próbuję pobrać dane wyjściowe wersji Java, ale w prawdziwej aplikacji będą to inne funkcje prywatne.

Pierwsze podejscie:

' Needs a reference to Windows Script Host Object Model
Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
Sub get_java_output()
    Dim cmd_windows    As New WshShell
    Dim execution_cmd  As WshExec
    Dim command_str    As String
    command_str = "java -version"
    Set execution_cmd = cmd_windows.exec("cmd.exe /c " & command_str)
    Do While execution_cmd.Status = WshRunning
        Sleep 20
    Loop
    final_string = execution_cmd.StdOut.ReadAll
    Debug.Print final_string
End Sub

Drugie podejście:

Sub get_java_output_2()
    Dim windows_shell As Object
    
    Set windows_shell = CreateObject("WScript.Shell")
    command_str = "java -version"
    shell_output = windows_shell.Run("cmd /c " & command_str & " > c:\temp\output.txt", 0, False)
    Set fso = CreateObject("Scripting.FileSystemObject")
    Set File = fso.OpenTextFile("c:\temp\output.txt", 1)
    final_string = File.ReadAll
    File.Close
    Debug.Print final_string
End Sub

Żaden z nich nie pracował dla mnie.

Chciałbym uniknąć używania plików tymczasowych, jak w moim przykładzie z drugiej próby. W ostatecznym użyciu będę nazywać tę funkcję setki tysięcy razy i wolę nie tworzyć takiej liczby plików ani nie edytować tego pliku tyle razy ...

Odpowiedzi

Joracosu Nov 26 2020 at 07:41

Znalazłem rozwiązanie dla obu prób i zasadniczo jest to ten sam problem: dane wyjściowe funkcji java wyświetlane w powłoce poleceń są traktowane jako błąd, dlatego nie są to dane wyjściowe. Tutaj wątpliwości zostały rozwiązane

W przypadku wysyłania wyjścia Java do pliku, jest to rozwiązywane za pomocą 2>zamiast tak, >jak jest to tutaj powiedziane . W każdym razie istnieje wiele różnych wariantów w zależności od tego, czego potrzebujesz, jak opisano w tym drugim linku . Drobnym problemem tej metody jest to, że utworzenie pliku wyjściowego wymaga czasu, dlatego ostateczna zmienna Runpolecenia musi być ustalona naTrue

A kod wygląda następująco:

Sub get_java_output_2()
    Dim windows_shell As Object
    
    Set windows_shell = CreateObject("WScript.Shell")
    command_str = "java -version"
    shell_output = windows_shell.Run("cmd /c " & command_str & " 2> c:\temp\output.txt", 0, True)
    Set fso = CreateObject("Scripting.FileSystemObject")
    Set File = fso.OpenTextFile("c:\temp\output.txt", 1)
    final_string = File.ReadAll
    File.Close
    Debug.Print final_string
End Sub

W przypadku bezpośredniego przenoszenia danych wyjściowych Java do zmiennej, jest to rozwiązywane za pomocą StdErrzamiast StdOut. Dostałem iluminację czytając ten link . WshExecObiekt składa się z trzech głównych elementów: StdErr, StdIni StdOut. Jeśli ciąg wyjściowy Java jest traktowany jako błąd, powinien znajdować się wewnątrz StdErr.

A kod wygląda następująco:

' Needs a reference to Windows Script Host Object Model
Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
Sub get_java_output()
    Dim cmd_windows    As New WshShell
    Dim execution_cmd  As WshExec
    Dim command_str    As String
    command_str = "java -version"
    Set execution_cmd = cmd_windows.exec(command_str)
    Do While execution_cmd.Status = WshRunning
        Sleep 20
    Loop
    final_string = execution_cmd.StdErr.ReadAll
    Debug.Print final_string
End Sub