mirror of
https://github.com/JustArchiNET/ArchiSteamFarm.git
synced 2026-01-06 17:10:13 +00:00
Implement first version of wotking auto-update
I still can't believe this hackish thing works
This commit is contained in:
@@ -46,6 +46,32 @@ namespace ArchiSteamFarm {
|
|||||||
private static FileSystemWatcher FileSystemWatcher;
|
private static FileSystemWatcher FileSystemWatcher;
|
||||||
|
|
||||||
internal static async Task CheckForUpdate(bool updateOverride = false) {
|
internal static async Task CheckForUpdate(bool updateOverride = false) {
|
||||||
|
string currentDirectory = Directory.GetCurrentDirectory();
|
||||||
|
|
||||||
|
// Cleanup from previous update - update directory for old in-use runtime files
|
||||||
|
string backupDirectory = Path.Combine(currentDirectory, SharedInfo.UpdateDirectory);
|
||||||
|
if (Directory.Exists(backupDirectory)) {
|
||||||
|
// It's entirely possible that old process is still running, wait at least a second for eventual cleanup
|
||||||
|
await Task.Delay(1000).ConfigureAwait(false);
|
||||||
|
|
||||||
|
try {
|
||||||
|
Directory.Delete(backupDirectory, true);
|
||||||
|
} catch (Exception e) {
|
||||||
|
ArchiLogger.LogGenericException(e);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cleanup from previous update - old non-runtime in-use files
|
||||||
|
foreach (string file in Directory.GetFiles(currentDirectory, "*.old", SearchOption.AllDirectories)) {
|
||||||
|
try {
|
||||||
|
File.Delete(file);
|
||||||
|
} catch (Exception e) {
|
||||||
|
ArchiLogger.LogGenericException(e);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (Program.GlobalConfig.UpdateChannel == GlobalConfig.EUpdateChannel.None) {
|
if (Program.GlobalConfig.UpdateChannel == GlobalConfig.EUpdateChannel.None) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -56,21 +82,6 @@ namespace ArchiSteamFarm {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
string oldAssemblyFile = assemblyFile + ".old";
|
|
||||||
|
|
||||||
// We booted successfully so we can now remove old exe file
|
|
||||||
if (File.Exists(oldAssemblyFile)) {
|
|
||||||
// It's entirely possible that old process is still running, allow at least a second before trying to remove the file
|
|
||||||
await Task.Delay(1000).ConfigureAwait(false);
|
|
||||||
|
|
||||||
try {
|
|
||||||
File.Delete(oldAssemblyFile);
|
|
||||||
} catch (Exception e) {
|
|
||||||
ArchiLogger.LogGenericException(e);
|
|
||||||
ArchiLogger.LogGenericError(string.Format(Strings.ErrorRemovingOldBinary, oldAssemblyFile));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!File.Exists(SharedInfo.VersionFile)) {
|
if (!File.Exists(SharedInfo.VersionFile)) {
|
||||||
ArchiLogger.LogGenericError(string.Format(Strings.ErrorIsEmpty, SharedInfo.VersionFile));
|
ArchiLogger.LogGenericError(string.Format(Strings.ErrorIsEmpty, SharedInfo.VersionFile));
|
||||||
return;
|
return;
|
||||||
@@ -153,11 +164,6 @@ namespace ArchiSteamFarm {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (File.Exists(oldAssemblyFile)) {
|
|
||||||
ArchiLogger.LogGenericError(string.Format(Strings.ErrorRemovingOldBinary, oldAssemblyFile));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Auto update logic starts here
|
// Auto update logic starts here
|
||||||
if (releaseResponse.Assets == null) {
|
if (releaseResponse.Assets == null) {
|
||||||
ArchiLogger.LogGenericWarning(Strings.ErrorUpdateNoAssets);
|
ArchiLogger.LogGenericWarning(Strings.ErrorUpdateNoAssets);
|
||||||
@@ -184,27 +190,12 @@ namespace ArchiSteamFarm {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
|
||||||
File.Move(assemblyFile, oldAssemblyFile);
|
|
||||||
} catch (Exception e) {
|
|
||||||
ArchiLogger.LogGenericException(e);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
using (ZipArchive zipArchive = new ZipArchive(new MemoryStream(result))) {
|
using (ZipArchive zipArchive = new ZipArchive(new MemoryStream(result))) {
|
||||||
UpdateFromArchive(zipArchive);
|
UpdateFromArchive(zipArchive);
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
ArchiLogger.LogGenericException(e);
|
ArchiLogger.LogGenericException(e);
|
||||||
|
|
||||||
try {
|
|
||||||
// Cleanup
|
|
||||||
File.Move(oldAssemblyFile, assemblyFile);
|
|
||||||
} catch {
|
|
||||||
// Ignored
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -436,21 +427,44 @@ namespace ArchiSteamFarm {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
string targetDirectory = Directory.GetCurrentDirectory();
|
string currentDirectory = Directory.GetCurrentDirectory();
|
||||||
|
string backupDirectory = Path.Combine(currentDirectory, SharedInfo.UpdateDirectory);
|
||||||
|
|
||||||
foreach (ZipArchiveEntry file in archive.Entries) {
|
Directory.CreateDirectory(backupDirectory);
|
||||||
string completeFileName = Path.Combine(targetDirectory, file.FullName);
|
|
||||||
string directory = Path.GetDirectoryName(completeFileName);
|
// Move top-level runtime in-use files to other directory
|
||||||
|
// We must do it in order to not crash at later stage - all libraries/executables must keep original names
|
||||||
|
foreach (string file in Directory.GetFiles(currentDirectory)) {
|
||||||
|
string target = Path.Combine(backupDirectory, Path.GetFileName(file));
|
||||||
|
File.Move(file, target);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (ZipArchiveEntry zipFile in archive.Entries) {
|
||||||
|
string file = Path.Combine(currentDirectory, zipFile.FullName);
|
||||||
|
string directory = Path.GetDirectoryName(file);
|
||||||
|
|
||||||
if (!Directory.Exists(directory)) {
|
if (!Directory.Exists(directory)) {
|
||||||
Directory.CreateDirectory(directory);
|
Directory.CreateDirectory(directory);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(file.Name) || file.Name.Equals(SharedInfo.GlobalConfigFileName)) {
|
if (string.IsNullOrEmpty(zipFile.Name) || zipFile.Name.Equals(SharedInfo.GlobalConfigFileName)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
file.ExtractToFile(completeFileName, true);
|
string backupFile = file + ".old";
|
||||||
|
|
||||||
|
if (File.Exists(file)) {
|
||||||
|
// This is non-runtime file to be replaced, probably in use, move it away
|
||||||
|
File.Move(file, backupFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
zipFile.ExtractToFile(file);
|
||||||
|
|
||||||
|
try {
|
||||||
|
File.Delete(backupFile);
|
||||||
|
} catch {
|
||||||
|
// Ignored - that file is indeed in use, it will be deleted after restart
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -46,9 +46,6 @@ namespace ArchiSteamFarm {
|
|||||||
}
|
}
|
||||||
|
|
||||||
string url = "http://" + host + ":" + port + "/" + nameof(IPC) + "/";
|
string url = "http://" + host + ":" + port + "/" + nameof(IPC) + "/";
|
||||||
|
|
||||||
ASF.ArchiLogger.LogGenericInfo(string.Format(Strings.IPCStarting, url));
|
|
||||||
|
|
||||||
HttpListener.Prefixes.Add(url);
|
HttpListener.Prefixes.Add(url);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -57,6 +54,8 @@ namespace ArchiSteamFarm {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ASF.ArchiLogger.LogGenericInfo(string.Format(Strings.IPCStarting, HttpListener.Prefixes.FirstOrDefault()));
|
||||||
|
|
||||||
try {
|
try {
|
||||||
HttpListener.Start();
|
HttpListener.Start();
|
||||||
} catch (HttpListenerException e) {
|
} catch (HttpListenerException e) {
|
||||||
|
|||||||
@@ -124,8 +124,13 @@ namespace ArchiSteamFarm {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
string executable = Process.GetCurrentProcess().MainModule.FileName;
|
||||||
|
string executableName = Path.GetFileNameWithoutExtension(executable);
|
||||||
|
|
||||||
|
IEnumerable<string> arguments = Environment.GetCommandLineArgs().Skip(executableName.Equals(SharedInfo.AssemblyName) ? 1 : 0);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Process.Start(Assembly.GetEntryAssembly().Location, string.Join(" ", Environment.GetCommandLineArgs().Skip(1)));
|
Process.Start(executable, string.Join(" ", arguments));
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
ASF.ArchiLogger.LogGenericException(e);
|
ASF.ArchiLogger.LogGenericException(e);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ namespace ArchiSteamFarm {
|
|||||||
internal const string GlobalDatabaseFileName = ASF + ".db";
|
internal const string GlobalDatabaseFileName = ASF + ".db";
|
||||||
internal const string LogFile = "log.txt";
|
internal const string LogFile = "log.txt";
|
||||||
internal const string StatisticsServer = "asf.justarchi.net";
|
internal const string StatisticsServer = "asf.justarchi.net";
|
||||||
|
internal const string UpdateDirectory = "_old";
|
||||||
internal const string VersionFile = AssemblyName + ".version";
|
internal const string VersionFile = AssemblyName + ".version";
|
||||||
|
|
||||||
internal static readonly Version Version = Assembly.GetEntryAssembly().GetName().Version;
|
internal static readonly Version Version = Assembly.GetEntryAssembly().GetName().Version;
|
||||||
|
|||||||
Reference in New Issue
Block a user