From 944d439cdd5b84ed71b4d3bed7b8ee5e543f66c8 Mon Sep 17 00:00:00 2001 From: Stephan van Rooij <1292510+svrooij@users.noreply.github.com> Date: Fri, 22 Dec 2023 00:32:40 +0100 Subject: [PATCH 1/7] fix: Changes to Winget stuff to sanitize urls --- .../WingetRepository.cs | 14 +++- .../Commands/PackageCommand.cs | 1 + .../Commands/PublishCommand.cs | 2 +- src/WingetIntune.Cli/packages.lock.json | 34 ++++---- .../Implementations/WingetManager.cs | 5 +- src/WingetIntune/WingetIntune.csproj | 6 +- src/WingetIntune/packages.lock.json | 34 ++++---- .../WingetIntune.Tests.csproj | 4 +- tests/WingetIntune.Tests/packages.lock.json | 78 +++++++++---------- 9 files changed, 96 insertions(+), 82 deletions(-) diff --git a/src/Winget.CommunityRepository/WingetRepository.cs b/src/Winget.CommunityRepository/WingetRepository.cs index 5cbc55c..56e0b08 100644 --- a/src/Winget.CommunityRepository/WingetRepository.cs +++ b/src/Winget.CommunityRepository/WingetRepository.cs @@ -33,11 +33,23 @@ public WingetRepository(HttpClient? httpClient = null, ILogger } public async ValueTask GetLatestVersion(string packageId, CancellationToken cancellationToken = default) + { + var entry = await GetEntry(packageId, cancellationToken); + return entry?.Version; + } + + public async ValueTask GetPackageId(string packageId, CancellationToken cancellationToken = default) + { + var entry = await GetEntry(packageId, cancellationToken); + return entry?.PackageId; + } + + private async ValueTask GetEntry(string packageId, CancellationToken cancellationToken = default) { await LoadEntries(cancellationToken, false, cacheFile); var entry = Entries!.FirstOrDefault(e => e.PackageId.Equals(packageId, StringComparison.OrdinalIgnoreCase)); - return entry?.Version; + return entry; } public async ValueTask> SearchPackage(string query, CancellationToken cancellationToken = default) diff --git a/src/WingetIntune.Cli/Commands/PackageCommand.cs b/src/WingetIntune.Cli/Commands/PackageCommand.cs index 7a0999b..a0615ce 100644 --- a/src/WingetIntune.Cli/Commands/PackageCommand.cs +++ b/src/WingetIntune.Cli/Commands/PackageCommand.cs @@ -69,6 +69,7 @@ private async Task HandleCommand(PackageCommandOptions options, InvocationC if (options.Version is null && options.Source == "winget" && !options.UseWinget) { logger.LogInformation("Getting latest version for {PackageId}", options.PackageId); + options.PackageId = (await repo.GetPackageId(options.PackageId, cancellationToken))!; options.Version = await repo.GetLatestVersion(options.PackageId, cancellationToken); } diff --git a/src/WingetIntune.Cli/Commands/PublishCommand.cs b/src/WingetIntune.Cli/Commands/PublishCommand.cs index 6da74ed..457b4ee 100644 --- a/src/WingetIntune.Cli/Commands/PublishCommand.cs +++ b/src/WingetIntune.Cli/Commands/PublishCommand.cs @@ -63,6 +63,7 @@ private async Task HandleCommand(PublishCommandOptions options, InvocationC logger.LogInformation("Try loading latest version from package index"); var repo = host.Services.GetRequiredService(); //repo.UseRespository = true; + options.PackageId = (await repo.GetPackageId(options.PackageId, cancellationToken)) ?? options.PackageId; options.Version = await repo.GetLatestVersion(options.PackageId, cancellationToken); } var tempInfo = await winget.GetPackageInfoAsync(options.PackageId, options.Version, options.Source, cancellationToken); @@ -73,7 +74,6 @@ private async Task HandleCommand(PublishCommandOptions options, InvocationC } if (options.AutoPackage && tempInfo.Source == PackageSource.Winget) { - await intuneManager.GenerateInstallerPackage(options.TempFolder, options.PackageFolder!, tempInfo, diff --git a/src/WingetIntune.Cli/packages.lock.json b/src/WingetIntune.Cli/packages.lock.json index 9ee5902..50f4676 100644 --- a/src/WingetIntune.Cli/packages.lock.json +++ b/src/WingetIntune.Cli/packages.lock.json @@ -112,10 +112,10 @@ }, "Microsoft.EntityFrameworkCore.Sqlite": { "type": "Transitive", - "resolved": "7.0.11", - "contentHash": "DFev72BUsvd+QI5aH+uwoXM8u3P1GwTsLToORj6CGQJrkd+8UukuSsCXOWxj0ThiGC11btcmjjFx4FGuB3F28g==", + "resolved": "7.0.14", + "contentHash": "8c8Hw2tmfy5YEsi9RL2/u2Qi9IwVbmj/yDlJy4iJPadeE3/AssLrgtobOBz4ftg2y5PVjFL59Gq7YzGLQH5q1A==", "dependencies": { - "Microsoft.EntityFrameworkCore.Sqlite.Core": "7.0.11", + "Microsoft.EntityFrameworkCore.Sqlite.Core": "7.0.14", "SQLitePCLRaw.bundle_e_sqlite3": "2.1.4" } }, @@ -445,8 +445,8 @@ }, "Microsoft.Identity.Client": { "type": "Transitive", - "resolved": "4.58.0", - "contentHash": "dRPo7/omWfLcxUniAvlsTduSm0YYpef6Mumlx1PjXfIeB8tWrXe5vK9h8Ld41u/5W569Sx5QKSz+VI4KtxsVjg==", + "resolved": "4.58.1", + "contentHash": "UOESBIUrJVhmJHOrZyKQSAbpVroV4kMYfCQG0rsEAnd4tocanCH3tqqnx9w++ToPCX5icznxBveFZxmyam0oqg==", "dependencies": { "Microsoft.IdentityModel.Abstractions": "6.22.0", "System.Diagnostics.DiagnosticSource": "7.0.2" @@ -454,19 +454,19 @@ }, "Microsoft.Identity.Client.Broker": { "type": "Transitive", - "resolved": "4.58.0", - "contentHash": "pctWgSDxgibpO/Vxho94IeF6Nmsax9psxeylm5UH0J+1zm8Mbw8pmDmFpd16wIJZSR19XjXFkx38Gnz9oZeP+A==", + "resolved": "4.58.1", + "contentHash": "gQvW2wkN7CLlfWZxHpYv0OC8Xrf+TNP2u1z8bodyGyEqQdHVIE9Tk1KtsBUW8n1v/akN71SHkb4262IkmjXiMw==", "dependencies": { - "Microsoft.Identity.Client": "4.58.0", + "Microsoft.Identity.Client": "4.58.1", "Microsoft.Identity.Client.NativeInterop": "0.13.14" } }, "Microsoft.Identity.Client.Extensions.Msal": { "type": "Transitive", - "resolved": "4.58.0", - "contentHash": "g799G8sjZmYmkbDn6jd+1mC/mxCHSHCDx3fm3z7U5OBpMhE1aiHpQ4pfXOibG6iD8JWBIckFME3JWf4oj8ttVQ==", + "resolved": "4.58.1", + "contentHash": "M1gK3sFPl9kVLHa0qwWEU3l3w13J/HmvDVM4QcTV+WvQh6aN0KWAsUKNPwlvMwGRHzFkVOWofoaM6xo5zbyADQ==", "dependencies": { - "Microsoft.Identity.Client": "4.58.0", + "Microsoft.Identity.Client": "4.58.1", "System.IO.FileSystem.AccessControl": "5.0.0", "System.Security.Cryptography.ProtectedData": "4.5.0" } @@ -618,8 +618,8 @@ }, "Riok.Mapperly": { "type": "Transitive", - "resolved": "3.2.0", - "contentHash": "EChq4G7PmEXhaPH4Ztw/CiHQ9iVg30Ir58vTA2MgGLsI+ciza5H4boLNK+mk+ik3eStwuA+ZeAxb4mhXVeDgFQ==" + "resolved": "3.3.0", + "contentHash": "zncD+ur/lys3vdStUsJa8A/g6fLABsfVOHKx7aFjZ3xBCGmSde8BEGcoLdhuC1Tpcyo6pgWSTigJqB4aPXSFiw==" }, "SQLitePCLRaw.bundle_e_sqlite3": { "type": "Transitive", @@ -908,7 +908,7 @@ "winget.communityrepository": { "type": "Project", "dependencies": { - "Microsoft.EntityFrameworkCore.Sqlite": "[7.0.11, )", + "Microsoft.EntityFrameworkCore.Sqlite": "[7.0.14, )", "Microsoft.EntityFrameworkCore.Sqlite.Core": "[7.0.14, )", "Mono.TextTemplating": "[2.3.1, )", "System.CodeDom": "[8.0.0, )", @@ -925,10 +925,10 @@ "Microsoft.Extensions.Logging.Abstractions": "[8.0.0, )", "Microsoft.Extensions.Options": "[8.0.0, )", "Microsoft.Graph.Beta": "[5.48.0-preview, )", - "Microsoft.Identity.Client.Broker": "[4.58.0, )", - "Microsoft.Identity.Client.Extensions.Msal": "[4.58.0, )", + "Microsoft.Identity.Client.Broker": "[4.58.1, )", + "Microsoft.Identity.Client.Extensions.Msal": "[4.58.1, )", "Microsoft.NETCore.Platforms": "[7.0.4, )", - "Riok.Mapperly": "[3.2.0, )", + "Riok.Mapperly": "[3.3.0, )", "SvRooij.ContentPrep": "[0.1.2, )", "Winget.CommunityRepository": "[1.0.0, )" } diff --git a/src/WingetIntune/Implementations/WingetManager.cs b/src/WingetIntune/Implementations/WingetManager.cs index 4e2597b..76dbff4 100644 --- a/src/WingetIntune/Implementations/WingetManager.cs +++ b/src/WingetIntune/Implementations/WingetManager.cs @@ -149,8 +149,9 @@ private async Task GetPackageInfoFromWingetManifestAsync(string id, internal static string CreateManifestUri(string id, string version, string? addition) { - var idParts = id.Split('.'); - return $"https://github.com/microsoft/winget-pkgs/raw/master/manifests/{id[0].ToString().ToLower()}/{string.Join("/", idParts)}/{version}/{id}{addition}.yaml"; + var sanitizedId = id.Replace("+", "%2B"); + var idParts = sanitizedId.Split('.'); + return $"https://github.com/microsoft/winget-pkgs/raw/master/manifests/{id[0].ToString().ToLower()}/{string.Join("/", idParts)}/{version}/{sanitizedId}{addition}.yaml"; } private static Exception CreateExceptionForFailedProcess(ProcessResult processResult) diff --git a/src/WingetIntune/WingetIntune.csproj b/src/WingetIntune/WingetIntune.csproj index f622ff0..66ad2b9 100644 --- a/src/WingetIntune/WingetIntune.csproj +++ b/src/WingetIntune/WingetIntune.csproj @@ -28,10 +28,10 @@ - - + + - + diff --git a/src/WingetIntune/packages.lock.json b/src/WingetIntune/packages.lock.json index 7d0462d..5dd4afd 100644 --- a/src/WingetIntune/packages.lock.json +++ b/src/WingetIntune/packages.lock.json @@ -57,21 +57,21 @@ }, "Microsoft.Identity.Client.Broker": { "type": "Direct", - "requested": "[4.58.0, )", - "resolved": "4.58.0", - "contentHash": "pctWgSDxgibpO/Vxho94IeF6Nmsax9psxeylm5UH0J+1zm8Mbw8pmDmFpd16wIJZSR19XjXFkx38Gnz9oZeP+A==", + "requested": "[4.58.1, )", + "resolved": "4.58.1", + "contentHash": "gQvW2wkN7CLlfWZxHpYv0OC8Xrf+TNP2u1z8bodyGyEqQdHVIE9Tk1KtsBUW8n1v/akN71SHkb4262IkmjXiMw==", "dependencies": { - "Microsoft.Identity.Client": "4.58.0", + "Microsoft.Identity.Client": "4.58.1", "Microsoft.Identity.Client.NativeInterop": "0.13.14" } }, "Microsoft.Identity.Client.Extensions.Msal": { "type": "Direct", - "requested": "[4.58.0, )", - "resolved": "4.58.0", - "contentHash": "g799G8sjZmYmkbDn6jd+1mC/mxCHSHCDx3fm3z7U5OBpMhE1aiHpQ4pfXOibG6iD8JWBIckFME3JWf4oj8ttVQ==", + "requested": "[4.58.1, )", + "resolved": "4.58.1", + "contentHash": "M1gK3sFPl9kVLHa0qwWEU3l3w13J/HmvDVM4QcTV+WvQh6aN0KWAsUKNPwlvMwGRHzFkVOWofoaM6xo5zbyADQ==", "dependencies": { - "Microsoft.Identity.Client": "4.58.0", + "Microsoft.Identity.Client": "4.58.1", "System.IO.FileSystem.AccessControl": "5.0.0", "System.Security.Cryptography.ProtectedData": "4.5.0" } @@ -84,9 +84,9 @@ }, "Riok.Mapperly": { "type": "Direct", - "requested": "[3.2.0, )", - "resolved": "3.2.0", - "contentHash": "EChq4G7PmEXhaPH4Ztw/CiHQ9iVg30Ir58vTA2MgGLsI+ciza5H4boLNK+mk+ik3eStwuA+ZeAxb4mhXVeDgFQ==" + "requested": "[3.3.0, )", + "resolved": "3.3.0", + "contentHash": "zncD+ur/lys3vdStUsJa8A/g6fLABsfVOHKx7aFjZ3xBCGmSde8BEGcoLdhuC1Tpcyo6pgWSTigJqB4aPXSFiw==" }, "SvRooij.ContentPrep": { "type": "Direct", @@ -154,10 +154,10 @@ }, "Microsoft.EntityFrameworkCore.Sqlite": { "type": "Transitive", - "resolved": "7.0.11", - "contentHash": "DFev72BUsvd+QI5aH+uwoXM8u3P1GwTsLToORj6CGQJrkd+8UukuSsCXOWxj0ThiGC11btcmjjFx4FGuB3F28g==", + "resolved": "7.0.14", + "contentHash": "8c8Hw2tmfy5YEsi9RL2/u2Qi9IwVbmj/yDlJy4iJPadeE3/AssLrgtobOBz4ftg2y5PVjFL59Gq7YzGLQH5q1A==", "dependencies": { - "Microsoft.EntityFrameworkCore.Sqlite.Core": "7.0.11", + "Microsoft.EntityFrameworkCore.Sqlite.Core": "7.0.14", "SQLitePCLRaw.bundle_e_sqlite3": "2.1.4" } }, @@ -255,8 +255,8 @@ }, "Microsoft.Identity.Client": { "type": "Transitive", - "resolved": "4.58.0", - "contentHash": "dRPo7/omWfLcxUniAvlsTduSm0YYpef6Mumlx1PjXfIeB8tWrXe5vK9h8Ld41u/5W569Sx5QKSz+VI4KtxsVjg==", + "resolved": "4.58.1", + "contentHash": "UOESBIUrJVhmJHOrZyKQSAbpVroV4kMYfCQG0rsEAnd4tocanCH3tqqnx9w++ToPCX5icznxBveFZxmyam0oqg==", "dependencies": { "Microsoft.IdentityModel.Abstractions": "6.22.0", "System.Diagnostics.DiagnosticSource": "7.0.2" @@ -666,7 +666,7 @@ "winget.communityrepository": { "type": "Project", "dependencies": { - "Microsoft.EntityFrameworkCore.Sqlite": "[7.0.11, )", + "Microsoft.EntityFrameworkCore.Sqlite": "[7.0.14, )", "Microsoft.EntityFrameworkCore.Sqlite.Core": "[7.0.14, )", "Mono.TextTemplating": "[2.3.1, )", "System.CodeDom": "[8.0.0, )", diff --git a/tests/WingetIntune.Tests/WingetIntune.Tests.csproj b/tests/WingetIntune.Tests/WingetIntune.Tests.csproj index a9a39ef..0316fac 100644 --- a/tests/WingetIntune.Tests/WingetIntune.Tests.csproj +++ b/tests/WingetIntune.Tests/WingetIntune.Tests.csproj @@ -25,8 +25,8 @@ - - + + runtime; build; native; contentfiles; analyzers; buildtransitive all diff --git a/tests/WingetIntune.Tests/packages.lock.json b/tests/WingetIntune.Tests/packages.lock.json index 1c571e8..083fc98 100644 --- a/tests/WingetIntune.Tests/packages.lock.json +++ b/tests/WingetIntune.Tests/packages.lock.json @@ -44,20 +44,20 @@ }, "xunit": { "type": "Direct", - "requested": "[2.6.2, )", - "resolved": "2.6.2", - "contentHash": "sErOyzTZBfgeLcdu5y3CkhCirZikCe9GwEv56jbQRjSa4FyI2tIHjfBRvlWqg7M78bfAGajrreH0IHnxrUOpVA==", + "requested": "[2.6.3, )", + "resolved": "2.6.3", + "contentHash": "4CoGp3iKZORZ9aaHdPrFcdlDBRI/ZFRyDZWJuP7r2idULEtWf+k0yGT80cF/v6nE/MQDXLMIuSGDIrHuPLC/+Q==", "dependencies": { - "xunit.analyzers": "1.6.0", - "xunit.assert": "2.6.2", - "xunit.core": "[2.6.2]" + "xunit.analyzers": "1.7.0", + "xunit.assert": "2.6.3", + "xunit.core": "[2.6.3]" } }, "xunit.runner.visualstudio": { "type": "Direct", - "requested": "[2.5.4, )", - "resolved": "2.5.4", - "contentHash": "YUtEOBdArAISyb1cTWcHc6/bilSDB9q5lc8ughPQP1MqlAKSkxKMBqLQ+tiWMFRBd2o22E59nLD/4V5R3jfZxQ==" + "requested": "[2.5.5, )", + "resolved": "2.5.5", + "contentHash": "AJsBBn8S00ZxdXPSIp8s+NcBQMO9tcll1UVCfGNoEi1DUH2z3f4Y1epV9nYbhgG6wFoTKJP6YuLT2MeTPV9gnA==" }, "Azure.Core": { "type": "Transitive", @@ -137,10 +137,10 @@ }, "Microsoft.EntityFrameworkCore.Sqlite": { "type": "Transitive", - "resolved": "7.0.11", - "contentHash": "DFev72BUsvd+QI5aH+uwoXM8u3P1GwTsLToORj6CGQJrkd+8UukuSsCXOWxj0ThiGC11btcmjjFx4FGuB3F28g==", + "resolved": "7.0.14", + "contentHash": "8c8Hw2tmfy5YEsi9RL2/u2Qi9IwVbmj/yDlJy4iJPadeE3/AssLrgtobOBz4ftg2y5PVjFL59Gq7YzGLQH5q1A==", "dependencies": { - "Microsoft.EntityFrameworkCore.Sqlite.Core": "7.0.11", + "Microsoft.EntityFrameworkCore.Sqlite.Core": "7.0.14", "SQLitePCLRaw.bundle_e_sqlite3": "2.1.4" } }, @@ -275,8 +275,8 @@ }, "Microsoft.Identity.Client": { "type": "Transitive", - "resolved": "4.58.0", - "contentHash": "dRPo7/omWfLcxUniAvlsTduSm0YYpef6Mumlx1PjXfIeB8tWrXe5vK9h8Ld41u/5W569Sx5QKSz+VI4KtxsVjg==", + "resolved": "4.58.1", + "contentHash": "UOESBIUrJVhmJHOrZyKQSAbpVroV4kMYfCQG0rsEAnd4tocanCH3tqqnx9w++ToPCX5icznxBveFZxmyam0oqg==", "dependencies": { "Microsoft.IdentityModel.Abstractions": "6.22.0", "System.Diagnostics.DiagnosticSource": "7.0.2" @@ -284,19 +284,19 @@ }, "Microsoft.Identity.Client.Broker": { "type": "Transitive", - "resolved": "4.58.0", - "contentHash": "pctWgSDxgibpO/Vxho94IeF6Nmsax9psxeylm5UH0J+1zm8Mbw8pmDmFpd16wIJZSR19XjXFkx38Gnz9oZeP+A==", + "resolved": "4.58.1", + "contentHash": "gQvW2wkN7CLlfWZxHpYv0OC8Xrf+TNP2u1z8bodyGyEqQdHVIE9Tk1KtsBUW8n1v/akN71SHkb4262IkmjXiMw==", "dependencies": { - "Microsoft.Identity.Client": "4.58.0", + "Microsoft.Identity.Client": "4.58.1", "Microsoft.Identity.Client.NativeInterop": "0.13.14" } }, "Microsoft.Identity.Client.Extensions.Msal": { "type": "Transitive", - "resolved": "4.58.0", - "contentHash": "g799G8sjZmYmkbDn6jd+1mC/mxCHSHCDx3fm3z7U5OBpMhE1aiHpQ4pfXOibG6iD8JWBIckFME3JWf4oj8ttVQ==", + "resolved": "4.58.1", + "contentHash": "M1gK3sFPl9kVLHa0qwWEU3l3w13J/HmvDVM4QcTV+WvQh6aN0KWAsUKNPwlvMwGRHzFkVOWofoaM6xo5zbyADQ==", "dependencies": { - "Microsoft.Identity.Client": "4.58.0", + "Microsoft.Identity.Client": "4.58.1", "System.IO.FileSystem.AccessControl": "5.0.0", "System.Security.Cryptography.ProtectedData": "4.5.0" } @@ -476,8 +476,8 @@ }, "Riok.Mapperly": { "type": "Transitive", - "resolved": "3.2.0", - "contentHash": "EChq4G7PmEXhaPH4Ztw/CiHQ9iVg30Ir58vTA2MgGLsI+ciza5H4boLNK+mk+ik3eStwuA+ZeAxb4mhXVeDgFQ==" + "resolved": "3.3.0", + "contentHash": "zncD+ur/lys3vdStUsJa8A/g6fLABsfVOHKx7aFjZ3xBCGmSde8BEGcoLdhuC1Tpcyo6pgWSTigJqB4aPXSFiw==" }, "SQLitePCLRaw.bundle_e_sqlite3": { "type": "Transitive", @@ -762,27 +762,27 @@ }, "xunit.analyzers": { "type": "Transitive", - "resolved": "1.6.0", - "contentHash": "b/Wbrqr/bFvcjqAbYdJyCCvjz+PjjKMnoK/K6sbcCBu94pqAkB2vBAHFo87wNq2awsLPAuq5MA7q0XexyQ3mJQ==" + "resolved": "1.7.0", + "contentHash": "lAcpaB0KnjWETbPDMsDPoQi6zS0uXUYopmyTQDWvILJWcL9jwMxXXGmDLptlMA6vGi5Z0LtudsYN+dEUTmuHaA==" }, "xunit.assert": { "type": "Transitive", - "resolved": "2.6.2", - "contentHash": "JOj2+zWS08M59bCk3MkZFcKj2Izb2zwkHSPIKJLvnZYLR2Nw6HifjvBCpa8XhMF3mxDuGwZ0+ncmlhE9WoEaZw==" + "resolved": "2.6.3", + "contentHash": "7JWrjxDIAwF1vBZyENu4BZaddNJijIQcIQcc+73sJPWaqzDmseysTYv2jR0IWBsWIGa6LSfMO/3+dH0fsHL5Wg==" }, "xunit.core": { "type": "Transitive", - "resolved": "2.6.2", - "contentHash": "LxJ06D9uTDyvHY52+Lym2TUlq3ObgAKSTuzM9gniau8qI1fd/CPag4PFaGs0RJfunUJtYHg9+XrS5EcW/5dxGA==", + "resolved": "2.6.3", + "contentHash": "rlrm//9cNAlCkh3p5mdggzfchZlcXowUVK3UPqKiaN7G0Wu7gOUNLLZej9twnwTCVe1h3FEi9PRwzXMMXpFwSQ==", "dependencies": { - "xunit.extensibility.core": "[2.6.2]", - "xunit.extensibility.execution": "[2.6.2]" + "xunit.extensibility.core": "[2.6.3]", + "xunit.extensibility.execution": "[2.6.3]" } }, "xunit.extensibility.core": { "type": "Transitive", - "resolved": "2.6.2", - "contentHash": "T8CmshbP1EeaDibLwgU/aEe53zrW0+x+mEz5aKxexS5vVyj1UwgDUjcTK/+prMF/9KgMHkgx1vIe7wv58wO6RQ==", + "resolved": "2.6.3", + "contentHash": "qWCpmK4nxFBsf68r35AgnrW6B+xjTCpjJYfJkaBaini4Myl/2P/Ro6WocVtJfpHilkatitVFgM3XVR0jthdJlQ==", "dependencies": { "NETStandard.Library": "1.6.1", "xunit.abstractions": "2.0.3" @@ -790,11 +790,11 @@ }, "xunit.extensibility.execution": { "type": "Transitive", - "resolved": "2.6.2", - "contentHash": "kKo7XqyLF8blXGqQHlqKQ+AzST42kpB7oG81Km/kFEzWVfeDMgaEquOLAr/ZiR4tnkUbbWYrY6CJPTavFqGn6Q==", + "resolved": "2.6.3", + "contentHash": "I+9OA9a6WVia40bxJi3KaxVcjTE1ouHqD0QcrjHA/hLl7Ozb5eQmV7ecLu3gRZlPLdcVN+If8IZcEmqytmLtkA==", "dependencies": { "NETStandard.Library": "1.6.1", - "xunit.extensibility.core": "[2.6.2]" + "xunit.extensibility.core": "[2.6.3]" } }, "YamlDotNet": { @@ -805,7 +805,7 @@ "winget.communityrepository": { "type": "Project", "dependencies": { - "Microsoft.EntityFrameworkCore.Sqlite": "[7.0.11, )", + "Microsoft.EntityFrameworkCore.Sqlite": "[7.0.14, )", "Microsoft.EntityFrameworkCore.Sqlite.Core": "[7.0.14, )", "Mono.TextTemplating": "[2.3.1, )", "System.CodeDom": "[8.0.0, )", @@ -822,10 +822,10 @@ "Microsoft.Extensions.Logging.Abstractions": "[8.0.0, )", "Microsoft.Extensions.Options": "[8.0.0, )", "Microsoft.Graph.Beta": "[5.48.0-preview, )", - "Microsoft.Identity.Client.Broker": "[4.58.0, )", - "Microsoft.Identity.Client.Extensions.Msal": "[4.58.0, )", + "Microsoft.Identity.Client.Broker": "[4.58.1, )", + "Microsoft.Identity.Client.Extensions.Msal": "[4.58.1, )", "Microsoft.NETCore.Platforms": "[7.0.4, )", - "Riok.Mapperly": "[3.2.0, )", + "Riok.Mapperly": "[3.3.0, )", "SvRooij.ContentPrep": "[0.1.2, )", "Winget.CommunityRepository": "[1.0.0, )" } From 2d19e4a3fa58a9a34da0012ceb6ff856b795403f Mon Sep 17 00:00:00 2001 From: Stephan van Rooij <1292510+svrooij@users.noreply.github.com> Date: Wed, 27 Dec 2023 13:04:41 +0100 Subject: [PATCH 2/7] fix: Improved detection by discovering winget location Thanks Rudy Ooms Fixed: #23 --- scripts/detection-with-version.ps1 | 40 +++++++++++++++++-- .../Intune/IntuneManagerConstants.cs | 35 +++++++++++++++- src/WingetIntune/Models/Mapper.cs | 1 + 3 files changed, 72 insertions(+), 4 deletions(-) diff --git a/scripts/detection-with-version.ps1 b/scripts/detection-with-version.ps1 index 427c83d..4bdef7d 100644 --- a/scripts/detection-with-version.ps1 +++ b/scripts/detection-with-version.ps1 @@ -1,7 +1,41 @@ -$packageId = "7zip.7zip" -$version = "23.02.0.0" +$packageId = "Sonos.Controller" +$version = "73.0.41050" -$wingetOutput = & "winget" "list" "--id" $packageId "--exact" "--disable-interactivity" "--accept-source-agreements" +$transcriptionPath = "$env:ProgramData\Microsoft\IntuneManagementExtension\Logs\$packageId-detection.log" +Start-Transcript -Path $transcriptionPath -Force + +Write-Host "Starting $packageId detection, log location: $transcriptionPath" + +# Need to get the full path of winget, because detection script is run in a different context +Function Get-WingetCmd { + + $WingetCmd = $null + #Get WinGet Path + + try { + # Get Admin Context Winget Location + $WingetInfo = (Get-Item "$env:ProgramFiles\WindowsApps\Microsoft.DesktopAppInstaller_*_8wekyb3d8bbwe\winget.exe").VersionInfo | Sort-Object -Property FileVersionRaw + # if multiple versions, pick most recent one + $WingetCmd = $WingetInfo[-1].FileName + } + catch { + #Get User context Winget Location + if (Test-Path "$env:LocalAppData\Microsoft\WindowsApps\Microsoft.DesktopAppInstaller_8wekyb3d8bbwe\winget.exe") + { + $WingetCmd ="$env:LocalAppData\Microsoft\WindowsApps\Microsoft.DesktopAppInstaller_8wekyb3d8bbwe\winget.exe" + } + } + Write-Host "Winget location: $WingetCmd" + return $WingetCmd +} + +$wingetCmd = Get-WingetCmd +if ($null -eq $wingetCmd) { + Write-Host "winget not detected" + Exit 1 +} + +$wingetOutput = & $wingetCmd "list" "--id" $packageId "--exact" "--disable-interactivity" "--accept-source-agreements" if($wingetOutput -is [array]) { $lastRow = $wingetOutput[$wingetOutput.Length -1] diff --git a/src/WingetIntune/Intune/IntuneManagerConstants.cs b/src/WingetIntune/Intune/IntuneManagerConstants.cs index 72f2eea..ca1175f 100644 --- a/src/WingetIntune/Intune/IntuneManagerConstants.cs +++ b/src/WingetIntune/Intune/IntuneManagerConstants.cs @@ -21,7 +21,40 @@ Exit 5 internal const string PsDetectionCommandTemplate = @"$packageId = ""{packageId}"" $version = ""{version}"" -$wingetOutput = & ""winget"" ""list"" ""--id"" $packageId ""--exact"" ""--disable-interactivity"" ""--accept-source-agreements"" +$transcriptionPath = ""$env:ProgramData\Microsoft\IntuneManagementExtension\Logs\$packageId-detection.log"" +Start-Transcript -Path $transcriptionPath -Force +Write-Host ""Starting $packageId detection, log location: $transcriptionPath"" + +# Need to get the full path of winget, because detection script is run in a different context +Function Get-WingetCmd { + + $WingetCmd = $null + #Get WinGet Path + + try { + # Get Admin Context Winget Location + $WingetInfo = (Get-Item ""$env:ProgramFiles\WindowsApps\Microsoft.DesktopAppInstaller_*_8wekyb3d8bbwe\winget.exe"").VersionInfo | Sort-Object -Property FileVersionRaw + # if multiple versions, pick most recent one + $WingetCmd = $WingetInfo[-1].FileName + } + catch { + #Get User context Winget Location + if (Test-Path ""$env:LocalAppData\Microsoft\WindowsApps\Microsoft.DesktopAppInstaller_8wekyb3d8bbwe\winget.exe"") + { + $WingetCmd =""$env:LocalAppData\Microsoft\WindowsApps\Microsoft.DesktopAppInstaller_8wekyb3d8bbwe\winget.exe"" + } + } + Write-Host ""Winget location: $WingetCmd"" + return $WingetCmd +} + +$wingetCmd = Get-WingetCmd +if ($null -eq $wingetCmd) { + Write-Host ""winget not detected"" + Exit 1 +} + +$wingetOutput = & $wingetCmd ""list"" ""--id"" $packageId ""--exact"" ""--disable-interactivity"" ""--accept-source-agreements"" if($wingetOutput -is [array]) { $lastRow = $wingetOutput[$wingetOutput.Length -1] diff --git a/src/WingetIntune/Models/Mapper.cs b/src/WingetIntune/Models/Mapper.cs index 0c504c7..684c347 100644 --- a/src/WingetIntune/Models/Mapper.cs +++ b/src/WingetIntune/Models/Mapper.cs @@ -86,6 +86,7 @@ public Win32LobApp ToWin32LobApp(PackageInfo packageInfo) new Win32LobAppPowerShellScriptDetection { ScriptContent = System.Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes(packageInfo.DetectionScript!)), + EnforceSignatureCheck = false, } }; } From 8d5d39c1e26ccab66c263c19e1ef484188e03340 Mon Sep 17 00:00:00 2001 From: Stephan van Rooij <1292510+svrooij@users.noreply.github.com> Date: Fri, 29 Dec 2023 12:22:03 +0100 Subject: [PATCH 3/7] feat: Worked out detection and uninstall scripts - Scripts using winget will now resolve correctly - Scripts transcribe to `C:\ProgramData\Microsoft\IntuneManagementExtension\Logs` --- README.md | 30 +++++++++-- .../Commands/PublishCommand.cs | 1 - .../Properties/launchSettings.json | 10 +++- src/WingetIntune.Cli/packages.lock.json | 6 +-- .../Implementations/WingetHelper.cs | 1 - src/WingetIntune/Intune/IntuneManager.cs | 22 ++++++-- .../Intune/IntuneManagerConstants.cs | 37 ++++++++++++-- src/WingetIntune/WingetIntune.csproj | 2 +- src/WingetIntune/packages.lock.json | 6 +-- .../WingetIntune.Tests.csproj | 4 +- tests/WingetIntune.Tests/packages.lock.json | 50 +++++++++---------- 11 files changed, 118 insertions(+), 51 deletions(-) diff --git a/README.md b/README.md index 92083ad..1b3093f 100644 --- a/README.md +++ b/README.md @@ -80,10 +80,10 @@ It will also write a `app.json` file with all the information about the app, for winget-intune package {PackageId} [--version {version}] [--source winget] --package-folder {PackageFolder} ``` -> The `packageId` is case sensitive, so make sure you use the correct casing. Tip: Copy it from the result of the `winget search {name}` command. +> The `packageId` ~~is case sensitive, so make sure you use the correct casing~~ will be matches against any package in the open source [index](https://github.com/svrooij/winget-pkgs-index). Tip: Copy it from the result of the `winget search {name}` command. -This command will download the [content-prep-tool](https://github.com/Microsoft/Microsoft-Win32-Content-Prep-Tool) automatically, and use it to create the `intunewin` file. -In a future version this might be replaced with a custom implementation, but for now this works. The SHA265 hash of the installer is checked and compared to the one in the `winget` manifest, to make sure you won't package a tampered installer. +Upon downloading the installer, the SHA256 hash is checked against the one in the `winget` manifest, to make sure you won't package a tampered installer. +Previously it used the closed source [content-prep-tool](https://github.com/Microsoft/Microsoft-Win32-Content-Prep-Tool) to generate the `intunewin` file, this has since been replaced with my own faster, open-souce and cross-platform [implementation](https://github.com/Svrooij/ContentPrep). ### Publish @@ -98,6 +98,30 @@ winget-intune publish {PackageId} --package-folder {PackageFolder} --tenant {Ten winget-intune publish {PackageId} --package-folder {PackageFolder} --token {Token} ``` +#### Assignement and categories + +You can also assign the app to a group, and set the categories. + +```Shell +# Add --category "Productivity" --category "Utilities" to the command to set the categories (use the exact name!) +winget-intune publish {PackageId} ... --category "Productivity" --category "Utilities" + +# Add --available "group-guid" to make the app available to a group (use the guid of the group) +# Add --available "all-users" to make the app available to all users +# Instead of --available you can also use --required to make the app required for the group +# Or if you want to remove the app from the group, use --uninstall +winget-intune publish {PackageId}... --available "3bac8336-623f-46bf-bcab-b5c61e3e5b7a" --available "all-users" +winget-intune publish {PackageId}... --available "3bac8336-623f-46bf-bcab-b5c61e3e5b7a" --available "all-users" +``` + +#### Auto-package + +You can also combine the `package` and `publish` command into one command, this will package the app and publish it to Intune. But this makes debugging harder, so when submitting issues, please don't use this option. + +```Shell +winget-intune publish {PackageId}... --auto-package +``` + ## Library (soon) I'm planning to release the actual intune specific code as a separate library, so you can use it in your own projects. This will be released as a separate package. diff --git a/src/WingetIntune.Cli/Commands/PublishCommand.cs b/src/WingetIntune.Cli/Commands/PublishCommand.cs index 457b4ee..df97d4c 100644 --- a/src/WingetIntune.Cli/Commands/PublishCommand.cs +++ b/src/WingetIntune.Cli/Commands/PublishCommand.cs @@ -125,7 +125,6 @@ internal class PublishCommandOptions : WinGetRootCommand.DefaultOptions public bool AutoPackage { get; set; } public string TempFolder { get; set; } - public Uri ContentPrepToolUrl { get; set; } public InstallerContext InstallerContext { get; set; } public Architecture Architecture { get; set; } } diff --git a/src/WingetIntune.Cli/Properties/launchSettings.json b/src/WingetIntune.Cli/Properties/launchSettings.json index a1afe19..5e1b3e3 100644 --- a/src/WingetIntune.Cli/Properties/launchSettings.json +++ b/src/WingetIntune.Cli/Properties/launchSettings.json @@ -26,13 +26,19 @@ }, "WingetIntune.Cli package 1Password": { "commandName": "Project", - "commandLineArgs": "publish AgileBits.1Password --package-folder c:\\tools\\packages --auto-package --available allusers", + "commandLineArgs": "package AgileBits.1Password --package-folder c:\\tools\\packages", + "environmentVariables": { + } + }, + "WingetIntune.Cli package Notepadd++": { + "commandName": "Project", + "commandLineArgs": "package \"Notepad++.Notepad++\" --package-folder c:\\tools\\packages", "environmentVariables": { } }, "WingetIntune.Cli info ohmyposh": { "commandName": "Project", - "commandLineArgs": "info JanDeDobbeleer.OhMyPosh --source winget", + "commandLineArgs": "publish JanDeDobbeleer.OhMyPosh --package-folder c:\\tools\\packages --category Productivity --available allusers --auto-package --username admin@codingstephan.onmicrosoft.com", "environmentVariables": { } }, diff --git a/src/WingetIntune.Cli/packages.lock.json b/src/WingetIntune.Cli/packages.lock.json index 50f4676..9b52091 100644 --- a/src/WingetIntune.Cli/packages.lock.json +++ b/src/WingetIntune.Cli/packages.lock.json @@ -653,8 +653,8 @@ }, "SvRooij.ContentPrep": { "type": "Transitive", - "resolved": "0.1.2", - "contentHash": "T3PjOmsa9dEUkOEIlnSF5a18X4EXFmnvizTiEK/saxz+HvahEM9IXls6Qx2zgLxNTN5/HSpXrcqE9Lx4M40pLA==", + "resolved": "0.1.3-alpha0001", + "contentHash": "9exebiAiEz1cn5XKxivypRmpG0t0ykSFrenU8GtwYzv3JrIlkXT6WdntsVYr181ebWhdAWOU4cjR5IgMjDqQMg==", "dependencies": { "Microsoft.Extensions.Logging.Abstractions": "7.0.1", "Microsoft.NETCore.Platforms": "7.0.4", @@ -929,7 +929,7 @@ "Microsoft.Identity.Client.Extensions.Msal": "[4.58.1, )", "Microsoft.NETCore.Platforms": "[7.0.4, )", "Riok.Mapperly": "[3.3.0, )", - "SvRooij.ContentPrep": "[0.1.2, )", + "SvRooij.ContentPrep": "[0.1.3-alpha0001, )", "Winget.CommunityRepository": "[1.0.0, )" } } diff --git a/src/WingetIntune/Implementations/WingetHelper.cs b/src/WingetIntune/Implementations/WingetHelper.cs index 4f116ad..ed694b0 100644 --- a/src/WingetIntune/Implementations/WingetHelper.cs +++ b/src/WingetIntune/Implementations/WingetHelper.cs @@ -116,7 +116,6 @@ public static string GetUninstallArgumentsForPackage(string packageId, string? s } args.Add(ArgSilent); - args.Add(ArgPackageAgreements); args.Add(ArgSourceAgreements); args.Add(ArgDisableInteractivity); diff --git a/src/WingetIntune/Intune/IntuneManager.cs b/src/WingetIntune/Intune/IntuneManager.cs index cedef9a..b15af0e 100644 --- a/src/WingetIntune/Intune/IntuneManager.cs +++ b/src/WingetIntune/Intune/IntuneManager.cs @@ -116,7 +116,7 @@ private async Task GenerateNoneMsiInstaller(string tempFolder, string outputFold // TODO Create Winget Install script await fileManager.WriteAllTextAsync( Path.Combine(packageTempFolder, "install.ps1"), - GetPsCommandContent(packageInfo.InstallCommandLine, "installed", $"Package {packageInfo.PackageIdentifier} v{packageInfo.Version} installed successfully"), + GetPsCommandContent(packageInfo.InstallCommandLine, "installed", $"Package {packageInfo.PackageIdentifier} v{packageInfo.Version} installed successfully", packageId: packageInfo.PackageIdentifier, action: "install"), cancellationToken); packageInfo.InstallCommandLine = $"powershell.exe -WindowStyle Hidden -ExecutionPolicy Bypass -File install.ps1"; packageInfo.InstallerFilename = "install.ps1"; @@ -127,7 +127,7 @@ await fileManager.WriteAllTextAsync( { await fileManager.WriteAllTextAsync( Path.Combine(packageTempFolder, "uninstall.ps1"), - GetPsCommandContent(packageInfo.UninstallCommandLine, "uninstalled", $"Package {packageInfo.PackageIdentifier} uninstalled successfully"), + GetPsCommandContent(packageInfo.UninstallCommandLine, "uninstalled", $"Package {packageInfo.PackageIdentifier} uninstalled successfully", packageId: packageInfo.PackageIdentifier, action: "uninstall"), cancellationToken); packageInfo.UninstallCommandLine = $"powershell.exe -WindowStyle Hidden -ExecutionPolicy Bypass -File uninstall.ps1"; } @@ -145,10 +145,22 @@ await fileManager.WriteAllTextAsync( await WriteReadmeAsync(packageFolder, packageInfo, cancellationToken); } - private static string GetPsCommandContent(string command, string successSearch, string message) + private static string GetPsCommandContent(string command, string successSearch, string message, string? packageId = null, string? action = null) { - var commandWithQuotes = string.Join(" ", command.Split(" ").Select(x => $"\"{x}\"")); - return IntuneManagerConstants.PsCommandTemplate.Replace("{command}", commandWithQuotes).Replace("{success}", successSearch).Replace("{message}", message); + var commandSplitted = command.Split(" "); + string commandWithQuotes = ""; + if (commandSplitted.Length > 1 && commandSplitted[0].Equals("winget", StringComparison.OrdinalIgnoreCase)) + { + commandWithQuotes = "$(Get-WingetCmd) "; + commandSplitted = commandSplitted.Skip(1).ToArray(); + } + commandWithQuotes += string.Join(" ", commandSplitted.Select(x => $"\"{x}\"")); + return IntuneManagerConstants.PsCommandTemplate + .Replace("{command}", commandWithQuotes) + .Replace("{success}", successSearch) + .Replace("{message}", message) + .Replace("{packageId}", packageId ?? Guid.NewGuid().ToString()) + .Replace("{action}", action ?? "unknown"); } public async Task LoadPackageInfoFromFolder(string packageFolder, string packageId, string version, CancellationToken cancellationToken = default) diff --git a/src/WingetIntune/Intune/IntuneManagerConstants.cs b/src/WingetIntune/Intune/IntuneManagerConstants.cs index ca1175f..deaeef3 100644 --- a/src/WingetIntune/Intune/IntuneManagerConstants.cs +++ b/src/WingetIntune/Intune/IntuneManagerConstants.cs @@ -5,7 +5,35 @@ internal class IntuneManagerConstants internal const string AllUsers = "AllUsers"; internal const string AllDevices = "AllDevices"; - internal const string PsCommandTemplate = @"$procOutput = & {command} + internal const string PsCommandTemplate = @"$packageId = ""{packageId}"" +$action = ""{action}"" + +Start-Transcript -Path ""$env:ProgramData\Microsoft\IntuneManagementExtension\Logs\$packageId-$action.log"" -Force +Write-Host ""Starting $packageId $action, log location: $transcriptionPath"" + +Function Get-WingetCmd { + + $WingetCmd = $null + #Get WinGet Path + + try { + # Get Admin Context Winget Location + $WingetInfo = (Get-Item ""$env:ProgramFiles\WindowsApps\Microsoft.DesktopAppInstaller_*_8wekyb3d8bbwe\winget.exe"").VersionInfo | Sort-Object -Property FileVersionRaw + # if multiple versions, pick most recent one + $WingetCmd = $WingetInfo[-1].FileName + } + catch { + #Get User context Winget Location + if (Test-Path ""$env:LocalAppData\Microsoft\WindowsApps\Microsoft.DesktopAppInstaller_8wekyb3d8bbwe\winget.exe"") + { + $WingetCmd =""$env:LocalAppData\Microsoft\WindowsApps\Microsoft.DesktopAppInstaller_8wekyb3d8bbwe\winget.exe"" + } + } + Write-Host ""Winget location: $WingetCmd"" + return $WingetCmd +} + +$procOutput = & {command} if($procOutput -is [array]) { $lastRow = $procOutput[$wingetOutput.Length -1] if ($lastRow.Contains(""{success}"")) { @@ -20,10 +48,9 @@ Exit 5 internal const string PsDetectionCommandTemplate = @"$packageId = ""{packageId}"" $version = ""{version}"" - -$transcriptionPath = ""$env:ProgramData\Microsoft\IntuneManagementExtension\Logs\$packageId-detection.log"" -Start-Transcript -Path $transcriptionPath -Force -Write-Host ""Starting $packageId detection, log location: $transcriptionPath"" + +Start-Transcript -Path ""$env:ProgramData\Microsoft\IntuneManagementExtension\Logs\$packageId-detection.log"" -Force +Write-Host ""Starting $packageId detection"" # Need to get the full path of winget, because detection script is run in a different context Function Get-WingetCmd { diff --git a/src/WingetIntune/WingetIntune.csproj b/src/WingetIntune/WingetIntune.csproj index 66ad2b9..a12c122 100644 --- a/src/WingetIntune/WingetIntune.csproj +++ b/src/WingetIntune/WingetIntune.csproj @@ -32,7 +32,7 @@ - + diff --git a/src/WingetIntune/packages.lock.json b/src/WingetIntune/packages.lock.json index 5dd4afd..050b6e1 100644 --- a/src/WingetIntune/packages.lock.json +++ b/src/WingetIntune/packages.lock.json @@ -90,9 +90,9 @@ }, "SvRooij.ContentPrep": { "type": "Direct", - "requested": "[0.1.2, )", - "resolved": "0.1.2", - "contentHash": "T3PjOmsa9dEUkOEIlnSF5a18X4EXFmnvizTiEK/saxz+HvahEM9IXls6Qx2zgLxNTN5/HSpXrcqE9Lx4M40pLA==", + "requested": "[0.1.3-alpha0001, )", + "resolved": "0.1.3-alpha0001", + "contentHash": "9exebiAiEz1cn5XKxivypRmpG0t0ykSFrenU8GtwYzv3JrIlkXT6WdntsVYr181ebWhdAWOU4cjR5IgMjDqQMg==", "dependencies": { "Microsoft.Extensions.Logging.Abstractions": "7.0.1", "Microsoft.NETCore.Platforms": "7.0.4", diff --git a/tests/WingetIntune.Tests/WingetIntune.Tests.csproj b/tests/WingetIntune.Tests/WingetIntune.Tests.csproj index 0316fac..0d210be 100644 --- a/tests/WingetIntune.Tests/WingetIntune.Tests.csproj +++ b/tests/WingetIntune.Tests/WingetIntune.Tests.csproj @@ -25,8 +25,8 @@ - - + + runtime; build; native; contentfiles; analyzers; buildtransitive all diff --git a/tests/WingetIntune.Tests/packages.lock.json b/tests/WingetIntune.Tests/packages.lock.json index 083fc98..b3c8ca7 100644 --- a/tests/WingetIntune.Tests/packages.lock.json +++ b/tests/WingetIntune.Tests/packages.lock.json @@ -44,20 +44,20 @@ }, "xunit": { "type": "Direct", - "requested": "[2.6.3, )", - "resolved": "2.6.3", - "contentHash": "4CoGp3iKZORZ9aaHdPrFcdlDBRI/ZFRyDZWJuP7r2idULEtWf+k0yGT80cF/v6nE/MQDXLMIuSGDIrHuPLC/+Q==", + "requested": "[2.6.4, )", + "resolved": "2.6.4", + "contentHash": "N7kgaWrx32hTy4140XsAlTYKgs/NQgMwnjPLSvAp/Qk+WAiniRBiY+Y6XGB+T7lx2UZSEDeDeK5x06HTz6LejA==", "dependencies": { - "xunit.analyzers": "1.7.0", - "xunit.assert": "2.6.3", - "xunit.core": "[2.6.3]" + "xunit.analyzers": "1.8.0", + "xunit.assert": "2.6.4", + "xunit.core": "[2.6.4]" } }, "xunit.runner.visualstudio": { "type": "Direct", - "requested": "[2.5.5, )", - "resolved": "2.5.5", - "contentHash": "AJsBBn8S00ZxdXPSIp8s+NcBQMO9tcll1UVCfGNoEi1DUH2z3f4Y1epV9nYbhgG6wFoTKJP6YuLT2MeTPV9gnA==" + "requested": "[2.5.6, )", + "resolved": "2.5.6", + "contentHash": "CW6uhMXNaQQNMSG1IWhHkBT+V5eqHqn7MP0zfNMhU9wS/sgKX7FGL3rzoaUgt26wkY3bpf7pDVw3IjXhwfiP4w==" }, "Azure.Core": { "type": "Transitive", @@ -511,8 +511,8 @@ }, "SvRooij.ContentPrep": { "type": "Transitive", - "resolved": "0.1.2", - "contentHash": "T3PjOmsa9dEUkOEIlnSF5a18X4EXFmnvizTiEK/saxz+HvahEM9IXls6Qx2zgLxNTN5/HSpXrcqE9Lx4M40pLA==", + "resolved": "0.1.3-alpha0001", + "contentHash": "9exebiAiEz1cn5XKxivypRmpG0t0ykSFrenU8GtwYzv3JrIlkXT6WdntsVYr181ebWhdAWOU4cjR5IgMjDqQMg==", "dependencies": { "Microsoft.Extensions.Logging.Abstractions": "7.0.1", "Microsoft.NETCore.Platforms": "7.0.4", @@ -762,27 +762,27 @@ }, "xunit.analyzers": { "type": "Transitive", - "resolved": "1.7.0", - "contentHash": "lAcpaB0KnjWETbPDMsDPoQi6zS0uXUYopmyTQDWvILJWcL9jwMxXXGmDLptlMA6vGi5Z0LtudsYN+dEUTmuHaA==" + "resolved": "1.8.0", + "contentHash": "ORSFwaO6HCB9/7UbXc6+kg6Ax2gu/CIdGlAVCsDbhkliB9Z3U8EvIfZuZehFVwfXolqa5cCTvskGgLmU9uJFMw==" }, "xunit.assert": { "type": "Transitive", - "resolved": "2.6.3", - "contentHash": "7JWrjxDIAwF1vBZyENu4BZaddNJijIQcIQcc+73sJPWaqzDmseysTYv2jR0IWBsWIGa6LSfMO/3+dH0fsHL5Wg==" + "resolved": "2.6.4", + "contentHash": "kM/TuJl7903/9RvqdMaFwpaDZyxb+2S4g7SXSyYmNBm97H+t425xh6xSZjnxijiTAEkgo4t7sgKlKKnWmaj/HQ==" }, "xunit.core": { "type": "Transitive", - "resolved": "2.6.3", - "contentHash": "rlrm//9cNAlCkh3p5mdggzfchZlcXowUVK3UPqKiaN7G0Wu7gOUNLLZej9twnwTCVe1h3FEi9PRwzXMMXpFwSQ==", + "resolved": "2.6.4", + "contentHash": "pQ0fAusP+PbaaLIhO55zCPrncFRxrjzPV3OlKxDdS4K9azyXd1mShS0J1rG3DK2/zBwmDnZ9wyZlZy9gX9dHEg==", "dependencies": { - "xunit.extensibility.core": "[2.6.3]", - "xunit.extensibility.execution": "[2.6.3]" + "xunit.extensibility.core": "[2.6.4]", + "xunit.extensibility.execution": "[2.6.4]" } }, "xunit.extensibility.core": { "type": "Transitive", - "resolved": "2.6.3", - "contentHash": "qWCpmK4nxFBsf68r35AgnrW6B+xjTCpjJYfJkaBaini4Myl/2P/Ro6WocVtJfpHilkatitVFgM3XVR0jthdJlQ==", + "resolved": "2.6.4", + "contentHash": "bThauxbB80/pxakJQ5z94MXhsnmHOdhMKXyTPJtzQ+tXrTLua7v+e84JorguQtgNFclmMQ02wh/eshobNmG3aQ==", "dependencies": { "NETStandard.Library": "1.6.1", "xunit.abstractions": "2.0.3" @@ -790,11 +790,11 @@ }, "xunit.extensibility.execution": { "type": "Transitive", - "resolved": "2.6.3", - "contentHash": "I+9OA9a6WVia40bxJi3KaxVcjTE1ouHqD0QcrjHA/hLl7Ozb5eQmV7ecLu3gRZlPLdcVN+If8IZcEmqytmLtkA==", + "resolved": "2.6.4", + "contentHash": "fqyq9RBYdsQDNzrhTGlTP3iL3XTboGvD62IxK2cXQcWEgl++6zsHoEr6NDKs1Jn9hiUGT3F6x8IUcc635uuloA==", "dependencies": { "NETStandard.Library": "1.6.1", - "xunit.extensibility.core": "[2.6.3]" + "xunit.extensibility.core": "[2.6.4]" } }, "YamlDotNet": { @@ -826,7 +826,7 @@ "Microsoft.Identity.Client.Extensions.Msal": "[4.58.1, )", "Microsoft.NETCore.Platforms": "[7.0.4, )", "Riok.Mapperly": "[3.3.0, )", - "SvRooij.ContentPrep": "[0.1.2, )", + "SvRooij.ContentPrep": "[0.1.3-alpha0001, )", "Winget.CommunityRepository": "[1.0.0, )" } } From 03703adb41bde3852fac5981314a6ba64f9508f7 Mon Sep 17 00:00:00 2001 From: Stephan van Rooij <1292510+svrooij@users.noreply.github.com> Date: Fri, 29 Dec 2023 12:26:34 +0100 Subject: [PATCH 4/7] chore: Fixed tests after uninstall command change --- tests/WingetIntune.Tests/WingetHelper.Tests.cs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/WingetIntune.Tests/WingetHelper.Tests.cs b/tests/WingetIntune.Tests/WingetHelper.Tests.cs index 176ead1..c7db7ca 100644 --- a/tests/WingetIntune.Tests/WingetHelper.Tests.cs +++ b/tests/WingetIntune.Tests/WingetHelper.Tests.cs @@ -39,12 +39,12 @@ public void GetShowArgumentsForPackage_ReturnsCorrectString() } [Theory] - [InlineData(true, InstallerContext.System, "uninstall --id my-fake-id --source winget --force --silent --accept-package-agreements --accept-source-agreements --disable-interactivity --scope system")] - [InlineData(false, InstallerContext.System, "uninstall --id my-fake-id --source winget --silent --accept-package-agreements --accept-source-agreements --disable-interactivity --scope system")] - [InlineData(true, InstallerContext.User, "uninstall --id my-fake-id --source winget --force --silent --accept-package-agreements --accept-source-agreements --disable-interactivity --scope user")] - [InlineData(false, InstallerContext.User, "uninstall --id my-fake-id --source winget --silent --accept-package-agreements --accept-source-agreements --disable-interactivity --scope user")] - [InlineData(true, InstallerContext.Unknown, "uninstall --id my-fake-id --source winget --force --silent --accept-package-agreements --accept-source-agreements --disable-interactivity")] - [InlineData(false, InstallerContext.Unknown, "uninstall --id my-fake-id --source winget --silent --accept-package-agreements --accept-source-agreements --disable-interactivity")] + [InlineData(true, InstallerContext.System, "uninstall --id my-fake-id --source winget --force --silent --accept-source-agreements --disable-interactivity --scope system")] + [InlineData(false, InstallerContext.System, "uninstall --id my-fake-id --source winget --silent --accept-source-agreements --disable-interactivity --scope system")] + [InlineData(true, InstallerContext.User, "uninstall --id my-fake-id --source winget --force --silent --accept-source-agreements --disable-interactivity --scope user")] + [InlineData(false, InstallerContext.User, "uninstall --id my-fake-id --source winget --silent --accept-source-agreements --disable-interactivity --scope user")] + [InlineData(true, InstallerContext.Unknown, "uninstall --id my-fake-id --source winget --force --silent --accept-source-agreements --disable-interactivity")] + [InlineData(false, InstallerContext.Unknown, "uninstall --id my-fake-id --source winget --silent --accept-source-agreements --disable-interactivity")] public void GetUninstallArgumentsForPackage_ReturnsCorrectString(bool force, InstallerContext installerContext, string expected) { var packageId = "my-fake-id"; From f60d97df0807b399915dfec11e7c2b5bc19acefb Mon Sep 17 00:00:00 2001 From: Stephan van Rooij <1292510+svrooij@users.noreply.github.com> Date: Tue, 2 Jan 2024 16:20:21 +0100 Subject: [PATCH 5/7] fix: Run winget in 64bit --- .../Implementations/WingetHelper.cs | 2 +- src/WingetIntune/Intune/IntuneManager.cs | 4 ++-- .../Intune/IntuneManagerConstants.cs | 5 ++++- .../WingetIntune.Tests/WingetHelper.Tests.cs | 20 +++++++++---------- 4 files changed, 17 insertions(+), 14 deletions(-) diff --git a/src/WingetIntune/Implementations/WingetHelper.cs b/src/WingetIntune/Implementations/WingetHelper.cs index ed694b0..41a7b6f 100644 --- a/src/WingetIntune/Implementations/WingetHelper.cs +++ b/src/WingetIntune/Implementations/WingetHelper.cs @@ -10,7 +10,7 @@ public static class WingetHelper internal const string ArgId = "--id"; internal const string ArgPackageAgreements = "--accept-package-agreements"; internal const string ArgScope = "--scope"; - internal const string ArgScopeSystem = "system"; + internal const string ArgScopeSystem = "machine"; internal const string ArgScopeUser = "user"; internal const string ArgSilent = "--silent"; internal const string ArgSource = "--source"; diff --git a/src/WingetIntune/Intune/IntuneManager.cs b/src/WingetIntune/Intune/IntuneManager.cs index b15af0e..17095da 100644 --- a/src/WingetIntune/Intune/IntuneManager.cs +++ b/src/WingetIntune/Intune/IntuneManager.cs @@ -118,7 +118,7 @@ await fileManager.WriteAllTextAsync( Path.Combine(packageTempFolder, "install.ps1"), GetPsCommandContent(packageInfo.InstallCommandLine, "installed", $"Package {packageInfo.PackageIdentifier} v{packageInfo.Version} installed successfully", packageId: packageInfo.PackageIdentifier, action: "install"), cancellationToken); - packageInfo.InstallCommandLine = $"powershell.exe -WindowStyle Hidden -ExecutionPolicy Bypass -File install.ps1"; + packageInfo.InstallCommandLine = $"%windir%\\sysnative\\windowspowershell\\v1.0\\powershell.exe -WindowStyle Hidden -ExecutionPolicy Bypass -File install.ps1"; packageInfo.InstallerFilename = "install.ps1"; } } @@ -129,7 +129,7 @@ await fileManager.WriteAllTextAsync( Path.Combine(packageTempFolder, "uninstall.ps1"), GetPsCommandContent(packageInfo.UninstallCommandLine, "uninstalled", $"Package {packageInfo.PackageIdentifier} uninstalled successfully", packageId: packageInfo.PackageIdentifier, action: "uninstall"), cancellationToken); - packageInfo.UninstallCommandLine = $"powershell.exe -WindowStyle Hidden -ExecutionPolicy Bypass -File uninstall.ps1"; + packageInfo.UninstallCommandLine = $"%windir%\\sysnative\\windowspowershell\\v1.0\\powershell.exe -WindowStyle Hidden -ExecutionPolicy Bypass -File uninstall.ps1"; } await intunePackager.CreatePackage(packageTempFolder, packageFolder, packageInfo.InstallerFilename!, packageInfo, cancellationToken); await DownloadLogoAsync(packageFolder, packageInfo.PackageIdentifier!, cancellationToken); diff --git a/src/WingetIntune/Intune/IntuneManagerConstants.cs b/src/WingetIntune/Intune/IntuneManagerConstants.cs index deaeef3..16db45f 100644 --- a/src/WingetIntune/Intune/IntuneManagerConstants.cs +++ b/src/WingetIntune/Intune/IntuneManagerConstants.cs @@ -9,7 +9,7 @@ internal class IntuneManagerConstants $action = ""{action}"" Start-Transcript -Path ""$env:ProgramData\Microsoft\IntuneManagementExtension\Logs\$packageId-$action.log"" -Force -Write-Host ""Starting $packageId $action, log location: $transcriptionPath"" +Write-Host ""Starting $packageId $action"" Function Get-WingetCmd { @@ -27,6 +27,9 @@ Function Get-WingetCmd { if (Test-Path ""$env:LocalAppData\Microsoft\WindowsApps\Microsoft.DesktopAppInstaller_8wekyb3d8bbwe\winget.exe"") { $WingetCmd =""$env:LocalAppData\Microsoft\WindowsApps\Microsoft.DesktopAppInstaller_8wekyb3d8bbwe\winget.exe"" + } else { + Write-Host ""winget not detected"" + Exit 1 } } Write-Host ""Winget location: $WingetCmd"" diff --git a/tests/WingetIntune.Tests/WingetHelper.Tests.cs b/tests/WingetIntune.Tests/WingetHelper.Tests.cs index c7db7ca..e3d8d99 100644 --- a/tests/WingetIntune.Tests/WingetHelper.Tests.cs +++ b/tests/WingetIntune.Tests/WingetHelper.Tests.cs @@ -6,14 +6,14 @@ namespace WingetIntune.Tests; public class WingetHelperTests { [Theory] - [InlineData(null, true, InstallerContext.System, "install --id my-fake-id --source winget --force --silent --accept-package-agreements --accept-source-agreements --disable-interactivity --scope system")] - [InlineData(null, false, InstallerContext.System, "install --id my-fake-id --source winget --silent --accept-package-agreements --accept-source-agreements --disable-interactivity --scope system")] + [InlineData(null, true, InstallerContext.System, "install --id my-fake-id --source winget --force --silent --accept-package-agreements --accept-source-agreements --disable-interactivity --scope machine")] + [InlineData(null, false, InstallerContext.System, "install --id my-fake-id --source winget --silent --accept-package-agreements --accept-source-agreements --disable-interactivity --scope machine")] [InlineData(null, true, InstallerContext.User, "install --id my-fake-id --source winget --force --silent --accept-package-agreements --accept-source-agreements --disable-interactivity --scope user")] [InlineData(null, false, InstallerContext.User, "install --id my-fake-id --source winget --silent --accept-package-agreements --accept-source-agreements --disable-interactivity --scope user")] [InlineData(null, true, InstallerContext.Unknown, "install --id my-fake-id --source winget --force --silent --accept-package-agreements --accept-source-agreements --disable-interactivity")] [InlineData(null, false, InstallerContext.Unknown, "install --id my-fake-id --source winget --silent --accept-package-agreements --accept-source-agreements --disable-interactivity")] - [InlineData("42.0.0", true, InstallerContext.System, "install --id my-fake-id --version 42.0.0 --source winget --force --silent --accept-package-agreements --accept-source-agreements --disable-interactivity --scope system")] - [InlineData("42.0.0", false, InstallerContext.System, "install --id my-fake-id --version 42.0.0 --source winget --silent --accept-package-agreements --accept-source-agreements --disable-interactivity --scope system")] + [InlineData("42.0.0", true, InstallerContext.System, "install --id my-fake-id --version 42.0.0 --source winget --force --silent --accept-package-agreements --accept-source-agreements --disable-interactivity --scope machine")] + [InlineData("42.0.0", false, InstallerContext.System, "install --id my-fake-id --version 42.0.0 --source winget --silent --accept-package-agreements --accept-source-agreements --disable-interactivity --scope machine")] [InlineData("42.0.0", true, InstallerContext.User, "install --id my-fake-id --version 42.0.0 --source winget --force --silent --accept-package-agreements --accept-source-agreements --disable-interactivity --scope user")] [InlineData("42.0.0", false, InstallerContext.User, "install --id my-fake-id --version 42.0.0 --source winget --silent --accept-package-agreements --accept-source-agreements --disable-interactivity --scope user")] [InlineData("42.0.0", true, InstallerContext.Unknown, "install --id my-fake-id --version 42.0.0 --source winget --force --silent --accept-package-agreements --accept-source-agreements --disable-interactivity")] @@ -39,8 +39,8 @@ public void GetShowArgumentsForPackage_ReturnsCorrectString() } [Theory] - [InlineData(true, InstallerContext.System, "uninstall --id my-fake-id --source winget --force --silent --accept-source-agreements --disable-interactivity --scope system")] - [InlineData(false, InstallerContext.System, "uninstall --id my-fake-id --source winget --silent --accept-source-agreements --disable-interactivity --scope system")] + [InlineData(true, InstallerContext.System, "uninstall --id my-fake-id --source winget --force --silent --accept-source-agreements --disable-interactivity --scope machine")] + [InlineData(false, InstallerContext.System, "uninstall --id my-fake-id --source winget --silent --accept-source-agreements --disable-interactivity --scope machine")] [InlineData(true, InstallerContext.User, "uninstall --id my-fake-id --source winget --force --silent --accept-source-agreements --disable-interactivity --scope user")] [InlineData(false, InstallerContext.User, "uninstall --id my-fake-id --source winget --silent --accept-source-agreements --disable-interactivity --scope user")] [InlineData(true, InstallerContext.Unknown, "uninstall --id my-fake-id --source winget --force --silent --accept-source-agreements --disable-interactivity")] @@ -55,14 +55,14 @@ public void GetUninstallArgumentsForPackage_ReturnsCorrectString(bool force, Ins } [Theory] - [InlineData(null, true, InstallerContext.System, "upgrade --id my-fake-id --source winget --force --silent --accept-package-agreements --accept-source-agreements --disable-interactivity --scope system")] - [InlineData(null, false, InstallerContext.System, "upgrade --id my-fake-id --source winget --silent --accept-package-agreements --accept-source-agreements --disable-interactivity --scope system")] + [InlineData(null, true, InstallerContext.System, "upgrade --id my-fake-id --source winget --force --silent --accept-package-agreements --accept-source-agreements --disable-interactivity --scope machine")] + [InlineData(null, false, InstallerContext.System, "upgrade --id my-fake-id --source winget --silent --accept-package-agreements --accept-source-agreements --disable-interactivity --scope machine")] [InlineData(null, true, InstallerContext.User, "upgrade --id my-fake-id --source winget --force --silent --accept-package-agreements --accept-source-agreements --disable-interactivity --scope user")] [InlineData(null, false, InstallerContext.User, "upgrade --id my-fake-id --source winget --silent --accept-package-agreements --accept-source-agreements --disable-interactivity --scope user")] [InlineData(null, true, InstallerContext.Unknown, "upgrade --id my-fake-id --source winget --force --silent --accept-package-agreements --accept-source-agreements --disable-interactivity")] [InlineData(null, false, InstallerContext.Unknown, "upgrade --id my-fake-id --source winget --silent --accept-package-agreements --accept-source-agreements --disable-interactivity")] - [InlineData("42.0.0", true, InstallerContext.System, "upgrade --id my-fake-id --version 42.0.0 --source winget --force --silent --accept-package-agreements --accept-source-agreements --disable-interactivity --scope system")] - [InlineData("42.0.0", false, InstallerContext.System, "upgrade --id my-fake-id --version 42.0.0 --source winget --silent --accept-package-agreements --accept-source-agreements --disable-interactivity --scope system")] + [InlineData("42.0.0", true, InstallerContext.System, "upgrade --id my-fake-id --version 42.0.0 --source winget --force --silent --accept-package-agreements --accept-source-agreements --disable-interactivity --scope machine")] + [InlineData("42.0.0", false, InstallerContext.System, "upgrade --id my-fake-id --version 42.0.0 --source winget --silent --accept-package-agreements --accept-source-agreements --disable-interactivity --scope machine")] [InlineData("42.0.0", true, InstallerContext.User, "upgrade --id my-fake-id --version 42.0.0 --source winget --force --silent --accept-package-agreements --accept-source-agreements --disable-interactivity --scope user")] [InlineData("42.0.0", false, InstallerContext.User, "upgrade --id my-fake-id --version 42.0.0 --source winget --silent --accept-package-agreements --accept-source-agreements --disable-interactivity --scope user")] [InlineData("42.0.0", true, InstallerContext.Unknown, "upgrade --id my-fake-id --version 42.0.0 --source winget --force --silent --accept-package-agreements --accept-source-agreements --disable-interactivity")] From fda15abaf06108fa95c5d81023c14b3030526bc4 Mon Sep 17 00:00:00 2001 From: Stephan van Rooij <1292510+svrooij@users.noreply.github.com> Date: Tue, 2 Jan 2024 16:20:58 +0100 Subject: [PATCH 6/7] docs: Improved documentation to show cross platform commands --- README.md | 41 +++++++++++-------- src/WingetIntune.Cli/Commands/AboutCommand.cs | 2 +- src/WingetIntune.Cli/Commands/CheckCommand.cs | 2 +- .../Commands/GenerateIndexCommand.cs | 2 +- src/WingetIntune.Cli/Commands/InfoCommand.cs | 2 +- .../Commands/InstallOrUpgradeCommand.cs | 3 +- src/WingetIntune.Cli/Commands/MsiCommand.cs | 2 +- .../Commands/PackageCommand.cs | 2 +- .../Commands/PublishCommand.cs | 2 +- .../Commands/WinGetRootCommand.cs | 10 +++-- 10 files changed, 39 insertions(+), 29 deletions(-) diff --git a/README.md b/README.md index 1b3093f..35cd12c 100644 --- a/README.md +++ b/README.md @@ -10,10 +10,12 @@ Take any (just msi installers for now) app from winget and upload it to Intune i - Generating the needed script information - Publish the app to Intune. -This application ~~is **Windows only** and~~ requires **Dotnet 7** to be installed on your computer. It's also a [beta application](#beta-application), so please report any issues you find. -A lot of commands run the `winget` command, so make sure you have the [App Installer](https://www.microsoft.com/p/app-installer/9nblggh4nns1) installed on your computer as well. +This application ~~is **Windows only** and~~ requires **Dotnet 7** to be installed on your computer. It's a [beta application](#beta-application), so please report any issues you find. +Some commands run the `winget` in the background and are thus Windows-only, make sure you have the [App Installer](https://www.microsoft.com/p/app-installer/9nblggh4nns1) installed on your computer if you want to use these commands. + +The `package` and `publish` commands are cross-platform, and should work on any platform that supports dotnet 7. These commands no longer use the winget executable, which also means any other sources than `winget` are no longer supported. +The `msi` command is still windows only, as it uses the `Microsoft.Deployment.WindowsInstaller` package. -This application used to be Windows only, but recently the main functionality is ported to other platforms by reducing the [platform dependencies](https://svrooij.io/2023/10/24/create-intunewin-file/). This means that the `package` and `publish` commands should work on any platform that supports dotnet 7. The `msi` command is still windows only, as it uses the `Microsoft.Deployment.WindowsInstaller` package. Both the `package` and `publish` won't support other sources than `winget`, and will use my [open-source winget index](https://github.com/svrooij/winget-pkgs-index/), instead of running winget to get the required information. [![LinkedIn Profile][badge_linkedin]][link_linkedin] [![Link Mastodon][badge_mastodon]][link_mastodon] @@ -51,7 +53,7 @@ The CLI has several commands, try them out yourself. ```Shell Description: - Enhanced Winget CLI for automations + winget-intune by @svrooij allows you to package any winget app for Intune Usage: winget-intune [command] [options] @@ -61,13 +63,14 @@ Options: -?, -h, --help Show help and usage information Commands: - install Installs or upgrades a package - check Check if a specific version in installed - info Show package info as json - package Package an app for Intune - publish Publish an packaged app to Intune - msi Extract info from MSI file - about Information about this package and it's author + package Package an app for Intune (cross platform) + publish Publish a packaged app to Intune (cross platform) + about Information about this package and it's author (cross platform) + install Installs or upgrades a package (Windows-only) + check Check if a specific version in installed (Windows-only) + info Show package info as json (Windows-only) + msi Extract info from MSI file (Windows-only) + ``` ### Package @@ -83,7 +86,9 @@ winget-intune package {PackageId} [--version {version}] [--source winget] --pack > The `packageId` ~~is case sensitive, so make sure you use the correct casing~~ will be matches against any package in the open source [index](https://github.com/svrooij/winget-pkgs-index). Tip: Copy it from the result of the `winget search {name}` command. Upon downloading the installer, the SHA256 hash is checked against the one in the `winget` manifest, to make sure you won't package a tampered installer. -Previously it used the closed source [content-prep-tool](https://github.com/Microsoft/Microsoft-Win32-Content-Prep-Tool) to generate the `intunewin` file, this has since been replaced with my own faster, open-souce and cross-platform [implementation](https://github.com/Svrooij/ContentPrep). + +The packaging command uses an open-source & cross-platform [implementation](https://github.com/Svrooij/ContentPrep) of the Windows-only & closed source [content-prep-tool](https://github.com/Microsoft/Microsoft-Win32-Content-Prep-Tool), to allow cross-platform building of the packages. +This new implementation is available as a dotnet library and a PowerShell module, so if you're into Intune packaging, check it out. ### Publish @@ -107,11 +112,11 @@ You can also assign the app to a group, and set the categories. winget-intune publish {PackageId} ... --category "Productivity" --category "Utilities" # Add --available "group-guid" to make the app available to a group (use the guid of the group) -# Add --available "all-users" to make the app available to all users +# Add --available "allusers" to make the app available to all users # Instead of --available you can also use --required to make the app required for the group -# Or if you want to remove the app from the group, use --uninstall -winget-intune publish {PackageId}... --available "3bac8336-623f-46bf-bcab-b5c61e3e5b7a" --available "all-users" -winget-intune publish {PackageId}... --available "3bac8336-623f-46bf-bcab-b5c61e3e5b7a" --available "all-users" +# Or if you want to remove the app for that group, use --uninstall +winget-intune publish {PackageId}... --required "3bac8336-623f-46bf-bcab-b5c61e3e5b7a" --required "allusers" +winget-intune publish {PackageId}... --uninstall "3bac8336-623f-46bf-bcab-b5c61e3e5b7a" --uninstall "allusers" ``` #### Auto-package @@ -132,8 +137,10 @@ If you want to contribute to this project, please check out the [contributing](h ## Usefull information -- [Microsoft-Win32-Content-Prep-Tool](https://github.com/microsoft/Microsoft-Win32-Content-Prep-Tool) - [Blog articles on Intune](https://svrooij.io/tags/intune/) +- Open-source [winget index](https://github.com/svrooij/winget-pkgs-index/) +- Open-source [PowerShell Content Prep](https://github.com/svrooij/contentprep) +- Closed source [Microsoft Win32 Content Prep tool](https://github.com/microsoft/Microsoft-Win32-Content-Prep-Tool) [badge_blog]: https://img.shields.io/badge/blog-svrooij.io-blue?style=for-the-badge [badge_linkedin]: https://img.shields.io/badge/LinkedIn-stephanvanrooij-blue?style=for-the-badge&logo=linkedin diff --git a/src/WingetIntune.Cli/Commands/AboutCommand.cs b/src/WingetIntune.Cli/Commands/AboutCommand.cs index 63caf65..e0a4ddd 100644 --- a/src/WingetIntune.Cli/Commands/AboutCommand.cs +++ b/src/WingetIntune.Cli/Commands/AboutCommand.cs @@ -8,7 +8,7 @@ namespace WingetIntune.Commands; internal class AboutCommand : Command { private const string name = "about"; - private const string description = "Information about this package and it's author"; + private const string description = "Information about this package and it's author (cross platform)"; public AboutCommand() : base(name, description) { diff --git a/src/WingetIntune.Cli/Commands/CheckCommand.cs b/src/WingetIntune.Cli/Commands/CheckCommand.cs index 2b9209c..bf0e76e 100644 --- a/src/WingetIntune.Cli/Commands/CheckCommand.cs +++ b/src/WingetIntune.Cli/Commands/CheckCommand.cs @@ -9,7 +9,7 @@ namespace WingetIntune.Commands; internal class CheckCommand : Command { private const string name = "check"; - private const string description = "Check if a specific version in installed"; + private const string description = "Check if a specific version in installed (Windows-only)"; public CheckCommand() : base(name, description) { diff --git a/src/WingetIntune.Cli/Commands/GenerateIndexCommand.cs b/src/WingetIntune.Cli/Commands/GenerateIndexCommand.cs index 1403744..6206493 100644 --- a/src/WingetIntune.Cli/Commands/GenerateIndexCommand.cs +++ b/src/WingetIntune.Cli/Commands/GenerateIndexCommand.cs @@ -16,7 +16,7 @@ namespace WingetIntune.Commands; internal class GenerateIndexCommand : Command { private const string name = "generate-index"; - private const string description = "(hidden) Generates the index.json file for the repository"; + private const string description = "(hidden) Generates the index.json file for the repository (cross platform)"; public GenerateIndexCommand() : base(name, description) { IsHidden = true; diff --git a/src/WingetIntune.Cli/Commands/InfoCommand.cs b/src/WingetIntune.Cli/Commands/InfoCommand.cs index f5a8378..6cd1baf 100644 --- a/src/WingetIntune.Cli/Commands/InfoCommand.cs +++ b/src/WingetIntune.Cli/Commands/InfoCommand.cs @@ -12,7 +12,7 @@ namespace WingetIntune.Commands; internal class InfoCommand : Command { private const string name = "info"; - private const string description = "Show package info as json"; + private const string description = "Show package info as json (Windows-only)"; public InfoCommand() : base(name, description) { diff --git a/src/WingetIntune.Cli/Commands/InstallOrUpgradeCommand.cs b/src/WingetIntune.Cli/Commands/InstallOrUpgradeCommand.cs index d393a49..fae1527 100644 --- a/src/WingetIntune.Cli/Commands/InstallOrUpgradeCommand.cs +++ b/src/WingetIntune.Cli/Commands/InstallOrUpgradeCommand.cs @@ -10,7 +10,7 @@ namespace WingetIntune.Commands internal class InstallOrUpgradeCommand : Command { private const string name = "install"; - private const string description = "Installs or upgrades a package"; + private const string description = "Installs or upgrades a package (Windows-only)"; public InstallOrUpgradeCommand() : base(name, description) { @@ -36,7 +36,6 @@ public InstallOrUpgradeCommand() : base(name, description) //AddOption(new Option(new string[] { "--accept-package-matching", "-p" }, "Accept package matching")); //AddOption(new Option(new string[] { "--accept-package-modified", "-u" }, "Accept package modified")); //AddOption(new Option(new string[] { "--accept-package"})) - this.Handler = CommandHandler.Create(HandleCommand); } diff --git a/src/WingetIntune.Cli/Commands/MsiCommand.cs b/src/WingetIntune.Cli/Commands/MsiCommand.cs index 3302d4a..b513e25 100644 --- a/src/WingetIntune.Cli/Commands/MsiCommand.cs +++ b/src/WingetIntune.Cli/Commands/MsiCommand.cs @@ -11,7 +11,7 @@ namespace WingetIntune.Commands; internal class MsiCommand : Command { private const string name = "msi"; - private const string description = "Extract info from MSI file"; + private const string description = "Extract info from MSI file (Windows-only)"; private Argument msiFileArgument = new Argument("msiFile", "Path to MSI file"); diff --git a/src/WingetIntune.Cli/Commands/PackageCommand.cs b/src/WingetIntune.Cli/Commands/PackageCommand.cs index a0615ce..ea7b36b 100644 --- a/src/WingetIntune.Cli/Commands/PackageCommand.cs +++ b/src/WingetIntune.Cli/Commands/PackageCommand.cs @@ -11,7 +11,7 @@ namespace WingetIntune.Commands; internal class PackageCommand : Command { private const string name = "package"; - private const string description = "Package an app for Intune"; + private const string description = "Package an app for Intune (cross platform)"; internal static readonly Option TempFolderOption = new Option("--temp-folder", () => Path.Combine(Path.GetTempPath(), "intunewin"), "Folder to store temporaty files") { diff --git a/src/WingetIntune.Cli/Commands/PublishCommand.cs b/src/WingetIntune.Cli/Commands/PublishCommand.cs index df97d4c..896e226 100644 --- a/src/WingetIntune.Cli/Commands/PublishCommand.cs +++ b/src/WingetIntune.Cli/Commands/PublishCommand.cs @@ -11,7 +11,7 @@ namespace WingetIntune.Commands; internal class PublishCommand : Command { private const string name = "publish"; - private const string description = "Publish a packaged app to Intune"; + private const string description = "Publish a packaged app to Intune (cross platform)"; internal static readonly Option TenantOption = new Option("--tenant", "Tenant ID to use for authentication"); internal static readonly Option UsernameOption = new Option("--username", "Username to use for authentication"); diff --git a/src/WingetIntune.Cli/Commands/WinGetRootCommand.cs b/src/WingetIntune.Cli/Commands/WinGetRootCommand.cs index 72e1cb9..a33294c 100644 --- a/src/WingetIntune.Cli/Commands/WinGetRootCommand.cs +++ b/src/WingetIntune.Cli/Commands/WinGetRootCommand.cs @@ -16,15 +16,19 @@ internal class WinGetRootCommand : RootCommand public WinGetRootCommand() { - Description = "Enhanced Winget CLI for automations"; + Description = "winget-intune by @svrooij allows you to package any winget app for Intune"; + // Cross platform commands AddCommand(new PackageCommand()); AddCommand(new PublishCommand()); + AddCommand(new AboutCommand()); + AddCommand(new GenerateIndexCommand()); + + // Windows only command AddCommand(new InstallOrUpgradeCommand()); AddCommand(new CheckCommand()); AddCommand(new InfoCommand()); AddCommand(new MsiCommand()); - AddCommand(new AboutCommand()); - AddCommand(new GenerateIndexCommand()); + AddGlobalOption(VerboseOption); AddGlobalOption(JsonOption); } From cdb84f9e79642ed6814efdf85b369bba3de44e47 Mon Sep 17 00:00:00 2001 From: Stephan van Rooij <1292510+svrooij@users.noreply.github.com> Date: Tue, 2 Jan 2024 16:24:31 +0100 Subject: [PATCH 7/7] chore: Formatting error --- src/WingetIntune.Cli/Commands/WinGetRootCommand.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/WingetIntune.Cli/Commands/WinGetRootCommand.cs b/src/WingetIntune.Cli/Commands/WinGetRootCommand.cs index a33294c..bf261a0 100644 --- a/src/WingetIntune.Cli/Commands/WinGetRootCommand.cs +++ b/src/WingetIntune.Cli/Commands/WinGetRootCommand.cs @@ -28,7 +28,7 @@ public WinGetRootCommand() AddCommand(new CheckCommand()); AddCommand(new InfoCommand()); AddCommand(new MsiCommand()); - + AddGlobalOption(VerboseOption); AddGlobalOption(JsonOption); }