diff --git a/.github/workflows/build-release.yml b/.github/workflows/build-release.yml index b8cf0a2a80..1a375e2e36 100644 --- a/.github/workflows/build-release.yml +++ b/.github/workflows/build-release.yml @@ -36,7 +36,7 @@ jobs: steps: - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@v6 - name: Resolve build parameters id: info @@ -98,7 +98,7 @@ jobs: steps: - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@v6 - name: Install Windows SDK UAP platform shell: pwsh @@ -119,7 +119,7 @@ jobs: dotnet-version: 8.0.x - name: Install Python - uses: actions/setup-python@v5 + uses: actions/setup-python@v6 with: python-version: '3.x' @@ -149,7 +149,7 @@ jobs: - name: Restore WinGet CLI cache id: winget-cache - uses: actions/cache/restore@v4 + uses: actions/cache/restore@v5 with: path: src/UniGetUI.PackageEngine.Managers.WinGet/winget-cli_${{ matrix.platform }} key: winget-cli-${{ runner.os }}-${{ matrix.platform }}-${{ hashFiles('scripts/fetch-winget-cli.ps1') }} @@ -165,24 +165,24 @@ jobs: - name: Save WinGet CLI cache if: steps.winget-cache.outputs.cache-hit != 'true' - uses: actions/cache/save@v4 + uses: actions/cache/save@v5 with: path: src/UniGetUI.PackageEngine.Managers.WinGet/winget-cli_${{ matrix.platform }} key: ${{ steps.winget-cache.outputs.cache-primary-key }} - name: Restore dependencies working-directory: src - run: dotnet restore + run: dotnet restore UniGetUI.sln - name: Run tests working-directory: src shell: pwsh run: | # Retry once to handle flaky tests (e.g. TaskRecyclerTests uses Random) - dotnet test --no-restore --verbosity q --nologo + dotnet test UniGetUI.sln --no-restore --verbosity q --nologo if ($LASTEXITCODE -ne 0) { Write-Host "::warning::First test run failed, retrying..." - dotnet test --no-restore --verbosity q --nologo + dotnet test UniGetUI.sln --no-restore --verbosity q --nologo if ($LASTEXITCODE -ne 0) { exit 1 } } @@ -190,7 +190,7 @@ jobs: shell: pwsh run: | $Platform = '${{ matrix.platform }}' - dotnet publish src/UniGetUI/UniGetUI.csproj /noLogo /p:Configuration=Release /p:Platform=$Platform -v m + dotnet publish src/UniGetUI/UniGetUI.csproj /noLogo /p:Configuration=Release /p:Platform=$Platform -p:RuntimeIdentifier=win-$Platform -v m if ($LASTEXITCODE -ne 0) { throw "dotnet publish failed" } # Stage binaries @@ -276,7 +276,7 @@ jobs: -TimestampServer '${{ vars.CODE_SIGNING_TIMESTAMP_SERVER }}' - name: Upload artifacts - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v7 with: name: UniGetUI-release-${{ matrix.platform }} path: output/* @@ -298,7 +298,7 @@ jobs: steps: - name: Download artifacts - uses: actions/download-artifact@v4 + uses: actions/download-artifact@v8 with: path: output diff --git a/.github/workflows/dotnet-test.yml b/.github/workflows/dotnet-test.yml index 706c408bbe..4e2ad44ccb 100644 --- a/.github/workflows/dotnet-test.yml +++ b/.github/workflows/dotnet-test.yml @@ -34,12 +34,25 @@ jobs: with: dotnet-version: 8.0.x + - name: Install Windows SDK UAP platform + shell: pwsh + run: | + # CsWinRT in WindowsPackageManager.Interop requires UAP 10.0.19041.0 platform metadata + $VsWhere = "${env:ProgramFiles(x86)}\Microsoft Visual Studio\Installer\vswhere.exe" + $VsInstaller = "${env:ProgramFiles(x86)}\Microsoft Visual Studio\Installer\vs_installer.exe" + $InstallPath = & $VsWhere -latest -property installationPath + & $VsInstaller modify --installPath $InstallPath ` + --add Microsoft.VisualStudio.Component.UWP.Support ` + --add Microsoft.VisualStudio.Component.Windows10SDK.19041 ` + --quiet --norestart --nocache | Out-Default + Write-Host "Windows SDK UAP platform installed" + # - name: Install WinGet # uses: Cyberboss/install-winget@v1 - name: Install dependencies working-directory: src - run: dotnet restore + run: dotnet restore UniGetUI.sln # - name: Test build # working-directory: src @@ -47,5 +60,5 @@ jobs: - name: Run Tests working-directory: src - run: dotnet test --no-restore --verbosity q --nologo + run: dotnet test UniGetUI.sln --no-restore --verbosity q --nologo diff --git a/AGENTS.md b/AGENTS.md index 300450b028..acf1345332 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,4 +1,4 @@ -# UniGetUI – Copilot Instructions +# UniGetUI - Copilot Instructions ## Project Overview @@ -8,13 +8,13 @@ UniGetUI is a WinUI 3 desktop app (C#/.NET 8, Windows App SDK) providing a GUI f The codebase follows a **layered, modular structure** with ~40 projects: -- **`UniGetUI/`** – WinUI 3 entry point, XAML pages, controls, and app shell (`EntryPoint.cs`, `MainWindow.xaml`) -- **`UniGetUI.Core.*`** – Shared infrastructure: `Logger`, `Settings`, `Tools` (includes `CoreTools.Translate()`), `IconEngine`, `LanguageEngine` -- **`UniGetUI.PackageEngine.Interfaces`** – Contracts: `IPackageManager`, `IPackage`, `IManagerSource`, `IPackageDetails` -- **`UniGetUI.PackageEngine.PackageManagerClasses`** – Base implementations: `PackageManager` (abstract), `Package`, helpers (`BasePkgDetailsHelper`, `BasePkgOperationHelper`, `BaseSourceHelper`) -- **`UniGetUI.PackageEngine.Managers.*`** – Concrete manager implementations (one project per manager: `WinGet`, `Scoop`, `Chocolatey`, `Pip`, `Npm`, etc.) -- **`UniGetUI.PackageEngine.Operations`** – Install/update/uninstall operation orchestration -- **`UniGetUI.Interface.*`** – Enums, telemetry, background API +- **`UniGetUI/`** - WinUI 3 entry point, XAML pages, controls, and app shell (`EntryPoint.cs`, `MainWindow.xaml`) +- **`UniGetUI.Core.*`** - Shared infrastructure: `Logger`, `Settings`, `Tools` (includes `CoreTools.Translate()`), `IconEngine`, `LanguageEngine` +- **`UniGetUI.PackageEngine.Interfaces`** - Contracts: `IPackageManager`, `IPackage`, `IManagerSource`, `IPackageDetails` +- **`UniGetUI.PackageEngine.PackageManagerClasses`** - Base implementations: `PackageManager` (abstract), `Package`, helpers (`BasePkgDetailsHelper`, `BasePkgOperationHelper`, `BaseSourceHelper`) +- **`UniGetUI.PackageEngine.Managers.*`** - Concrete manager implementations (one project per manager: `WinGet`, `Scoop`, `Chocolatey`, `Pip`, `Npm`, etc.) +- **`UniGetUI.PackageEngine.Operations`** - Install/update/uninstall operation orchestration +- **`UniGetUI.Interface.*`** - Enums, telemetry, background API ## Adding a New Package Manager @@ -27,9 +27,9 @@ protected override IReadOnlyList GetInstalledPackages_UnSafe(); ``` Each manager also provides three helper classes (in a `Helpers/` subfolder): -- `*PkgDetailsHelper` extends `BasePkgDetailsHelper` – overrides `GetDetails_UnSafe`, `GetInstallableVersions_UnSafe`, `GetIcon_UnSafe`, etc. -- `*PkgOperationHelper` extends `BasePkgOperationHelper` – overrides `_getOperationParameters`, `_getOperationResult` -- `*SourceHelper` extends `BaseSourceHelper` – overrides `GetSources_UnSafe`, `GetAddSourceParameters`, etc. +- `*PkgDetailsHelper` extends `BasePkgDetailsHelper` - overrides `GetDetails_UnSafe`, `GetInstallableVersions_UnSafe`, `GetIcon_UnSafe`, etc. +- `*PkgOperationHelper` extends `BasePkgOperationHelper` - overrides `_getOperationParameters`, `_getOperationResult` +- `*SourceHelper` extends `BaseSourceHelper` - overrides `GetSources_UnSafe`, `GetAddSourceParameters`, etc. The constructor sets `Capabilities`, `Properties`, and wires the helpers. See `src/UniGetUI.PackageEngine.Managers.Scoop/Scoop.cs` as a clean reference implementation. @@ -42,13 +42,10 @@ dotnet test --verbosity q --nologo # Publish release build dotnet publish src/UniGetUI/UniGetUI.csproj /p:Configuration=Release /p:Platform=x64 - -# Full release (runs version script, tests, publish, installer) -build_release.cmd ``` - Target framework: `net8.0-windows10.0.26100.0` (min `10.0.19041`) -- Build generates secrets via `src/UniGetUI/Services/generate-secrets.ps1` and integrity tree via `scripts/generate_integrity_tree.py` +- Build generates secrets via `src/UniGetUI/Services/generate-secrets.ps1` and integrity tree via `scripts/generate-integrity-tree.ps1` - Self-contained, publish-trimmed (partial), Windows App SDK self-contained - Tests use **xUnit** (`[Fact]`, `Assert.*`) @@ -72,7 +69,7 @@ Use `CoreTools.Translate("text")` for all user-facing strings. Parameterized: `C ### Manager conventions - `FALSE_PACKAGE_NAMES`, `FALSE_PACKAGE_IDS`, `FALSE_PACKAGE_VERSIONS` static arrays filter CLI parsing noise -- Manager initialization flows through `Initialize()` → `_loadManagerExecutableFile()` → `_loadManagerVersion()` → `_performExtraLoadingSteps()` +- Manager initialization flows through `Initialize()` -> `_loadManagerExecutableFile()` -> `_loadManagerVersion()` -> `_performExtraLoadingSteps()` - Operations that may fail return `OperationVeredict` (note: intentional misspelling used throughout codebase) ## Key Files diff --git a/build_release.cmd b/build_release.cmd deleted file mode 100644 index 0a8777c38c..0000000000 --- a/build_release.cmd +++ /dev/null @@ -1,85 +0,0 @@ -@echo off - -rem update resources -python scripts/apply_versions.py - -rem pushd scripts -rem python download_translations.py -rem popd .. - -rem clean old builds -taskkill /im wingetui.exe /f -taskkill /im unigetui.exe /f - -rem Run tests -dotnet test src/UniGetUI.sln -v q --nologo - -rem check exit code of the last command -if %errorlevel% neq 0 ( - echo "The tests failed!." - pause -) - -rem build executable -dotnet clean src/UniGetUI.sln -v m -nologo -dotnet publish src/UniGetUI/UniGetUI.csproj /noLogo /property:Configuration=Release /property:Platform=x64 -v m -if %errorlevel% neq 0 ( - echo "DotNet publish has failed!" - pause -) -rem sign code - -rmdir /Q /S unigetui_bin - -mkdir unigetui_bin -robocopy src\UniGetUI\bin\x64\Release\net8.0-windows10.0.26100.0\win-x64\publish unigetui_bin *.* /MOVE /E - - -set /p signfiles="Do you want to sign the files? [Y/n]: " -if /i "%signfiles%" neq "n" ( - %signcommand% "unigetui_bin/UniGetUI.exe" "unigetui_bin/*.dll" - - if %errorlevel% neq 0 ( - echo "Signing has failed!" - pause - ) -) - -pushd unigetui_bin -copy UniGetUI.exe WingetUI.exe -popd - - -rem Generate integrity -python3 scripts\generate_integrity_tree.py %cd%\unigetui_bin - -rmdir /q /s output -mkdir output -cd unigetui_bin -7z a -tzip "..\output\UniGetUI.x64.zip" "*" -cd .. -if %errorlevel% neq 0 ( - echo "Compression of unigetui_bin into output/UniGetUI.x64.zip has failed!" - pause -) - -set INSTALLATOR="%localappdata%\Programs\Inno Setup 6\ISCC.exe" -if exist %INSTALLATOR% ( - %INSTALLATOR% "UniGetUI.iss" - move "UniGetUI Installer.exe" "UniGetUI.Installer.exe" - del "WingetUI.Installer.exe" - copy "UniGetUI.Installer.exe" "WingetUI.Installer.exe" - move "UniGetUI.Installer.exe" output\ - move "WingetUI.Installer.exe" output\ - rmdir /q /s unigetui_bin - - pwsh.exe -Command echo """UniGetUI.Installer.exe SHA256: ``$((Get-FileHash 'output\UniGetUI.Installer.exe').Hash)``""" - pwsh.exe -Command echo """UniGetUI.x64.zip SHA256: ``$((Get-FileHash 'output\UniGetUI.x64.zip').Hash)``""" - echo . - pause - "output\UniGetUI.Installer.exe" -) else ( - echo "Make installer was skipped, because the installer is missing." -) - -pause diff --git a/scripts/apply_versions.py b/scripts/apply_versions.py deleted file mode 100644 index faf4955e35..0000000000 --- a/scripts/apply_versions.py +++ /dev/null @@ -1,88 +0,0 @@ -import os -import glob - -os.chdir(os.path.join(os.path.dirname(__file__), "..")) # move to root project - -try: - # floatval = input("Enter version code (X.XXX) : ") - # versionCode = float(floatval) - versionName = str(input("Enter version name (string) : ")) - - if versionName == "": - print("Version changer script aborted") - exit() - - BuildNumber = -1 - c = "" - if os.path.exists("scripts/BuildNumber"): - with open("scripts/BuildNumber", "r") as f: - c = f.read() - - BuildNumber = int(c) if c != "" else int(input("Build number file was empty. Insert (integer) build number: "))-1 - print(f"Build number set to {BuildNumber+1}") - with open("scripts/BuildNumber", "w") as f: - f.write(str(BuildNumber+1)) - - - versionISS = str(input("Enter version (X.X.X.X) : ")) - while not versionISS.count('.') == 3: - versionISS = str(input("Incorrect format. Enter version (X.X.X.X) : ")) - - def fileReplaceLinesWith(filename: str, list: dict[str, str], encoding="utf-8"): - with open(filename, "r+", encoding=encoding, errors="ignore") as f: - data = "" - for line in f.readlines(): - match = False - for key, value in list.items(): - if (key in line): - data += f"{key}{value}" - match = True - continue - if (not match): - data += line - f.seek(0) - f.write(data) - f.truncate() - - fileReplaceLinesWith("src/UniGetUI.Core.Data/CoreData.cs", { - " public const string VersionName =": f" \"{versionName}\"; // Do not modify this line, use file scripts/apply_versions.py\n", - " public const int BuildNumber =": f" {BuildNumber+1}; // Do not modify this line, use file scripts/apply_versions.py\n", - }, encoding="utf-8-sig") - - - fileReplaceLinesWith("src/SharedAssemblyInfo.cs", { - "[assembly: AssemblyVersion(\"": f"{versionISS}\")]\n", - "[assembly: AssemblyFileVersion(\"": f"{versionISS}\")]\n", - "[assembly: AssemblyInformationalVersion(\"": f"{versionName}\")]\n", - "[assembly: AssemblyInformationalVersionAttribute(\"": f"{versionName}\")]\n", - "[assembly: AssemblyVersionAttribute(\"": f"{versionISS}\")]\n", - # Your replacement dictionary here - }, encoding="utf-8-sig") - - fileReplaceLinesWith("UniGetUI.iss", { - "#define MyAppVersion": f" \"{versionName}\"\n", - "VersionInfoVersion=": f"{versionISS}\n", - "VersionInfoProductVersion=": f"{versionISS}\n", - }, encoding="utf-8-sig") - - IS_BETA = (input("Is this a beta release? [y/N]: ").lower().strip() == "y") - - BETA_APP_NAME = "UniGetUI (PreRelease)" - STABLE_APP_NAME = "UniGetUI" - - fileReplaceLinesWith("UniGetUI.iss", { - "UninstallDisplayName=\"": f"{BETA_APP_NAME if IS_BETA else STABLE_APP_NAME}\"\n", - }, encoding="utf-8-sig") - - fileReplaceLinesWith("src/UniGetUI/app.manifest", { - " version=": f" \"{versionISS}\"\n", - }, encoding="utf-8-sig") - - print("done!") - -except FileNotFoundError as e: - print(f"Error: {e.strerror}: {e.filename}") - os.system("pause") -except Exception as e: - print(f"Error: {str(e)}") - os.system("pause") diff --git a/scripts/generate_integrity_tree.py b/scripts/generate_integrity_tree.py deleted file mode 100644 index f1e18e92ed..0000000000 --- a/scripts/generate_integrity_tree.py +++ /dev/null @@ -1,41 +0,0 @@ -import os, sys -import json -import hashlib -try: - - if len(sys.argv) < 2: - raise ValueError("A directory path must be provided as an argument.") - - root_dir: str = sys.argv[1] - if not os.path.isdir(root_dir): - raise FileNotFoundError(f"The directory '{root_dir}' does not exist.") - - integrity_data = {} - script_name = os.path.basename(__file__) - output_filename = "IntegrityTree.json" - - for subdir, _, files in os.walk(root_dir): - for filename in files: - if filename == script_name or filename == output_filename: - continue - - file_path = os.path.join(subdir, filename) - relative_path = os.path.relpath(file_path, root_dir).replace('\\', '/') - if("--min-output" not in sys.argv): print(f" - Computing MD5SUM of {relative_path}...") - - with open(file_path, 'rb') as f: - md5_hash = hashlib.md5(f.read()) - - integrity_data[relative_path] = md5_hash.hexdigest() - - output_file_path = os.path.join(root_dir, output_filename) - with open(output_file_path, 'w') as f: - json.dump(integrity_data, f, indent=4, sort_keys=True) - - print(f"Integrity tree was generated and saved to {root_dir.strip('/')}/{output_filename}") - - - -except Exception as e: - print(e) - os.system("pause") \ No newline at end of file diff --git a/scripts/set-version.ps1 b/scripts/set-version.ps1 index 6478281019..012b53f64e 100644 --- a/scripts/set-version.ps1 +++ b/scripts/set-version.ps1 @@ -2,7 +2,7 @@ <# .SYNOPSIS Stamps version information into all required source files. - CI-friendly replacement for the interactive scripts/apply_versions.py. + CI-friendly version stamping script for local builds and CI. .PARAMETER Version Semantic version string, e.g. "3.3.7" or "3.4.0-beta1". @@ -68,8 +68,8 @@ function Set-LinesByPrefix { # --- CoreData.cs --- Set-LinesByPrefix -FilePath (Join-Path $RepoRoot "src" "UniGetUI.Core.Data" "CoreData.cs") -Replacements @{ - 'public const string VersionName =' = " public const string VersionName = `"$Version`"; // Do not modify this line, use file scripts/apply_versions.py" - 'public const int BuildNumber =' = " public const int BuildNumber = $BuildNumber; // Do not modify this line, use file scripts/apply_versions.py" + 'public const string VersionName =' = " public const string VersionName = `"$Version`"; // Do not modify this line, use file scripts/set-version.ps1" + 'public const int BuildNumber =' = " public const int BuildNumber = $BuildNumber; // Do not modify this line, use file scripts/set-version.ps1" } # --- SharedAssemblyInfo.cs --- @@ -90,7 +90,7 @@ Set-LinesByPrefix -FilePath (Join-Path $RepoRoot "UniGetUI.iss") -Replacements @ $ManifestPath = Join-Path $RepoRoot "src" "UniGetUI" "app.manifest" if (Test-Path $ManifestPath) { $content = Get-Content $ManifestPath -Raw -Encoding utf8BOM - $content = $content -Replace '(? enable - net8.0-windows10.0.26100.0 - 10.0.19041.0 - 10.0.26100.56 8.0.407 Devolutions Inc. and the contributors @@ -14,10 +11,31 @@ + net8.0 + 10.0.26100.0 + $(PortableTargetFramework)-windows$(WindowsTargetPlatformVersion) + + + + true + $(PortableTargetFramework);$(WindowsTargetFramework) + $(PortableTargetFramework) + + + + $(SharedTargetFrameworks) + + + + 10.0.19041.0 + 10.0.26100.56 true win-x64;win-arm64 - win-$(Platform) - x64 + win-$(Platform) + + + + x64;arm64 true false Debug;Release diff --git a/src/ExternalLibraries.Clipboard/ExternalLibraries.Clipboard.csproj b/src/ExternalLibraries.Clipboard/ExternalLibraries.Clipboard.csproj index 1b70e7392e..1c504771f0 100644 --- a/src/ExternalLibraries.Clipboard/ExternalLibraries.Clipboard.csproj +++ b/src/ExternalLibraries.Clipboard/ExternalLibraries.Clipboard.csproj @@ -1,5 +1,10 @@  + + $(WindowsTargetFramework) + + + diff --git a/src/ExternalLibraries.FilePickers/ExternalLibraries.FilePickers.csproj b/src/ExternalLibraries.FilePickers/ExternalLibraries.FilePickers.csproj index 1b70e7392e..1c504771f0 100644 --- a/src/ExternalLibraries.FilePickers/ExternalLibraries.FilePickers.csproj +++ b/src/ExternalLibraries.FilePickers/ExternalLibraries.FilePickers.csproj @@ -1,5 +1,10 @@  + + $(WindowsTargetFramework) + + + diff --git a/src/SharedAssemblyInfo.cs b/src/SharedAssemblyInfo.cs index 4415200dfa..f7c98c2905 100644 --- a/src/SharedAssemblyInfo.cs +++ b/src/SharedAssemblyInfo.cs @@ -1,5 +1,7 @@ using System.Reflection; +#if WINDOWS using System.Runtime.Versioning; +#endif [assembly: AssemblyProduct("UniGetUI")] [assembly: AssemblyDescription("UniGetUI")] @@ -9,4 +11,6 @@ [assembly: AssemblyVersion("3.3.7.0")] [assembly: AssemblyFileVersion("3.3.7.0")] [assembly: AssemblyInformationalVersion("3.3.7")] +#if WINDOWS [assembly: SupportedOSPlatform("windows10.0.19041")] +#endif diff --git a/src/UniGetUI.Avalonia.slnx b/src/UniGetUI.Avalonia.slnx new file mode 100644 index 0000000000..bd919bdeb9 --- /dev/null +++ b/src/UniGetUI.Avalonia.slnx @@ -0,0 +1,204 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/UniGetUI.Core.Classes.Tests/UniGetUI.Core.Classes.Tests.csproj b/src/UniGetUI.Core.Classes.Tests/UniGetUI.Core.Classes.Tests.csproj index 466532b205..2820a5963b 100644 --- a/src/UniGetUI.Core.Classes.Tests/UniGetUI.Core.Classes.Tests.csproj +++ b/src/UniGetUI.Core.Classes.Tests/UniGetUI.Core.Classes.Tests.csproj @@ -1,6 +1,8 @@ + $(PortableTargetFramework) + false true diff --git a/src/UniGetUI.Core.Classes/UniGetUI.Core.Classes.csproj b/src/UniGetUI.Core.Classes/UniGetUI.Core.Classes.csproj index 9791ba7566..37104013bb 100644 --- a/src/UniGetUI.Core.Classes/UniGetUI.Core.Classes.csproj +++ b/src/UniGetUI.Core.Classes/UniGetUI.Core.Classes.csproj @@ -1,7 +1,5 @@ - - diff --git a/src/UniGetUI.Core.Data.Tests/UniGetUI.Core.Data.Tests.csproj b/src/UniGetUI.Core.Data.Tests/UniGetUI.Core.Data.Tests.csproj index bcb4ded59d..37eb555bba 100644 --- a/src/UniGetUI.Core.Data.Tests/UniGetUI.Core.Data.Tests.csproj +++ b/src/UniGetUI.Core.Data.Tests/UniGetUI.Core.Data.Tests.csproj @@ -1,5 +1,10 @@ + + $(PortableTargetFramework) + + + diff --git a/src/UniGetUI.Core.Data/CoreCredentialStore.cs b/src/UniGetUI.Core.Data/CoreCredentialStore.cs new file mode 100644 index 0000000000..e0e281d3f3 --- /dev/null +++ b/src/UniGetUI.Core.Data/CoreCredentialStore.cs @@ -0,0 +1,107 @@ +using System.Net; +using System.Security.Cryptography; +using System.Text; +using UniGetUI.Core.Logging; +#if WINDOWS +using Windows.Security.Credentials; +#endif + +namespace UniGetUI.Core.Data; + +public static class CoreCredentialStore +{ + public static NetworkCredential? GetCredential(string resourceName, string userName) + { + string? secret = GetSecret(resourceName, userName); + return secret is null + ? null + : new NetworkCredential + { + UserName = userName, + Password = secret, + }; + } + + public static void SetCredential(string resourceName, string userName, string password) + => SetSecret(resourceName, userName, password); + + public static string? GetSecret(string resourceName, string userName) + { + try + { +#if WINDOWS + var vault = new PasswordVault(); + var credential = vault.Retrieve(resourceName, userName); + credential.RetrievePassword(); + return credential.Password; +#else + string secretPath = GetSecretPath(resourceName, userName); + return File.Exists(secretPath) ? File.ReadAllText(secretPath) : null; +#endif + } + catch (Exception ex) + { + Logger.Warn($"Unable to retrieve secret for resource '{resourceName}': {ex.Message}"); + return null; + } + } + + public static void SetSecret(string resourceName, string userName, string secret) + { + try + { +#if WINDOWS + DeleteSecret(resourceName, userName); + var vault = new PasswordVault(); + vault.Add(new PasswordCredential(resourceName, userName, secret)); +#else + string storageDirectory = GetStorageDirectory(); + Directory.CreateDirectory(storageDirectory); + File.WriteAllText(GetSecretPath(resourceName, userName), secret); +#endif + } + catch (Exception ex) + { + Logger.Error($"Unable to persist secret for resource '{resourceName}'"); + Logger.Error(ex); + } + } + + public static void DeleteSecret(string resourceName, string userName) + { + try + { +#if WINDOWS + var vault = new PasswordVault(); + IReadOnlyList credentials = vault.FindAllByResource(resourceName) ?? []; + foreach (PasswordCredential credential in credentials.Where(credential => credential.UserName == userName)) + { + vault.Remove(credential); + } +#else + string secretPath = GetSecretPath(resourceName, userName); + if (File.Exists(secretPath)) + { + File.Delete(secretPath); + } +#endif + } + catch (Exception ex) + { + Logger.Error($"Unable to delete secret for resource '{resourceName}'"); + Logger.Error(ex); + } + } + + private static string GetStorageDirectory() + => Path.Join(CoreData.UniGetUIDataDirectory, "SecureStorage"); + + private static string GetSecretPath(string resourceName, string userName) + => Path.Join(GetStorageDirectory(), GetStableFileName(resourceName, userName)); + + private static string GetStableFileName(string resourceName, string userName) + { + byte[] hash = SHA256.HashData(Encoding.UTF8.GetBytes($"{resourceName}\n{userName}")); + return Convert.ToHexString(hash) + ".secret"; + } +} \ No newline at end of file diff --git a/src/UniGetUI.Core.Data/CoreData.cs b/src/UniGetUI.Core.Data/CoreData.cs index e20fd01e45..53838dd914 100644 --- a/src/UniGetUI.Core.Data/CoreData.cs +++ b/src/UniGetUI.Core.Data/CoreData.cs @@ -1,4 +1,5 @@ using System.Diagnostics; +using System.Text; using UniGetUI.Core.Logging; namespace UniGetUI.Core.Data @@ -7,8 +8,8 @@ public static class CoreData { private static int? __code_page; public static int CODE_PAGE { get => __code_page ??= GetCodePage(); } - public const string VersionName = "3.3.7"; // Do not modify this line, use file scripts/apply_versions.py - public const int BuildNumber = 106; // Do not modify this line, use file scripts/apply_versions.py + public const string VersionName = "3.3.7"; // Do not modify this line, use file scripts/set-version.ps1 + public const int BuildNumber = 106; // Do not modify this line, use file scripts/set-version.ps1 public const string UserAgentString = $"UniGetUI/{VersionName} (https://marticliment.com/unigetui/; contact@marticliment.com)"; @@ -62,7 +63,7 @@ public static string UniGetUIDataDirectory } string old_path = Path.Join(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".wingetui"); - string new_path = Path.Join(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "UniGetUI"); + string new_path = Path.Join(GetLocalDataRoot(), "UniGetUI"); return GetNewDataDirectoryOrMoveOld(old_path, new_path); } } @@ -190,8 +191,9 @@ public static string UniGetUI_DefaultBackupDirectory { get { - string old_dir = Path.Join(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "WingetUI"); - string new_dir = Path.Join(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "UniGetUI"); + string documentsDirectory = GetDocumentsRoot(); + string old_dir = Path.Join(documentsDirectory, "WingetUI"); + string new_dir = Path.Join(documentsDirectory, "UniGetUI"); return GetNewDataDirectoryOrMoveOld(old_dir, new_dir); } } @@ -227,7 +229,7 @@ public static string UniGetUIExecutableDirectory Logger.Error("System.Reflection.Assembly.GetExecutingAssembly().Location returned an empty path"); - return Path.Join(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles), "UniGetUI"); + return AppContext.BaseDirectory.TrimEnd(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar); } } @@ -241,12 +243,14 @@ public static string UniGetUIExecutableFile string? filename = Process.GetCurrentProcess().MainModule?.FileName; if (filename is not null) { - return filename.Replace(".dll", ".exe"); + return NormalizeExecutablePath(filename); } Logger.Error("System.Reflection.Assembly.GetExecutingAssembly().Location returned an empty path"); - return Path.Join(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles), "UniGetUI", "UniGetUI.exe"); + return OperatingSystem.IsWindows() + ? Path.Join(UniGetUIExecutableDirectory, "UniGetUI.exe") + : NormalizeExecutablePath(Path.Join(UniGetUIExecutableDirectory, "UniGetUI")); } } @@ -357,6 +361,11 @@ private static string GetNewDataDirectoryOrMoveOld(string old_path, string new_p private static int GetCodePage() { + if (!OperatingSystem.IsWindows()) + { + return Encoding.UTF8.CodePage; + } + try { using Process p = new Process @@ -390,6 +399,57 @@ private static int GetCodePage() } } - public static readonly string PowerShell5 = Path.Join(Environment.SystemDirectory, "windowspowershell\\v1.0\\powershell.exe"); + public static readonly string PowerShell5 = OperatingSystem.IsWindows() + ? Path.Join(Environment.SystemDirectory, "windowspowershell\\v1.0\\powershell.exe") + : "pwsh"; + + private static string GetLocalDataRoot() + { + string localApplicationData = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData); + if (!string.IsNullOrWhiteSpace(localApplicationData)) + { + return localApplicationData; + } + + string? xdgDataHome = Environment.GetEnvironmentVariable("XDG_DATA_HOME"); + if (!string.IsNullOrWhiteSpace(xdgDataHome)) + { + return xdgDataHome; + } + + return Path.Join(GetUserHomeDirectory(), ".local", "share"); + } + + private static string GetDocumentsRoot() + { + string documentsDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments); + if (!string.IsNullOrWhiteSpace(documentsDirectory)) + { + return documentsDirectory; + } + + return Path.Join(GetUserHomeDirectory(), "Documents"); + } + + private static string GetUserHomeDirectory() + { + string userProfile = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile); + if (!string.IsNullOrWhiteSpace(userProfile)) + { + return userProfile; + } + + return Environment.GetEnvironmentVariable("HOME") ?? AppContext.BaseDirectory; + } + + private static string NormalizeExecutablePath(string path) + { + if (OperatingSystem.IsWindows() && path.EndsWith(".dll", StringComparison.OrdinalIgnoreCase)) + { + return Path.ChangeExtension(path, ".exe"); + } + + return path; + } } } diff --git a/src/UniGetUI.Core.Data/UniGetUI.Core.Data.csproj b/src/UniGetUI.Core.Data/UniGetUI.Core.Data.csproj index 43e50dfde6..2329f02494 100644 --- a/src/UniGetUI.Core.Data/UniGetUI.Core.Data.csproj +++ b/src/UniGetUI.Core.Data/UniGetUI.Core.Data.csproj @@ -1,7 +1,5 @@ - - diff --git a/src/UniGetUI.Core.IconEngine.Tests/UniGetUI.Core.IconEngine.Tests.csproj b/src/UniGetUI.Core.IconEngine.Tests/UniGetUI.Core.IconEngine.Tests.csproj index fc6796b6fd..f523803f79 100644 --- a/src/UniGetUI.Core.IconEngine.Tests/UniGetUI.Core.IconEngine.Tests.csproj +++ b/src/UniGetUI.Core.IconEngine.Tests/UniGetUI.Core.IconEngine.Tests.csproj @@ -3,6 +3,8 @@ + $(PortableTargetFramework) + false true diff --git a/src/UniGetUI.Core.IconStore/IconCacheEngine.cs b/src/UniGetUI.Core.IconStore/IconCacheEngine.cs index 3444e2754f..3a0c5140a4 100644 --- a/src/UniGetUI.Core.IconStore/IconCacheEngine.cs +++ b/src/UniGetUI.Core.IconStore/IconCacheEngine.cs @@ -1,4 +1,3 @@ -extern alias DrawingCommon; using System.Collections.ObjectModel; using System.Security.Cryptography; using PhotoSauce.MagicScaler; @@ -232,7 +231,7 @@ cachedIconFile is not null && if (icon.ValidationMethod is IconValidationMethod.PackageVersion or IconValidationMethod.UriSource && new[] { "png", "webp", "tif", "avif" }.Contains(extension)) { - DownsizeImage(cachedIconFile, extension); + DownsizeImage(cachedIconFile); } Logger.Debug($"Icon for Location={iconLocation} has been downloaded and verified properly (if applicable) ({icon.ValidationMethod})"); @@ -253,19 +252,15 @@ cachedIconFile is not null && /// /// The given image will be downsized to the expected size of an icon, if required /// - private static void DownsizeImage(string cachedIconFile, string extension) - { // Yes, the extension parameter could be extracted from cachedIconFile + private static void DownsizeImage(string cachedIconFile) + { try { const int MAX_SIDE = 192; - int width, height; - - using (var fileStream = new FileStream(cachedIconFile, FileMode.Open, FileAccess.Read, FileShare.Read)) - using (var image = DrawingCommon.System.Drawing.Image.FromStream(fileStream, false, false)) - { - height = image.Height; - width = image.Width; - } + ImageFileInfo imageInfo = ImageFileInfo.Load(cachedIconFile); + ImageFileInfo.FrameInfo frameInfo = imageInfo.Frames[0]; + int width = frameInfo.Width; + int height = frameInfo.Height; // Calculate target size for the icon to be at max 192x192. if (width > MAX_SIDE || height > MAX_SIDE) diff --git a/src/UniGetUI.Core.IconStore/UniGetUI.Core.IconEngine.csproj b/src/UniGetUI.Core.IconStore/UniGetUI.Core.IconEngine.csproj index 3e9fb7beeb..e8ce530823 100644 --- a/src/UniGetUI.Core.IconStore/UniGetUI.Core.IconEngine.csproj +++ b/src/UniGetUI.Core.IconStore/UniGetUI.Core.IconEngine.csproj @@ -13,7 +13,6 @@ - diff --git a/src/UniGetUI.Core.Language.Tests/UniGetUI.Core.LanguageEngine.Tests.csproj b/src/UniGetUI.Core.Language.Tests/UniGetUI.Core.LanguageEngine.Tests.csproj index 9a0f8ca432..1c2e54bab6 100644 --- a/src/UniGetUI.Core.Language.Tests/UniGetUI.Core.LanguageEngine.Tests.csproj +++ b/src/UniGetUI.Core.Language.Tests/UniGetUI.Core.LanguageEngine.Tests.csproj @@ -3,6 +3,8 @@ + $(PortableTargetFramework) + false true diff --git a/src/UniGetUI.Core.LanguageEngine/UniGetUI.Core.LanguageEngine.csproj b/src/UniGetUI.Core.LanguageEngine/UniGetUI.Core.LanguageEngine.csproj index 1f53d75e84..10d2b3bee6 100644 --- a/src/UniGetUI.Core.LanguageEngine/UniGetUI.Core.LanguageEngine.csproj +++ b/src/UniGetUI.Core.LanguageEngine/UniGetUI.Core.LanguageEngine.csproj @@ -1,7 +1,5 @@ - - diff --git a/src/UniGetUI.Core.Logger/UniGetUI.Core.Logging.csproj b/src/UniGetUI.Core.Logger/UniGetUI.Core.Logging.csproj index 409bafff79..6c35193aa1 100644 --- a/src/UniGetUI.Core.Logger/UniGetUI.Core.Logging.csproj +++ b/src/UniGetUI.Core.Logger/UniGetUI.Core.Logging.csproj @@ -1,7 +1,5 @@ - - diff --git a/src/UniGetUI.Core.Logging.Tests/UniGetUI.Core.Logging.Tests.csproj b/src/UniGetUI.Core.Logging.Tests/UniGetUI.Core.Logging.Tests.csproj index 69dea26089..1955578c9a 100644 --- a/src/UniGetUI.Core.Logging.Tests/UniGetUI.Core.Logging.Tests.csproj +++ b/src/UniGetUI.Core.Logging.Tests/UniGetUI.Core.Logging.Tests.csproj @@ -3,6 +3,8 @@ + $(PortableTargetFramework) + false true diff --git a/src/UniGetUI.Core.SecureSettings/SecureGHTokenManager.cs b/src/UniGetUI.Core.SecureSettings/SecureGHTokenManager.cs index e66b7b3a1c..ebb6d1beb7 100644 --- a/src/UniGetUI.Core.SecureSettings/SecureGHTokenManager.cs +++ b/src/UniGetUI.Core.SecureSettings/SecureGHTokenManager.cs @@ -1,4 +1,4 @@ -using Windows.Security.Credentials; +using UniGetUI.Core.Data; using UniGetUI.Core.Logging; namespace UniGetUI.Core.SecureSettings @@ -18,12 +18,10 @@ public static void StoreToken(string token) try { - var vault = new PasswordVault(); - var newCredential = new PasswordCredential(GitHubResourceName, UserName, token); if (GetToken() is not null) DeleteToken(); // Delete any old token(s) - vault.Add(newCredential); + CoreCredentialStore.SetSecret(GitHubResourceName, UserName, token); Logger.Info("GitHub access token stored/updated securely."); } catch (Exception ex) @@ -37,11 +35,14 @@ public static void StoreToken(string token) { try { - var vault = new PasswordVault(); - var credential = vault.Retrieve(GitHubResourceName, UserName); - credential.RetrievePassword(); + string? token = CoreCredentialStore.GetSecret(GitHubResourceName, UserName); + if (token is null) + { + return null; + } + Logger.Debug("GitHub access token retrieved."); - return credential.Password; + return token; } catch (Exception ex) { @@ -54,13 +55,8 @@ public static void DeleteToken() { try { - var vault = new PasswordVault(); - var credentials = vault.FindAllByResource(GitHubResourceName) ?? []; - foreach (var cred in credentials) - { - vault.Remove(cred); - Logger.Info("GitHub access token deleted."); - } + CoreCredentialStore.DeleteSecret(GitHubResourceName, UserName); + Logger.Info("GitHub access token deleted."); } catch (Exception ex) { diff --git a/src/UniGetUI.Core.SecureSettings/SecureSettings.cs b/src/UniGetUI.Core.SecureSettings/SecureSettings.cs index ed496501f0..b4f132c0ca 100644 --- a/src/UniGetUI.Core.SecureSettings/SecureSettings.cs +++ b/src/UniGetUI.Core.SecureSettings/SecureSettings.cs @@ -53,8 +53,7 @@ public static bool Get(K key) string purifiedUser = CoreTools.MakeValidFileName(Environment.UserName); - var appData = Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles); - var settingsLocation = Path.Join(appData, "UniGetUI\\SecureSettings", purifiedUser); + var settingsLocation = Path.Join(GetSecureSettingsRoot(), purifiedUser); var settingFile = Path.Join(settingsLocation, purifiedSetting); if (!Directory.Exists(settingsLocation)) @@ -75,6 +74,11 @@ public static async Task TrySet(K key, bool enabled) string purifiedUser = CoreTools.MakeValidFileName(Environment.UserName); + if (!OperatingSystem.IsWindows()) + { + return ApplyForUser(purifiedUser, purifiedSetting, enabled) is 0; + } + using Process p = new Process(); p.StartInfo = new() { @@ -104,8 +108,7 @@ public static int ApplyForUser(string username, string setting, bool enable) string purifiedUser = CoreTools.MakeValidFileName(username); - var appData = Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles); - var settingsLocation = Path.Join(appData, "UniGetUI\\SecureSettings", purifiedUser); + var settingsLocation = Path.Join(GetSecureSettingsRoot(), purifiedUser); var settingFile = Path.Join(settingsLocation, purifiedSetting); if (!Directory.Exists(settingsLocation)) @@ -133,4 +136,14 @@ public static int ApplyForUser(string username, string setting, bool enable) return -1; } } + + private static string GetSecureSettingsRoot() + { + if (OperatingSystem.IsWindows()) + { + return Path.Join(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles), "UniGetUI", "SecureSettings"); + } + + return Path.Join(CoreData.UniGetUIDataDirectory, "SecureSettings"); + } } diff --git a/src/UniGetUI.Core.SecureSettings/UniGetUI.Core.SecureSettings.csproj b/src/UniGetUI.Core.SecureSettings/UniGetUI.Core.SecureSettings.csproj index 704c7f08fb..f5614d0e25 100644 --- a/src/UniGetUI.Core.SecureSettings/UniGetUI.Core.SecureSettings.csproj +++ b/src/UniGetUI.Core.SecureSettings/UniGetUI.Core.SecureSettings.csproj @@ -1,5 +1,6 @@ + diff --git a/src/UniGetUI.Core.Settings.Tests/UniGetUI.Core.Settings.Tests.csproj b/src/UniGetUI.Core.Settings.Tests/UniGetUI.Core.Settings.Tests.csproj index c15ff9f7c0..f6df2a00d3 100644 --- a/src/UniGetUI.Core.Settings.Tests/UniGetUI.Core.Settings.Tests.csproj +++ b/src/UniGetUI.Core.Settings.Tests/UniGetUI.Core.Settings.Tests.csproj @@ -1,5 +1,10 @@ + + $(PortableTargetFramework) + + + diff --git a/src/UniGetUI.Core.Settings/SettingsEngine_Extras.cs b/src/UniGetUI.Core.Settings/SettingsEngine_Extras.cs index dc63aaaf02..21f9d7c8a7 100644 --- a/src/UniGetUI.Core.Settings/SettingsEngine_Extras.cs +++ b/src/UniGetUI.Core.Settings/SettingsEngine_Extras.cs @@ -1,7 +1,7 @@ using System.Net; using System.Text.Json; using System.Text.Json.Serialization.Metadata; -using Windows.Security.Credentials; +using UniGetUI.Core.Data; using UniGetUI.Core.Logging; namespace UniGetUI.Core.SettingsEngine; @@ -44,14 +44,8 @@ public static bool AreProgressNotificationsDisabled() { try { - var vault = new PasswordVault(); - var credentials = vault.Retrieve(PROXY_RES_ID, GetValue(K.ProxyUsername)); - - return new NetworkCredential() - { - UserName = credentials.UserName, - Password = credentials.Password, - }; + string username = GetValue(K.ProxyUsername); + return username.Length is 0 ? null : CoreCredentialStore.GetCredential(PROXY_RES_ID, username); } catch (Exception ex) { @@ -65,9 +59,8 @@ public static void SetProxyCredentials(string username, string password) { try { - var vault = new PasswordVault(); SetValue(K.ProxyUsername, username); - vault.Add(new PasswordCredential(PROXY_RES_ID, username, password)); + CoreCredentialStore.SetCredential(PROXY_RES_ID, username, password); } catch (Exception ex) { diff --git a/src/UniGetUI.Core.Settings/UniGetUI.Core.Settings.csproj b/src/UniGetUI.Core.Settings/UniGetUI.Core.Settings.csproj index 7345b7129c..526f14e344 100644 --- a/src/UniGetUI.Core.Settings/UniGetUI.Core.Settings.csproj +++ b/src/UniGetUI.Core.Settings/UniGetUI.Core.Settings.csproj @@ -1,7 +1,5 @@ - - diff --git a/src/UniGetUI.Core.Tools.Tests/MetaTests.cs b/src/UniGetUI.Core.Tools.Tests/MetaTests.cs index 0594d65a5e..9f88a0bc5f 100644 --- a/src/UniGetUI.Core.Tools.Tests/MetaTests.cs +++ b/src/UniGetUI.Core.Tools.Tests/MetaTests.cs @@ -8,7 +8,7 @@ public class MetaTests public void TestJsonSerializationOptions() { // This test ensures that any json operation has the proper serialization options set (required for TRIM support) - var solutionDirectory = Path.GetFullPath(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, @"..\..\..\..\..\..")); + var solutionDirectory = FindRepositoryRoot(); var csFiles = Directory.GetFiles(solutionDirectory, "*.cs", SearchOption.AllDirectories) .Where(file => !file.Contains(@"bin\") && !file.Contains(@"obj\") && !file.EndsWith(".g.cs") && !file.EndsWith("Tests.cs")); @@ -30,7 +30,7 @@ public void TestJsonSerializationOptions() public void TestHttpClientInstantiation() { // This test ensures that any instantiation of HttpClient contains at least one empty line after it - var solutionDirectory = Path.GetFullPath(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, @"..\..\..\..\..\..")); + var solutionDirectory = FindRepositoryRoot(); var csFiles = Directory.GetFiles(solutionDirectory, "*.cs", SearchOption.AllDirectories) .Where(file => !file.Contains(@"bin\") && !file.Contains(@"obj\") && !file.EndsWith(".g.cs") && !file.EndsWith("Tests.cs") && !file.EndsWith("LanguageEngine.cs")); @@ -46,5 +46,22 @@ public void TestHttpClientInstantiation() } } + private static string FindRepositoryRoot() + { + DirectoryInfo? currentDirectory = new(AppDomain.CurrentDomain.BaseDirectory); + + while (currentDirectory is not null) + { + if (File.Exists(Path.Join(currentDirectory.FullName, "AGENTS.md")) + && Directory.Exists(Path.Join(currentDirectory.FullName, "src"))) + { + return currentDirectory.FullName; + } + + currentDirectory = currentDirectory.Parent; + } + + throw new DirectoryNotFoundException("Unable to locate the UniGetUI repository root from the test output directory."); + } } diff --git a/src/UniGetUI.Core.Tools.Tests/ToolsTests.cs b/src/UniGetUI.Core.Tools.Tests/ToolsTests.cs index 54c953b16a..8087a1c60c 100644 --- a/src/UniGetUI.Core.Tools.Tests/ToolsTests.cs +++ b/src/UniGetUI.Core.Tools.Tests/ToolsTests.cs @@ -34,7 +34,8 @@ public void TranslateFunctionTester(string textEntry, bool TranslationExists) [Fact] public async Task TestWhichFunctionForExistingFile() { - Tuple result = await CoreTools.WhichAsync("cmd.exe"); + string existingCommand = OperatingSystem.IsWindows() ? "cmd.exe" : "sh"; + Tuple result = await CoreTools.WhichAsync(existingCommand); Assert.True(result.Item1); Assert.True(File.Exists(result.Item2)); } @@ -42,7 +43,7 @@ public async Task TestWhichFunctionForExistingFile() [Fact] public async Task TestWhichFunctionForNonExistingFile() { - Tuple result = await CoreTools.WhichAsync("nonexistentfile.exe"); + Tuple result = await CoreTools.WhichAsync("nonexistentfile-does-not-exist"); Assert.False(result.Item1); Assert.Equal("", result.Item2); } diff --git a/src/UniGetUI.Core.Tools.Tests/UniGetUI.Core.Tools.Tests.csproj b/src/UniGetUI.Core.Tools.Tests/UniGetUI.Core.Tools.Tests.csproj index 87b6ef886c..8b9e3710f6 100644 --- a/src/UniGetUI.Core.Tools.Tests/UniGetUI.Core.Tools.Tests.csproj +++ b/src/UniGetUI.Core.Tools.Tests/UniGetUI.Core.Tools.Tests.csproj @@ -1,5 +1,10 @@ + + $(PortableTargetFramework) + + + diff --git a/src/UniGetUI.Core.Tools/Tools.cs b/src/UniGetUI.Core.Tools/Tools.cs index a5d85eb602..26c52f7a78 100644 --- a/src/UniGetUI.Core.Tools/Tools.cs +++ b/src/UniGetUI.Core.Tools/Tools.cs @@ -1,11 +1,13 @@ using System.Collections; using System.Diagnostics; using System.Net; +using System.Net.NetworkInformation; using System.Security.Cryptography; using System.Security.Principal; using System.Text; +#if WINDOWS using Windows.Networking.Connectivity; -using ABI.Windows.ApplicationModel.UserDataTasks; +#endif using UniGetUI.Core.Classes; using UniGetUI.Core.Data; using UniGetUI.Core.Language; @@ -88,8 +90,8 @@ public static string AutoTranslated(string text) /// public static void RelaunchProcess() { - Logger.Debug("Launching process: " + Environment.GetCommandLineArgs()[0].Replace(".dll", ".exe")); - Process.Start(Environment.GetCommandLineArgs()[0].Replace(".dll", ".exe")); + Logger.Debug("Launching process: " + CoreData.UniGetUIExecutableFile); + Process.Start(CoreData.UniGetUIExecutableFile); Logger.Warn("About to kill process"); Environment.Exit(0); } @@ -109,30 +111,27 @@ public static List WhichMultiple(string command, bool updateEnv = true) command = command.Replace(";", "").Replace("&", "").Trim(); Logger.Debug($"Begin \"which\" search for command {command}"); - string PATH = Environment.GetEnvironmentVariable("PATH", EnvironmentVariableTarget.User) + ";"; - PATH += Environment.GetEnvironmentVariable("PATH", EnvironmentVariableTarget.Machine) + ";"; - PATH += Environment.GetEnvironmentVariable("PATH", EnvironmentVariableTarget.Process); - PATH = PATH.Replace(";;", ";").Trim(';'); + string pathValue = GetSearchPath(); Process process = new() { StartInfo = new ProcessStartInfo { - FileName = Path.Join(Environment.SystemDirectory, "where.exe"), + FileName = OperatingSystem.IsWindows() ? Path.Join(Environment.SystemDirectory, "where.exe") : "which", Arguments = command, UseShellExecute = false, RedirectStandardOutput = true, RedirectStandardError = true, CreateNoWindow = true, - StandardOutputEncoding = CodePagesEncodingProvider.Instance.GetEncoding(CoreData.CODE_PAGE), - StandardErrorEncoding = CodePagesEncodingProvider.Instance.GetEncoding(CoreData.CODE_PAGE), + StandardOutputEncoding = GetCommandOutputEncoding(), + StandardErrorEncoding = GetCommandOutputEncoding(), } }; if (updateEnv) { process.StartInfo = UpdateEnvironmentVariables(process.StartInfo); } - process.StartInfo.Environment["PATH"] = PATH; + process.StartInfo.Environment["PATH"] = pathValue; try { @@ -219,11 +218,20 @@ public static async Task LaunchBatchFile(string path, string WindowTitle = "", b try { using Process p = new(); - p.StartInfo.FileName = "cmd.exe"; - p.StartInfo.Arguments = "/C start \"" + WindowTitle + "\" \"" + path + "\""; - p.StartInfo.UseShellExecute = true; + if (OperatingSystem.IsWindows()) + { + p.StartInfo.FileName = "cmd.exe"; + p.StartInfo.Arguments = "/C start \"" + WindowTitle + "\" \"" + path + "\""; + p.StartInfo.UseShellExecute = true; + p.StartInfo.Verb = RunAsAdmin ? "runas" : ""; + } + else + { + p.StartInfo.FileName = "/bin/sh"; + p.StartInfo.ArgumentList.Add(path); + p.StartInfo.UseShellExecute = false; + } p.StartInfo.CreateNoWindow = true; - p.StartInfo.Verb = RunAsAdmin ? "runas" : ""; p.Start(); await p.WaitForExitAsync(); } @@ -241,6 +249,11 @@ public static bool IsAdministrator() { try { + if (!OperatingSystem.IsWindows()) + { + return string.Equals(Environment.UserName, "root", StringComparison.Ordinal); + } + return new WindowsPrincipal(WindowsIdentity.GetCurrent()) .IsInRole(WindowsBuiltInRole.Administrator); } @@ -550,23 +563,11 @@ public static long HashStringAsLong(string inputString) /// The location of the real folder where to point public static void CreateSymbolicLinkDir(string linkPath, string targetPath) { - var startInfo = new ProcessStartInfo - { - FileName = "cmd.exe", - Arguments = $"/c mklink /D \"{linkPath}\" \"{targetPath}\"", - UseShellExecute = false, - CreateNoWindow = true, - RedirectStandardOutput = true, - RedirectStandardError = true - }; - - Process? p = Process.Start(startInfo); - p?.WaitForExit(); + Directory.CreateSymbolicLink(linkPath, targetPath); - if (p is null || p.ExitCode != 0) + if (!Directory.Exists(linkPath)) { - throw new InvalidOperationException( - $"The operation did not complete successfully: \n{p?.StandardOutput.ReadToEnd()}\n{p?.StandardError.ReadToEnd()}\n"); + throw new InvalidOperationException($"The symbolic link '{linkPath}' was not created successfully."); } } @@ -601,6 +602,16 @@ public static ProcessStartInfo UpdateEnvironmentVariables() /// public static ProcessStartInfo UpdateEnvironmentVariables(ProcessStartInfo info) { + if (!OperatingSystem.IsWindows()) + { + foreach (DictionaryEntry env in Environment.GetEnvironmentVariables()) + { + info.Environment[env.Key?.ToString() ?? "UNKNOWN"] = env.Value?.ToString(); + } + + return info; + } + foreach (DictionaryEntry env in Environment.GetEnvironmentVariables(EnvironmentVariableTarget.Machine)) { info.Environment[env.Key?.ToString() ?? "UNKNOWN"] = env.Value?.ToString(); @@ -637,6 +648,7 @@ public static void _waitForInternetConnection() Logger.Debug("Checking for internet connectivity..."); bool internetLost = false; +#if WINDOWS var profile = NetworkInformation.GetInternetConnectionProfile(); while (profile is null || profile.GetNetworkConnectivityLevel() is not NetworkConnectivityLevel.InternetAccess) { @@ -648,6 +660,17 @@ public static void _waitForInternetConnection() internetLost = true; } } +#else + while (!NetworkInterface.GetIsNetworkAvailable()) + { + Thread.Sleep(1000); + if (!internetLost) + { + Logger.Warn("User is not connected to the internet, waiting for an internet connection to be available..."); + internetLost = true; + } + } +#endif Logger.Debug("Internet connectivity was established."); } @@ -701,6 +724,12 @@ public static async Task ShowFileOnExplorer(string path) { if (!File.Exists(path)) throw new FileNotFoundException($"The file {path} was not found"); + if (!OperatingSystem.IsWindows()) + { + Launch(Path.GetDirectoryName(path)); + return; + } + Process p = new() { StartInfo = new() @@ -767,5 +796,24 @@ public static async void FinalizeDangerousTask(Task t) Logger.Error(ex); } } + + private static Encoding GetCommandOutputEncoding() + => OperatingSystem.IsWindows() + ? CodePagesEncodingProvider.Instance.GetEncoding(CoreData.CODE_PAGE) ?? Encoding.UTF8 + : Encoding.UTF8; + + private static string GetSearchPath() + { + if (!OperatingSystem.IsWindows()) + { + return Environment.GetEnvironmentVariable("PATH") ?? string.Empty; + } + + string separator = Path.PathSeparator.ToString(); + string pathValue = (Environment.GetEnvironmentVariable("PATH", EnvironmentVariableTarget.User) ?? string.Empty) + separator; + pathValue += (Environment.GetEnvironmentVariable("PATH", EnvironmentVariableTarget.Machine) ?? string.Empty) + separator; + pathValue += Environment.GetEnvironmentVariable("PATH", EnvironmentVariableTarget.Process) ?? string.Empty; + return pathValue.Replace(separator + separator, separator).Trim(Path.PathSeparator); + } } } diff --git a/src/UniGetUI.Core.Tools/UniGetUI.Core.Tools.csproj b/src/UniGetUI.Core.Tools/UniGetUI.Core.Tools.csproj index 68a45eb974..a378f23844 100644 --- a/src/UniGetUI.Core.Tools/UniGetUI.Core.Tools.csproj +++ b/src/UniGetUI.Core.Tools/UniGetUI.Core.Tools.csproj @@ -1,7 +1,5 @@ - - diff --git a/src/UniGetUI.Interface.BackgroundApi/UniGetUI.Interface.BackgroundApi.csproj b/src/UniGetUI.Interface.BackgroundApi/UniGetUI.Interface.BackgroundApi.csproj index d1695ed4db..95bc771584 100644 --- a/src/UniGetUI.Interface.BackgroundApi/UniGetUI.Interface.BackgroundApi.csproj +++ b/src/UniGetUI.Interface.BackgroundApi/UniGetUI.Interface.BackgroundApi.csproj @@ -1,5 +1,5 @@ - + diff --git a/src/UniGetUI.Interface.Enums/UniGetUI.Interface.Enums.csproj b/src/UniGetUI.Interface.Enums/UniGetUI.Interface.Enums.csproj index 409bafff79..6c35193aa1 100644 --- a/src/UniGetUI.Interface.Enums/UniGetUI.Interface.Enums.csproj +++ b/src/UniGetUI.Interface.Enums/UniGetUI.Interface.Enums.csproj @@ -1,7 +1,5 @@ - - diff --git a/src/UniGetUI.Interface.Telemetry/UniGetUI.Interface.Telemetry.csproj b/src/UniGetUI.Interface.Telemetry/UniGetUI.Interface.Telemetry.csproj index 46c73de583..7a7abce30e 100644 --- a/src/UniGetUI.Interface.Telemetry/UniGetUI.Interface.Telemetry.csproj +++ b/src/UniGetUI.Interface.Telemetry/UniGetUI.Interface.Telemetry.csproj @@ -1,13 +1,6 @@ - - - - - - - false UniGetUI.Interface.Telemetry diff --git a/src/UniGetUI.PAckageEngine.Interfaces/UniGetUI.PackageEngine.Interfaces.csproj b/src/UniGetUI.PAckageEngine.Interfaces/UniGetUI.PackageEngine.Interfaces.csproj index 9252dd20ed..73f1a85ea9 100644 --- a/src/UniGetUI.PAckageEngine.Interfaces/UniGetUI.PackageEngine.Interfaces.csproj +++ b/src/UniGetUI.PAckageEngine.Interfaces/UniGetUI.PackageEngine.Interfaces.csproj @@ -1,19 +1,12 @@ - + - - - - - 10.0.19041.0 - - + 10.0.19041.0 3.1.0.0 3.1.0-beta0 UniGetUI 3.1.0-beta0 Copyright 2021-2026 Devolutions Inc. - diff --git a/src/UniGetUI.PackageEngine.Enums/UniGetUI.PackageEngine.Structs.csproj b/src/UniGetUI.PackageEngine.Enums/UniGetUI.PackageEngine.Structs.csproj index 409bafff79..6c35193aa1 100644 --- a/src/UniGetUI.PackageEngine.Enums/UniGetUI.PackageEngine.Structs.csproj +++ b/src/UniGetUI.PackageEngine.Enums/UniGetUI.PackageEngine.Structs.csproj @@ -1,7 +1,5 @@ - - diff --git a/src/UniGetUI.PackageEngine.Managers.Cargo/UniGetUI.PackageEngine.Managers.Cargo.csproj b/src/UniGetUI.PackageEngine.Managers.Cargo/UniGetUI.PackageEngine.Managers.Cargo.csproj index 0a7d08ff3e..3b628742de 100644 --- a/src/UniGetUI.PackageEngine.Managers.Cargo/UniGetUI.PackageEngine.Managers.Cargo.csproj +++ b/src/UniGetUI.PackageEngine.Managers.Cargo/UniGetUI.PackageEngine.Managers.Cargo.csproj @@ -1,7 +1,5 @@ - - diff --git a/src/UniGetUI.PackageEngine.Managers.Chocolatey/UniGetUI.PackageEngine.Managers.Chocolatey.csproj b/src/UniGetUI.PackageEngine.Managers.Chocolatey/UniGetUI.PackageEngine.Managers.Chocolatey.csproj index f08f57afb2..54ea79f720 100644 --- a/src/UniGetUI.PackageEngine.Managers.Chocolatey/UniGetUI.PackageEngine.Managers.Chocolatey.csproj +++ b/src/UniGetUI.PackageEngine.Managers.Chocolatey/UniGetUI.PackageEngine.Managers.Chocolatey.csproj @@ -1,5 +1,10 @@ + + $(WindowsTargetFramework) + + + diff --git a/src/UniGetUI.PackageEngine.Managers.Dotnet/UniGetUI.PackageEngine.Managers.Dotnet.csproj b/src/UniGetUI.PackageEngine.Managers.Dotnet/UniGetUI.PackageEngine.Managers.Dotnet.csproj index 88af26a6cd..aab332b650 100644 --- a/src/UniGetUI.PackageEngine.Managers.Dotnet/UniGetUI.PackageEngine.Managers.Dotnet.csproj +++ b/src/UniGetUI.PackageEngine.Managers.Dotnet/UniGetUI.PackageEngine.Managers.Dotnet.csproj @@ -1,7 +1,5 @@ - - diff --git a/src/UniGetUI.PackageEngine.Managers.Generic.NuGet/UniGetUI.PackageEngine.Managers.Generic.NuGet.csproj b/src/UniGetUI.PackageEngine.Managers.Generic.NuGet/UniGetUI.PackageEngine.Managers.Generic.NuGet.csproj index e5d9ed7210..06896b0964 100644 --- a/src/UniGetUI.PackageEngine.Managers.Generic.NuGet/UniGetUI.PackageEngine.Managers.Generic.NuGet.csproj +++ b/src/UniGetUI.PackageEngine.Managers.Generic.NuGet/UniGetUI.PackageEngine.Managers.Generic.NuGet.csproj @@ -1,7 +1,5 @@ - - diff --git a/src/UniGetUI.PackageEngine.Managers.Npm/UniGetUI.PackageEngine.Managers.Npm.csproj b/src/UniGetUI.PackageEngine.Managers.Npm/UniGetUI.PackageEngine.Managers.Npm.csproj index 6eb175c046..601ac03e65 100644 --- a/src/UniGetUI.PackageEngine.Managers.Npm/UniGetUI.PackageEngine.Managers.Npm.csproj +++ b/src/UniGetUI.PackageEngine.Managers.Npm/UniGetUI.PackageEngine.Managers.Npm.csproj @@ -1,7 +1,5 @@ - - diff --git a/src/UniGetUI.PackageEngine.Managers.Pip/UniGetUI.PackageEngine.Managers.Pip.csproj b/src/UniGetUI.PackageEngine.Managers.Pip/UniGetUI.PackageEngine.Managers.Pip.csproj index 6eb175c046..601ac03e65 100644 --- a/src/UniGetUI.PackageEngine.Managers.Pip/UniGetUI.PackageEngine.Managers.Pip.csproj +++ b/src/UniGetUI.PackageEngine.Managers.Pip/UniGetUI.PackageEngine.Managers.Pip.csproj @@ -1,7 +1,5 @@ - - diff --git a/src/UniGetUI.PackageEngine.Managers.PowerShell/UniGetUI.PackageEngine.Managers.PowerShell.csproj b/src/UniGetUI.PackageEngine.Managers.PowerShell/UniGetUI.PackageEngine.Managers.PowerShell.csproj index 88af26a6cd..b0cd3742ef 100644 --- a/src/UniGetUI.PackageEngine.Managers.PowerShell/UniGetUI.PackageEngine.Managers.PowerShell.csproj +++ b/src/UniGetUI.PackageEngine.Managers.PowerShell/UniGetUI.PackageEngine.Managers.PowerShell.csproj @@ -1,5 +1,10 @@ + + $(WindowsTargetFramework) + + + diff --git a/src/UniGetUI.PackageEngine.Managers.PowerShell7/PowerShell7.cs b/src/UniGetUI.PackageEngine.Managers.PowerShell7/PowerShell7.cs index 868c633141..64e194007b 100644 --- a/src/UniGetUI.PackageEngine.Managers.PowerShell7/PowerShell7.cs +++ b/src/UniGetUI.PackageEngine.Managers.PowerShell7/PowerShell7.cs @@ -46,7 +46,7 @@ public PowerShell7() Description = CoreTools.Translate("PowerShell's package manager. Find libraries and scripts to expand PowerShell capabilities
Contains: Modules, Scripts, Cmdlets"), IconId = IconType.PowerShell, ColorIconId = "powershell_color", - ExecutableFriendlyName = "pwsh.exe", + ExecutableFriendlyName = OperatingSystem.IsWindows() ? "pwsh.exe" : "pwsh", InstallVerb = "Install-PSResource", UninstallVerb = "Uninstall-PSResource", UpdateVerb = "Update-PSResource", @@ -124,7 +124,7 @@ protected override IReadOnlyList _getInstalledPackages_UnSafe() } public override IReadOnlyList FindCandidateExecutableFiles() - => CoreTools.WhichMultiple("pwsh.exe"); + => CoreTools.WhichMultiple(OperatingSystem.IsWindows() ? "pwsh.exe" : "pwsh"); protected override void _loadManagerExecutableFile(out bool found, out string path, out string callArguments) { diff --git a/src/UniGetUI.PackageEngine.Managers.PowerShell7/UniGetUI.PackageEngine.Managers.PowerShell7.csproj b/src/UniGetUI.PackageEngine.Managers.PowerShell7/UniGetUI.PackageEngine.Managers.PowerShell7.csproj index b49355fdf4..cccbb33784 100644 --- a/src/UniGetUI.PackageEngine.Managers.PowerShell7/UniGetUI.PackageEngine.Managers.PowerShell7.csproj +++ b/src/UniGetUI.PackageEngine.Managers.PowerShell7/UniGetUI.PackageEngine.Managers.PowerShell7.csproj @@ -1,7 +1,6 @@ - diff --git a/src/UniGetUI.PackageEngine.Managers.Scoop/UniGetUI.PackageEngine.Managers.Scoop.csproj b/src/UniGetUI.PackageEngine.Managers.Scoop/UniGetUI.PackageEngine.Managers.Scoop.csproj index 6eb175c046..53f07f9f83 100644 --- a/src/UniGetUI.PackageEngine.Managers.Scoop/UniGetUI.PackageEngine.Managers.Scoop.csproj +++ b/src/UniGetUI.PackageEngine.Managers.Scoop/UniGetUI.PackageEngine.Managers.Scoop.csproj @@ -1,5 +1,10 @@ + + $(WindowsTargetFramework) + + + diff --git a/src/UniGetUI.PackageEngine.Managers.Vcpkg/UniGetUI.PackageEngine.Managers.Vcpkg.csproj b/src/UniGetUI.PackageEngine.Managers.Vcpkg/UniGetUI.PackageEngine.Managers.Vcpkg.csproj index 8cb9ba8743..19dba2617d 100644 --- a/src/UniGetUI.PackageEngine.Managers.Vcpkg/UniGetUI.PackageEngine.Managers.Vcpkg.csproj +++ b/src/UniGetUI.PackageEngine.Managers.Vcpkg/UniGetUI.PackageEngine.Managers.Vcpkg.csproj @@ -1,7 +1,5 @@ - - diff --git a/src/UniGetUI.PackageEngine.Managers.WinGet/UniGetUI.PackageEngine.Managers.WinGet.csproj b/src/UniGetUI.PackageEngine.Managers.WinGet/UniGetUI.PackageEngine.Managers.WinGet.csproj index 723b7bc9f5..0194d4718d 100644 --- a/src/UniGetUI.PackageEngine.Managers.WinGet/UniGetUI.PackageEngine.Managers.WinGet.csproj +++ b/src/UniGetUI.PackageEngine.Managers.WinGet/UniGetUI.PackageEngine.Managers.WinGet.csproj @@ -1,6 +1,8 @@ + $(WindowsTargetFramework) + $(Platform) x64 $(MSBuildProjectDirectory)\winget-cli_$(WingetCliArchitecture) diff --git a/src/UniGetUI.PackageEngine.Operations/PackageOperations.cs b/src/UniGetUI.PackageEngine.Operations/PackageOperations.cs index 2f0ec6af39..bddbf8e6a7 100644 --- a/src/UniGetUI.PackageEngine.Operations/PackageOperations.cs +++ b/src/UniGetUI.PackageEngine.Operations/PackageOperations.cs @@ -7,11 +7,13 @@ using UniGetUI.PackageEngine.Classes.Packages.Classes; using UniGetUI.PackageEngine.Enums; using UniGetUI.PackageEngine.Interfaces; -using UniGetUI.PackageEngine.Managers.WingetManager; using UniGetUI.PackageEngine.PackageClasses; using UniGetUI.PackageEngine.PackageLoader; using UniGetUI.PackageEngine.Serializable; using UniGetUI.PackageOperations; +#if WINDOWS +using UniGetUI.PackageEngine.Managers.WingetManager; +#endif namespace UniGetUI.PackageEngine.Operations { @@ -106,7 +108,7 @@ protected sealed override void PrepareProcessStartInfo() Arguments = $"{Package.Manager.Status.ExecutableCallArgs} {operation_args}"; } - if (IsAdmin && Package.Manager is WinGet) + if (IsAdmin && IsWinGetManager(Package.Manager)) { RedirectWinGetTempFolder(); } @@ -127,6 +129,15 @@ protected sealed override Task GetProcessVeredict(int ReturnC return Task.FromResult(Package.Manager.OperationHelper.GetResult(Package, Role, Output, ReturnCode)); } + private static bool IsWinGetManager(IPackageManager manager) + { +#if WINDOWS + return manager is WinGet; +#else + return false; +#endif + } + public override Task GetOperationIcon() { return TaskRecycler.RunOrAttachAsync(Package.GetIconUrl); diff --git a/src/UniGetUI.PackageEngine.Operations/SourceOperations.cs b/src/UniGetUI.PackageEngine.Operations/SourceOperations.cs index a1a9cc4460..bead74ecc0 100644 --- a/src/UniGetUI.PackageEngine.Operations/SourceOperations.cs +++ b/src/UniGetUI.PackageEngine.Operations/SourceOperations.cs @@ -3,8 +3,10 @@ using UniGetUI.Core.Tools; using UniGetUI.PackageEngine.Enums; using UniGetUI.PackageEngine.Interfaces; -using UniGetUI.PackageEngine.Managers.WingetManager; using UniGetUI.PackageOperations; +#if WINDOWS +using UniGetUI.PackageEngine.Managers.WingetManager; +#endif namespace UniGetUI.PackageEngine.Operations { @@ -50,21 +52,39 @@ protected override void ApplyRetryAction(string retryMode) public static IReadOnlyList CreateInstallPreOps(IManagerSource source, bool forceLocalWinGet) { - if (source.Manager is not WinGet) return []; + if (!IsWinGetManager(source.Manager)) return []; if (forceLocalWinGet) return []; - if (source.Manager.Status.ExecutablePath == WinGet.BundledWinGetPath) return []; + if (source.Manager.Status.ExecutablePath == GetBundledWinGetPath()) return []; return [new(new AddSourceOperation(source, true), mustSucceed: true)]; } public static IReadOnlyList CreateUninstallPreOps(IManagerSource source, bool forceLocalWinGet) { - if (source.Manager is not WinGet) return []; + if (!IsWinGetManager(source.Manager)) return []; if (forceLocalWinGet) return []; - if (source.Manager.Status.ExecutablePath == WinGet.BundledWinGetPath) return []; + if (source.Manager.Status.ExecutablePath == GetBundledWinGetPath()) return []; // In this case, must succeed is set to false since we cannot ensure that bundled WinGet will // have this source added return [new(new RemoveSourceOperation(source, true), mustSucceed: false)]; } + + protected static bool IsWinGetManager(IPackageManager manager) + { +#if WINDOWS + return manager is WinGet; +#else + return false; +#endif + } + + protected static string? GetBundledWinGetPath() + { +#if WINDOWS + return WinGet.BundledWinGetPath; +#else + return null; +#endif + } } public class AddSourceOperation : SourceOperation @@ -79,9 +99,9 @@ public AddSourceOperation(IManagerSource source, bool forceLocalWinGet = false) protected override void PrepareProcessStartInfo() { var exePath = Source.Manager.Status.ExecutablePath; - if (Source.Manager is WinGet && _forceLocalWinGet) + if (IsWinGetManager(Source.Manager) && _forceLocalWinGet) { - exePath = WinGet.BundledWinGetPath; + exePath = GetBundledWinGetPath() ?? exePath; } bool admin = false; @@ -90,7 +110,7 @@ protected override void PrepareProcessStartInfo() if (Settings.Get(Settings.K.DoCacheAdminRights) || Settings.Get(Settings.K.DoCacheAdminRightsForBatches)) RequestCachingOfUACPrompt(); - if (Source.Manager is WinGet) + if (IsWinGetManager(Source.Manager)) RedirectWinGetTempFolder(); admin = true; @@ -140,9 +160,9 @@ public RemoveSourceOperation(IManagerSource source, bool forceLocalWinGet = fals protected override void PrepareProcessStartInfo() { var exePath = Source.Manager.Status.ExecutablePath; - if (Source.Manager is WinGet && _forceLocalWinGet) + if (IsWinGetManager(Source.Manager) && _forceLocalWinGet) { - exePath = WinGet.BundledWinGetPath; + exePath = GetBundledWinGetPath() ?? exePath; } bool admin = false; if (RequiresAdminRights()) @@ -150,7 +170,7 @@ protected override void PrepareProcessStartInfo() if (Settings.Get(Settings.K.DoCacheAdminRights) || Settings.Get(Settings.K.DoCacheAdminRightsForBatches)) RequestCachingOfUACPrompt(); - if (Source.Manager is WinGet) + if (IsWinGetManager(Source.Manager)) RedirectWinGetTempFolder(); admin = true; diff --git a/src/UniGetUI.PackageEngine.Operations/UniGetUI.PackageEngine.Operations.csproj b/src/UniGetUI.PackageEngine.Operations/UniGetUI.PackageEngine.Operations.csproj index a08ce766c6..b4a1fe2c19 100644 --- a/src/UniGetUI.PackageEngine.Operations/UniGetUI.PackageEngine.Operations.csproj +++ b/src/UniGetUI.PackageEngine.Operations/UniGetUI.PackageEngine.Operations.csproj @@ -1,27 +1,20 @@ - - - - - - - - - - - + + + + diff --git a/src/UniGetUI.PackageEngine.PackageEngine/PEInterface.cs b/src/UniGetUI.PackageEngine.PackageEngine/PEInterface.cs index 5df649111b..d80ca9bc2a 100644 --- a/src/UniGetUI.PackageEngine.PackageEngine/PEInterface.cs +++ b/src/UniGetUI.PackageEngine.PackageEngine/PEInterface.cs @@ -2,17 +2,19 @@ using UniGetUI.Core.Logging; using UniGetUI.PackageEngine.Interfaces; using UniGetUI.PackageEngine.Managers.CargoManager; -using UniGetUI.PackageEngine.Managers.ChocolateyManager; using UniGetUI.PackageEngine.Managers.DotNetManager; using UniGetUI.PackageEngine.Managers.NpmManager; using UniGetUI.PackageEngine.Managers.PipManager; using UniGetUI.PackageEngine.Managers.PowerShell7Manager; -using UniGetUI.PackageEngine.Managers.PowerShellManager; -using UniGetUI.PackageEngine.Managers.ScoopManager; -using UniGetUI.PackageEngine.Managers.WingetManager; using UniGetUI.PackageEngine.Managers.VcpkgManager; using UniGetUI.PackageEngine.PackageClasses; using UniGetUI.PackageEngine.PackageLoader; +#if WINDOWS +using UniGetUI.PackageEngine.Managers.ChocolateyManager; +using UniGetUI.PackageEngine.Managers.PowerShellManager; +using UniGetUI.PackageEngine.Managers.ScoopManager; +using UniGetUI.PackageEngine.Managers.WingetManager; +#endif namespace UniGetUI.PackageEngine { @@ -23,18 +25,32 @@ public static class PEInterface { private const int ManagerLoadTimeout = 60; // 60 seconds timeout for Package Manager initialization (in seconds) +#if WINDOWS public static readonly WinGet WinGet = new(); public static readonly Scoop Scoop = new(); public static readonly Chocolatey Chocolatey = new(); +#endif public static readonly Npm Npm = new(); public static readonly Pip Pip = new(); public static readonly DotNet DotNet = new(); - public static readonly PowerShell PowerShell = new(); public static readonly PowerShell7 PowerShell7 = new(); +#if WINDOWS + public static readonly PowerShell PowerShell = new(); +#endif public static readonly Cargo Cargo = new(); public static readonly Vcpkg Vcpkg = new(); - public static readonly IPackageManager[] Managers = [WinGet, Scoop, Chocolatey, Npm, Pip, Cargo, Vcpkg, DotNet, PowerShell, PowerShell7]; + public static readonly IPackageManager[] Managers = CreateManagers(); + + private static IPackageManager[] CreateManagers() + { + List managers = [Npm, Pip, Cargo, Vcpkg, DotNet, PowerShell7]; +#if WINDOWS + managers.InsertRange(0, [WinGet, Scoop, Chocolatey]); + managers.Add(PowerShell); +#endif + return [.. managers]; + } public static void LoadLoaders() { diff --git a/src/UniGetUI.PackageEngine.PackageEngine/UniGetUI.PackageEngine.PEInterface.csproj b/src/UniGetUI.PackageEngine.PackageEngine/UniGetUI.PackageEngine.PEInterface.csproj index 92ae6427b0..e44ad4e6a7 100644 --- a/src/UniGetUI.PackageEngine.PackageEngine/UniGetUI.PackageEngine.PEInterface.csproj +++ b/src/UniGetUI.PackageEngine.PackageEngine/UniGetUI.PackageEngine.PEInterface.csproj @@ -1,32 +1,32 @@ - - - - - - - + + + + + + + diff --git a/src/UniGetUI.PackageEngine.PackageLoader/UniGetUI.PackageEngine.PackageLoaders.csproj b/src/UniGetUI.PackageEngine.PackageLoader/UniGetUI.PackageEngine.PackageLoaders.csproj index 66dc2028a1..37e3af7d3f 100644 --- a/src/UniGetUI.PackageEngine.PackageLoader/UniGetUI.PackageEngine.PackageLoaders.csproj +++ b/src/UniGetUI.PackageEngine.PackageLoader/UniGetUI.PackageEngine.PackageLoaders.csproj @@ -1,5 +1,4 @@ - diff --git a/src/UniGetUI.PackageEngine.PackageManagerClasses/Manager/PackageManager.cs b/src/UniGetUI.PackageEngine.PackageManagerClasses/Manager/PackageManager.cs index 328e704cb4..8e46a0fbc1 100644 --- a/src/UniGetUI.PackageEngine.PackageManagerClasses/Manager/PackageManager.cs +++ b/src/UniGetUI.PackageEngine.PackageManagerClasses/Manager/PackageManager.cs @@ -1,4 +1,3 @@ -using ABI.Windows.UI.Text.Core; using UniGetUI.Core.Logging; using UniGetUI.Core.SettingsEngine; using UniGetUI.Core.SettingsEngine.SecureSettings; diff --git a/src/UniGetUI.PackageEngine.PackageManagerClasses/UniGetUI.PackageEngine.Classes.csproj b/src/UniGetUI.PackageEngine.PackageManagerClasses/UniGetUI.PackageEngine.Classes.csproj index ceb88260c2..0724f7b3ab 100644 --- a/src/UniGetUI.PackageEngine.PackageManagerClasses/UniGetUI.PackageEngine.Classes.csproj +++ b/src/UniGetUI.PackageEngine.PackageManagerClasses/UniGetUI.PackageEngine.Classes.csproj @@ -1,7 +1,5 @@ - - diff --git a/src/UniGetUI.PackageEngine.Serializable.Tests/TestInstallOptions.cs b/src/UniGetUI.PackageEngine.Serializable.Tests/TestInstallOptions.cs index da1d6078ee..dd911b5667 100644 --- a/src/UniGetUI.PackageEngine.Serializable.Tests/TestInstallOptions.cs +++ b/src/UniGetUI.PackageEngine.Serializable.Tests/TestInstallOptions.cs @@ -1,5 +1,4 @@ using System.Text.Json.Nodes; -using WinRT.Interop; using Xunit.Sdk; namespace UniGetUI.PackageEngine.Serializable.Tests; diff --git a/src/UniGetUI.PackageEngine.Serializable.Tests/UniGetUI.PackageEngine.Serializable.Tests.csproj b/src/UniGetUI.PackageEngine.Serializable.Tests/UniGetUI.PackageEngine.Serializable.Tests.csproj index 1b66bb895a..6017a732f4 100644 --- a/src/UniGetUI.PackageEngine.Serializable.Tests/UniGetUI.PackageEngine.Serializable.Tests.csproj +++ b/src/UniGetUI.PackageEngine.Serializable.Tests/UniGetUI.PackageEngine.Serializable.Tests.csproj @@ -1,7 +1,8 @@ - net8.0-windows10.0.26100.0 + $(PortableTargetFramework) + false true diff --git a/src/UniGetUI.PackageEngine.Serializable/UniGetUI.PackageEngine.Serializable.csproj b/src/UniGetUI.PackageEngine.Serializable/UniGetUI.PackageEngine.Serializable.csproj index 8561cc9883..3ed00d4994 100644 --- a/src/UniGetUI.PackageEngine.Serializable/UniGetUI.PackageEngine.Serializable.csproj +++ b/src/UniGetUI.PackageEngine.Serializable/UniGetUI.PackageEngine.Serializable.csproj @@ -1,7 +1,5 @@ - - diff --git a/src/UniGetUI.sln b/src/UniGetUI.sln index d71e0676e3..5fdbdef3f9 100644 --- a/src/UniGetUI.sln +++ b/src/UniGetUI.sln @@ -110,173 +110,339 @@ EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|x64 = Debug|x64 + Debug|arm64 = Debug|arm64 Release|x64 = Release|x64 + Release|arm64 = Release|arm64 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {80305A17-2534-48DC-8F75-41F70FCCEAAF}.Debug|x64.ActiveCfg = Debug|x64 + {80305A17-2534-48DC-8F75-41F70FCCEAAF}.Debug|arm64.ActiveCfg = Debug|arm64 {80305A17-2534-48DC-8F75-41F70FCCEAAF}.Debug|x64.Build.0 = Debug|x64 + {80305A17-2534-48DC-8F75-41F70FCCEAAF}.Debug|arm64.Build.0 = Debug|arm64 {80305A17-2534-48DC-8F75-41F70FCCEAAF}.Release|x64.ActiveCfg = Release|x64 + {80305A17-2534-48DC-8F75-41F70FCCEAAF}.Release|arm64.ActiveCfg = Release|arm64 {80305A17-2534-48DC-8F75-41F70FCCEAAF}.Release|x64.Build.0 = Release|x64 + {80305A17-2534-48DC-8F75-41F70FCCEAAF}.Release|arm64.Build.0 = Release|arm64 {52AC982E-7382-4746-BB66-4003698FCC02}.Debug|x64.ActiveCfg = Debug|x64 + {52AC982E-7382-4746-BB66-4003698FCC02}.Debug|arm64.ActiveCfg = Debug|arm64 {52AC982E-7382-4746-BB66-4003698FCC02}.Debug|x64.Build.0 = Debug|x64 + {52AC982E-7382-4746-BB66-4003698FCC02}.Debug|arm64.Build.0 = Debug|arm64 {52AC982E-7382-4746-BB66-4003698FCC02}.Release|x64.ActiveCfg = Release|x64 + {52AC982E-7382-4746-BB66-4003698FCC02}.Release|arm64.ActiveCfg = Release|arm64 {52AC982E-7382-4746-BB66-4003698FCC02}.Release|x64.Build.0 = Release|x64 + {52AC982E-7382-4746-BB66-4003698FCC02}.Release|arm64.Build.0 = Release|arm64 {5F5EF76B-D755-4C12-ADAE-11F08CE3D936}.Debug|x64.ActiveCfg = Debug|x64 + {5F5EF76B-D755-4C12-ADAE-11F08CE3D936}.Debug|arm64.ActiveCfg = Debug|arm64 {5F5EF76B-D755-4C12-ADAE-11F08CE3D936}.Debug|x64.Build.0 = Debug|x64 + {5F5EF76B-D755-4C12-ADAE-11F08CE3D936}.Debug|arm64.Build.0 = Debug|arm64 {5F5EF76B-D755-4C12-ADAE-11F08CE3D936}.Release|x64.ActiveCfg = Release|x64 + {5F5EF76B-D755-4C12-ADAE-11F08CE3D936}.Release|arm64.ActiveCfg = Release|arm64 {5F5EF76B-D755-4C12-ADAE-11F08CE3D936}.Release|x64.Build.0 = Release|x64 + {5F5EF76B-D755-4C12-ADAE-11F08CE3D936}.Release|arm64.Build.0 = Release|arm64 {B70A6F17-08C8-4194-BBE8-668CA920CFF3}.Debug|x64.ActiveCfg = Debug|x64 + {B70A6F17-08C8-4194-BBE8-668CA920CFF3}.Debug|arm64.ActiveCfg = Debug|arm64 {B70A6F17-08C8-4194-BBE8-668CA920CFF3}.Debug|x64.Build.0 = Debug|x64 + {B70A6F17-08C8-4194-BBE8-668CA920CFF3}.Debug|arm64.Build.0 = Debug|arm64 {B70A6F17-08C8-4194-BBE8-668CA920CFF3}.Release|x64.ActiveCfg = Release|x64 + {B70A6F17-08C8-4194-BBE8-668CA920CFF3}.Release|arm64.ActiveCfg = Release|arm64 {B70A6F17-08C8-4194-BBE8-668CA920CFF3}.Release|x64.Build.0 = Release|x64 + {B70A6F17-08C8-4194-BBE8-668CA920CFF3}.Release|arm64.Build.0 = Release|arm64 {72180B0C-3D20-4AAD-B015-A9337B91406E}.Debug|x64.ActiveCfg = Debug|x64 + {72180B0C-3D20-4AAD-B015-A9337B91406E}.Debug|arm64.ActiveCfg = Debug|arm64 {72180B0C-3D20-4AAD-B015-A9337B91406E}.Debug|x64.Build.0 = Debug|x64 + {72180B0C-3D20-4AAD-B015-A9337B91406E}.Debug|arm64.Build.0 = Debug|arm64 {72180B0C-3D20-4AAD-B015-A9337B91406E}.Release|x64.ActiveCfg = Release|x64 + {72180B0C-3D20-4AAD-B015-A9337B91406E}.Release|arm64.ActiveCfg = Release|arm64 {72180B0C-3D20-4AAD-B015-A9337B91406E}.Release|x64.Build.0 = Release|x64 + {72180B0C-3D20-4AAD-B015-A9337B91406E}.Release|arm64.Build.0 = Release|arm64 {1977360F-2E42-45E6-9369-AB1EE59CC5C5}.Debug|x64.ActiveCfg = Debug|x64 + {1977360F-2E42-45E6-9369-AB1EE59CC5C5}.Debug|arm64.ActiveCfg = Debug|arm64 {1977360F-2E42-45E6-9369-AB1EE59CC5C5}.Debug|x64.Build.0 = Debug|x64 + {1977360F-2E42-45E6-9369-AB1EE59CC5C5}.Debug|arm64.Build.0 = Debug|arm64 {1977360F-2E42-45E6-9369-AB1EE59CC5C5}.Release|x64.ActiveCfg = Release|x64 + {1977360F-2E42-45E6-9369-AB1EE59CC5C5}.Release|arm64.ActiveCfg = Release|arm64 {1977360F-2E42-45E6-9369-AB1EE59CC5C5}.Release|x64.Build.0 = Release|x64 + {1977360F-2E42-45E6-9369-AB1EE59CC5C5}.Release|arm64.Build.0 = Release|arm64 {25C6CE64-2D61-4832-B6D2-45AFC52E2447}.Debug|x64.ActiveCfg = Debug|x64 + {25C6CE64-2D61-4832-B6D2-45AFC52E2447}.Debug|arm64.ActiveCfg = Debug|arm64 {25C6CE64-2D61-4832-B6D2-45AFC52E2447}.Debug|x64.Build.0 = Debug|x64 + {25C6CE64-2D61-4832-B6D2-45AFC52E2447}.Debug|arm64.Build.0 = Debug|arm64 {25C6CE64-2D61-4832-B6D2-45AFC52E2447}.Release|x64.ActiveCfg = Release|x64 + {25C6CE64-2D61-4832-B6D2-45AFC52E2447}.Release|arm64.ActiveCfg = Release|arm64 {25C6CE64-2D61-4832-B6D2-45AFC52E2447}.Release|x64.Build.0 = Release|x64 + {25C6CE64-2D61-4832-B6D2-45AFC52E2447}.Release|arm64.Build.0 = Release|arm64 {8156B6D8-BD7E-4201-BD8B-8C9B00177F88}.Debug|x64.ActiveCfg = Debug|x64 + {8156B6D8-BD7E-4201-BD8B-8C9B00177F88}.Debug|arm64.ActiveCfg = Debug|arm64 {8156B6D8-BD7E-4201-BD8B-8C9B00177F88}.Debug|x64.Build.0 = Debug|x64 + {8156B6D8-BD7E-4201-BD8B-8C9B00177F88}.Debug|arm64.Build.0 = Debug|arm64 {8156B6D8-BD7E-4201-BD8B-8C9B00177F88}.Release|x64.ActiveCfg = Release|x64 + {8156B6D8-BD7E-4201-BD8B-8C9B00177F88}.Release|arm64.ActiveCfg = Release|arm64 {8156B6D8-BD7E-4201-BD8B-8C9B00177F88}.Release|x64.Build.0 = Release|x64 + {8156B6D8-BD7E-4201-BD8B-8C9B00177F88}.Release|arm64.Build.0 = Release|arm64 {990F5AFF-ABF6-4019-865D-604D2B23DE2C}.Debug|x64.ActiveCfg = Debug|x64 + {990F5AFF-ABF6-4019-865D-604D2B23DE2C}.Debug|arm64.ActiveCfg = Debug|arm64 {990F5AFF-ABF6-4019-865D-604D2B23DE2C}.Debug|x64.Build.0 = Debug|x64 + {990F5AFF-ABF6-4019-865D-604D2B23DE2C}.Debug|arm64.Build.0 = Debug|arm64 {990F5AFF-ABF6-4019-865D-604D2B23DE2C}.Release|x64.ActiveCfg = Release|x64 + {990F5AFF-ABF6-4019-865D-604D2B23DE2C}.Release|arm64.ActiveCfg = Release|arm64 {990F5AFF-ABF6-4019-865D-604D2B23DE2C}.Release|x64.Build.0 = Release|x64 + {990F5AFF-ABF6-4019-865D-604D2B23DE2C}.Release|arm64.Build.0 = Release|arm64 {380E9F5A-23DE-4F5A-9644-EFA51AD1D8E8}.Debug|x64.ActiveCfg = Debug|x64 + {380E9F5A-23DE-4F5A-9644-EFA51AD1D8E8}.Debug|arm64.ActiveCfg = Debug|arm64 {380E9F5A-23DE-4F5A-9644-EFA51AD1D8E8}.Debug|x64.Build.0 = Debug|x64 + {380E9F5A-23DE-4F5A-9644-EFA51AD1D8E8}.Debug|arm64.Build.0 = Debug|arm64 {380E9F5A-23DE-4F5A-9644-EFA51AD1D8E8}.Release|x64.ActiveCfg = Release|x64 + {380E9F5A-23DE-4F5A-9644-EFA51AD1D8E8}.Release|arm64.ActiveCfg = Release|arm64 {380E9F5A-23DE-4F5A-9644-EFA51AD1D8E8}.Release|x64.Build.0 = Release|x64 + {380E9F5A-23DE-4F5A-9644-EFA51AD1D8E8}.Release|arm64.Build.0 = Release|arm64 {5A48C2FD-16E4-4B44-BC2C-D793C50E66F2}.Debug|x64.ActiveCfg = Debug|x64 + {5A48C2FD-16E4-4B44-BC2C-D793C50E66F2}.Debug|arm64.ActiveCfg = Debug|arm64 {5A48C2FD-16E4-4B44-BC2C-D793C50E66F2}.Debug|x64.Build.0 = Debug|x64 + {5A48C2FD-16E4-4B44-BC2C-D793C50E66F2}.Debug|arm64.Build.0 = Debug|arm64 {5A48C2FD-16E4-4B44-BC2C-D793C50E66F2}.Release|x64.ActiveCfg = Release|x64 + {5A48C2FD-16E4-4B44-BC2C-D793C50E66F2}.Release|arm64.ActiveCfg = Release|arm64 {5A48C2FD-16E4-4B44-BC2C-D793C50E66F2}.Release|x64.Build.0 = Release|x64 + {5A48C2FD-16E4-4B44-BC2C-D793C50E66F2}.Release|arm64.Build.0 = Release|arm64 {9AD1DEC9-1561-4753-AB4B-E81FBDBA5C9E}.Debug|x64.ActiveCfg = Debug|x64 + {9AD1DEC9-1561-4753-AB4B-E81FBDBA5C9E}.Debug|arm64.ActiveCfg = Debug|arm64 {9AD1DEC9-1561-4753-AB4B-E81FBDBA5C9E}.Debug|x64.Build.0 = Debug|x64 + {9AD1DEC9-1561-4753-AB4B-E81FBDBA5C9E}.Debug|arm64.Build.0 = Debug|arm64 {9AD1DEC9-1561-4753-AB4B-E81FBDBA5C9E}.Release|x64.ActiveCfg = Release|x64 + {9AD1DEC9-1561-4753-AB4B-E81FBDBA5C9E}.Release|arm64.ActiveCfg = Release|arm64 {9AD1DEC9-1561-4753-AB4B-E81FBDBA5C9E}.Release|x64.Build.0 = Release|x64 + {9AD1DEC9-1561-4753-AB4B-E81FBDBA5C9E}.Release|arm64.Build.0 = Release|arm64 {E40BFCBB-7A02-4E2C-AFDB-A717359EF4FC}.Debug|x64.ActiveCfg = Debug|x64 + {E40BFCBB-7A02-4E2C-AFDB-A717359EF4FC}.Debug|arm64.ActiveCfg = Debug|arm64 {E40BFCBB-7A02-4E2C-AFDB-A717359EF4FC}.Debug|x64.Build.0 = Debug|x64 + {E40BFCBB-7A02-4E2C-AFDB-A717359EF4FC}.Debug|arm64.Build.0 = Debug|arm64 {E40BFCBB-7A02-4E2C-AFDB-A717359EF4FC}.Release|x64.ActiveCfg = Release|x64 + {E40BFCBB-7A02-4E2C-AFDB-A717359EF4FC}.Release|arm64.ActiveCfg = Release|arm64 {E40BFCBB-7A02-4E2C-AFDB-A717359EF4FC}.Release|x64.Build.0 = Release|x64 + {E40BFCBB-7A02-4E2C-AFDB-A717359EF4FC}.Release|arm64.Build.0 = Release|arm64 {562B4814-2A78-4692-90BE-A727AABCEC85}.Debug|x64.ActiveCfg = Debug|x64 + {562B4814-2A78-4692-90BE-A727AABCEC85}.Debug|arm64.ActiveCfg = Debug|arm64 {562B4814-2A78-4692-90BE-A727AABCEC85}.Debug|x64.Build.0 = Debug|x64 + {562B4814-2A78-4692-90BE-A727AABCEC85}.Debug|arm64.Build.0 = Debug|arm64 {562B4814-2A78-4692-90BE-A727AABCEC85}.Release|x64.ActiveCfg = Release|x64 + {562B4814-2A78-4692-90BE-A727AABCEC85}.Release|arm64.ActiveCfg = Release|arm64 {562B4814-2A78-4692-90BE-A727AABCEC85}.Release|x64.Build.0 = Release|x64 + {562B4814-2A78-4692-90BE-A727AABCEC85}.Release|arm64.Build.0 = Release|arm64 {1A51EA31-6D78-4E98-B767-41A02C6E34D8}.Debug|x64.ActiveCfg = Debug|x64 + {1A51EA31-6D78-4E98-B767-41A02C6E34D8}.Debug|arm64.ActiveCfg = Debug|arm64 {1A51EA31-6D78-4E98-B767-41A02C6E34D8}.Debug|x64.Build.0 = Debug|x64 + {1A51EA31-6D78-4E98-B767-41A02C6E34D8}.Debug|arm64.Build.0 = Debug|arm64 {1A51EA31-6D78-4E98-B767-41A02C6E34D8}.Release|x64.ActiveCfg = Release|x64 + {1A51EA31-6D78-4E98-B767-41A02C6E34D8}.Release|arm64.ActiveCfg = Release|arm64 {1A51EA31-6D78-4E98-B767-41A02C6E34D8}.Release|x64.Build.0 = Release|x64 + {1A51EA31-6D78-4E98-B767-41A02C6E34D8}.Release|arm64.Build.0 = Release|arm64 {230BF08C-C039-473B-933F-3BF647440E0E}.Debug|x64.ActiveCfg = Debug|x64 + {230BF08C-C039-473B-933F-3BF647440E0E}.Debug|arm64.ActiveCfg = Debug|arm64 {230BF08C-C039-473B-933F-3BF647440E0E}.Debug|x64.Build.0 = Debug|x64 + {230BF08C-C039-473B-933F-3BF647440E0E}.Debug|arm64.Build.0 = Debug|arm64 {230BF08C-C039-473B-933F-3BF647440E0E}.Release|x64.ActiveCfg = Release|x64 + {230BF08C-C039-473B-933F-3BF647440E0E}.Release|arm64.ActiveCfg = Release|arm64 {230BF08C-C039-473B-933F-3BF647440E0E}.Release|x64.Build.0 = Release|x64 + {230BF08C-C039-473B-933F-3BF647440E0E}.Release|arm64.Build.0 = Release|arm64 {C55F4BA7-BBDD-42A4-88C1-FD3C411EB234}.Debug|x64.ActiveCfg = Debug|x64 + {C55F4BA7-BBDD-42A4-88C1-FD3C411EB234}.Debug|arm64.ActiveCfg = Debug|arm64 {C55F4BA7-BBDD-42A4-88C1-FD3C411EB234}.Debug|x64.Build.0 = Debug|x64 + {C55F4BA7-BBDD-42A4-88C1-FD3C411EB234}.Debug|arm64.Build.0 = Debug|arm64 {C55F4BA7-BBDD-42A4-88C1-FD3C411EB234}.Release|x64.ActiveCfg = Release|x64 + {C55F4BA7-BBDD-42A4-88C1-FD3C411EB234}.Release|arm64.ActiveCfg = Release|arm64 {C55F4BA7-BBDD-42A4-88C1-FD3C411EB234}.Release|x64.Build.0 = Release|x64 + {C55F4BA7-BBDD-42A4-88C1-FD3C411EB234}.Release|arm64.Build.0 = Release|arm64 {2979E556-5859-4E88-A1D4-EAB72F82294E}.Debug|x64.ActiveCfg = Debug|x64 + {2979E556-5859-4E88-A1D4-EAB72F82294E}.Debug|arm64.ActiveCfg = Debug|arm64 {2979E556-5859-4E88-A1D4-EAB72F82294E}.Debug|x64.Build.0 = Debug|x64 + {2979E556-5859-4E88-A1D4-EAB72F82294E}.Debug|arm64.Build.0 = Debug|arm64 {2979E556-5859-4E88-A1D4-EAB72F82294E}.Release|x64.ActiveCfg = Release|x64 + {2979E556-5859-4E88-A1D4-EAB72F82294E}.Release|arm64.ActiveCfg = Release|arm64 {2979E556-5859-4E88-A1D4-EAB72F82294E}.Release|x64.Build.0 = Release|x64 + {2979E556-5859-4E88-A1D4-EAB72F82294E}.Release|arm64.Build.0 = Release|arm64 {7E098666-DE8C-4ABF-B709-4CE7B1A491B0}.Debug|x64.ActiveCfg = Debug|x64 + {7E098666-DE8C-4ABF-B709-4CE7B1A491B0}.Debug|arm64.ActiveCfg = Debug|arm64 {7E098666-DE8C-4ABF-B709-4CE7B1A491B0}.Debug|x64.Build.0 = Debug|x64 + {7E098666-DE8C-4ABF-B709-4CE7B1A491B0}.Debug|arm64.Build.0 = Debug|arm64 {7E098666-DE8C-4ABF-B709-4CE7B1A491B0}.Release|x64.ActiveCfg = Release|x64 + {7E098666-DE8C-4ABF-B709-4CE7B1A491B0}.Release|arm64.ActiveCfg = Release|arm64 {7E098666-DE8C-4ABF-B709-4CE7B1A491B0}.Release|x64.Build.0 = Release|x64 + {7E098666-DE8C-4ABF-B709-4CE7B1A491B0}.Release|arm64.Build.0 = Release|arm64 {D47CC16E-466B-4D58-A8FC-ECAE5C9606FC}.Debug|x64.ActiveCfg = Debug|x64 + {D47CC16E-466B-4D58-A8FC-ECAE5C9606FC}.Debug|arm64.ActiveCfg = Debug|arm64 {D47CC16E-466B-4D58-A8FC-ECAE5C9606FC}.Debug|x64.Build.0 = Debug|x64 + {D47CC16E-466B-4D58-A8FC-ECAE5C9606FC}.Debug|arm64.Build.0 = Debug|arm64 {D47CC16E-466B-4D58-A8FC-ECAE5C9606FC}.Release|x64.ActiveCfg = Release|x64 + {D47CC16E-466B-4D58-A8FC-ECAE5C9606FC}.Release|arm64.ActiveCfg = Release|arm64 {D47CC16E-466B-4D58-A8FC-ECAE5C9606FC}.Release|x64.Build.0 = Release|x64 + {D47CC16E-466B-4D58-A8FC-ECAE5C9606FC}.Release|arm64.Build.0 = Release|arm64 {1143176D-B7F0-477C-90BB-72289068D927}.Debug|x64.ActiveCfg = Debug|x64 + {1143176D-B7F0-477C-90BB-72289068D927}.Debug|arm64.ActiveCfg = Debug|arm64 {1143176D-B7F0-477C-90BB-72289068D927}.Debug|x64.Build.0 = Debug|x64 + {1143176D-B7F0-477C-90BB-72289068D927}.Debug|arm64.Build.0 = Debug|arm64 {1143176D-B7F0-477C-90BB-72289068D927}.Release|x64.ActiveCfg = Release|x64 + {1143176D-B7F0-477C-90BB-72289068D927}.Release|arm64.ActiveCfg = Release|arm64 {1143176D-B7F0-477C-90BB-72289068D927}.Release|x64.Build.0 = Release|x64 + {1143176D-B7F0-477C-90BB-72289068D927}.Release|arm64.Build.0 = Release|arm64 {E454D3A5-C5C6-4291-BE96-220CF0D5CFFD}.Debug|x64.ActiveCfg = Debug|x64 + {E454D3A5-C5C6-4291-BE96-220CF0D5CFFD}.Debug|arm64.ActiveCfg = Debug|arm64 {E454D3A5-C5C6-4291-BE96-220CF0D5CFFD}.Debug|x64.Build.0 = Debug|x64 + {E454D3A5-C5C6-4291-BE96-220CF0D5CFFD}.Debug|arm64.Build.0 = Debug|arm64 {E454D3A5-C5C6-4291-BE96-220CF0D5CFFD}.Release|x64.ActiveCfg = Release|x64 + {E454D3A5-C5C6-4291-BE96-220CF0D5CFFD}.Release|arm64.ActiveCfg = Release|arm64 {E454D3A5-C5C6-4291-BE96-220CF0D5CFFD}.Release|x64.Build.0 = Release|x64 + {E454D3A5-C5C6-4291-BE96-220CF0D5CFFD}.Release|arm64.Build.0 = Release|arm64 {57D094C1-6913-46BF-A657-84A5F46D4EE7}.Debug|x64.ActiveCfg = Debug|x64 + {57D094C1-6913-46BF-A657-84A5F46D4EE7}.Debug|arm64.ActiveCfg = Debug|arm64 {57D094C1-6913-46BF-A657-84A5F46D4EE7}.Debug|x64.Build.0 = Debug|x64 + {57D094C1-6913-46BF-A657-84A5F46D4EE7}.Debug|arm64.Build.0 = Debug|arm64 {57D094C1-6913-46BF-A657-84A5F46D4EE7}.Release|x64.ActiveCfg = Release|x64 + {57D094C1-6913-46BF-A657-84A5F46D4EE7}.Release|arm64.ActiveCfg = Release|arm64 {57D094C1-6913-46BF-A657-84A5F46D4EE7}.Release|x64.Build.0 = Release|x64 + {57D094C1-6913-46BF-A657-84A5F46D4EE7}.Release|arm64.Build.0 = Release|arm64 {740E2894-903D-4B94-9C32-B630593BEB16}.Debug|x64.ActiveCfg = Debug|x64 + {740E2894-903D-4B94-9C32-B630593BEB16}.Debug|arm64.ActiveCfg = Debug|arm64 {740E2894-903D-4B94-9C32-B630593BEB16}.Debug|x64.Build.0 = Debug|x64 + {740E2894-903D-4B94-9C32-B630593BEB16}.Debug|arm64.Build.0 = Debug|arm64 {740E2894-903D-4B94-9C32-B630593BEB16}.Release|x64.ActiveCfg = Release|x64 + {740E2894-903D-4B94-9C32-B630593BEB16}.Release|arm64.ActiveCfg = Release|arm64 {740E2894-903D-4B94-9C32-B630593BEB16}.Release|x64.Build.0 = Release|x64 + {740E2894-903D-4B94-9C32-B630593BEB16}.Release|arm64.Build.0 = Release|arm64 {D401F706-A182-46E3-A25C-B0BF5AA0D07E}.Debug|x64.ActiveCfg = Debug|x64 + {D401F706-A182-46E3-A25C-B0BF5AA0D07E}.Debug|arm64.ActiveCfg = Debug|arm64 {D401F706-A182-46E3-A25C-B0BF5AA0D07E}.Debug|x64.Build.0 = Debug|x64 + {D401F706-A182-46E3-A25C-B0BF5AA0D07E}.Debug|arm64.Build.0 = Debug|arm64 {D401F706-A182-46E3-A25C-B0BF5AA0D07E}.Release|x64.ActiveCfg = Release|x64 + {D401F706-A182-46E3-A25C-B0BF5AA0D07E}.Release|arm64.ActiveCfg = Release|arm64 {D401F706-A182-46E3-A25C-B0BF5AA0D07E}.Release|x64.Build.0 = Release|x64 + {D401F706-A182-46E3-A25C-B0BF5AA0D07E}.Release|arm64.Build.0 = Release|arm64 {0FFA3F96-A68A-453F-A5FE-0C281EC371C7}.Debug|x64.ActiveCfg = Debug|x64 + {0FFA3F96-A68A-453F-A5FE-0C281EC371C7}.Debug|arm64.ActiveCfg = Debug|arm64 {0FFA3F96-A68A-453F-A5FE-0C281EC371C7}.Debug|x64.Build.0 = Debug|x64 + {0FFA3F96-A68A-453F-A5FE-0C281EC371C7}.Debug|arm64.Build.0 = Debug|arm64 {0FFA3F96-A68A-453F-A5FE-0C281EC371C7}.Release|x64.ActiveCfg = Release|x64 + {0FFA3F96-A68A-453F-A5FE-0C281EC371C7}.Release|arm64.ActiveCfg = Release|arm64 {0FFA3F96-A68A-453F-A5FE-0C281EC371C7}.Release|x64.Build.0 = Release|x64 + {0FFA3F96-A68A-453F-A5FE-0C281EC371C7}.Release|arm64.Build.0 = Release|arm64 {5FA79592-DE5B-46FF-9E05-34A2E72A7AF7}.Debug|x64.ActiveCfg = Debug|x64 + {5FA79592-DE5B-46FF-9E05-34A2E72A7AF7}.Debug|arm64.ActiveCfg = Debug|arm64 {5FA79592-DE5B-46FF-9E05-34A2E72A7AF7}.Debug|x64.Build.0 = Debug|x64 + {5FA79592-DE5B-46FF-9E05-34A2E72A7AF7}.Debug|arm64.Build.0 = Debug|arm64 {5FA79592-DE5B-46FF-9E05-34A2E72A7AF7}.Release|x64.ActiveCfg = Release|x64 + {5FA79592-DE5B-46FF-9E05-34A2E72A7AF7}.Release|arm64.ActiveCfg = Release|arm64 {5FA79592-DE5B-46FF-9E05-34A2E72A7AF7}.Release|x64.Build.0 = Release|x64 + {5FA79592-DE5B-46FF-9E05-34A2E72A7AF7}.Release|arm64.Build.0 = Release|arm64 {09FD3D3A-1EFC-4AEE-B3D7-096D238E0D1A}.Debug|x64.ActiveCfg = Debug|x64 + {09FD3D3A-1EFC-4AEE-B3D7-096D238E0D1A}.Debug|arm64.ActiveCfg = Debug|arm64 {09FD3D3A-1EFC-4AEE-B3D7-096D238E0D1A}.Debug|x64.Build.0 = Debug|x64 + {09FD3D3A-1EFC-4AEE-B3D7-096D238E0D1A}.Debug|arm64.Build.0 = Debug|arm64 {09FD3D3A-1EFC-4AEE-B3D7-096D238E0D1A}.Release|x64.ActiveCfg = Release|x64 + {09FD3D3A-1EFC-4AEE-B3D7-096D238E0D1A}.Release|arm64.ActiveCfg = Release|arm64 {09FD3D3A-1EFC-4AEE-B3D7-096D238E0D1A}.Release|x64.Build.0 = Release|x64 + {09FD3D3A-1EFC-4AEE-B3D7-096D238E0D1A}.Release|arm64.Build.0 = Release|arm64 {BDB7A8F3-87A6-4B77-9E0F-6BC785CBCF2B}.Debug|x64.ActiveCfg = Debug|x64 + {BDB7A8F3-87A6-4B77-9E0F-6BC785CBCF2B}.Debug|arm64.ActiveCfg = Debug|arm64 {BDB7A8F3-87A6-4B77-9E0F-6BC785CBCF2B}.Debug|x64.Build.0 = Debug|x64 + {BDB7A8F3-87A6-4B77-9E0F-6BC785CBCF2B}.Debug|arm64.Build.0 = Debug|arm64 {BDB7A8F3-87A6-4B77-9E0F-6BC785CBCF2B}.Release|x64.ActiveCfg = Release|x64 + {BDB7A8F3-87A6-4B77-9E0F-6BC785CBCF2B}.Release|arm64.ActiveCfg = Release|arm64 {BDB7A8F3-87A6-4B77-9E0F-6BC785CBCF2B}.Release|x64.Build.0 = Release|x64 + {BDB7A8F3-87A6-4B77-9E0F-6BC785CBCF2B}.Release|arm64.Build.0 = Release|arm64 {27E0B288-7DFF-468D-9360-035E8CE123CB}.Debug|x64.ActiveCfg = Debug|x64 + {27E0B288-7DFF-468D-9360-035E8CE123CB}.Debug|arm64.ActiveCfg = Debug|arm64 {27E0B288-7DFF-468D-9360-035E8CE123CB}.Debug|x64.Build.0 = Debug|x64 + {27E0B288-7DFF-468D-9360-035E8CE123CB}.Debug|arm64.Build.0 = Debug|arm64 {27E0B288-7DFF-468D-9360-035E8CE123CB}.Release|x64.ActiveCfg = Release|x64 + {27E0B288-7DFF-468D-9360-035E8CE123CB}.Release|arm64.ActiveCfg = Release|arm64 {27E0B288-7DFF-468D-9360-035E8CE123CB}.Release|x64.Build.0 = Release|x64 + {27E0B288-7DFF-468D-9360-035E8CE123CB}.Release|arm64.Build.0 = Release|arm64 {20F43119-EA00-440D-B3B5-44F96592F4C8}.Debug|x64.ActiveCfg = Debug|x64 + {20F43119-EA00-440D-B3B5-44F96592F4C8}.Debug|arm64.ActiveCfg = Debug|arm64 {20F43119-EA00-440D-B3B5-44F96592F4C8}.Debug|x64.Build.0 = Debug|x64 + {20F43119-EA00-440D-B3B5-44F96592F4C8}.Debug|arm64.Build.0 = Debug|arm64 {20F43119-EA00-440D-B3B5-44F96592F4C8}.Release|x64.ActiveCfg = Release|x64 + {20F43119-EA00-440D-B3B5-44F96592F4C8}.Release|arm64.ActiveCfg = Release|arm64 {20F43119-EA00-440D-B3B5-44F96592F4C8}.Release|x64.Build.0 = Release|x64 + {20F43119-EA00-440D-B3B5-44F96592F4C8}.Release|arm64.Build.0 = Release|arm64 {CC400751-216E-4BB2-8103-495B4E273477}.Debug|x64.ActiveCfg = Debug|x64 + {CC400751-216E-4BB2-8103-495B4E273477}.Debug|arm64.ActiveCfg = Debug|arm64 {CC400751-216E-4BB2-8103-495B4E273477}.Debug|x64.Build.0 = Debug|x64 + {CC400751-216E-4BB2-8103-495B4E273477}.Debug|arm64.Build.0 = Debug|arm64 {CC400751-216E-4BB2-8103-495B4E273477}.Release|x64.ActiveCfg = Release|x64 + {CC400751-216E-4BB2-8103-495B4E273477}.Release|arm64.ActiveCfg = Release|arm64 {CC400751-216E-4BB2-8103-495B4E273477}.Release|x64.Build.0 = Release|x64 + {CC400751-216E-4BB2-8103-495B4E273477}.Release|arm64.Build.0 = Release|arm64 {F4E7301D-9C8A-4A4A-92D2-35B896642BF6}.Debug|x64.ActiveCfg = Debug|x64 + {F4E7301D-9C8A-4A4A-92D2-35B896642BF6}.Debug|arm64.ActiveCfg = Debug|arm64 {F4E7301D-9C8A-4A4A-92D2-35B896642BF6}.Debug|x64.Build.0 = Debug|x64 + {F4E7301D-9C8A-4A4A-92D2-35B896642BF6}.Debug|arm64.Build.0 = Debug|arm64 {F4E7301D-9C8A-4A4A-92D2-35B896642BF6}.Release|x64.ActiveCfg = Release|x64 + {F4E7301D-9C8A-4A4A-92D2-35B896642BF6}.Release|arm64.ActiveCfg = Release|arm64 {F4E7301D-9C8A-4A4A-92D2-35B896642BF6}.Release|x64.Build.0 = Release|x64 + {F4E7301D-9C8A-4A4A-92D2-35B896642BF6}.Release|arm64.Build.0 = Release|arm64 {29450002-5F93-4886-922E-30350C9C3442}.Debug|x64.ActiveCfg = Debug|x64 + {29450002-5F93-4886-922E-30350C9C3442}.Debug|arm64.ActiveCfg = Debug|arm64 {29450002-5F93-4886-922E-30350C9C3442}.Debug|x64.Build.0 = Debug|x64 + {29450002-5F93-4886-922E-30350C9C3442}.Debug|arm64.Build.0 = Debug|arm64 {29450002-5F93-4886-922E-30350C9C3442}.Release|x64.ActiveCfg = Release|x64 + {29450002-5F93-4886-922E-30350C9C3442}.Release|arm64.ActiveCfg = Release|arm64 {29450002-5F93-4886-922E-30350C9C3442}.Release|x64.Build.0 = Release|x64 + {29450002-5F93-4886-922E-30350C9C3442}.Release|arm64.Build.0 = Release|arm64 {C396E5F6-C6D9-465D-9903-7E33D0841E6A}.Debug|x64.ActiveCfg = Debug|x64 + {C396E5F6-C6D9-465D-9903-7E33D0841E6A}.Debug|arm64.ActiveCfg = Debug|arm64 {C396E5F6-C6D9-465D-9903-7E33D0841E6A}.Debug|x64.Build.0 = Debug|x64 + {C396E5F6-C6D9-465D-9903-7E33D0841E6A}.Debug|arm64.Build.0 = Debug|arm64 {C396E5F6-C6D9-465D-9903-7E33D0841E6A}.Release|x64.ActiveCfg = Release|x64 + {C396E5F6-C6D9-465D-9903-7E33D0841E6A}.Release|arm64.ActiveCfg = Release|arm64 {C396E5F6-C6D9-465D-9903-7E33D0841E6A}.Release|x64.Build.0 = Release|x64 + {C396E5F6-C6D9-465D-9903-7E33D0841E6A}.Release|arm64.Build.0 = Release|arm64 {54DA0549-366F-4E70-B5D1-0B8891D0A2A5}.Debug|x64.ActiveCfg = Debug|x64 + {54DA0549-366F-4E70-B5D1-0B8891D0A2A5}.Debug|arm64.ActiveCfg = Debug|arm64 {54DA0549-366F-4E70-B5D1-0B8891D0A2A5}.Debug|x64.Build.0 = Debug|x64 + {54DA0549-366F-4E70-B5D1-0B8891D0A2A5}.Debug|arm64.Build.0 = Debug|arm64 {54DA0549-366F-4E70-B5D1-0B8891D0A2A5}.Release|x64.ActiveCfg = Release|x64 + {54DA0549-366F-4E70-B5D1-0B8891D0A2A5}.Release|arm64.ActiveCfg = Release|arm64 {54DA0549-366F-4E70-B5D1-0B8891D0A2A5}.Release|x64.Build.0 = Release|x64 + {54DA0549-366F-4E70-B5D1-0B8891D0A2A5}.Release|arm64.Build.0 = Release|arm64 {E337A71E-3C30-4315-B8F1-57CBC5CF50A6}.Debug|x64.ActiveCfg = Debug|x64 + {E337A71E-3C30-4315-B8F1-57CBC5CF50A6}.Debug|arm64.ActiveCfg = Debug|arm64 {E337A71E-3C30-4315-B8F1-57CBC5CF50A6}.Debug|x64.Build.0 = Debug|x64 + {E337A71E-3C30-4315-B8F1-57CBC5CF50A6}.Debug|arm64.Build.0 = Debug|arm64 {E337A71E-3C30-4315-B8F1-57CBC5CF50A6}.Release|x64.ActiveCfg = Release|x64 + {E337A71E-3C30-4315-B8F1-57CBC5CF50A6}.Release|arm64.ActiveCfg = Release|arm64 {E337A71E-3C30-4315-B8F1-57CBC5CF50A6}.Release|x64.Build.0 = Release|x64 + {E337A71E-3C30-4315-B8F1-57CBC5CF50A6}.Release|arm64.Build.0 = Release|arm64 {727866B8-BBD5-43B9-933A-78199F65429C}.Debug|x64.ActiveCfg = Debug|x64 + {727866B8-BBD5-43B9-933A-78199F65429C}.Debug|arm64.ActiveCfg = Debug|arm64 {727866B8-BBD5-43B9-933A-78199F65429C}.Debug|x64.Build.0 = Debug|x64 + {727866B8-BBD5-43B9-933A-78199F65429C}.Debug|arm64.Build.0 = Debug|arm64 {727866B8-BBD5-43B9-933A-78199F65429C}.Release|x64.ActiveCfg = Release|x64 + {727866B8-BBD5-43B9-933A-78199F65429C}.Release|arm64.ActiveCfg = Release|arm64 {727866B8-BBD5-43B9-933A-78199F65429C}.Release|x64.Build.0 = Release|x64 + {727866B8-BBD5-43B9-933A-78199F65429C}.Release|arm64.Build.0 = Release|arm64 {3C8BF564-B4B5-44A7-9D8C-102C2F820EAF}.Debug|x64.ActiveCfg = Debug|x64 + {3C8BF564-B4B5-44A7-9D8C-102C2F820EAF}.Debug|arm64.ActiveCfg = Debug|arm64 {3C8BF564-B4B5-44A7-9D8C-102C2F820EAF}.Debug|x64.Build.0 = Debug|x64 + {3C8BF564-B4B5-44A7-9D8C-102C2F820EAF}.Debug|arm64.Build.0 = Debug|arm64 {3C8BF564-B4B5-44A7-9D8C-102C2F820EAF}.Release|x64.ActiveCfg = Release|x64 + {3C8BF564-B4B5-44A7-9D8C-102C2F820EAF}.Release|arm64.ActiveCfg = Release|arm64 {3C8BF564-B4B5-44A7-9D8C-102C2F820EAF}.Release|x64.Build.0 = Release|x64 + {3C8BF564-B4B5-44A7-9D8C-102C2F820EAF}.Release|arm64.Build.0 = Release|arm64 {F1610A61-5444-4C11-9447-13CCA327887E}.Debug|x64.ActiveCfg = Debug|x64 + {F1610A61-5444-4C11-9447-13CCA327887E}.Debug|arm64.ActiveCfg = Debug|arm64 {F1610A61-5444-4C11-9447-13CCA327887E}.Debug|x64.Build.0 = Debug|x64 + {F1610A61-5444-4C11-9447-13CCA327887E}.Debug|arm64.Build.0 = Debug|arm64 {F1610A61-5444-4C11-9447-13CCA327887E}.Release|x64.ActiveCfg = Release|x64 + {F1610A61-5444-4C11-9447-13CCA327887E}.Release|arm64.ActiveCfg = Release|arm64 {F1610A61-5444-4C11-9447-13CCA327887E}.Release|x64.Build.0 = Release|x64 + {F1610A61-5444-4C11-9447-13CCA327887E}.Release|arm64.Build.0 = Release|arm64 {B0E59327-933E-4DB0-BD2D-FB16EB9B4194}.Debug|x64.ActiveCfg = Debug|x64 + {B0E59327-933E-4DB0-BD2D-FB16EB9B4194}.Debug|arm64.ActiveCfg = Debug|arm64 {B0E59327-933E-4DB0-BD2D-FB16EB9B4194}.Debug|x64.Build.0 = Debug|x64 + {B0E59327-933E-4DB0-BD2D-FB16EB9B4194}.Debug|arm64.Build.0 = Debug|arm64 {B0E59327-933E-4DB0-BD2D-FB16EB9B4194}.Release|x64.ActiveCfg = Release|x64 + {B0E59327-933E-4DB0-BD2D-FB16EB9B4194}.Release|arm64.ActiveCfg = Release|arm64 {B0E59327-933E-4DB0-BD2D-FB16EB9B4194}.Release|x64.Build.0 = Release|x64 + {B0E59327-933E-4DB0-BD2D-FB16EB9B4194}.Release|arm64.Build.0 = Release|arm64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/src/UniGetUI/UniGetUI.csproj b/src/UniGetUI/UniGetUI.csproj index 1b2fb3ca50..186066534a 100644 --- a/src/UniGetUI/UniGetUI.csproj +++ b/src/UniGetUI/UniGetUI.csproj @@ -1,6 +1,8 @@  + $(WindowsTargetFramework) + WinExe UniGetUI app.manifest diff --git a/src/WindowsPackageManager.Interop/ExternalLibraries.WindowsPackageManager.Interop.csproj b/src/WindowsPackageManager.Interop/ExternalLibraries.WindowsPackageManager.Interop.csproj index 85575c3f5a..aab72c57cc 100644 --- a/src/WindowsPackageManager.Interop/ExternalLibraries.WindowsPackageManager.Interop.csproj +++ b/src/WindowsPackageManager.Interop/ExternalLibraries.WindowsPackageManager.Interop.csproj @@ -1,6 +1,8 @@ + $(WindowsTargetFramework) + true diff --git a/test_publish.cmd b/test_publish.cmd deleted file mode 100644 index 49652f3561..0000000000 --- a/test_publish.cmd +++ /dev/null @@ -1,8 +0,0 @@ -@echo off -rmdir /q /s src\UniGetUI\bin\x64\Release\net8.0-windows10.0.26100.0\win-x64\publish\ -dotnet publish src/UniGetUI/UniGetUI.csproj /noLogo /property:Configuration=Release /property:Platform=x64 -v m -%signcommand% "src\UniGetUI\bin\x64\Release\net8.0-windows10.0.26100.0\win-x64\publish\UniGetUI.exe" -python3 scripts\generate_integrity_tree.py %cd%\src\UniGetUI\bin\x64\Release\net8.0-windows10.0.26100.0\win-x64\publish\ -echo %cd%\src\UniGetUI\bin\x64\Release\net8.0-windows10.0.26100.0\win-x64\publish\ -src\UniGetUI\bin\x64\Release\net8.0-windows10.0.26100.0\win-x64\publish\UniGetUI.exe -pause \ No newline at end of file diff --git a/test_publish_nosign.cmd b/test_publish_nosign.cmd deleted file mode 100644 index 6c94856ce4..0000000000 --- a/test_publish_nosign.cmd +++ /dev/null @@ -1,7 +0,0 @@ -@echo off -rmdir /q /s src\UniGetUI\bin\x64\Release\net8.0-windows10.0.26100.0\win-x64\publish\ -dotnet publish src/UniGetUI/UniGetUI.csproj /noLogo /property:Configuration=Release /property:Platform=x64 -v m -python3 scripts\generate_integrity_tree.py %cd%\src\UniGetUI\bin\x64\Release\net8.0-windows10.0.26100.0\win-x64\publish\ -echo %cd%\src\UniGetUI\bin\x64\Release\net8.0-windows10.0.26100.0\win-x64\publish\ -src\UniGetUI\bin\x64\Release\net8.0-windows10.0.26100.0\win-x64\publish\UniGetUI.exe -pause \ No newline at end of file