From f8e0b89d697a403044d826d1d095ee0c06baa5b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=AD=20Climent?= Date: Sun, 24 Aug 2025 01:33:38 +0200 Subject: [PATCH 1/7] add basic structure --- .../Pages/SoftwarePages/PackageBundlesPage.cs | 141 ++++++++++++++++++ 1 file changed, 141 insertions(+) diff --git a/src/UniGetUI/Pages/SoftwarePages/PackageBundlesPage.cs b/src/UniGetUI/Pages/SoftwarePages/PackageBundlesPage.cs index b049aef01f..18e7dc3a6a 100644 --- a/src/UniGetUI/Pages/SoftwarePages/PackageBundlesPage.cs +++ b/src/UniGetUI/Pages/SoftwarePages/PackageBundlesPage.cs @@ -196,6 +196,7 @@ public override void GenerateToolBar() AppBarButton RemoveSelected = new(); AppBarButton SaveBundle = new(); + AppBarButton ToBatchScript = new(); AppBarButton AddPackagesToBundle = new(); AppBarButton PackageDetails = new(); AppBarButton SharePackage = new(); @@ -206,6 +207,8 @@ public override void GenerateToolBar() ToolBar.PrimaryCommands.Add(OpenBundle); ToolBar.PrimaryCommands.Add(SaveBundle); ToolBar.PrimaryCommands.Add(new AppBarSeparator()); + ToolBar.PrimaryCommands.Add(ToBatchScript); + ToolBar.PrimaryCommands.Add(new AppBarSeparator()); ToolBar.PrimaryCommands.Add(AddPackagesToBundle); ToolBar.PrimaryCommands.Add(RemoveSelected); ToolBar.PrimaryCommands.Add(new AppBarSeparator()); @@ -223,6 +226,7 @@ public override void GenerateToolBar() { InstallSkipHash, CoreTools.Translate("Skip integrity checks") }, { DownloadInstallers, CoreTools.Translate("Download selected installers") }, { OpenBundle, CoreTools.Translate("Open") }, + { ToBatchScript, CoreTools.Translate("Create batch script")}, { RemoveSelected, CoreTools.Translate("Remove selection from bundle") }, { SaveBundle, CoreTools.Translate("Save as") }, { AddPackagesToBundle, CoreTools.Translate("Add packages to bundle") }, @@ -239,6 +243,7 @@ public override void GenerateToolBar() { InstallSkipHash, IconType.Checksum }, { DownloadInstallers, IconType.Download }, { OpenBundle, IconType.OpenFolder }, + { ToBatchScript, IconType.Console}, { RemoveSelected, IconType.Delete}, { SaveBundle, IconType.SaveAs }, { AddPackagesToBundle, IconType.AddTo }, @@ -290,6 +295,7 @@ IReadOnlyList GetCheckedNonInstalledPackages() DownloadInstallers.Click += (_, _) => _ = MainApp.Operations.Download(FilteredPackages.GetCheckedPackages(), TEL_InstallReferral.FROM_BUNDLE); OpenBundle.Click += async (_, _) => await AskOpenFromFile(); SaveBundle.Click += async (_, _) => await SaveFile(); + ToBatchScript.Click += (_, _) => _ = CreateBatchScript(); SharePackage.Click += (_, _) => { @@ -741,5 +747,140 @@ public static IPackage DeserializeIncompatiblePackage(SerializableIncompatiblePa { return new InvalidImportedPackage(raw_package, source); } + + + public async Task CreateBatchScript() + { + try + { + string defaultName = CoreTools.Translate("Install batch script") + ".cmd"; + string file = await Task.Run(() => (new FileSavePicker(MainApp.Instance.MainWindow.GetWindowHandle())).Show(["*.cmd", "*.bat"], defaultName)); + if (file != String.Empty) + { + // Loading dialog + int loadingId = DialogHelper.ShowLoadingDialog(CoreTools.Translate("Saving packages, please wait...")); + + var packages = new List(); + var commands = new List(); + + foreach (var _p in Loader.Packages) + { + if (_p is ImportedPackage package) + { + packages.Add(package.Name + " from " + package.Manager.DisplayName); + commands.Add( + package.Manager.Properties.ExecutableFriendlyName + " " + string.Join(' ', + package.Manager.OperationHelper.GetParameters(package, package.installation_options, OperationType.Install))); + } + } + + await File.WriteAllTextAsync(file, GenerateCommandString(packages, commands)); + + DialogHelper.HideLoadingDialog(loadingId); + DialogHelper.ShowDismissableBalloon( + CoreTools.Translate("Success!"), + CoreTools.Translate("The batch file was created successfully on {0}", file)); + + await CoreTools.ShowFileOnExplorer(file); + } + } + catch (Exception ex) + { + DialogHelper.HideAllLoadingDialogs(); + Logger.Error("An error occurred while attempting to export a batch file"); + Logger.Error(ex); + DialogHelper.ShowDismissableBalloon( + CoreTools.Translate("An error occurred"), + CoreTools.Translate("An error occurred while attempting to create a installable batch file:") + " " + ex.Message); + } + } + + + private string GenerateCommandString(IReadOnlyList names, IReadOnlyList commands) + { + return $$""" + @echo off + setlocal enabledelayedexpansion + + echo. + echo ======================================================== + echo. + echo __ __ _ ______ __ __ ______ + echo / / / /___ (_) ____/__ / /_/ / / / _/ + echo / / / / __ \/ / / __/ _ \/ __/ / / // / + echo / /_/ / / / / / /_/ / __/ /_/ /_/ // / + echo \____/_/ /_/_/\____/\___/\__/\____/___/ + echo UniGetUI Package Installer Batch Script + echo Created with UniGetUI Version {{CoreData.VersionName}} + echo. + echo https://www.marticliment.com/unigetui + echo https://github.com/marticliment/UniGetUI + echo. + echo ======================================================== + echo. + echo NOTES: + echo ^ ^ - Packages will be installed with the install options specified at the time of creation of this batch file. + echo ^ ^ - The install process will not be as reliable as importing a package collection into UniGetUI. + echo ^ ^ - Error detection will be done through exit-code, so it may not be 100% accurate. + echo ^ ^ - Some of the packages may require elevation. Some of them may ask for permission, but others may fail. Consider running this script elevated. + echo ^ ^ - You can skip confirmation prompts by running this batch file with the parameter `/DisablePausePrompts` + echo. + echo. + IF NOT "%1"=="/DisablePausePrompts" (pause) + echo. + echo This script will install the following programs: + {{string.Join('\n', names.Select(x => $"echo ^ ^ - {x}"))}} + echo. + IF NOT "%1"=="/DisablePausePrompts" (pause) + cls + + set "success_count=0" + set "failure_count=0" + set "commands_run=0" + set "results=" + + set commands=^{{string.Join(",", commands.Select(x => $"\"cmd.exe /C {x}\""))}} + + :: ======================================================== + :: RUN COMMANDS AND TRACK RESULTS + :: ======================================================== + for %%C in (%commands%) do ( + echo Running: %%~C + call %%~C + if !errorlevel! EQU 0 ( + echo [SUCCESS] %%~C + set /a success_count+=1 + set "results=!results!✓ %%~C\r\n" + ) else ( + echo [FAILURE] %%~C + set /a failure_count+=1 + set "results=!results!✗ %%~C\r\n" + ) + set /a commands_run+=1 + echo. + ) + + echo ======================================================== + echo OPERATION SUMMARY + echo ======================================================== + echo Total commands run: %commands_run% + echo Successful: %success_count% + echo Failed: %failure_count% + echo. + echo Details: + echo !results! + echo ======================================================== + + if %failure_count% GTR 0 ( + echo Some commands failed. Please check the log above. + ) else ( + echo All commands executed successfully! + ) + echo. + IF NOT "%1"=="/DisablePausePrompts" (pause) + if %failure_count% GTR 0 (set errorlevel=1) else (set errorlevel=0) + endlocal + """; + } } } From 7ac59dca76090b2f16ed64fdef5ebf7554044932 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=AD=20Climent?= Date: Sun, 24 Aug 2025 12:11:33 +0200 Subject: [PATCH 2/7] Add support for pre-ops and post-ops, --- .../Pages/SoftwarePages/PackageBundlesPage.cs | 45 +++++++++++++------ 1 file changed, 31 insertions(+), 14 deletions(-) diff --git a/src/UniGetUI/Pages/SoftwarePages/PackageBundlesPage.cs b/src/UniGetUI/Pages/SoftwarePages/PackageBundlesPage.cs index 18e7dc3a6a..787e6e0c85 100644 --- a/src/UniGetUI/Pages/SoftwarePages/PackageBundlesPage.cs +++ b/src/UniGetUI/Pages/SoftwarePages/PackageBundlesPage.cs @@ -757,20 +757,37 @@ public async Task CreateBatchScript() string file = await Task.Run(() => (new FileSavePicker(MainApp.Instance.MainWindow.GetWindowHandle())).Show(["*.cmd", "*.bat"], defaultName)); if (file != String.Empty) { - // Loading dialog int loadingId = DialogHelper.ShowLoadingDialog(CoreTools.Translate("Saving packages, please wait...")); var packages = new List(); var commands = new List(); + var forceKill = Settings.Get(Settings.K.KillProcessesThatRefuseToDie); foreach (var _p in Loader.Packages) { if (_p is ImportedPackage package) { packages.Add(package.Name + " from " + package.Manager.DisplayName); - commands.Add( - package.Manager.Properties.ExecutableFriendlyName + " " + string.Join(' ', - package.Manager.OperationHelper.GetParameters(package, package.installation_options, OperationType.Install))); + + foreach (var process in package.installation_options.KillBeforeOperation) + { // Kill required processes, if any. Forcekill if the user has enable said option + commands.Add($"taskkill /im \"{process}\"" + (forceKill ? " /f" : "")); + } + + if (package.installation_options.PreInstallCommand != "") + { // Add pre-operation + commands.Add(package.installation_options.PreInstallCommand); + } + + // Add install command + var exeName = package.Manager.Properties.ExecutableFriendlyName; + var param = package.Manager.OperationHelper.GetParameters(package, package.installation_options, OperationType.Install) + commands.Add($"{exeName} {string.Join(' ',param)}"); + + if (package.installation_options.PostInstallCommand != "") + { // Add post-operation + commands.Add(package.installation_options.PostInstallCommand); + } } } @@ -801,7 +818,10 @@ private string GenerateCommandString(IReadOnlyList names, IReadOnlyList< return $$""" @echo off setlocal enabledelayedexpansion - + (set LF=^ + %=DO NOT REMOVE THIS=% + ) + echo. echo ======================================================== echo. @@ -813,22 +833,19 @@ echo __ __ _ ______ __ __ ______ echo UniGetUI Package Installer Batch Script echo Created with UniGetUI Version {{CoreData.VersionName}} echo. - echo https://www.marticliment.com/unigetui - echo https://github.com/marticliment/UniGetUI - echo. echo ======================================================== echo. echo NOTES: + echo ^ ^ - The install process will not be as reliable as importing a bundle with UniGetUI. Expect issues and errors. echo ^ ^ - Packages will be installed with the install options specified at the time of creation of this batch file. - echo ^ ^ - The install process will not be as reliable as importing a package collection into UniGetUI. - echo ^ ^ - Error detection will be done through exit-code, so it may not be 100% accurate. + echo ^ ^ - Error/Sucess detection may not be 100% accurate. echo ^ ^ - Some of the packages may require elevation. Some of them may ask for permission, but others may fail. Consider running this script elevated. echo ^ ^ - You can skip confirmation prompts by running this batch file with the parameter `/DisablePausePrompts` echo. echo. IF NOT "%1"=="/DisablePausePrompts" (pause) echo. - echo This script will install the following programs: + echo This script will attempt to install the following packages: {{string.Join('\n', names.Select(x => $"echo ^ ^ - {x}"))}} echo. IF NOT "%1"=="/DisablePausePrompts" (pause) @@ -850,11 +867,11 @@ echo Created with UniGetUI Version {{CoreData.VersionName}} if !errorlevel! EQU 0 ( echo [SUCCESS] %%~C set /a success_count+=1 - set "results=!results!✓ %%~C\r\n" + set "results=!results![ OK ] %%~C!LF!" ) else ( echo [FAILURE] %%~C set /a failure_count+=1 - set "results=!results!✗ %%~C\r\n" + set "results=!results![FAILED] %%~C!LF!" ) set /a commands_run+=1 echo. @@ -878,7 +895,7 @@ echo All commands executed successfully! ) echo. IF NOT "%1"=="/DisablePausePrompts" (pause) - if %failure_count% GTR 0 (set errorlevel=1) else (set errorlevel=0) + if %failure_count% GTR 0 (powershell.exe -Command "exit 1") else (powershell.exe -Command "exit 0") endlocal """; } From 5e7e133b4aeabbf8ea3432ee85ae13627f16e1b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=AD=20Climent?= Date: Sun, 24 Aug 2025 12:11:48 +0200 Subject: [PATCH 3/7] Extend usage of CoreTools.ShowFileOnExplorer() --- .../Controls/OperationWidgets/OperationControl.cs | 13 +------------ .../Pages/DialogPages/DesktopShortcuts.xaml.cs | 6 ++---- src/UniGetUI/Pages/LogPages/LogPage.xaml.cs | 6 +----- .../Pages/SoftwarePages/PackageBundlesPage.cs | 10 ++++------ 4 files changed, 8 insertions(+), 27 deletions(-) diff --git a/src/UniGetUI/Controls/OperationWidgets/OperationControl.cs b/src/UniGetUI/Controls/OperationWidgets/OperationControl.cs index e47d157444..451333cd39 100644 --- a/src/UniGetUI/Controls/OperationWidgets/OperationControl.cs +++ b/src/UniGetUI/Controls/OperationWidgets/OperationControl.cs @@ -669,18 +669,7 @@ public List GetOperationOptions() Text = CoreTools.Translate("Show in explorer"), IconName = IconType.OpenFolder, }; - showFileInExplorer.Click += (_, _) => - { - try - { - Process.Start("explorer.exe", "/select," + $"\"{downloadOp.DownloadLocation}\""); - } - catch (Exception ex) - { - Logger.Error($"An error occurred while attempting to show the file {downloadOp.DownloadLocation} on explorer."); - Logger.Error(ex); - } - }; + showFileInExplorer.Click += (_, _) => _ = CoreTools.ShowFileOnExplorer(downloadOp.DownloadLocation); showFileInExplorer.IsEnabled = downloadOp.Status is OperationStatus.Succeeded; optionsMenu.Add(showFileInExplorer); } diff --git a/src/UniGetUI/Pages/DialogPages/DesktopShortcuts.xaml.cs b/src/UniGetUI/Pages/DialogPages/DesktopShortcuts.xaml.cs index 70757b58c4..373c9bf633 100644 --- a/src/UniGetUI/Pages/DialogPages/DesktopShortcuts.xaml.cs +++ b/src/UniGetUI/Pages/DialogPages/DesktopShortcuts.xaml.cs @@ -7,6 +7,7 @@ using UniGetUI.PackageEngine.Classes.Packages.Classes; using UniGetUI.Pages.DialogPages; using UniGetUI.Core.SettingsEngine; +using UniGetUI.Core.Tools; // To learn more about WinUI, the WinUI project structure, // and more about our project templates, see: http://aka.ms/winui-project-info. @@ -158,10 +159,7 @@ public ShortcutEntry(string path, bool isDeletable) IsDeletable = isDeletable; } - public void OpenShortcutPath() - { - Process.Start("explorer.exe", "/select," + $"\"{Path}\""); - } + public void OpenShortcutPath() => _ = CoreTools.ShowFileOnExplorer(Path); public void ResetShortcut() { diff --git a/src/UniGetUI/Pages/LogPages/LogPage.xaml.cs b/src/UniGetUI/Pages/LogPages/LogPage.xaml.cs index 6d4840b576..acb869667d 100644 --- a/src/UniGetUI/Pages/LogPages/LogPage.xaml.cs +++ b/src/UniGetUI/Pages/LogPages/LogPage.xaml.cs @@ -87,11 +87,7 @@ public async Task _exportButton_Click() LogTextBox.SelectAll(); await File.WriteAllTextAsync(file.Path, LogTextBox.SelectedText); LogTextBox.Select(LogTextBox.SelectionStart, LogTextBox.SelectionStart); - Process.Start(new ProcessStartInfo - { - FileName = "explorer.exe", - Arguments = @$"/select, ""{file.Path}""" - }); + await CoreTools.ShowFileOnExplorer(file.Path); } } diff --git a/src/UniGetUI/Pages/SoftwarePages/PackageBundlesPage.cs b/src/UniGetUI/Pages/SoftwarePages/PackageBundlesPage.cs index 787e6e0c85..22f9f749db 100644 --- a/src/UniGetUI/Pages/SoftwarePages/PackageBundlesPage.cs +++ b/src/UniGetUI/Pages/SoftwarePages/PackageBundlesPage.cs @@ -533,13 +533,11 @@ public async Task SaveFile() DialogHelper.HideLoadingDialog(loadingId); - // Launch file - Process.Start(new ProcessStartInfo - { - FileName = "explorer.exe", - Arguments = @$"/select, ""{file}""" - }); + DialogHelper.ShowDismissableBalloon( + CoreTools.Translate("Success!"), + CoreTools.Translate("The bundle was created successfully on {0}", file)); + await CoreTools.ShowFileOnExplorer(file); HasUnsavedChanges = false; } From edb51a60d453fb723a65c8baea41ded333466125 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=AD=20Climent?= Date: Sun, 24 Aug 2025 12:12:13 +0200 Subject: [PATCH 4/7] Update PackageBundlesPage.cs --- src/UniGetUI/Pages/SoftwarePages/PackageBundlesPage.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/UniGetUI/Pages/SoftwarePages/PackageBundlesPage.cs b/src/UniGetUI/Pages/SoftwarePages/PackageBundlesPage.cs index 22f9f749db..01a7b3a446 100644 --- a/src/UniGetUI/Pages/SoftwarePages/PackageBundlesPage.cs +++ b/src/UniGetUI/Pages/SoftwarePages/PackageBundlesPage.cs @@ -779,7 +779,8 @@ public async Task CreateBatchScript() // Add install command var exeName = package.Manager.Properties.ExecutableFriendlyName; - var param = package.Manager.OperationHelper.GetParameters(package, package.installation_options, OperationType.Install) + var param = package.Manager.OperationHelper.GetParameters(package, + package.installation_options, OperationType.Install); commands.Add($"{exeName} {string.Join(' ',param)}"); if (package.installation_options.PostInstallCommand != "") From d5ddf37871a35460bf5009fe60108a37bce5f8e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=AD=20Climent?= Date: Sun, 24 Aug 2025 13:12:10 +0200 Subject: [PATCH 5/7] Migrate script from CMD to PowerShell --- .../Pages/SoftwarePages/PackageBundlesPage.cs | 157 +++++++++--------- 1 file changed, 76 insertions(+), 81 deletions(-) diff --git a/src/UniGetUI/Pages/SoftwarePages/PackageBundlesPage.cs b/src/UniGetUI/Pages/SoftwarePages/PackageBundlesPage.cs index 01a7b3a446..94021bd5c2 100644 --- a/src/UniGetUI/Pages/SoftwarePages/PackageBundlesPage.cs +++ b/src/UniGetUI/Pages/SoftwarePages/PackageBundlesPage.cs @@ -751,8 +751,8 @@ public async Task CreateBatchScript() { try { - string defaultName = CoreTools.Translate("Install batch script") + ".cmd"; - string file = await Task.Run(() => (new FileSavePicker(MainApp.Instance.MainWindow.GetWindowHandle())).Show(["*.cmd", "*.bat"], defaultName)); + string defaultName = CoreTools.Translate("Install script") + ".ps1"; + string file = await Task.Run(() => (new FileSavePicker(MainApp.Instance.MainWindow.GetWindowHandle())).Show(["*.ps1"], defaultName)); if (file != String.Empty) { int loadingId = DialogHelper.ShowLoadingDialog(CoreTools.Translate("Saving packages, please wait...")); @@ -815,87 +815,82 @@ public async Task CreateBatchScript() private string GenerateCommandString(IReadOnlyList names, IReadOnlyList commands) { return $$""" - @echo off - setlocal enabledelayedexpansion - (set LF=^ - %=DO NOT REMOVE THIS=% - ) - - echo. - echo ======================================================== - echo. - echo __ __ _ ______ __ __ ______ - echo / / / /___ (_) ____/__ / /_/ / / / _/ - echo / / / / __ \/ / / __/ _ \/ __/ / / // / - echo / /_/ / / / / / /_/ / __/ /_/ /_/ // / - echo \____/_/ /_/_/\____/\___/\__/\____/___/ - echo UniGetUI Package Installer Batch Script - echo Created with UniGetUI Version {{CoreData.VersionName}} - echo. - echo ======================================================== - echo. - echo NOTES: - echo ^ ^ - The install process will not be as reliable as importing a bundle with UniGetUI. Expect issues and errors. - echo ^ ^ - Packages will be installed with the install options specified at the time of creation of this batch file. - echo ^ ^ - Error/Sucess detection may not be 100% accurate. - echo ^ ^ - Some of the packages may require elevation. Some of them may ask for permission, but others may fail. Consider running this script elevated. - echo ^ ^ - You can skip confirmation prompts by running this batch file with the parameter `/DisablePausePrompts` - echo. - echo. - IF NOT "%1"=="/DisablePausePrompts" (pause) - echo. - echo This script will attempt to install the following packages: - {{string.Join('\n', names.Select(x => $"echo ^ ^ - {x}"))}} - echo. - IF NOT "%1"=="/DisablePausePrompts" (pause) - cls - - set "success_count=0" - set "failure_count=0" - set "commands_run=0" - set "results=" - - set commands=^{{string.Join(",", commands.Select(x => $"\"cmd.exe /C {x}\""))}} - - :: ======================================================== - :: RUN COMMANDS AND TRACK RESULTS - :: ======================================================== - for %%C in (%commands%) do ( - echo Running: %%~C - call %%~C - if !errorlevel! EQU 0 ( - echo [SUCCESS] %%~C - set /a success_count+=1 - set "results=!results![ OK ] %%~C!LF!" - ) else ( - echo [FAILURE] %%~C - set /a failure_count+=1 - set "results=!results![FAILED] %%~C!LF!" - ) - set /a commands_run+=1 - echo. + Clear-Host + Write-Host "" + Write-Host "========================================================" + Write-Host "" + Write-Host " __ __ _ ______ __ __ ______" -ForegroundColor Cyan + Write-Host " / / / /___ (_) ____/__ / /_/ / / / _/" -ForegroundColor Cyan + Write-Host " / / / / __ \/ / / __/ _ \/ __/ / / // /" -ForegroundColor Cyan + Write-Host " / /_/ / / / / / /_/ / __/ /_/ /_/ // /" -ForegroundColor Cyan + Write-Host " \____/_/ /_/_/\____/\___/\__/\____/___/" -ForegroundColor Cyan + Write-Host " UniGetUI Package Installer Batch Script" + Write-Host " Created with UniGetUI Version {{CoreData.VersionName}}" + Write-Host "" + Write-Host "========================================================" + Write-Host "" + Write-Host "NOTES:" -ForegroundColor Yellow + Write-Host " - The install process will not be as reliable as importing a bundle with UniGetUI. Expect issues and errors." -ForegroundColor Yellow + Write-Host " - Packages will be installed with the install options specified at the time of creation of this batch file." -ForegroundColor Yellow + Write-Host " - Error/Sucess detection may not be 100% accurate." -ForegroundColor Yellow + Write-Host " - Some of the packages may require elevation. Some of them may ask for permission, but others may fail. Consider running this script elevated." -ForegroundColor Yellow + Write-Host " - You can skip confirmation prompts by running this batch file with the parameter `/DisablePausePrompts` " -ForegroundColor Yellow + Write-Host "" + Write-Host "" + if ($args[0] -ne "/DisablePausePrompts") { pause } + Write-Host "" + Write-Host "This script will attempt to install the following packages:" + {{string.Join('\n', names.Select(x => $"Write-Host \" - {x}\""))}} + Write-Host "" + if ($args[0] -ne "/DisablePausePrompts") { pause } + Clear-Host + + $success_count=0 + $failure_count=0 + $commands_run=0 + $results="" + + $commands= @( + {{string.Join(",\n ", commands.Select(x => $"'cmd.exe /C {x.Replace("'", "''")}'"))}} ) - echo ======================================================== - echo OPERATION SUMMARY - echo ======================================================== - echo Total commands run: %commands_run% - echo Successful: %success_count% - echo Failed: %failure_count% - echo. - echo Details: - echo !results! - echo ======================================================== - - if %failure_count% GTR 0 ( - echo Some commands failed. Please check the log above. - ) else ( - echo All commands executed successfully! - ) - echo. - IF NOT "%1"=="/DisablePausePrompts" (pause) - if %failure_count% GTR 0 (powershell.exe -Command "exit 1") else (powershell.exe -Command "exit 0") - endlocal + foreach ($command in $commands) { + Write-Host "Running: $command" -ForegroundColor Yellow + cmd.exe /C $command + if ($LASTEXITCODE -eq 0) { + Write-Host "[ OK ] $command" -ForegroundColor Green + $success_count++ + $results += "$([char]0x1b)[32m[ OK ] $command`n" + } + else { + Write-Host "[ FAIL ] $command" -ForegroundColor Red + $failure_count++ + $results += "$([char]0x1b)[31m[ FAIL ] $command`n" + } + $commands_run++ + Write-Host "" + } + + Write-Host "========================================================" + Write-Host " OPERATION SUMMARY" + Write-Host "========================================================" + Write-Host "Total commands run: $commands_run" + Write-Host "Successful: $success_count" + Write-Host "Failed: $failure_count" + Write-Host "" + Write-Host "Details:" + Write-Host "$results$([char]0x1b)[37m" + Write-Host "========================================================" + + if ($failure_count -gt 0) { + Write-Host "Some commands failed. Please check the log above." -ForegroundColor Yellow + } + else { + Write-Host "All commands executed successfully!" -ForegroundColor Green + } + Write-Host "" + if ($args[0] -ne "/DisablePausePrompts") { pause } + exit $failure_count """; } } From fd72ddf1adb04c41fe23dc647cf6aec8548d96eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=AD=20Climent?= Date: Sun, 24 Aug 2025 13:57:49 +0200 Subject: [PATCH 6/7] Update PackageBundlesPage.cs --- src/UniGetUI/Pages/SoftwarePages/PackageBundlesPage.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/UniGetUI/Pages/SoftwarePages/PackageBundlesPage.cs b/src/UniGetUI/Pages/SoftwarePages/PackageBundlesPage.cs index 94021bd5c2..aa77d9e2e7 100644 --- a/src/UniGetUI/Pages/SoftwarePages/PackageBundlesPage.cs +++ b/src/UniGetUI/Pages/SoftwarePages/PackageBundlesPage.cs @@ -226,7 +226,7 @@ public override void GenerateToolBar() { InstallSkipHash, CoreTools.Translate("Skip integrity checks") }, { DownloadInstallers, CoreTools.Translate("Download selected installers") }, { OpenBundle, CoreTools.Translate("Open") }, - { ToBatchScript, CoreTools.Translate("Create batch script")}, + { ToBatchScript, CoreTools.Translate("Create .ps1 script")}, { RemoveSelected, CoreTools.Translate("Remove selection from bundle") }, { SaveBundle, CoreTools.Translate("Save as") }, { AddPackagesToBundle, CoreTools.Translate("Add packages to bundle") }, @@ -795,7 +795,7 @@ public async Task CreateBatchScript() DialogHelper.HideLoadingDialog(loadingId); DialogHelper.ShowDismissableBalloon( CoreTools.Translate("Success!"), - CoreTools.Translate("The batch file was created successfully on {0}", file)); + CoreTools.Translate("The installation script saved to {0}", file)); await CoreTools.ShowFileOnExplorer(file); } @@ -803,11 +803,11 @@ public async Task CreateBatchScript() catch (Exception ex) { DialogHelper.HideAllLoadingDialogs(); - Logger.Error("An error occurred while attempting to export a batch file"); + Logger.Error("An error occurred while attempting to export an installation script"); Logger.Error(ex); DialogHelper.ShowDismissableBalloon( CoreTools.Translate("An error occurred"), - CoreTools.Translate("An error occurred while attempting to create a installable batch file:") + " " + ex.Message); + CoreTools.Translate("An error occurred while attempting to create an installation script:") + " " + ex.Message); } } From b47d3e8837f6bc7a2cdbffb8e8c954d57170cf56 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=AD=20Climent?= Date: Sun, 24 Aug 2025 19:24:55 +0200 Subject: [PATCH 7/7] add telemetry support to batch script creation --- src/UniGetUI.Interface.Telemetry/TelemetryHandler.cs | 11 +++++++---- .../Pages/SoftwarePages/PackageBundlesPage.cs | 8 +++++--- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/src/UniGetUI.Interface.Telemetry/TelemetryHandler.cs b/src/UniGetUI.Interface.Telemetry/TelemetryHandler.cs index 6c5ff1133c..f02d5ba483 100644 --- a/src/UniGetUI.Interface.Telemetry/TelemetryHandler.cs +++ b/src/UniGetUI.Interface.Telemetry/TelemetryHandler.cs @@ -188,12 +188,15 @@ private static async void PackageEndpoint(IPackage package, string endpoint, TEL // ------------------------------------------------------------------------- public static void ImportBundle(BundleFormatType type) - => BundlesEndpoint("import", type); + => BundlesEndpoint("import", type.ToString()); public static void ExportBundle(BundleFormatType type) - => BundlesEndpoint("export", type); + => BundlesEndpoint("export", type.ToString()); - private static async void BundlesEndpoint(string endpoint, BundleFormatType type) + public static void ExportBatch() + => BundlesEndpoint("export", "PS1_SCRIPT"); + + private static async void BundlesEndpoint(string endpoint, string type) { try { @@ -204,7 +207,7 @@ private static async void BundlesEndpoint(string endpoint, BundleFormatType type var request = new HttpRequestMessage(HttpMethod.Post, $"{HOST}/bundles/{endpoint}"); request.Headers.Add("clientId", ID); - request.Headers.Add("bundleType", type.ToString()); + request.Headers.Add("bundleType", type); HttpClient _httpClient = new(CoreTools.GenericHttpClientParameters); HttpResponseMessage response = await _httpClient.SendAsync(request); diff --git a/src/UniGetUI/Pages/SoftwarePages/PackageBundlesPage.cs b/src/UniGetUI/Pages/SoftwarePages/PackageBundlesPage.cs index aa77d9e2e7..b271708cc1 100644 --- a/src/UniGetUI/Pages/SoftwarePages/PackageBundlesPage.cs +++ b/src/UniGetUI/Pages/SoftwarePages/PackageBundlesPage.cs @@ -797,6 +797,8 @@ public async Task CreateBatchScript() CoreTools.Translate("Success!"), CoreTools.Translate("The installation script saved to {0}", file)); + TelemetryHandler.ExportBatch(); + await CoreTools.ShowFileOnExplorer(file); } } @@ -824,17 +826,17 @@ private string GenerateCommandString(IReadOnlyList names, IReadOnlyList< Write-Host " / / / / __ \/ / / __/ _ \/ __/ / / // /" -ForegroundColor Cyan Write-Host " / /_/ / / / / / /_/ / __/ /_/ /_/ // /" -ForegroundColor Cyan Write-Host " \____/_/ /_/_/\____/\___/\__/\____/___/" -ForegroundColor Cyan - Write-Host " UniGetUI Package Installer Batch Script" + Write-Host " UniGetUI Package Installer Script" Write-Host " Created with UniGetUI Version {{CoreData.VersionName}}" Write-Host "" Write-Host "========================================================" Write-Host "" Write-Host "NOTES:" -ForegroundColor Yellow Write-Host " - The install process will not be as reliable as importing a bundle with UniGetUI. Expect issues and errors." -ForegroundColor Yellow - Write-Host " - Packages will be installed with the install options specified at the time of creation of this batch file." -ForegroundColor Yellow + Write-Host " - Packages will be installed with the install options specified at the time of creation of this script." -ForegroundColor Yellow Write-Host " - Error/Sucess detection may not be 100% accurate." -ForegroundColor Yellow Write-Host " - Some of the packages may require elevation. Some of them may ask for permission, but others may fail. Consider running this script elevated." -ForegroundColor Yellow - Write-Host " - You can skip confirmation prompts by running this batch file with the parameter `/DisablePausePrompts` " -ForegroundColor Yellow + Write-Host " - You can skip confirmation prompts by running this script with the parameter `/DisablePausePrompts` " -ForegroundColor Yellow Write-Host "" Write-Host "" if ($args[0] -ne "/DisablePausePrompts") { pause }