【问题标题】:Run a command via Runtime.exec from java code inside Web Archive (WAR deployed in Jetty)通过 Runtime.exec 从 Web Archive 中的 java 代码运行命令(WAR 部署在 Jetty 中)
【发布时间】: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 的一部分。 ApplicationContextSpring 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


【解决方案1】:

对我和我的注意力不集中感到羞耻。问题实际上出在“其他地方”。 WAR 是由 maven 构建的,并且可执行文件像任何其他资源一样被处理,因此校验和与原始文件相比是不同的。我从过滤中排除了 exe 文件(在 pom.xml 中),它开始正常工作。

【讨论】:

  • 谢谢,你拯救了我的一天;)
猜你喜欢
  • 1970-01-01
  • 2019-06-25
  • 2012-01-18
  • 2010-09-13
  • 2015-10-26
  • 1970-01-01
  • 2011-10-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多