Implement first version of wotking auto-update

I still can't believe this hackish thing works
This commit is contained in:
JustArchi
2017-07-01 06:10:15 +02:00
parent fc1493d0a3
commit 2140fcedc2
4 changed files with 64 additions and 45 deletions

View File

@@ -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
}
} }
} }

View File

@@ -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) {

View File

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

View File

@@ -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;