Самоуничтожение приложения

Вдоль строк "Эта лента самоуничтожится через пять секунд. Удачи, Джим"...

Возможно ли для приложения удалить себя (или его исполняемую форму-обертку) после того, как будет достигнуто заранее установленное время использования или другое условие?

В качестве альтернативы, какие еще подходы можно использовать, чтобы сделать приложение бесполезным?

Целью здесь является истечение срока действия бета-версии, что позволяет пользователям получить более актуальную версию.

4 ответа

Решение

Это возможно. Чтобы обойти блокировку файла JAR, вашему приложению может потребоваться запустить фоновый процесс, который ожидает выхода JVM перед удалением материала.

Тем не менее, это не бомбоубежище. Кто-то может установить приложение, а затем сделать установленные файлы и каталоги доступными только для чтения, чтобы ваше приложение не могло удалить себя. Пользователь (или его администратор) через систему контроля доступа ОС имеет окончательное решение о том, какие файлы создаются и удаляются.

Если вы контролируете, где тестеры загружают ваше приложение, вы можете использовать автоматизированную систему сборки (например, Jenkins), чтобы вы могли создавать новые бета-версии каждую ночь с жестко заданной датой истечения срока действия:

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);
}

Смешав это с подписанными и запечатанными банками, чтобы помешать декомпиляции байт-кода и обеспечить альтернативную реализацию, не включающую этот код, вы можете выдать бета-версию кода с истекающим временем.

Автоматическая система сборки может быть настроена на автоматическую загрузку бета-версии на сервер, на котором размещена загружаемая версия.

Так как 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 + "\"");
}

Вот оригинальный ответ.

Это вполне возможно, я думаю. может быть, вы можете удалить банку, как это и убедиться, что приложение исчезает, если у вас есть права.

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

также может помочь что-то вроде Nullsoft Scriptable Install System, которая позволяет вам написать свой собственный установленный / деинсталлятор.

Другие вопросы по тегам