15

就像“这盘磁带将在五秒钟内自毁。祝你好运,吉姆” ......

一旦达到预设的使用时间或其他条件,应用程序是否有可能删除自己(或其可执行包装形式)?

或者,可以使用哪些其他方法使应用程序无用?

这里的目的是让测试版过期,邀请用户获得更新的版本。

4

4 回答 4

8

有可能的。为了绕过对 JAR 文件的锁定,您的应用程序可能需要生成一个后台进程,该进程会等到 JVM 退出后再删除内容。

但是,这不是防弹的。有人可以安装应用程序,然后将安装的文件和目录设为只读,这样您的应用程序就无法自行删除。用户(或其管理员)通过操作系统的访问控制系统对创建和删除哪些文件拥有最终决定权。

于 2012-04-11T14:44:57.003 回答
5

如果您控制测试人员下载您的应用程序的位置,您可以使用自动构建系统(例如Jenkins),您可以每晚创建一个具有硬编码到期日期的新 beta 版本:

private static final Date EXPIRY_DATE = <90 days in the future from build date>;

上述日期由构建过程自动插入

if (EXPIRY_DATE.before(new Date()) {
    System.out.println("Get a new beta version, please");
    System.exit(1);
}

将其与已签名和密封的 jars混合使用,为反编译字节码设置障碍并提供不包含该代码的替代实现,您可以分发代码的过期测试版。

自动构建系统可以配置为自动将 beta 版本上传到托管下载版本的服务器。

于 2012-04-11T14:48:16.067 回答
1

由于 Windows 在JAR运行时锁定文件,因此您无法从自己的 Java 代码中删除它,因此您需要一个Batch文件:

private static void selfDestructWindowsJARFile() throws Exception
{
    String resourceName = "self-destruct.bat";
    File scriptFile = File.createTempFile(FilenameUtils.getBaseName(resourceName), "." + FilenameUtils.getExtension(resourceName));

    try (FileWriter fileWriter = new FileWriter(scriptFile);
         PrintWriter printWriter = new PrintWriter(fileWriter))
    {
        printWriter.println("taskkill /F /IM \"java.exe\"");
        printWriter.println("DEL /F \"" + ProgramDirectoryUtilities.getCurrentJARFilePath() + "\"");
        printWriter.println("start /b \"\" cmd /c del \"%~f0\"&exit /b");
    }

    Desktop.getDesktop().open(scriptFile);
}

public static void selfDestructJARFile() throws Exception
{
    if (SystemUtils.IS_OS_WINDOWS)
    {
        selfDestructWindowsJARFile();
    } else
    {
        // Unix does not lock the JAR file so we can just delete it
        File directoryFilePath = ProgramDirectoryUtilities.getCurrentJARFilePath();
        Files.delete(directoryFilePath.toPath());
    }

    System.exit(0);
}

ProgramDirectoryUtilities班级:

public class ProgramDirectoryUtilities
{
    private static String getJarName()
    {
        return new File(ProgramDirectoryUtilities.class.getProtectionDomain()
                .getCodeSource()
                .getLocation()
                .getPath())
                .getName();
    }

    public static boolean isRunningFromJAR()
    {
        String jarName = getJarName();
        return jarName.contains(".jar");
    }

    public static String getProgramDirectory()
    {
        if (isRunningFromJAR())
        {
            return getCurrentJARDirectory();
        } else
        {
            return getCurrentProjectDirectory();
        }
    }

    private static String getCurrentProjectDirectory()
    {
        return new File("").getAbsolutePath();
    }

    public static String getCurrentJARDirectory()
    {
        try
        {
            return getCurrentJARFilePath().getParent();
        } catch (URISyntaxException exception)
        {
            exception.printStackTrace();
        }

        throw new IllegalStateException("Unexpected null JAR path");
    }

    public static File getCurrentJARFilePath() throws URISyntaxException
    {
        return new File(ProgramDirectoryUtilities.class.getProtectionDomain().getCodeSource().getLocation().toURI().getPath());
    }
}

受此问题启发的解决方案。


这是适用于 Windows 的更好方法:

private static void selfDestructWindowsJARFile() throws Exception
{
    String currentJARFilePath = ProgramDirectoryUtilities.getCurrentJARFilePath().toString();
    Runtime runtime = Runtime.getRuntime();
    runtime.exec("cmd /c ping localhost -n 2 > nul && del \"" + currentJARFilePath + "\"");
}

是原始答案。

于 2017-10-30T14:15:02.590 回答
-1

我猜这很有可能。也许你可以像这样删除 jar 并确保应用程序消失,因为你有权利。

File jar = new File(".\\app.jar");
jar.deleteOnExit();
System.exit(0);

还使用Nullsoft Scriptable Install System 之类的东西,它使您能够编写自己的安装/卸载程序应该会有所帮助。

于 2012-04-11T14:37:43.587 回答