Похоже, что его довольно легко решить, но я недостаточно разбираюсь в использовании пакетных файлов для его решения самостоятельно. У меня есть Java-метод, который создает построитель процессов и запускает пакетный файл в процессе. Командный файл использует команду xcopy для копирования одного каталога в другой. Пока командный файл работает в фоновом режиме, окно Java, содержащее JTextArea, отображает вывод процесса (копируемые каталоги). Окно также имеет кнопку остановки, которая вызывает следующий код:Процесс пакетного файла, убитый в Java: xcopy не закрывается
stopped = true;
backgroundTask.cancel(true);
backgroundTask.done();
сделано метод выглядит следующим образом:
protected void done() {
statusLabel.setText((this.getState()).toString() + " " + status);
stopButton.setEnabled(false);
bar.setIndeterminate(false);
if(stopped == false){
JOptionPane.showMessageDialog(null, "Backup Complete.");
closeWindow();
}
else if (stopped == true){
JOptionPane.showMessageDialog(null, "Backup Cancelled.");
closeWindow();
}
}
Теперь для того, чтобы запустить пакетный файл в фоновом режиме, я использую следующий код (первоначально предложил мне trashgod):
protected Integer doInBackground() throws IOException {
try {
ProcessBuilder pb = new ProcessBuilder(commands);
pb.redirectErrorStream(true);
Process p = pb.start();
String s;
BufferedReader stdout = new BufferedReader(
new InputStreamReader(p.getInputStream()));
while ((s = stdout.readLine()) != null && !isCancelled()) {
publish(s);
}
if (!isCancelled()) {
status = p.waitFor();
}
p.getInputStream().close();
p.getOutputStream().close();
p.getErrorStream().close();
p.destroy();
closeWindow();
} catch (IOException | InterruptedException ex) {
ex.printStackTrace(System.err);
}
return status;
}
проблема, которую я имею это: Когда я запускаю программу, файлы копировать только штраф, если я не нажать кнопку остановки на иллюминатор На переднем плане. Когда я, что он говорит мне резервная копия была отменена (как предполагается), но оставляет три дополнительных процессов, выполняющихся, которые видны в диспетчере задач:
Я предполагаю, что первый - «расширенная утилита копирования» является виновником. Поскольку он не закрывается, он оставляет другие два процесса cmd. Однако это довольно необразованная догадка.
Когда я запускаю программу, а затем останавливаю ее, проводник Windows становится очень нестабильным, иногда зависающим, а иногда и сбоем. Навигация по папкам - особенно с копиями каталогов - очень медленный, и кажется, что каталоги продолжают копироваться даже после того, как процесс (предположительно) остановлен. Я считаю, что это потому, что эти линии никогда не достигались:
p.getInputStream().close();
p.getOutputStream().close();
p.getErrorStream().close();
p.destroy();
так что процесс никогда не был убит. Я все еще работаю над тем, чтобы полностью уничтожить процессы, когда нажата кнопка остановки, но если у кого-то есть мысли, я бы с радостью их услышал!
EDIT
Я решил опубликовать весь класс, поскольку только дает определенные методы, вероятно, не дает достаточной информации. Вот весь класс:
package diana;
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.Toolkit;
import java.awt.event.*;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.List;
import javax.swing.*;
@SuppressWarnings("serial")
public class Progress extends JFrame {
public String[] commands;
private final JLabel statusLabel = new JLabel("Status: ", JLabel.CENTER);
private final JTextArea textArea = new JTextArea(20, 20);
private JButton stopButton = new JButton("Stop");
private JProgressBar bar = new JProgressBar();
private BackgroundTask backgroundTask;
private ProcessBuilder pb;
private Process p;
public boolean stopped = false;
public void setCommands(String[] cmds) {
commands = cmds;
}
private final ActionListener buttonActions = new ActionListener() {
@Override
public void actionPerformed(ActionEvent ae) {
JButton source = (JButton) ae.getSource();
if (source == stopButton) {
stopped = true;
backgroundTask.cancel(true);
backgroundTask.done();
} else {
backgroundTask = new BackgroundTask(commands);
}
}
};
private void displayGUI(String[] cmds) {
commands = cmds;
JFrame frame = new JFrame("Backup Progress");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
JPanel panel = new JPanel();
panel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
panel.setLayout(new BorderLayout(5, 5));
JScrollPane sp = new JScrollPane();
sp.setBorder(BorderFactory.createTitledBorder("Output: "));
sp.setViewportView(textArea);
textArea.setText(null);
stopButton.setEnabled(true);
backgroundTask = new BackgroundTask(commands);
backgroundTask.execute();
bar.setIndeterminate(true);
stopButton.addActionListener(buttonActions);
JPanel buttonPanel = new JPanel();
buttonPanel.add(stopButton);
buttonPanel.add(bar);
panel.add(statusLabel, BorderLayout.PAGE_START);
panel.add(sp, BorderLayout.CENTER);
panel.add(buttonPanel, BorderLayout.PAGE_END);
frame.setContentPane(panel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
/* Close current window */
public void closeWindow() throws IOException {
p.getInputStream().close();
p.getOutputStream().close();
p.getErrorStream().close();
p.destroy();
WindowEvent close = new WindowEvent(this, WindowEvent.WINDOW_CLOSING);
Toolkit.getDefaultToolkit().getSystemEventQueue().postEvent(close);
System.exit(0);
}
private class BackgroundTask extends SwingWorker<Integer, String> {
private int status;
public String[] commands;
public BackgroundTask(String[] cmds) {
commands = cmds;
statusLabel.setText((this.getState()).toString());
}
@Override
protected Integer doInBackground() throws IOException {
try {
pb = new ProcessBuilder(commands);
pb.redirectErrorStream(true);
p = pb.start();
String s;
BufferedReader stdout = new BufferedReader(
new InputStreamReader(p.getInputStream()));
while ((s = stdout.readLine()) != null && !isCancelled()) {
publish(s);
}
if (!isCancelled()) {
status = p.waitFor();
}
closeWindow();
} catch (IOException | InterruptedException ex) {
ex.printStackTrace(System.err);
}
return status;
}
@Override
protected void process(List<String> messages) {
statusLabel.setText((this.getState()).toString());
for (String message : messages) {
textArea.append(message + "\n");
}
}
@Override
protected void done() {
statusLabel.setText((this.getState()).toString() + " " + status);
stopButton.setEnabled(false);
bar.setIndeterminate(false);
if (stopped == false) {
JOptionPane.showMessageDialog(null, "Backup Complete.");
try {
closeWindow();
} catch (IOException e) {
e.printStackTrace();
}
} else if (stopped == true) {
JOptionPane.showMessageDialog(null, "Backup Cancelled.");
try {
closeWindow();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
public void run(String[] cmds) {
commands = cmds;
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
new Progress().displayGUI(commands);
}
});
}
}
Еще раз, я не могу взять кредит на этот код, как это в основном обеспечивается SO члена trashgod. Кроме того, пожалуйста, извините за любые заявления, оставленные там для отладки, которые я, возможно, забыл удалить.
Это хороший момент. Я надеялся, что существует способ фактически полностью уничтожить весь процесс с Java. Думаю, мы это увидим. – DerStrom8