想实现这样的功能,程序自身运行完后删除自己这个EXE文件。
通过写一个BAT文件来删除,不知道哪出了问题,请教各位大牛指点迷津。
BAT文件是这样的内容:
:pp
del d:\TestRun.exe
if exist d:\TestRun.exe  goto pp
del %0
java文件:
import java.io.*;
import java.io.IOException;public class TestRun{

public static void main(String[] args){
FileWriter fw = null;
String batcode = ":pp\ndel d:\\TestRun.exe\nif exist d:\\TestRun.exe  goto pp\ndel %0"; try{
fw = new FileWriter("d:/te.bat");
fw.write(batcode,0,batcode.length());
fw.close();
String cmd = "cmd.exe /c d:\\te.bat";
Runtime.getRuntime( ).exec( cmd );

}catch(IOException e){
e.printStackTrace();
System.out.println("文件写入错误");
System.exit(-1);
}

}
}java文件编译后做成TestRun.exe,存在D盘根目录下。
功能实现不了,请各位指点迷津,这个测试程序该怎么写。100分在线等。

解决方案 »

  1.   

    删除的了就怪了你是在程序中启动这个bat文件的,那么bat文件去删除这个程序时必然会被操作系统拒绝,因为这个程序正在使用中。标准的做法是:
    1、在bat中启动该exe程序;
    2、在同一个bat中检查exe退出码是否正常(为了避免如果失败了,用户还要重复运行);
    3、在同一个bat中删除该exe程序(这时exe程序已经运行完毕退出了)。
      

  2.   

    感谢楼上,但是我的原始思路是用.EXE删除程序本身,bat文件只是为了删除程序本身产生出来的临时文件。
      

  3.   

    要能删除这个exe,需要两个条件:
    1、另一个独立进程(而非子进程)中执行删除命令;
    2、exe程序结束(退出)。尝试用 start 而非 cmd 命令来启动bat脚本吧。
      

  4.   

    回复于:2012-04-12 10:37:37要能删除这个exe,需要两个条件:
    1、另一个独立进程(而非子进程)中执行删除命令;
    2、exe程序结束(退出)。尝试用 start 而非 cmd 命令来启动bat脚本吧。 
      

  5.   

    have a try
    public static void main(String[] args){
    Runtime.getRuntime().addShutdownHook(new Thread() { //追加程序结束hook,也就是说程序结束时会调用这个hook处理
        public void run() {
            Runtime.getRuntime().exec("cmd d:/te.bat"); //在hook处理中调用bat删除程序
        }
    }); //以下是LZ生成bat文件的代码
    FileWriter fw = null;
    String batcode = ":pp\ndel d:\\TestRun.exe\nif exist d:\\TestRun.exe goto pp\ndel %0";try{
    fw = new FileWriter("d:/te.bat");
    fw.write(batcode,0,batcode.length());
    fw.close();
    String cmd = "cmd.exe /c d:\\te.bat";
    Runtime.getRuntime( ).exec( cmd );}catch(IOException e){
    e.printStackTrace();
    System.out.println("文件写入错误");
    System.exit(-1);
    }}
    }
      

  6.   

    啊哈,突然发现另一个问题,你生成的这个bat,似乎又不容易删除了。
      

  7.   

    可以删除,del %0 就是删除bat本身,自己删除自己,系统会出个警告信息,不过能删除
      

  8.   


    不错:
    del /Q /F %0
      

  9.   


    尝试了我4楼说的:用start代替cmd么?
      

  10.   

    start也不行,我一开始的思路就是这个,但是也不行
      

  11.   

    java可能搞不定 汇编吧 你这是想搞个病毒么
      

  12.   

    不知道你是怎么编译成exe的
    做了个测试,可以成功删除编译后的class文件和临时bat文件import java.io.*;
    import java.lang.management.*;
    public class DelTest {
        public static void main(String[] args){
            //在删除程序之前,强制杀掉当前进程,所以程序启动时先获取程序进程ID
            final String pid = ManagementFactory.getRuntimeMXBean().getName().replaceAll("(\\d+).*", "$1");
            Runtime.getRuntime().addShutdownHook(new Thread() { //添加程序结束hook
                public void run() {
                    try {
                        Runtime.getRuntime().exec("taskkill /F /PID " + pid); //先强制杀死进程
                        Runtime.getRuntime().exec("e:\\Test\\del.bat");//再调用bat删除文件,这里直接调用bat,不需要使用cmd或start                } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            });         //注意bat文件是\r\n换行
            String batcode = ":pp\r\ndel /F /Q e:\\Test\\DelTest*.class\r\nif exist e:\\Test\\DelTest*.class goto pp\r\ndel /F /Q %0\r\n";        try{
                PrintStream ps = new PrintStream("e:\\Test\\del.bat");
                ps.print(batcode); //其实为了保证\r\n换行,可以用ps.println(cmdstr)来输出每一行bat指令
                ps.close();        } catch (IOException e){
                e.printStackTrace();
            }    }
    }
      

  13.   

    奇怪,殺死自己的進程之後還可以繼續執行程序嗎(除非不是當前執行進程),addShutDownHook是在JVM生命期內調用的吧
    還有class文件看來可以在程序執行時被刪除
      

  14.   

    首先,其实Runntime的exec启动的进程跟Thread的start的调度一样,Runtime的exec只是创建了一个进程,但是进程什么时候执行由系统调度,就像Thread的start虽然启动了线程,但是不代表线程一定马上执行,所以
    Runtime.getRuntime().exec("taskkill /F /PID " + pid); //这里会杀死父进程,但是子进程未必马上执行
    Runtime.getRuntime().exec("e:\\Test\\del.bat");//所以父进程有可能能执行到这里才被杀死其次,Runtime的exec启动的进程是独立的,即使父进程死亡了,子进程依然进行,可以通过以下的例子来验证import java.io.*;
    import java.lang.management.*;
    import javax.swing.*;public class DelTest {
        public static void main(String[] args) throws Throwable {
            final String pid = ManagementFactory.getRuntimeMXBean().getName().replaceAll("(\\d+).*", "$1");
            Runtime.getRuntime().addShutdownHook(new Thread() {
                public void run() {
                    try {
                        //Runtime.getRuntime().exec("taskkill /F /PID " + pid);
                        //Runtime.getRuntime().exec("e:\\Test\\del.bat");
                        
                        //启动一个子进程打开一个窗口,看看父进程死亡后子进程是否死亡
                        Runtime.getRuntime().exec("java.exe TestFrame"); 
                        sleep(1000); //为了保证后续代码延迟,主线程稍微休眠一会                    System.out.println("杀死父进程前...");
                        //启动一个子进程杀死父进程
                        Runtime.getRuntime().exec("taskkill /F /PID " + pid); 
                        sleep(2000); //为了保证后续代码的延迟,主线程稍微休眠一会,注释掉这行再试试看
                        System.out.println("杀死父进程后..."); //这里没有被打印,
                        //说明父进程死亡后,父进程后续代码不会被执行
                        //但是窗口没有关闭,说明子进程没有因为父进程死亡而结束
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            });         String batcode = ":pp\r\ndel /F /Q e:\\Test\\DelTest*.class\r\nif exist e:\\Test\\DelTest*.class goto pp\r\ndel /F /Q %0\r\n";        try{
                PrintStream ps = new PrintStream("e:\\Test\\del.bat");
                ps.print(batcode);
                ps.close();        } catch (IOException e){
                e.printStackTrace();
            }
        }
    }class TestFrame extends JFrame {
        public TestFrame() {
            setSize(400, 300);
            setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            setVisible(true);
        }    public static void main(String[] args) {
            new TestFrame();
        }
    }所以,最初9L的代码应该是可以的,只是由于子进程可能还没来得及被执行,父进程就退出了,所以可以在启动子进程以后稍微延迟一会就好了,因为LZ原来的bat本身是带有循环删除的import java.io.*;
    import java.lang.management.*;public class DelTest {
        public static void main(String[] args) throws Throwable {
            Runtime.getRuntime().addShutdownHook(new Thread() {
                public void run() {
                    try {
                        Runtime.getRuntime().exec("e:\\Test\\del.bat"); //不用杀死父进程了
                        sleep(2000); //延迟父进程结束时间,让子进程有机会启动后父进程再退出就可以了                } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            });         String batcode = ":pp\r\ndel /F /Q e:\\Test\\DelTest*.class\r\nif exist e:\\Test\\DelTest*.class goto pp\r\ndel /F /Q %0\r\n";        try{
                PrintStream ps = new PrintStream("e:\\Test\\del.bat");
                ps.print(batcode);
                ps.close();        } catch (IOException e){
                e.printStackTrace();
            }
        }
    }
    另外,还有一种思路,可以考虑用File的deleteOnExit()
    比如
    File f = new File("xxx\\yyy.exe");
    f.deleteOnExit();
    不知道效果如何,删除程序本身测试过,删除其他文件应该是没问题的
      

  15.   

    首先,其实Runntime的exec启动的进程跟Thread的start的调度一样,Runtime的exec只是创建了一个进程,但是进程什么时候执行由系统调度,就像Thread的start虽然启动了线程,但是不代表线程一定马上执行,所以
    Runtime.getRuntime().exec("taskkill /F /PID " + pid); //这里会杀死父进程,但是子进程未必马上执行
    Runtime.getRuntime().exec("e:\\Test\\del.bat");//所以父进程有可能能执行到这里才被杀死其次,Runtime的exec启动的进程是独立的,即使父进程死亡了,子进程依然进行,可以通过以下的例子来验证import java.io.*;
    import java.lang.management.*;
    import javax.swing.*;public class DelTest {
        public static void main(String[] args) throws Throwable {
            final String pid = ManagementFactory.getRuntimeMXBean().getName().replaceAll("(\\d+).*", "$1");
            Runtime.getRuntime().addShutdownHook(new Thread() {
                public void run() {
                    try {
                        //Runtime.getRuntime().exec("taskkill /F /PID " + pid);
                        //Runtime.getRuntime().exec("e:\\Test\\del.bat");
                        
                        //启动一个子进程打开一个窗口,看看父进程死亡后子进程是否死亡
                        Runtime.getRuntime().exec("java.exe TestFrame"); 
                        sleep(1000); //为了保证后续代码延迟,主线程稍微休眠一会                    System.out.println("杀死父进程前...");
                        //启动一个子进程杀死父进程
                        Runtime.getRuntime().exec("taskkill /F /PID " + pid); 
                        sleep(2000); //为了保证后续代码的延迟,主线程稍微休眠一会,注释掉这行再试试看
                        System.out.println("杀死父进程后..."); //这里没有被打印,
                        //说明父进程死亡后,父进程后续代码不会被执行
                        //但是窗口没有关闭,说明子进程没有因为父进程死亡而结束
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            });         String batcode = ":pp\r\ndel /F /Q e:\\Test\\DelTest*.class\r\nif exist e:\\Test\\DelTest*.class goto pp\r\ndel /F /Q %0\r\n";        try{
                PrintStream ps = new PrintStream("e:\\Test\\del.bat");
                ps.print(batcode);
                ps.close();        } catch (IOException e){
                e.printStackTrace();
            }
        }
    }class TestFrame extends JFrame {
        public TestFrame() {
            setSize(400, 300);
            setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            setVisible(true);
        }    public static void main(String[] args) {
            new TestFrame();
        }
    }所以,最初9L的代码应该是可以的,只是由于子进程可能还没来得及被执行,父进程就退出了,所以可以在启动子进程以后稍微延迟一会就好了,因为LZ原来的bat本身是带有循环删除的import java.io.*;
    import java.lang.management.*;public class DelTest {
        public static void main(String[] args) throws Throwable {
            Runtime.getRuntime().addShutdownHook(new Thread() {
                public void run() {
                    try {
                        Runtime.getRuntime().exec("e:\\Test\\del.bat"); //不用杀死父进程了
                        sleep(2000); //延迟父进程结束时间,让子进程有机会启动后父进程再退出就可以了                } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            });         String batcode = ":pp\r\ndel /F /Q e:\\Test\\DelTest*.class\r\nif exist e:\\Test\\DelTest*.class goto pp\r\ndel /F /Q %0\r\n";        try{
                PrintStream ps = new PrintStream("e:\\Test\\del.bat");
                ps.print(batcode);
                ps.close();        } catch (IOException e){
                e.printStackTrace();
            }
        }
    }
    另外,还有一种思路,可以考虑用File的deleteOnExit()
    比如
    File f = new File("xxx\\yyy.exe");
    f.deleteOnExit();
    不知道效果如何,删除程序本身测试过,删除其他文件应该是没问题的
      

  16.   

    笔误
    删除程序本身测试过,因为不知道LZ怎么编译成exe的
      

  17.   

    但是父進程貌似得存在以hold住子進程的啟動過程,可能存在一個類似隊列的結構在父進程中待啟動。
      

  18.   


    不知道是怎么回事,第一遍生成的exe文件,达到了预想的效果。但是后来exe文件运行的几遍测试后都没有达到预想的效果,不是留有bat文件就是连exe文件也没删除掉!
    我用的win7操作系统加360安全卫士,不知道和这个有没有关系。
      

  19.   

    我用的是exe4j_windows_4_4_1生成的exe文件