【问题标题】:Java-Application: Execute Batch File with subprocess / UNC PathJava-应用程序:使用子进程/UNC 路径执行批处理文件
【发布时间】:2012-07-30 12:12:00
【问题描述】:

我想在我的 java 应用程序中执行一个批处理文件。

我想这样执行:

   String[] args = new String[] {
                    "C:/Users/User1/Desktop/Bachelor Thesis/JDBC Connector/jdbc_5.2_sp1_patch05/bin/connect.bat",
                    "start",
                    "-f",
                    "C:/Users/User1/Content-Integration Testing Framework/JDBC Connector/etc/db.xml" };

Process p = Runtime.getRuntime().exec(args);
p.waitFor();

            BufferedReader prout = new BufferedReader(new InputStreamReader(p.getErrorStream()));
            String buffer;
            while ((buffer = prout.readLine()) != null) {
                System.out.println(buffer);
                buffer = prout.readLine();
            }

解释:
让我们考虑一下我会使用正常的 cmd 执行。我会打开cmd,然后我会去我的目录:

cd C:/Users/User1/Desktop/Bachelor Thesis/JDBC Connector/jdbc_5.2_sp1_patch05/bin

Afterwars 我将使用以下命令启动批处理文件:

connect start -f C:/Users/User1/Content-Integration Testing Framework/JDBC Connector/etc/db.xml

在命令行上这工作正常,它启动批处理,在这个批处理中有一个子进程正在启动:

if exist %JAVA_HOME%\bin\java.exe (
java -XX:NewSize=%NEWSIZE% -XX:NewRatio=1 -Xms%MAXHEAP% -Xmx%MAXHEAP% -Dfile.encoding=%ENCODING% -Djava.ext.dirs=%EXT_DIR% com.fastsearch.esp.connectors.jdbc.JDBCConnector %1 %2 %3 %4 %5 %6 %7
) else (echo Is JAVA_HOME=%JAVA_HOME% set correctly?)

但是在我的 Java 应用程序中执行时,我遇到了以下问题: 它只打印我的批处理文件的第一个回显,但子进程没有启动。当我捕捉到错误流(如上面的代码所示)时,它说:

UNC-Pfade werden nicht unterstützt. (UNC-Paths are not supported)
java.lang.NoClassDefFoundError: com/fastsearch/esp/connectors/jdbc/JDBCConnector

经过一番研究,我发现由于当前工作目录或类似的原因,cmd 无法启动子进程。我不是很明白。

实际情况是,我想在我的 Java 应用程序中执行带有必要参数(开始、-f 和路径)的批处理文件。当我直接在 cmd 上执行语句时,一切正常,但在我的 java 应用程序中它很糟糕。

这是完整的批处理文件,也许这会有所帮助:

@echo off
rem This bat file should setup the java env and run the connector manager
SETLOCAL

echo Copyright (c) Microsoft Corporation.  All rights reserved.

rem !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
rem Java 1.6 must be installed and set here
rem !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

if NOT defined JAVA_HOME (
   echo Sorry..
   echo You have NOT set JAVA_HOME - Should point to where JRE 1.6.x or later is installed
   echo Exiting.......
   goto end
)
set JAVA_HOME=%JAVA_HOME%
:: Remove quotes if exist, then add quotes in case spaces
SET JAVA_HOME=###%JAVA_HOME%###
SET JAVA_HOME=%JAVA_HOME:"###=%
SET JAVA_HOME=%JAVA_HOME:###"=%
SET JAVA_HOME=%JAVA_HOME:###=%
SET JAVA_HOME="%JAVA_HOME%"

SET PATH=%JAVA_HOME%\bin
SET EXT_DIR=..\lib;%JAVA_HOME%\lib;%JAVA_HOME%\lib\ext
SET CLASSPATH=..\etc
SET MAXHEAP=1408m
SET NEWSIZE=256m
SET ENCODING=UTF8

if exist %JAVA_HOME%\bin\java.exe (
java -XX:NewSize=%NEWSIZE% -XX:NewRatio=1 -Xms%MAXHEAP% -Xmx%MAXHEAP% -Dfile.encoding=%ENCODING% -Djava.ext.dirs=%EXT_DIR% com.fastsearch.esp.connectors.jdbc.JDBCConnector %1 %2 %3 %4 %5 %6 %7
) else (echo Is JAVA_HOME=%JAVA_HOME% set correctly?)

:end

【问题讨论】:

    标签: java batch-file subprocess execute unc


    【解决方案1】:

    正如您所提到的,您的问题很可能是您没有从正确的目录执行批处理文件。当您打开命令行控制台并 cd 进入包含批处理文件的目录时,该操作会设置正确的 current working directory (CWD)。

    您可以通过在输入批处理文件之前或之后更改 CWD 来解决它。


    让我们从批处理文件中的 CWD 开始;我们在这里也有很多选择,但让我们保持简单,只需更改 CWD:

    set MYDIR=%~dp0
    cd %MYDIR%
    

    第一行使用了一些批处理文件魔法来获取当前正在执行的批处理文件所在的目录。那将是“C:/Users/User1/Desktop/Bachelor Thesis/JDBC Connector/jdbc_5.2_sp1_patch05/bin/”

    另类

    您可以使用 Runtime.getRuntime().exec() 的替代形式来更改 CWD:
    Runtime.getRuntime().exec(String[] cmdarray, String[] envp, File dir)

    调用为:

    File workingDir = new File("C:/Users/User1/Desktop/Bachelor Thesis/JDBC Connector/jdbc_5.2_sp1_patch05/bin/");
    Runtime.getRuntime().exec(args, null, workingDir);
    

    我强烈建议您为您的工作目录声明一个 static final const 值,或者找到一些方法来消除程序中该值的硬编码。

    【讨论】:

    • 首先我要感谢您的回答。我会在几分钟/几小时内尝试这个,然后我会给出反馈。但这对我来说很清楚。
    • 我尝试了以下方法:static final String workingdirectory = "C:/Users/User1/Desktop/Bachelor Thesis/JDBC Connector/jdbc_5.2_sp1_patch05/bin/"; String[] args3 = new String[] { "connect.bat", "-h" }; File workingDir = new File(workingdirectory); Runtime.exec(args3, null, workingDir); 但在最后一行代码变红并告诉我:不能对非静态方法 exec 进行静态引用跨度>
    • 尝试使用 Runtime.getRuntime().exec 而不是 Runtime.exec,就像原来的那样。
    • 好吧,对不起,那是我的错。但它又应该如何...还有另一个错误:Cannot run program "connect.bat" (in directory "C:\Users\User1\Desktop\Bachelor Thesis\JDBC Connector\jdbc_5.2_sp1_patch05\bin"): CreateProcess error=2, Das System kann die angegebene Datei nicht finden 我检查了 5 次路径,它必须是正确的,但 java 没有找到它。我也尝试了你的第一个替代方案,只是将这两行代码放在我的批处理文件中,但仍然存在不支持 UNC-Paths 的错误。我只是不明白为什么它不起作用:(
    • 1.您可以在正确的目录中启动 cmd.exe 吗? 2.我看到Cannot run program "connect.bat",没有全限定路径;您是否从 connect.bat 前面为 String[0] 删除了完整路径? - 继续,将其保留在 String[0] 上。
    【解决方案2】:

    我想现在把正确答案写下来作为总结。但我不得不提一下,这是 Richard Sitze 的想法,而不是我的。

    static final String workingdirectory = "C:/Users/User1/Desktop/Bachelor Thesis/JDBC Connector/jdbc_5.2_sp1_patch05/bin"; 
        String[] args = new String[] {"C:/Users/User1/Desktop/Bachelor Thesis/JDBC Connector/jdbc_5.2_sp1_patch05/bin/connect.bat",
                "start",
                "-f",
                "C:/Users/User1/Content-Integration Testing Framework/JDBC Connector/etc/db.xml" };
        Process p = Runtime.getRuntime().exec(args2, null, workingDir);
        BufferedReader prout = new BufferedReader(new InputStreamReader(p.getInputStream()));
                    String buffer;
                    while ((buffer = prout.readLine()) != null) {
                        System.out.println(buffer);
                        buffer = prout.readLine();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-10-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-09-13
      • 1970-01-01
      • 2012-01-25
      相关资源
      最近更新 更多