Java InvocationTargetException и недопустимые ошибки доступа к памяти

У меня есть Java-программа (обернутая в exe), которая запускает другую основную Java-программу (также обернутую в exe), которая имеет манифест администратора. Из-за манифеста администратора я использую сценарий Shell32X для взаимодействия с приглашением UAC для запуска основной программы.

Вот скрипт Shell32X:

import java.util.Arrays;
import java.util.List;

import com.sun.jna.Native;
import com.sun.jna.Pointer;
import com.sun.jna.Structure;
import com.sun.jna.WString;
import com.sun.jna.platform.win32.Shell32;
import com.sun.jna.platform.win32.WinDef.HINSTANCE;
import com.sun.jna.platform.win32.WinDef.HWND;
import com.sun.jna.platform.win32.WinNT.HANDLE;
import com.sun.jna.platform.win32.WinReg.HKEY;
import com.sun.jna.win32.W32APIOptions;

public interface Shell32X extends Shell32
{
    Shell32X INSTANCE = (Shell32X)Native.loadLibrary("shell32", Shell32X.class, W32APIOptions.UNICODE_OPTIONS);

    int SW_HIDE = 0;
    int SW_MAXIMIZE = 3;
    int SW_MINIMIZE = 6;
    int SW_RESTORE = 9;
    int SW_SHOW = 5;
    int SW_SHOWDEFAULT = 10;
    int SW_SHOWMAXIMIZED = 3;
    int SW_SHOWMINIMIZED = 2;
    int SW_SHOWMINNOACTIVE = 7;
    int SW_SHOWNA = 8;
    int SW_SHOWNOACTIVATE = 4;
    int SW_SHOWNORMAL = 1;

    /** File not found. */
    int SE_ERR_FNF = 2;

    /** Path not found. */
    int SE_ERR_PNF = 3;

    /** Access denied. */
    int SE_ERR_ACCESSDENIED = 5;

    /** Out of memory. */
    int SE_ERR_OOM = 8;

    /** DLL not found. */
    int SE_ERR_DLLNOTFOUND = 32;

    /** Cannot share an open file. */
    int SE_ERR_SHARE = 26;



    int SEE_MASK_NOCLOSEPROCESS = 0x00000040;


    int ShellExecute(int i, String lpVerb, String lpFile, String lpParameters, String lpDirectory, int nShow);
    boolean ShellExecuteEx(SHELLEXECUTEINFO lpExecInfo);



    public static class SHELLEXECUTEINFO extends Structure
    {
        /*
         * DWORD     cbSize;
         * ULONG     fMask;
         * HWND      hwnd;
         * LPCTSTR   lpVerb;
         * LPCTSTR   lpFile;
         * LPCTSTR   lpParameters;
         * LPCTSTR   lpDirectory;
         * int       nShow;
         * HINSTANCE hInstApp;
         * LPVOID    lpIDList;
         * LPCTSTR   lpClass;
         * HKEY      hkeyClass;
         * DWORD     dwHotKey;
         * union {
         *  HANDLE hIcon;
         *  HANDLE hMonitor;
         * } DUMMYUNIONNAME;
         * HANDLE    hProcess;
         */

        public int cbSize = size();
        public int dwHotKey;
        public int fMask;
        public HINSTANCE hInstApp;
        public HKEY hKeyClass;
        public HANDLE hMonitor;
        public HANDLE hProcess;
        public HWND hwnd;
        public WString lpClass;
        public WString lpDirectory;
        public WString lpFile;
        public Pointer lpIDList;
        public WString lpParameters;
        public WString lpVerb;
        public int nShow;




        /*
         * Actually:
         * union {
         *  HANDLE hIcon;
         *  HANDLE hMonitor;
         * } DUMMYUNIONNAME;
         */


        @SuppressWarnings({ "unchecked", "rawtypes" })
        protected List getFieldOrder() {
            return Arrays.asList(new String[] {
                "cbSize", 
                "dwHotKey",
                "fMask", 
                "hInstApp",
                "hKeyClass", 
                "hMonitor", 
                "hProcess",
                "hwnd", 
                "lpClass",
                "lpDirectory",
                "lpFile", 
                "lpIDList", 
                "lpParameters",
                "lpVerb", 
                "nShow"
            });
        }
    }
}

Вот код в программе запуска, которая вызывает приглашение UAC и запускает основную программу:

public static void main(String[] args) 
            throws IOException, InterruptedException, InvocationTargetException {
    call("MainProgram.exe", "");
}

public static void call(String command, String args) throws InvocationTargetException
    {
        lock.lock();
        try {
            Shell32X.SHELLEXECUTEINFO execInfo = new Shell32X.SHELLEXECUTEINFO();
            execInfo.lpFile = new WString(command);

            if (args != null) {
                execInfo.lpParameters = new WString(args);
            }
            execInfo.nShow = Shell32X.SW_SHOWDEFAULT;
            execInfo.fMask = Shell32X.SEE_MASK_NOCLOSEPROCESS;
            execInfo.lpVerb = new WString("runas");
            boolean result = Shell32X.INSTANCE.ShellExecuteEx(execInfo);

            if (!result) {
                int lastError = Kernel32.INSTANCE.GetLastError();
                String errorMessage = Kernel32Util.formatMessageFromLastErrorCode(lastError);
                throw new RuntimeException("Error performing elevation: " + lastError + ": " + errorMessage + " (apperror=" + execInfo.hInstApp + ")");
            }
        } finally {
            lock.unlock();
        }
        return;
    }

(игнорировать lock(), это связано с чем-то другим)

Программа запуска должна взаимодействовать с приглашением UAC и вызывать основную программу.
Когда я запутываю код, основная программа работает нормально, а программа запуска работает нормально, ЗА ИСКЛЮЧЕНИЕМ приглашения UAC не появляется и основная программа не вызывается.
Я экспортирую в качестве работающей фляги и с необходимыми библиотеками, упакованными в флягу. Я использую ProGuard, чтобы запутать банки и Launch4j, чтобы обернуть банки в exe.

Это ошибка, которую я получаю при запуске программы запуска:

Exception in thread "main" java.lang.reflect.InvocationTargetException
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
        at java.lang.reflect.Method.invoke(Unknown Source)
        at org.eclipse.jdt.internal.jarinjarloader.JarRsrcLoader.main(Unknown Source)
Caused by: java.lang.Error: Invalid memory access
        at com.sun.jna.Native.getWideString(Native Method)
        at com.sun.jna.Pointer.getWideString(Pointer.java:685)
        at com.sun.jna.Pointer.getValue(Pointer.java:414)
        at com.sun.jna.Structure.readField(Structure.java:720)
        at com.sun.jna.Structure.read(Structure.java:580)
        at com.sun.jna.Structure.autoRead(Structure.java:2074)
        at com.sun.jna.Function.invoke(Function.java:374)
        at com.sun.jna.Library$Handler.invoke(Library.java:244)
        at com.sun.proxy.$Proxy0.ShellExecuteEx(Unknown Source)
        at launcher.Launcher.call(Unknown Source)
        at launcher.Launcher.main(Unknown Source)
        ... 5 more

Я исследовал это в течение 3 дней, и я до сих пор не знаю, что это значит или как это исправить. Пожалуйста, помогите мне.

ОБНОВИТЬ:

Я добавил исключение InvocationTargetException в мой метод call(). Это новое сообщение об ошибке:

java.lang.Error: Structure.getFieldOrder() on class launcher.Shell32X$SHELLEXECUTEINFO does not provide enough names [15] ([cbSize, dwHotKey, fMask, hInstApp, hKeyClass, hMonitor, hProcess, hwnd, lpClass, lpDirectory, lpFile, lpIDList, lpParameters, lpVerb, nShow]) to match declared fields [6] ([fMask, hInstApp, lpFile, lpParameters, lpVerb, nShow])

0 ответов

Другие вопросы по тегам