using LANCommander.SDK.Extensions; using LANCommander.SDK.Helpers; using LANCommander.SDK.Models; using LANCommander.SDK.PowerShell; using Microsoft.Extensions.Logging; using System; using System.IO; using System.Linq; using System.Threading; using System.Threading.Tasks; using LANCommander.SDK.Abstractions; using Microsoft.Extensions.DependencyInjection; namespace LANCommander.SDK.Services; public partial class ScriptClient { public async Task Tool_RunDetectInstallScriptAsync(string installDirectory, Guid gameId, Guid toolId) { bool result = default; var gameManifest = await ManifestHelper.ReadAsync(installDirectory, gameId); var toolManifest = await ManifestHelper.ReadAsync(installDirectory, toolId); var path = ScriptHelper.GetScriptFilePath(installDirectory, toolId, Enums.ScriptType.DetectInstall); if (File.Exists(path) && !SupportsCurrentRuntime(toolManifest.Scripts, Enums.ScriptType.DetectInstall)) { logger?.LogTrace("Skipping detect install script; not supported on the current runtime"); return result; } try { if (File.Exists(path)) { using (var op = logger.BeginOperation("Executing install detection script")) { var script = powerShellScriptFactory.Create(Enums.ScriptType.DetectInstall); script.AddVariable("InstallDirectory", installDirectory); script.AddVariable("GameManifest", gameManifest); script.AddVariable("ToolManifest", toolManifest); script.AddVariable("DefaultInstallDirectory", settingsProvider.CurrentValue.Games.InstallDirectories.FirstOrDefault()); script.AddVariable("ServerAddress", connectionClient.GetServerAddress()); try { op.Enrich("InstallDirectory", installDirectory) .Enrich("GameManifestPath", ManifestHelper.GetPath(installDirectory, gameId)) .Enrich("ToolManifestPath", ManifestHelper.GetPath(installDirectory, toolId)) .Enrich("ScriptPath", path) .Enrich("GameTitle", gameManifest.Title) .Enrich("GameId", gameManifest.Id) .Enrich("ToolName", toolManifest.Name) .Enrich("ToolId", toolManifest.Id); } catch (Exception ex) { logger?.LogError(ex, "Could not enrich logs"); } if (gameManifest.CustomFields != null && gameManifest.CustomFields.Any()) { foreach (var customField in gameManifest.CustomFields) { script.AddVariable(customField.Name, customField.Value); } } script.UseWorkingDirectory(Path.Combine(GameClient.GetMetadataDirectoryPath(installDirectory, toolId))); script.UseFile(path); if (Debug) script.EnableDebug(); var handled = await RunScriptExternallyAsync(script); if (!handled) { using (var timeoutCancellationTokenSource = new CancellationTokenSource()) { var task = script.ExecuteAsync(); var completedTask = await Task.WhenAny(task, Task.Delay(TimeSpan.FromSeconds(10), timeoutCancellationTokenSource.Token)); if (completedTask == task) { await timeoutCancellationTokenSource.CancelAsync(); return await task; } else { throw new TimeoutException("The operation has timed out."); } } } result = await script.ExecuteAsync(); op.Complete(); } } } catch (Exception ex) { logger?.LogError(ex, "Ran into an unexpected error when attempting to run a Detect Install script"); } return result; } public async Task Tool_RunInstallScriptAsync(string installDirectory, Guid toolId) { int result = default; var toolManifest = await ManifestHelper.ReadAsync(installDirectory, toolId); var path = ScriptHelper.GetScriptFilePath(installDirectory, toolId, Enums.ScriptType.Install); if (Path.Exists(path) && !SupportsCurrentRuntime(toolManifest.Scripts, Enums.ScriptType.Install)) { logger?.LogTrace("Skipping install script; not supported on the current runtime"); return result; } try { if (Path.Exists(path)) { using (var op = logger.BeginOperation("Executing install detection script")) { var script = powerShellScriptFactory.Create(Enums.ScriptType.Install); script.AddVariable("InstallDirectory", installDirectory); script.AddVariable("ToolManifest", toolManifest); script.AddVariable("DefaultInstallDirectory", settingsProvider.CurrentValue.Games.InstallDirectories.FirstOrDefault()); script.AddVariable("ServerAddress", connectionClient.GetServerAddress()); try { op .Enrich("InstallDirectory", installDirectory) .Enrich("ToolManifestPath", ManifestHelper.GetPath(installDirectory, toolId)) .Enrich("ScriptPath", path) .Enrich("ToolName", toolManifest.Name) .Enrich("ToolId", toolManifest.Id); } catch (Exception ex) { logger?.LogError(ex, "Could not enrich logs"); } var extractionPath = Path.Combine(GameClient.GetMetadataDirectoryPath(installDirectory, toolId), "Files"); script.UseWorkingDirectory(extractionPath); script.UseFile(path); if (Debug) script.EnableDebug(); var handled = await RunScriptExternallyAsync(script); if (!handled) result = await script.ExecuteAsync(); op.Complete(); } } } catch (Exception ex) { logger?.LogError(ex, "Ran into an unexpected error when attempting to run a Detect Install script"); } return result; } public async Task Tool_RunUninstallScriptAsync(string installDirectory, Guid toolId) { int result = default; var toolManifest = await ManifestHelper.ReadAsync(installDirectory, toolId); var path = ScriptHelper.GetScriptFilePath(installDirectory, toolId, Enums.ScriptType.Uninstall); if (Path.Exists(path) && !SupportsCurrentRuntime(toolManifest.Scripts, Enums.ScriptType.Uninstall)) { logger?.LogTrace("Skipping uninstall script; not supported on the current runtime"); return result; } try { if (Path.Exists(path)) { using (var op = logger.BeginOperation("Executing uninstall script")) { var script = powerShellScriptFactory.Create(Enums.ScriptType.Uninstall); script.AddVariable("InstallDirectory", installDirectory); script.AddVariable("ToolManifest", toolManifest); script.AddVariable("DefaultInstallDirectory", settingsProvider.CurrentValue.Games.InstallDirectories.FirstOrDefault()); script.AddVariable("ServerAddress", connectionClient.GetServerAddress()); try { op .Enrich("InstallDirectory", installDirectory) .Enrich("ToolManifestPath", ManifestHelper.GetPath(installDirectory, toolId)) .Enrich("ScriptPath", path) .Enrich("ToolName", toolManifest.Name) .Enrich("ToolId", toolManifest.Id); } catch (Exception ex) { logger?.LogError(ex, "Could not enrich logs"); } var extractionPath = Path.Combine(GameClient.GetMetadataDirectoryPath(installDirectory, toolId), "Files"); script.UseWorkingDirectory(extractionPath); script.UseFile(path); if (Debug) script.EnableDebug(); var handled = await RunScriptExternallyAsync(script); if (!handled) result = await script.ExecuteAsync(); op.Complete(); } } } catch (Exception ex) { logger?.LogError(ex, "Ran into an unexpected error when attempting to run an Uninstall script"); } return result; } public async Task Tool_RunBeforeStartScriptAsync(string installDirectory, Guid toolId) { int result = default; try { var toolManifest = await ManifestHelper.ReadAsync(installDirectory, toolId); var path = ScriptHelper.GetScriptFilePath(installDirectory, toolId, Enums.ScriptType.BeforeStart); if (File.Exists(path) && !SupportsCurrentRuntime(toolManifest.Scripts, Enums.ScriptType.BeforeStart)) { logger?.LogTrace("Skipping before start script; not supported on the current runtime"); return result; } using (var op = logger.BeginOperation("Executing before start script")) { if (File.Exists(path)) { var script = powerShellScriptFactory.Create(Enums.ScriptType.BeforeStart); script.AddVariable("InstallDirectory", installDirectory); script.AddVariable("ToolManifest", toolManifest); script.AddVariable("DefaultInstallDirectory", settingsProvider.CurrentValue.Games.InstallDirectories.FirstOrDefault()); script.AddVariable("ServerAddress", connectionClient.GetServerAddress()); try { op .Enrich("InstallDirectory", installDirectory) .Enrich("ToolManifestPath", ManifestHelper.GetPath(installDirectory, toolId)) .Enrich("ScriptPath", path) .Enrich("ToolName", toolManifest.Name) .Enrich("ToolId", toolManifest.Id); } catch (Exception ex) { logger?.LogError(ex, "Could not enrich logs"); } var extractionPath = Path.Combine(GameClient.GetMetadataDirectoryPath(installDirectory, toolId), "Files"); script.UseWorkingDirectory(extractionPath); script.UseFile(path); if (Debug) script.EnableDebug(); var handled = await RunScriptExternallyAsync(script); if (!handled) result = await script.ExecuteAsync(); } else { logger?.LogTrace("No before start script found"); } op.Complete(); } } catch (Exception ex) { logger?.LogError(ex, "Ran into an unexpected error when attempting to run a Before Start script"); } return result; } public async Task Tool_RunAfterStopScriptAsync(string installDirectory, Guid toolId) { int result = default; try { var toolManifest = await ManifestHelper.ReadAsync(installDirectory, toolId); var path = ScriptHelper.GetScriptFilePath(installDirectory, toolId, Enums.ScriptType.AfterStop); if (File.Exists(path) && !SupportsCurrentRuntime(toolManifest.Scripts, Enums.ScriptType.AfterStop)) { logger?.LogTrace("Skipping after stop script; not supported on the current runtime"); return result; } using (var op = logger.BeginOperation("Executing after stop script")) { if (File.Exists(path)) { var script = powerShellScriptFactory.Create(Enums.ScriptType.AfterStop); script.AddVariable("InstallDirectory", installDirectory); script.AddVariable("ToolManifest", toolManifest); script.AddVariable("DefaultInstallDirectory", settingsProvider.CurrentValue.Games.InstallDirectories.FirstOrDefault()); script.AddVariable("ServerAddress", connectionClient.GetServerAddress()); try { op .Enrich("InstallDirectory", installDirectory) .Enrich("ToolManifestPath", ManifestHelper.GetPath(installDirectory, toolId)) .Enrich("ScriptPath", path) .Enrich("ToolName", toolManifest.Name) .Enrich("ToolId", toolManifest.Id); } catch (Exception ex) { logger?.LogError(ex, "Could not enrich logs"); } var extractionPath = Path.Combine(GameClient.GetMetadataDirectoryPath(installDirectory, toolId), "Files"); script.UseWorkingDirectory(extractionPath); script.UseFile(path); if (Debug) script.EnableDebug(); var handled = await RunScriptExternallyAsync(script); if (!handled) result = await script.ExecuteAsync(); } else { logger?.LogTrace("No after stop script found"); } op.Complete(); } } catch (Exception ex) { logger?.LogError(ex, "Ran into an unexpected error when attempting to run an After Stop script"); } return result; } public async Task Tool_RunPackageScriptAsync(Script packageScript, Tool tool, string latestArchivePath = null) { try { using (var op = logger.BeginOperation("Executing tool package script")) { var script = powerShellScriptFactory.Create(Enums.ScriptType.Package); script.AddVariable("Tool", tool); if (!string.IsNullOrEmpty(latestArchivePath)) script.AddVariable("LatestArchivePath", latestArchivePath); script.UseInline(packageScript.Contents); try { op .Enrich("ToolId", tool.Id) .Enrich("ToolName", tool.Name) .Enrich("ScriptId", packageScript.Id) .Enrich("ScriptName", packageScript.Name); } catch (Exception ex) { logger?.LogError(ex, "Could not enrich logs"); } if (Debug) script.EnableDebug(); return await script.ExecuteAsync(); } } catch (Exception ex) { logger?.LogError(ex, "Could not execute tool package script"); } return null; } }