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;
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) {
return;
}
@@ -56,21 +82,6 @@ namespace ArchiSteamFarm {
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)) {
ArchiLogger.LogGenericError(string.Format(Strings.ErrorIsEmpty, SharedInfo.VersionFile));
return;
@@ -153,11 +164,6 @@ namespace ArchiSteamFarm {
return;
}
if (File.Exists(oldAssemblyFile)) {
ArchiLogger.LogGenericError(string.Format(Strings.ErrorRemovingOldBinary, oldAssemblyFile));
return;
}
// Auto update logic starts here
if (releaseResponse.Assets == null) {
ArchiLogger.LogGenericWarning(Strings.ErrorUpdateNoAssets);
@@ -184,27 +190,12 @@ namespace ArchiSteamFarm {
return;
}
try {
File.Move(assemblyFile, oldAssemblyFile);
} catch (Exception e) {
ArchiLogger.LogGenericException(e);
return;
}
try {
using (ZipArchive zipArchive = new ZipArchive(new MemoryStream(result))) {
UpdateFromArchive(zipArchive);
}
} catch (Exception e) {
ArchiLogger.LogGenericException(e);
try {
// Cleanup
File.Move(oldAssemblyFile, assemblyFile);
} catch {
// Ignored
}
return;
}
@@ -436,21 +427,44 @@ namespace ArchiSteamFarm {
return;
}
string targetDirectory = Directory.GetCurrentDirectory();
string currentDirectory = Directory.GetCurrentDirectory();
string backupDirectory = Path.Combine(currentDirectory, SharedInfo.UpdateDirectory);
foreach (ZipArchiveEntry file in archive.Entries) {
string completeFileName = Path.Combine(targetDirectory, file.FullName);
string directory = Path.GetDirectoryName(completeFileName);
Directory.CreateDirectory(backupDirectory);
// 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)) {
Directory.CreateDirectory(directory);
}
if (string.IsNullOrEmpty(file.Name) || file.Name.Equals(SharedInfo.GlobalConfigFileName)) {
if (string.IsNullOrEmpty(zipFile.Name) || zipFile.Name.Equals(SharedInfo.GlobalConfigFileName)) {
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) + "/";
ASF.ArchiLogger.LogGenericInfo(string.Format(Strings.IPCStarting, url));
HttpListener.Prefixes.Add(url);
}
@@ -57,6 +54,8 @@ namespace ArchiSteamFarm {
return;
}
ASF.ArchiLogger.LogGenericInfo(string.Format(Strings.IPCStarting, HttpListener.Prefixes.FirstOrDefault()));
try {
HttpListener.Start();
} catch (HttpListenerException e) {

View File

@@ -124,8 +124,13 @@ namespace ArchiSteamFarm {
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 {
Process.Start(Assembly.GetEntryAssembly().Location, string.Join(" ", Environment.GetCommandLineArgs().Skip(1)));
Process.Start(executable, string.Join(" ", arguments));
} catch (Exception e) {
ASF.ArchiLogger.LogGenericException(e);
}

View File

@@ -39,6 +39,7 @@ namespace ArchiSteamFarm {
internal const string GlobalDatabaseFileName = ASF + ".db";
internal const string LogFile = "log.txt";
internal const string StatisticsServer = "asf.justarchi.net";
internal const string UpdateDirectory = "_old";
internal const string VersionFile = AssemblyName + ".version";
internal static readonly Version Version = Assembly.GetEntryAssembly().GetName().Version;