Obtener la salida de una cadena Java de VBA

Nov 25 2020

Necesito obtener la cadena de salida de una función java en mi proyecto VBA. Como ejemplo rápido, estoy tratando de obtener la salida de la versión de Java instalada, pero en la aplicación real habrá otras funciones privadas.

Primer intento:

' 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

Segundo intento:

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

Ninguno de ellos funcionó para mí.

Me gustaría evitar el uso de archivos temporales como en el ejemplo de mi segundo intento. En el uso final, llamaré a esta función cientos de miles de veces, y prefiero no crear esa cantidad de archivos o editar ese archivo tantas veces ...

Respuestas

Joracosu Nov 26 2020 at 07:41

Encontré la solución para ambos intentos y básicamente es el mismo problema: el resultado de una función de Java que se muestra en el shell de comandos se trata como un error, por lo tanto, no es un resultado. La duda se resolvió aquí

En el caso de enviar la salida de java a un archivo, se resuelve usando en 2>lugar de >como se dice aquí . De todos modos, hay muchas variantes diferentes dependiendo de lo que necesites, como se informa en este otro enlace . Un problema menor de este método es que la creación del archivo de salida necesita un tiempo para realizarse, por lo tanto, la variable final del Runcomando debe establecerse enTrue

Y el código es el siguiente:

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

En el caso de llevar directamente la salida de java a una variable, se resuelve usando en StdErrlugar de StdOut. Tengo la iluminación leyendo este enlace . El WshExecobjeto tiene tres elementos principales: StdErr, StdIny StdOut. Si la cadena de salida de Java se trata como un error, debería estar dentro StdErr.

Y el código es el siguiente:

' 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