這似乎應該很容易解決,但我不熟悉使用批處理文件來解決它自己。我有一個Java方法,它創建一個流程構建器並在流程中運行一個批處理文件。批處理文件使用xcopy命令將一個目錄複製到另一個目錄。當批處理文件在後臺運行時,包含JTextArea的Java窗口將顯示進程的輸出(正在複製的目錄)。該窗口也有一個停止按鈕,它調用下面的代碼:批處理文件進程在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();
所以這個過程永遠不會被殺死。當按下停止按鈕時,我仍然在努力完成殺死進程的任何方式,但如果有人有想法,我很樂意聽到他們的聲音!
編輯
我選擇發佈整個類,因爲只給某些方法可能不提供足夠的信息。這裏是整個班級:
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成員垃圾回收提供。此外,請原諒那裏留下的調試,我可能忘記刪除。
這是一個很好的觀點。我希望有一種方法可以從Java程序化地殺死整個進程。我想我們會看到。 – DerStrom8