Самостоятельно удаляемое приложение в C# в одном исполняемом файле
Можно ли сделать приложение на C#, которое сможет удалить себя в каком-то состоянии.
Мне нужно написать программу обновления для моего приложения, но я не хочу, чтобы исполняемый файл оставался после процесса обновления.
Существует официальный.Net OneClick, но из-за некоторых несовместимостей с моим HTTP-сервером и некоторых проблем с самим OneClick я вынужден сделать его самостоятельно.
Джордж.
[РЕДАКТИРОВАТЬ] Более подробно:
У меня есть: Исполняемый файл приложения, который загружает средство обновления ("патч", но не совсем), этот "патч" обновляет сам исполняемый файл приложения.
Приложение выполняется следующим образом:
Application: Start -> Check Version -> Download new Updater -> Start Updater -> exit;
Updater: Start -> do it's work -> start Application Executable -> self delete (this is where I get stuck);
7 ответов
Если вы используете Process.Start, вы можете передать Del
параметр и путь к приложению, которое вы хотите удалить.
ProcessStartInfo Info=new ProcessStartInfo();
Info.Arguments="/C choice /C Y /N /D Y /T 3 & Del "+
Application.ExecutablePath;
Info.WindowStyle=ProcessWindowStyle.Hidden;
Info.CreateNoWindow=true;
Info.FileName="cmd.exe";
Process.Start(Info);
Фрагмент кода, взятый из этой статьи
Я предлагаю вам использовать командный файл в качестве начальной загрузки, и пусть он удаляет себя и исполняемый файл впоследствии
public static class Updater
{
public static void Main()
{
string path = @"updater.bat";
if (!File.Exists(path))
{
// Create a file to write to.
using (StreamWriter sw = File.CreateText(path))
{
sw.WriteLine("updater.exe");
sw.WriteLine("delete updater.exe /y");
sw.WriteLine("delete updater.bat /y");
}
System.Process.Start(path);
}
else
{
RunUpdateProcess();
}
}
private void RunUpdateProcess()
{
.....
}
}
Это сложно, не вводя еще один процесс (который вы затем захотите удалить, без сомнения). В вашем случае у вас уже есть 2 процесса - updater.exe и application.exe. Вероятно, я бы просто использовал приложение delete updater.exe, когда оно оттуда появилось - вы можете использовать простой аргумент командной строки или вызов IPC от updater.exe до application.exe для его запуска. Это не совсем самораспаковывающийся EXE-файл, но он отвечает требованиям, которые я считаю.
Для полной обработки и других опций вы должны прочитать окончательную обработку самораспаковывающихся EXE-файлов. Примеры кода находятся в C (или ASM), но должны быть p/invokable.
Я бы наверное попробовал CreateFile с FILE_FLAG_DELETE_ON_CLOSE
для updater.exe с чем-то вроде (psuedo code):
var h = CreateFile(
"updater.exe",
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_DELETE,
NULL,
CREATE_NEW,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_DELETE_ON_CLOSE
);
byte[] updaterBytes = GetUpdaterBytesFromWeb();
File.WriteAllBytes("updater.exe", updaterBytes);
Process.Start("updater.exe");
После выхода из application.exe, updater.exe имеет дескриптор файла 1. При выходе из Updater.exe он падает до 0 и должен быть удален.
Не могли бы вы просто удалить программу обновления из приложения? то есть:
Приложение: Пуск -> [Удалить старое обновление, если оно есть] -> Проверить версию -> Загрузить новое обновление -> Запустить обновление -> выйти;
Обновление: Пуск -> Выполнить обновление -> Запустить приложение -> выйти;
Приложение: Пуск -> [Удалить старый апдейтер, если он есть] -> ...
Ваша вторая строка может быть
Updater: Star -> do it's work -> start Application Executable -> Updater Exits -> Application deletes your Updater.exe
М-м-м, так позволь мне понять это прямо. Вы получили приложение application.exe и ваше приложение Updater Updater.exe?
Поэтому, когда вы запускаете application.exe, он проверяет какой-либо веб-сервер на наличие более новой версии, а затем запускает updater.exe. И вы хотите, чтобы updater.exe удалил себя после того, как закончил обновление? Или вы хотите удалить загруженный патч (или аналогичный)? Пожалуйста, будьте немного точнее.
Учтите, что при удалении updater.exe вы должны заново создать его для следующего процесса обновления.
public void uninstall() {
string app_name = Application.StartupPath + "\\" + Application.ProductName + ".exe";
string bat_name = app_name + ".bat";
string bat = "@echo off\n"
+ ":loop\n"
+ "del \"" + app_name + "\"\n"
+ "if Exist \"" + app_name + "\" GOTO loop\n"
+ "del %0";
StreamWriter file = new StreamWriter(bat_name);
file.Write(bat);
file.Close();
Process bat_call = new Process();
bat_call.StartInfo.FileName = bat_name;
bat_call.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
bat_call.StartInfo.UseShellExecute = true;
bat_call.Start();
Application.Exit();
}
Самостоятельное удаление с помощью внешнего исполняемого файла ".bat" для приложений Windows.