【发布时间】:2014-05-12 06:48:48
【问题描述】:
我的电脑在 Windows7 64 位下运行,我有一个实用程序(.exe,非常旧的 [~WinXP 时代],没有可用的资源),我想从部署到 Jetty 的 java 代码中调用它。 如果我从控制台启动实用程序,我不会收到任何错误。如果我通过简单的 java 包装器启动实用程序:
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");
}
}
我也没有错误。 但如果我从 WAR I 中调用此代码(比 Runtime.getRuntime().exec("util.exe") 复杂一点,因为我需要计算二进制文件的绝对路径)获取带有以下消息的 IOException:
CreateProcess 错误=216,此版本的 %1 与您正在运行的 Windows 版本不兼容。检查您计算机的系统信息,看看您是否需要 x86(32 位)或 x64(64 位)版本的程序,然后联系软件发行商
我尝试使用 -d32 选项启动码头,尝试将不同版本的 java(JRE/JDK,均为 6/7,均为 32/64 位)放入 JAVA_HOME 和 PATH 中,但没有成功。
有没有人遇到过类似的问题?有办法解决吗?
[更新] 我附上了一些服务器代码。 CommandLine 和 FileUtils 是 Apache Commons 的一部分。 ApplicationContext 与 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
}
【问题讨论】:
-
如果您在两种情况下都启动相同的可执行文件,无论是简单的还是复杂的,问题应该出在其他地方。您是否检查过代码是否构建了正确的启动/执行字符串,是否有机会发布完整代码而不是简单示例?
-
附上源码,请看。可执行文件是 100% 相同的。尽管路径中有许多“\\\\”,但最终字符串看起来不错——它们将被截断为 \\。反正报错信息不代表路径不对,但环境可能是……
-
我问是因为如果可执行文件相同,我怀疑整个表达式可能会评估为您的 util 以外的其他内容,从而导致该错误。顺便说一句,如果您使用的是
commons-exec,为什么不一直使用new DefaultExecutor().execute(command);?这会使用cmd /c生成您的命令 -
是的,我试过 DefaultExecutor。不幸的是,它没有任何区别。结果是一样的。
标签: java windows 32bit-64bit servlet-container