Запуск Java из макроса VBA в Windows 7 в обход System32 / SysWOW64 javaw.exe - PullRequest
0 голосов
/ 24 октября 2018

Есть ли способ обойти 32-битную версию Java (может быть, другой способ запустить процесс в VBA для вызова 64-битной версии cmd, отключить UAC или какой-либо другой вид твика), который находится "принудительно "с помощью следующего кода VBA (это всего лишь предположение, я объясняю процесс отладки ниже):

handleDbl = Shell("javaw -cp theJar.jar com.java.SampleClass", vbNormalFocus)

Главное здесь заключается в том, что я хочу поделиться своим макросом и не добавлять дополнительные инструкцииполучатель, поэтому я пытаюсь сделать все в коде (я использую позднюю привязку для кода VBA, чтобы избежать установки ссылок вручную и тому подобного).

Процесс отладки

Ошибкабыло выброшено, поэтому я использовал следующую строку:

handleDbl = Shell("cmd /k java -cp theJar.jar com.java.SampleClass", vbNormalFocus)

И получил ошибку Exception in thread "main" java.lang.UnsupportedClassVersionError: Unsupported major.minor version, поэтому я проверил java -version и попытался выяснить, с какой java работал:

C:\>where java
C:\Windows\System32\java.exe
C:\Program Files\Java\_anyJava.x.x.x_\bin\java.exe

Я пошел в папку System32, и там не было Java, но я знал, что оттуда происходит перенаправление на C:\Windows\SysWOW64, поэтому я сравнил ранее извлеченную версию Java сC:\Windows\SysWOW64\java.exe -version и они совпали.

После этого я проверил свою версию Outlook и оказался 32-битной установкой.Это был намек, но в основном это был тот самый большой * 32 рядом с cmd.exe в диспетчере задач.Я не знаю, изменится ли 64-битный Outlook или он будет таким же из-за реализации VBA, но я пришел к выводу, что функция Shell из VBA вызывает 32-битный вызов Java.

Ответы [ 2 ]

0 голосов
/ 07 ноября 2018

Сэм ответ отличный, но мне просто стало не по себе от того, что пользователь прошел через дополнительные настройки, поэтому я написал несколько функций для проверки версий java и уведомления пользователя, если его там нет (пришлось бы установить javaв любом случае) так вот мой код.Это может содержать некоторые полезные вещи.

Private Function IsJavaAvailable(ByVal displayMessage As Boolean, Optional ByVal isJavaMandatory As Boolean) As Boolean
    Dim availability As Boolean
    Dim minJavaVersion As Integer
    minJavaVersion = 8

    'isJavaSetup is a global variable
    If (Not isJavaSetup) Then
        javawPathQuoted = GetMinimumJavaVersion(minJavaVersion)
        If StrComp(javawPathQuoted, "") <> 0 Then
            isJavaSetup = True
        End If
        SetGlobalVars
    End If

    If javawPathQuoted = Empty Then
        availability = False
    Else
        availability = True
    End If

    If (displayMessage) Then
        If (isJavaMandatory) Then
            If Not availability Then
                MsgBox "This functionality is NOT available without Java " & minJavaVersion & "." & _
                vbNewLine & vbNewLine & _
                "Please install Java " & minJavaVersion & " or higher.", vbCritical, _
                "Mimimum Version Required: Java " & minJavaVersion
            End If
        Else
            If Not availability Then
                MsgBox "Some features of this functionality were disabled." & _
                vbNewLine & vbNewLine & _
                "Please install Java " & minJavaVersion & " or higher.", vbExclamation, _
                "Mimimum Version Required: Java " & minJavaVersion
            End If

        End If
    End If

    IsJavaAvailable = availability

End Function

Private Function GetMinimumJavaVersion(ByVal javaMinimumMajorVersionInt As Integer) As String

    'Run a shell command, returning the output as a string
    Dim commandStr As String
    Dim javawPathVar As Variant
    Dim javaPathStr As Variant
    Dim javaVersionStr As String
    Dim javaMajorVersionInt As Integer

    Dim detectedJavaPaths As Collection
    Dim javaVersionElements As Collection
    Dim javaVersionOutput As Collection
    Dim detectedJavaVersions As Collection

    Dim suitableJavawPath As String

    'Check available javaw executables in the SO
    commandStr = "where javaw"
    Set detectedJavaPaths = GetCommandOutput(commandStr)
    Set detectedJavaVersions = New Collection

    For Each javawPathVar In detectedJavaPaths

        'Look for java.exe instead of javaw.exe by substituting it in path
        '  javaw.exe does NOT return version output like java.exe
        javaPathStr = StrReverse(Replace(StrReverse(javawPathVar), StrReverse("javaw.exe"), StrReverse("java.exe"), , 1))
        commandStr = """" & javaPathStr & """" & " -version"
        Set javaVersionOutput = GetCommandOutput(commandStr)
        javaVersionStr = javaVersionOutput.item(1)

        Debug.Print "Getting java version: ", commandStr
        Debug.Print "Version detected: "; javaVersionStr

        Set javaVersionElements = SplitOnDelimiter(javaVersionStr, " ")

        'Check that output is not an error or something else
        'java version "1.8.0_75"
        If javaVersionElements.Count > 2 Then
            If StrComp(javaVersionElements.item(1), "java", vbTextCompare) = 0 Then
                If StrComp(javaVersionElements.item(2), "version", vbTextCompare) = 0 Then
                    detectedJavaVersions.Add javaVersionStr
                    'Remove quotes from "1.8.0_75", split on '.', get 2nd item (java major version) and cast it to Integer
                    javaMajorVersionInt = CInt(SplitOnDelimiter(SplitOnDelimiter(javaVersionElements.item(3), """").item(1), ".").item(2))
                    'JAR will only run in Java 8 or later
                    If (javaMajorVersionInt >= javaMinimumMajorVersionInt) Then
                        'Validate that "javaw.exe" exists since the validation was made with "java.exe"
                        Debug.Print "Verifying if javaw.exe exists: ", javawPathVar
                        If Len(Dir(javawPathVar)) > 0 Then
                            suitableJavawPath = javawPathVar
                            Debug.Print "A suitable javaw.exe version found: ", suitableJavawPath
                            Exit For
                        End If
                    End If
                End If
            End If
        End If
    Next javawPathVar

    GetMinimumJavaVersion = suitableJavawPath

End Function

Private Function GetCommandOutput(ByRef commandStr As String) As Collection

    'Run a shell command, returning the output as a string
    Dim shellObj As Object
    Set shellObj = CreateObject("WScript.Shell")

    'run command
    Dim wshScriptExecObj As Object
    Dim stdOutObj As Object
    Dim stdErrObj As Object
    Set wshScriptExecObj = shellObj.Exec(commandStr)
    Set stdOutObj = wshScriptExecObj.StdOut
    Set stdErrObj = wshScriptExecObj.StdErr

    'handle the results as they are written to and read from the StdOut object
    Dim fullOutputCollection As Collection
    Set fullOutputCollection = New Collection

    Dim lineStr As String
    While Not stdOutObj.AtEndOfStream
        lineStr = stdOutObj.ReadLine
        If lineStr <> "" Then
            fullOutputCollection.Add lineStr
        End If
    Wend

    If fullOutputCollection.Count = 0 Then
        While Not stdErrObj.AtEndOfStream
            lineStr = stdErrObj.ReadLine
            If lineStr <> "" Then
                fullOutputCollection.Add lineStr
            End If
        Wend
    End If



    Set GetCommandOutput = fullOutputCollection

End Function
0 голосов
/ 24 октября 2018

Обычно устанавливается переменная окружения JAVA_HOME.Если это так, то вы можете сделать что-то вроде этого:

Dim JavaExe As String
JavaExe = """" & Environ("JAVA_HOME") & "\bin\java.exe"""
handleDbl = Shell("cmd /k " & JavaExe & " -cp theJar.jar com.java.SampleClass", vbNormalFocus)

Если оно не установлено, вам нужно будет найти его путем некоторого поиска, прежде чем скомпилировать команду.

...