Java-приложение: выполнение пакетного файла с подпроцессом/путем UNC

Я хочу выполнить пакетный файл в своем 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

После этого я запускал пакетный файл с помощью следующей команды:

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 есть проблемы с запуском подпроцессов из-за текущего рабочего каталога или чего-то в этом роде. Я действительно этого не понимал.

Дело в том, что я хочу выполнить пакетный файл с его необходимыми параметрами (начало, -f и путь) в моем приложении Java. Когда я выполняю операторы непосредственно в 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

person Metalhead89    schedule 30.07.2012    source источник


Ответы (2)


Как вы уже упоминали, весьма вероятно, что ваша проблема заключается в том, что вы не выполняете командный файл из нужного каталога. Когда вы открываете консоль командной строки и 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 для вашего рабочего каталога или найти какой-нибудь способ устранить жесткое кодирование этого значения в вашей программе.

person Richard Sitze    schedule 30.07.2012
comment
Сначала хочу поблагодарить вас за ответ. Я попробую это через несколько минут / часов, а потом дам отзыв. Но звучит ясно для меня. - person Metalhead89; 31.07.2012
comment
Я пробовал следующее: 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 - person Metalhead89; 31.07.2012
comment
Попробуйте Runtime.getRuntime().exec вместо Runtime.exec, как в оригинале. - person Richard Sitze; 31.07.2012
comment
Хорошо, извините, это была моя вина. А как же быть иначе...там другая ошибка: 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-пути не поддерживаются. Я просто не понимаю, почему это не работает :( - person Metalhead89; 01.08.2012
comment
1. Можете ли вы запустить cmd.exe в правильном каталоге? 2. Я вижу Cannot run program "connect.bat" без полного пути; вы удалили полный путь перед connect.bat для String[0]? - продолжайте и оставьте его на String[0]. - person Richard Sitze; 01.08.2012
comment
ТЫ ОБАЛДЕННЫЙ!!! Вы спасли мою жизнь. С вашей помощью теперь все работает отлично. В качестве резюме я бы ответил на вопрос ниже, может быть, это кому-то нужно. Большое спасибо. - person Metalhead89; 02.08.2012

Я хотел бы записать правильный ответ сейчас в качестве резюме. Но я должен упомянуть, что это идея Ричарда Ситце, а не моя.

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();
            }
person Metalhead89    schedule 02.08.2012