My PC in running under Windows7 64 bit, and I have an utility (.exe, very legacy [~WinXP age], no sources available) that I'd like to invoke from java code deployed into Jetty. If I launch utility from console I get no errors. If I launch utility via simple java wrapper:
import java.util.*;
import java.io.*;
public class Wrapper {
public static void main(String[] args) throws IOException {
System.out.println(System.getProperty("java.version"));
Runtime.getRuntime().exec("util.exe -opt1 -opt2");
}
}
I get no errors as well. But in case I invoke this code (a bit more complex than Runtime.getRuntime().exec("util.exe") because I need to calculate absolute path to the binary file) from inside WAR I get IOException with following message:
CreateProcess error=216, This version of %1 is not compatible with the version of Windows you're running. Check your computer's system information to see whether you need a x86 (32-bit) or x64 (64-bit) version of the program, and then contact the software publisher
I've tried to launch jetty with -d32 option, tried to put different versions of java (both JRE/JDK, both 6/7, both 32/64 bit) into JAVA_HOME and PATH — and haven't succeed.
Did anyone face similar issues? Is it possible to resolve them?
[UPDATED] I've attached some server-code. CommandLine & FileUtils are part of Apache Commons. ApplicationContext relates to Spring Framework.
public class ImageLoader implements ApplicationContextAware {
private final static String UTIL_EXECUTABLE = "util.exe";
private final static String TEMP_FILE_PREFIX = "tmpFilePrefix";
private ApplicationContext applicationContext;
private File binaryPath;
@PostConstruct
public void init() throws Exception {
if (applicationContext instanceof WebApplicationContext) {
Resource binaryRoot = applicationContext.getResource(
"WEB-INF/classes/executable");
this.binaryPath = binaryRoot.getFile();
}
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
/**
* Download db image from device.
*/
public byte[] downloadImage(Device device) throws LoaderException {
try {
File file = downloadWindows(device);
return FileUtils.readFileToByteArray(file);
} catch (Exception ex) {
throw new LoaderException("Error downloading file: " + ex.getMessage(), ex);
}
}
private File downloadWindows(final Device device) throws Exception {
File tmpFile = File.createTempFile(TEMP_FILE_PREFIX, null);
CommandLine command = generateCommand(ActionType.download, tmpFile, device.getTargetIP(), "user", "pass");
Runtime.getRuntime().exec(command.toString());
return tmpFile;
}
protected CommandLine generateCommand(ActionType actionType, File file, String targetIP, String userName, String userPassword) throws IOException {
String bin = this.binaryPath.getPath() + "\\" + UTIL_EXECUTABLE;
// safe to use \\ because code only runs if WAR deployed under Windows
CommandLine commandLine = new CommandLine(bin.replace("\\", "\\\\"));
commandLine.addArgument(actionType.name());
commandLine.addArgument(file.getAbsolutePath().replace("\\", "\\\\"));
commandLine.addArgument(targetIP);
commandLine.addArgument(userName);
commandLine.addArgument(userPassword);
return commandLine;
}
}
enum ActionType {
download,
upload
}
Shame on me and my inattention. The problem actually was "elsewhere". The WAR was built by maven and the executable was processed like any other resource, so checksum was different in compare to original file. I excluded exe-files from filteing (in pom.xml) and it began to work correct.