2016-11-11 5 views
1

У меня есть приложение, которое использует JNA для выполнения любого другого приложения с использованием CreateProcess api. Это работает очень хорошо, но когда мне нужно выполнить 32-разрядную версию собственного приложения для системы, выполняется 64-разрядная версия (присутствует в папке SysWOW64), например: notepad.exe 64 бит.JNA: Как использовать CreateProcess для выполнения 32-разрядной версии системного родного приложения в 64-битных системах?

Итак, существует какой-то способ решить эту проблему?

Я пробовал использовать Wow64DisableWow64FsRedirection, но, похоже, не работает.

enter image description here

Мой код:

Execute класс:

import com.sun.jna.Native; 
import com.sun.jna.Pointer; 
import com.sun.jna.Structure; 
import com.sun.jna.WString; 
import static com.sun.jna.platform.win32.WinBase.STARTF_USESHOWWINDOW; 
import static com.sun.jna.platform.win32.WinUser.SW_HIDE; 
import com.sun.jna.win32.StdCallLibrary; 
import java.util.Arrays; 
import java.util.List; 


public class Execute { 

    public interface Kernel32 extends StdCallLibrary { 
    Kernel32 INSTANCE = (Kernel32) Native.loadLibrary("kernel32", Kernel32.class); 

    boolean CreateProcessA(
      String lpApplicationName 
      , String lpCommandLine 
      , Structure lpProcessAttributes 
      , Structure lpThreadAttributes 
      , boolean bInheritHandles 
      , int dwCreationFlags 
      , Structure lpEnvironment 
      , String lpCurrentDirectory 
      , Structure lpStartupInfo 
      , Structure lpProcessInformation); 
} 

public static class ProcessInformation extends Structure { 
    public Pointer hProcess; 
    public Pointer hThread; 
    public int dwProcessId; 
    public int dwThreadId; 

     @Override 
     protected List getFieldOrder() { 
     return Arrays.asList(new String[] { "hProcess", "hThread", "dwProcessId", "dwThreadId" }); 
    } 
    } 

public static class StartupInfoA extends Structure { 
    public int cb; 
    public WString lpReserved; 
    public WString lpDesktop; 
    public WString lpTitle; 
    public int dwX; 
    public int dwY; 
    public int dwXSize; 
    public int dwYSize; 
    public int dwXCountChars; 
    public int dwYCountChars; 
    public int dwFillAttribute; 
    public int dwFlags; 
    public short wShowWindow; 
    public short cbReserved2; 
    public Pointer lpReserved2; 
    public Pointer hStdInput; 
    public Pointer hStdOutput; 
    public Pointer hStdError; 

     @Override 
     protected List getFieldOrder() { 
     return Arrays.asList(new String[] { "cb", "lpReserved", "lpDesktop", "lpTitle", "dwX", "dwY", "dwXSize", "dwYSize", "dwXCountChars", "dwYCountChars", "dwFillAttribute", "dwFlags", "wShowWindow", "cbReserved2", "lpReserved2", "hStdInput", "hStdOutput", "hStdError" }); 
    } 
    } 

public static void ExecuteProc(String software){ 

     ProcessInformation processInformation = new ProcessInformation(); 
     StartupInfoA startupInfo = new StartupInfoA(); 
     startupInfo.dwFlags = STARTF_USESHOWWINDOW; 
     startupInfo.wShowWindow = SW_HIDE; 

     Kernel32.INSTANCE.CreateProcessA(software, null 
       , null 
       , null 
       , true 
       , 0 
       , null 
       , "C:\\Windows\\System32\\" 
       , startupInfo 
       , processInformation); 
    } 

} 

Main:

public static native boolean Wow64DisableWow64FsRedirection(PointerByReference OldValue); 

public static void Exec() { 

     PointerByReference lpBuffer = new PointerByReference(); 

     Wow64DisableWow64FsRedirection(lpBuffer); // fails here 

     String sysdir = System.getenv("WINDIR") + "\\System32\\"; 
     ExecuteProc(sysdir + "notepad.exe"); 

} 
+1

Вы должны использовать 32-битную версию JRE для выполнения 32-битного кода в 64-битных операционных системах. –

ответ

0

--- Обновлено, потому что Windows хорошо, Windows ---

32-разрядные исполняемые файлы находятся в SysWOW64, а 64-разрядные исполняемые файлы находятся в System32. По-видимому, этот странный выбор имеет смысл для людей в Редмонде.

--- Остальной поста следует, с обновлениями ---

Вы спрашиваете 64 разрядную программу для загрузки и интерфейс с 32-битными исполняемыми. «Совместимость» для 32-битных исполняемых файлов не распространяется на их связывание с 64-битными программами.

Вам необходимо запустить 32-битную JVM, чтобы интерфейс JNI соответствовал требуемой среде.

Однако ваш пример может даже не нуждаться в JNI. Если вы запускаете 32-битные автономные программы, вам не нужно использовать JNI. Вместо этого вы можете использовать ProcessBuilder и передать аргументы командной строки оболочке, чтобы эффективно обеспечить запуск 32-битного исполняемого файла.

ProcessBuilder pb = new ProcessBuider(String.format("%s\\SysWOW64\\notepad.exe", System.getEnv("WINDIR")); 
Process process = pb.start(); 

JNI для когда вам нужно связать JVM для собственных библиотек, это не является предпочтительным способом запуска собственных приложений. ProcessBuilder - это то, что вы предпочитаете запускать собственные приложения.

+0

ваше предложение все еще выполняет 64-разрядную версию «notepad.exe» :-( – Saulo

+0

@Saulo По-видимому, 32-разрядные исполняемые файлы не хранятся в System32, а в SysWOW64. Это соглашение об именах, которое любили бы только программисты в Редмонде. –

+1

имеет смысл с чисто технической точки зрения, за то, что мало что стоит. (Плюс изменение названия системной папки Windows NT, вероятно, вызвало бы всевозможные проблемы с обратной совместимостью.) –

1

Это может быть неприемлемо для вашей настройки в зависимости от ваших потребностей, но у меня возникла эта проблема, когда мы перешли в 64-разрядную операционную систему для нашего терминального сервера, и у нас была собственная Java-приложение, которое требовало правильной работы 32-разрядной версии Java.

Мое решение было идти в 64-битном каталог Java, переименовывать java.exe и javaw.exe к java.exe.bak и javaw.exe.bak, соответственно, а затем заменить эти файлы с патрубками, которые начали в 32-разрядную версию Java вместо этого. Это было приемлемо в нашем случае, так как у нас есть только одно приложение, которое использует Java, и мы не предвидели сами писать больше никаких приложений в Java идти вперед:

// Stub file that launches the 32-bit java.exe 
// Intended to replace the 64-bit java executable to ensure that (OUR APPLICATION) which only works with 32-bit java works correctly 
// Author: Govind Parmar 

#include <Windows.h> 
#include <strsafe.h> 

HRESULT __cdecl cat_argv(int argc, WCHAR *argv[], WCHAR *argstr, int cchargstr) 
{ 
    int i; 
    HRESULT hr; 
    ZeroMemory(argstr, sizeof(WCHAR) * cchargstr); 

    // first arg is program name; start with i=1 instead of 0 
    for (i = 1; i < argc; i++) 
    { 
     // Space out arguments 
     hr = StringCchCat(argstr, cchargstr, L" "); 
     if (FAILED(hr)) break; 

     hr = StringCchCat(argstr, cchargstr, argv[i]); 
     if (FAILED(hr)) break; 

    } 
    return hr; 
} 

int __cdecl wmain(int argc, WCHAR *argv[]) 
{ 
    STARTUPINFO si; 
    PROCESS_INFORMATION pi; 
    WCHAR args[8192]; 
    DWORD dwExit; 
    ZeroMemory(&si, sizeof(STARTUPINFO)); 
    ZeroMemory(&pi, sizeof(PROCESS_INFORMATION)); 

    si.cb = sizeof(STARTUPINFO); 
    if (FAILED(cat_argv(argc, argv, args, 8192))) 
    { 
     _putws(L"Could not concatenate argument string!"); 
     return 0; 
    } 

    CreateProcess(L"C:\\Program Files (x86)\\Java\\jre1.8.0_101\\bin\\java.exe", args, NULL, NULL, FALSE, CREATE_UNICODE_ENVIRONMENT, NULL, L"C:\\Program Files (x86)\\Java\\jre1.8.0_101\\bin\\", &si, &pi); 

    WaitForSingleObject(pi.hProcess, INFINITE); 
    GetExitCodeProcess(pi.hProcess, &dwExit); 
    CloseHandle(pi.hProcess); 
    CloseHandle(pi.hThread); 
    return dwExit; 
} 
+2

Возможно, вы не смогли установить 64-разрядную версию, и установил 32-битную версию JRE для аналогичных результатов с более легким в обслуживании решением. –

+0

Теперь я хочу знать, если сегодня 32-разрядная версия JVM присутствует на большой части ПК (с установленной 32 или 64-битной системой). 64-битная система обычно представляет собой JVM 64 бит? – Saulo

+1

@Saulo жаль позднего ответа, но вы действительно не должны принимать решения на основе wh у вас * ожидать * найти на чьем-то компьютере; вы должны узнать, что они установили, а затем выполнить соответствующие действия для каждого варианта использования –