Skip to content

Commit

Permalink
Fix pathcer upadate
Browse files Browse the repository at this point in the history
  • Loading branch information
Laeng committed May 24, 2024
1 parent 2381ff6 commit 1640c05
Show file tree
Hide file tree
Showing 5 changed files with 241 additions and 9 deletions.
4 changes: 2 additions & 2 deletions SCTools/SCTool_Redesigned/Pages/updatePatcher.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ namespace SCTool_Redesigned.Pages
/// </summary>
public partial class updatePatcher : Page
{
private static ApplicationUpdater _updater = new ApplicationUpdater(GetUpdateRepository(), App.ExecutableDir, Properties.Resources.UpdateScript, new CustomPackageVerifier());
private static CancellationTokenSource _cancellationToken = new CancellationTokenSource(); //TODO: Dispose, cancel when exit
private static CustomApplicationUpdater _updater = new(GetUpdateRepository(), App.ExecutableDir, Properties.Resources.UpdateScript, new CustomPackageVerifier());
private static CancellationTokenSource _cancellationToken = new(); //TODO: Dispose, cancel when exit
public updatePatcher()
{
InitializeComponent();
Expand Down
2 changes: 1 addition & 1 deletion SCTools/SCTool_Redesigned/Properties/Resources.ko-KR.resx
Original file line number Diff line number Diff line change
Expand Up @@ -401,7 +401,7 @@
<value>**문서를 불러올 수 없습니다.**</value>
</data>
<data name="UI_Desc_UpdatingProgram" xml:space="preserve">
<value>런처 업데이트 중</value>
<value>패쳐 업데이트 중</value>
</data>
<data name="UI_Desc_Welcome" xml:space="preserve">
<value>환영합니다</value>
Expand Down
10 changes: 5 additions & 5 deletions SCTools/SCTool_Redesigned/Resources/update.bat
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,14 @@ set updatepath=%workpath%updates\
set latestpath=%updatepath%latest\

timeout 1
xcopy "%latestpath%*.*" "%workpath%" /s /k /h /y
::xcopy "%latestpath%*.*" "%workpath%" /s /k /h /y
if not errorlevel 0 goto update_error

del "%updatepath%latest.json"
del "%updatepath%latest.zip"
del /q "%latestpath%*"
for /d %%p in ("%latestpath%*.*") do rmdir /s /q "%%p"
rmdir /s /q "%latestpath%"
::del "%updatepath%latest.zip"
::del /q "%latestpath%*"
::for /d %%p in ("%latestpath%*.*") do rmdir /s /q "%%p"
::rmdir /s /q "%latestpath%"

start "" "%workpath%Shatagon.exe" update_status 0
exit
Expand Down
232 changes: 232 additions & 0 deletions SCTools/SCTool_Redesigned/Update/CustomApplicationUpdater.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,232 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO.Compression;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using NLog;
using NSW.StarCitizen.Tools.Lib.Helpers;
using NSW.StarCitizen.Tools.Lib.Update;

namespace SCTool_Redesigned.Update
{
public class CustomApplicationUpdater : IDisposable
{
private static readonly Logger _logger = LogManager.GetCurrentClassLogger();
private readonly IUpdateRepository _updateRepository;
private readonly IPackageVerifier _packageVerifier;
private readonly string _executableDir;
private readonly string _updateScriptContent;
private readonly string _updateScriptPath;
private readonly string _updatesStoragePath;
private readonly string _schedInstallArchivePath;
private readonly string _schedInstallExecutablePath;
private readonly string _schedInstallJsonPath;
private readonly string _installUnpackedDir;
private readonly string _installUnpackedExecutablePath;
private readonly string _currentVersion;

public interface IPackageVerifier
{
bool VerifyPackage(string path);
}

public event EventHandler MonitorStarted
{
add { _updateRepository.MonitorStarted += value; }
remove { _updateRepository.MonitorStarted -= value; }
}

public event EventHandler MonitorStopped
{
add { _updateRepository.MonitorStopped += value; }
remove { _updateRepository.MonitorStopped -= value; }
}

public event EventHandler<string> MonitorNewVersion
{
add { _updateRepository.MonitorNewVersion += value; }
remove { _updateRepository.MonitorNewVersion -= value; }
}

public bool AllowPreReleases
{
get => _updateRepository.AllowPreReleases;
set => _updateRepository.AllowPreReleases = value;
}

public CustomApplicationUpdater(IUpdateRepository updateRepository, string executableDir,
string updateScriptContent, IPackageVerifier packageVerifier)
{
if (updateRepository.CurrentVersion == null)
throw new InvalidOperationException("update repository current version is not set");
_updateRepository = updateRepository;
_executableDir = executableDir;
_updateScriptContent = updateScriptContent;
_packageVerifier = packageVerifier;
_updateScriptPath = Path.Combine(_executableDir, "update.bat");
_updatesStoragePath = Path.Combine(_executableDir, "updates");
_schedInstallArchivePath = Path.Combine(_updatesStoragePath, "latest.zip");
_schedInstallExecutablePath = Path.Combine(_updatesStoragePath, "shatagon.exe");
_schedInstallJsonPath = Path.Combine(_updatesStoragePath, "latest.json");
_installUnpackedDir = Path.Combine(_updatesStoragePath, "latest");
_installUnpackedExecutablePath = Path.Combine(_updatesStoragePath, "latest", "shatagon.exe");
_currentVersion = _updateRepository.CurrentVersion;
}

public void Dispose() => _updateRepository.Dispose();

public void MonitorStart(int refreshTime) => _updateRepository.MonitorStart(refreshTime);

public void MonitorStop() => _updateRepository.MonitorStop();

public async Task<UpdateInfo?> CheckForUpdateVersionAsync(CancellationToken cancellationToken)
{
var latestUpdateInfo = await _updateRepository.GetLatestAsync(cancellationToken);
if (latestUpdateInfo != null && string.Compare(latestUpdateInfo.GetVersion(),
_currentVersion, StringComparison.OrdinalIgnoreCase) != 0)
{
return latestUpdateInfo;
}
return null;
}

public async Task<string> DownloadVersionAsync(UpdateInfo version, CancellationToken cancellationToken, IDownloadProgress downloadProgress)
{
if (!Directory.Exists(_updatesStoragePath))
{
Directory.CreateDirectory(_updatesStoragePath);
}
return await _updateRepository.DownloadAsync(version, _updatesStoragePath, cancellationToken, downloadProgress);
}

public InstallUpdateStatus InstallScheduledUpdate()
{
_logger.Info("Install scheduled update");
if (ExtractReadyInstallUpdate() && ExtractUpdateScript())
{
using var updateProcess = new Process();
updateProcess.StartInfo.UseShellExecute = false;
updateProcess.StartInfo.RedirectStandardInput = false;
updateProcess.StartInfo.RedirectStandardOutput = false;
updateProcess.StartInfo.RedirectStandardError = false;
updateProcess.StartInfo.ErrorDialog = false;
updateProcess.StartInfo.CreateNoWindow = true;
updateProcess.StartInfo.WorkingDirectory = _executableDir;
updateProcess.StartInfo.FileName = _updateScriptPath;
if (!updateProcess.Start())
{
RemoveUpdateScript();
_logger.Info($"Failed launch updater script: {_updateScriptPath}");
return InstallUpdateStatus.LaunchScriptError;
}
return InstallUpdateStatus.Success;
}
CancelScheduleInstallUpdate();
return InstallUpdateStatus.ExtractFilesError;
}

public UpdateInfo? GetScheduledUpdateInfo() => File.Exists(_schedInstallArchivePath) ? JsonHelper.ReadFile<GitHubUpdateInfo>(_schedInstallJsonPath) : null;

public bool IsAlreadyInstalledVersion(UpdateInfo updateInfo) =>
string.Compare(updateInfo.GetVersion(), _currentVersion, StringComparison.OrdinalIgnoreCase) == 0;

public void ApplyScheduledUpdateProps(UpdateInfo updateInfo) => _updateRepository.SetCurrentVersion(updateInfo.GetVersion());

public bool ScheduleInstallUpdate(UpdateInfo updateInfo, string filePath)
{
_logger.Info($"Shedule install update with version: {updateInfo.GetVersion()}");
if (File.Exists(filePath))
{
_updateRepository.SetCurrentVersion(_currentVersion);
try
{
if (!Directory.Exists(_updatesStoragePath))
{
Directory.CreateDirectory(_updatesStoragePath);
}
if (File.Exists(_schedInstallArchivePath))
{
File.Delete(_schedInstallArchivePath);
}
File.Move(filePath, _schedInstallArchivePath);
if (JsonHelper.WriteFile(_schedInstallJsonPath, updateInfo))
{
_updateRepository.SetCurrentVersion(updateInfo.GetVersion());
return true;
}
_logger.Error($"Failed write schedule json: {_schedInstallJsonPath}");
return false;
}
catch (Exception e)
{
_logger.Error(e, $"Exception during schedule install update at: {filePath}");
CancelScheduleInstallUpdate();
return false;
}
}
_logger.Error($"No schedule update package: {filePath}");
return false;
}

public bool CancelScheduleInstallUpdate()
{
_updateRepository.SetCurrentVersion(_currentVersion);
if (File.Exists(_schedInstallJsonPath))
FileUtils.DeleteFileNoThrow(_schedInstallJsonPath);
return File.Exists(_schedInstallArchivePath) &&
FileUtils.DeleteFileNoThrow(_schedInstallArchivePath);
}

public void RemoveUpdateScript()
{
if (File.Exists(_updateScriptPath))
{
FileUtils.DeleteFileNoThrow(_updateScriptPath);
}
}

private bool ExtractUpdateScript()
{
try
{
File.WriteAllText(_updateScriptPath, _updateScriptContent);
}
catch (Exception e)
{
_logger.Error(e, $"Failed extract update script to: {_updateScriptPath}");
return false;
}
return true;
}

private bool ExtractReadyInstallUpdate()
{
var installUnpackedDir = new DirectoryInfo(_installUnpackedDir);
var extractTempDir = new DirectoryInfo(Path.Combine(_updatesStoragePath, "temp_" + Path.GetRandomFileName()));
try
{
if (installUnpackedDir.Exists && !FileUtils.DeleteDirectoryNoThrow(installUnpackedDir, true))
{
_logger.Error($"Already exist extract directory can't be removed: {_installUnpackedDir}");
return false;
}

Directory.CreateDirectory(_installUnpackedDir);
File.Move(_schedInstallExecutablePath, _installUnpackedExecutablePath);
}
catch (Exception e)
{
_logger.Error(e, $"Failed extract update package to: {_installUnpackedDir}");
if (extractTempDir.Exists)
FileUtils.DeleteDirectoryNoThrow(extractTempDir, true);
if (installUnpackedDir.Exists)
FileUtils.DeleteDirectoryNoThrow(installUnpackedDir, true);
return false;
}
return true;
}
}
}
2 changes: 1 addition & 1 deletion SCTools/SCTool_Redesigned/Update/CustomPackageVerifier.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

namespace SCTool_Redesigned.Update
{
internal class CustomPackageVerifier : ApplicationUpdater.IPackageVerifier
internal class CustomPackageVerifier : CustomApplicationUpdater.IPackageVerifier
{
private string ExecutorName = Assembly.GetExecutingAssembly().GetName().Name;

Expand Down

0 comments on commit 1640c05

Please sign in to comment.