批处理文件进程在Java中被终止:xcopy未关闭
这看起来应该很容易解决,但我对批处理文件的使用还不够熟悉,无法自己解决。我有一个Java方法,它创建一个process builder并在流程中运行一个批处理文件。批处理文件使用xcopy命令将一个目录复制到另一个目录。当批处理文件在后台运行时,一个包含JTextArea的Java窗口将显示进程的输出(正在复制的目录)。该窗口还有一个停止按钮,它调用以下代码:批处理文件进程在Java中被终止:xcopy未关闭,java,batch-file,xcopy,kill-process,Java,Batch File,Xcopy,Kill Process,这看起来应该很容易解决,但我对批处理文件的使用还不够熟悉,无法自己解决。我有一个Java方法,它创建一个process builder并在流程中运行一个批处理文件。批处理文件使用xcopy命令将一个目录复制到另一个目录。当批处理文件在后台运行时,一个包含JTextArea的Java窗口将显示进程的输出(正在复制的目录)。该窗口还有一个停止按钮,它调用以下代码: stopped = true; backgroundTask.cancel(true); backgroundTask.done();
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();
}
}
现在,为了在后台运行批处理文件,我使用以下代码(最初由垃圾神向我建议):
我遇到的问题是:当我运行程序时,除非我按下前台窗口上的停止按钮,否则文件复制得很好。当我这样做时,它告诉我备份被取消了(正如它应该做的那样),但它会让三个额外的进程运行,这三个进程在任务管理器中可见:
我的猜测是第一个--“扩展拷贝实用程序”是罪魁祸首。因为它没有关闭,所以它会让另外两个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);
}
});
}
}
package;
导入java.awt.BorderLayout;
导入java.awt.EventQueue;
导入java.awt.Toolkit;
导入java.awt.event.*;
导入java.io.BufferedReader;
导入java.io.IOException;
导入java.io.InputStreamReader;
导入java.util.List;
导入javax.swing.*;
@抑制警告(“串行”)
公共类进程扩展JFrame{
公共字符串[]命令;
专用最终JLabel statusLabel=新JLabel(“状态:”,JLabel.CENTER);
私有最终JTextArea textArea=新JTextArea(20,20);
私有JButton stopButton=新JButton(“停止”);
私有JProgressBar=新JProgressBar();
私人背景任务背景任务;
私有进程生成器pb;
私有进程p;
公共布尔停止=false;
公共void setCommands(字符串[]cmds){
commands=cmds;
}
私有最终ActionListener按钮操作=新建ActionListener(){
@凌驾
已执行的公共无效行动(行动事件ae){
JButton source=(JButton)ae.getSource();
如果(源==停止按钮){
停止=真;
backgroundTask.cancel(true);
backgroundTask.done();
}否则{
backgroundTask=新的backgroundTask(命令);
}
}
};
私有void displayGUI(字符串[]cmds){
commands=cmds;
JFrame=新JFrame(“备份进度”);
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
JPanel面板=新的JPanel();
panel.setBorder(BorderFactory.createEmptyByOrder(5,5,5,5));
面板设置布局(新边框布局(5,5));
JScrollPane sp=新的JScrollPane();
sp.setboorder(BorderFactory.createTitledBorder(“输出:”);
sp.setViewportView(文本区域);
textArea.setText(空);
stopButton.setEnabled(真);
backgroundTask=新的backgroundTask(命令);
backgroundTask.execute();
bar.setUndeterminate(真);
stopButton.addActionListener(按钮操作);
JPanel buttonPanel=新的JPanel();
按钮面板。添加(停止按钮);
按钮面板。添加(条);
panel.add(状态标签、边框布局、页面开始);
面板.添加(sp,BorderLayout.CENTER);
面板。添加(按钮面板,边框布局。第页\结束);
frame.setContentPane(面板);
frame.pack();
frame.setLocationByPlatform(真);
frame.setVisible(true);
}
/*关闭当前窗口*/
public void closeWindow()引发IOException{
p、 getInputStream().close();
p、 getOutputStream().close();
p、 getErrorStream().close();
p、 破坏();
WindowEvent close=新的WindowEvent(这是WindowEvent.WINDOW\u CLOSING);
Toolkit.getDefaultToolkit().getSystemEventQueue().postEvent(关闭);
系统出口(0);
}
私有类BackgroundTask扩展SwingWorker{
私人身份;
公共字符串[]命令;
公共背景任务(字符串[]cmds){
commands=cmds;
statusLabel.setText((this.getState()).toString());
}
@凌驾
受保护的整数doInBackground()引发IOException{
试一试{
pb=新的ProcessBuilder(命令);
pb.重定向错误流(真);
p=pb.start();
字符串s;
BufferedReader标准输出=新的BufferedReader(
新的InputStreamReader(p.getInputStream());
而((s=stdout.readLine())!=null&&!isCancelled()){
出版;
}
如果(!isCancelled()){
状态=p.waitFor();
}
关闭窗口();
}捕获(IOException | InterruptedException ex){
例如printStackTrace(System.err);
}
返回状态;
}
@凌驾
受保护的无效进程(列出消息){
地位
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);
}
});
}
}
InputStream is = null;
Process p = null;
try {
ProcessBuilder pb = new ProcessBuilder(commands);
pb.redirectErrorStream(true);
p = pb.start();
StringBuilder sb = new StringBuilder(128);
is = p.getInputStream();
int in = -1;
while (!isCancelled() && (in = is.read()) != -1) {
sb.append((char)in));
if (((char)in) == '\n') {
publish(sb.toString());
sb.delete(0, sb.length());
}
}
if (!isCancelled()) {
status = p.waitFor();
} else {
p.destroy();
}
} catch (IOException ex) {
ex.printStackTrace(System.err);
} catch (InterruptedException ex) {
ex.printStackTrace(System.err);
try {
p.destroy();
} catch (Exception exp) {
}
} finally {
try {
is.close();
} catch (Exception exp) {
}
// Make sure you are re-syncing this to the EDT first...
closeWindow();
}
static void copyTree(final Path source, final Path destination)
throws IOException {
if (Files.isDirectory(source)) {
Files.walkFileTree(source, new SimpleFileVisitor<Path>()
{
@Override
public FileVisitResult preVisitDirectory(Path dir,
BasicFileAttributes attributes)
throws IOException {
if (Thread.interrupted()) {
throw new InterruptedIOException();
}
Path destinationDir =
destination.resolve(source.relativize(dir));
Files.createDirectories(destinationDir);
BasicFileAttributeView view =
Files.getFileAttributeView(destinationDir,
BasicFileAttributeView.class);
view.setTimes(
attributes.lastModifiedTime(),
attributes.lastAccessTime(),
attributes.creationTime());
return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult visitFile(Path file,
BasicFileAttributes attributes)
throws IOException {
if (Thread.interrupted()) {
throw new InterruptedIOException();
}
Files.copy(file,
destination.resolve(source.relativize(file)),
StandardCopyOption.COPY_ATTRIBUTES,
LinkOption.NOFOLLOW_LINKS);
return FileVisitResult.CONTINUE;
}
});
} else {
Files.copy(source, destination,
StandardCopyOption.COPY_ATTRIBUTES,
LinkOption.NOFOLLOW_LINKS);
}
}