diff --git a/.config/tsaoptions.json b/.config/tsaoptions.json index 9590e04d11..82c2bbbd50 100644 --- a/.config/tsaoptions.json +++ b/.config/tsaoptions.json @@ -1,8 +1,8 @@ { "instanceUrl": "https://microsoft.visualstudio.com", "projectName": "os", - "areaPath": "OS\\Windows Client and Services\\ADEPT\\OWL (Open Windows pLatform)\\Rendering\\WinAppSDK Engineering System", - "iterationPath": "OS\\2211", + "areaPath": "OS\\Windows Client and Services\\ADEPT\\NEON\\Windex\\WinAppSDK Engineering System", + "iterationPath": "OS\\2311", "notificationAliases": [ "WinAppSDK-Build@microsoft.com" ], "ignoreBranchName": true, "codebaseName": "WinAppSDK-Foundation" diff --git a/.github/ISSUE_TEMPLATE/bug-report.yaml b/.github/ISSUE_TEMPLATE/bug-report.yaml index a5669abb00..bbbc4f3e37 100644 --- a/.github/ISSUE_TEMPLATE/bug-report.yaml +++ b/.github/ISSUE_TEMPLATE/bug-report.yaml @@ -35,8 +35,7 @@ body: label: NuGet package version description: Specify the version of Windows App SDK (or Project Reunion) you're using. options: - - "Windows App SDK 1.3.2: 1.3.230602002" - - "Windows App SDK 1.4 Preview 1: 1.4.230628000-preview1" + - "Windows App SDK 1.4.2: 1.4.231008000" - "Windows App SDK 1.4 Experimental 1: 1.4.230518007-experimental1" - type: dropdown attributes: diff --git a/Directory.Build.props b/Directory.Build.props index eda87b76b3..91952db2eb 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -19,6 +19,8 @@ true $(RepoRoot)\packages + true + $(RepoRoot)\WasdkStrongNameSign.snk diff --git a/NuGet.config b/NuGet.config index d0813052b1..454c97cd1a 100644 --- a/NuGet.config +++ b/NuGet.config @@ -7,7 +7,7 @@ - + diff --git a/TestAll.ps1 b/TestAll.ps1 index 9703d76314..7243526981 100644 --- a/TestAll.ps1 +++ b/TestAll.ps1 @@ -1,16 +1,33 @@ <# .SYNOPSIS - Run the TAEF dlls generated by WinAppSDK + Run the WinAppSDK tests .DESCRIPTION The TestAll script will take the folder input and look for subfolders containing a .testdef file. WinAppSDK - components define a testdef with the following schema and runs the TAEF dll in the subfolder. + components define a testdef with the following schema and runs the test in the subfolder. + + *.testdef are JSON files with the schema per JSON Schema 2020-12 (https://json-schema.org): + { + "$id": "https://microsoft.com/windowsappsdk/schemas/testdef/2023/08", + + "type": "object", + "properties": { + "Description": { "type": "string" }, + "Type": { "enum": ["TAEF", "Powershell"], "default": "TAEF" }, + "Filename": { "type": "string" }, + "Parameters": { "type": "string" }, + "Architectures": { "type": "array", "items": { "type": "string" } }, + "Status": { "enum": ["Enabled", "Disabled"] }, + }, + "required": ["Description", "Filename", "Architectures", "Status"] + } Example: { "Tests": [ { "Description": "This module tests the push notifications component in WinAppSDK.", + "Type": "TAEF", "Filename": "PushNotificationTests.dll", "Parameters": "", "Architectures": ["x86", "x64", "arm64"], @@ -38,12 +55,16 @@ param( [Parameter(Mandatory=$true)] [string]$OutputFolder, + [Parameter(Mandatory=$true)] [string]$Platform, + [Parameter(Mandatory=$true)] [string]$Configuration, + [Parameter(Mandatory=$false)] [Switch]$Test, + [Parameter(Mandatory=$false)] [Switch]$List ) @@ -52,7 +73,7 @@ $StartTime = Get-Date $lastexitcode = 0 Set-StrictMode -Version 3.0 -function Get-TaefTests +function Get-Tests { $configPlat = Join-Path $Configuration $Platform $outputFolderPath = Join-Path $OutputFolder $configPlat @@ -66,6 +87,16 @@ function Get-TaefTests $baseId = $testdef.BaseName foreach ($testConfig in $testJson.Tests) { + $testConfig | Write-Host + if ($testConfig -contains 'Type') + { + $testType = $testConfig.Type + } + else + { + $testType = 'TAEF' + } + $id = $baseId + "-Test$count" $t = [PSCustomObject]@{} $t | Add-Member -MemberType NoteProperty -Name 'Test' -Value $id @@ -75,6 +106,7 @@ function Get-TaefTests $t | Add-Member -MemberType NoteProperty -Name 'Architectures' -Value $testConfig.Architectures $t | Add-Member -MemberType NoteProperty -Name 'Status' -Value $testConfig.Status $t | Add-Member -MemberType NoteProperty -Name 'TestDef' -Value $testdef.FullName + $t | Add-Member -MemberType NoteProperty -Name 'Type' -Value $testType $tests += $t $count += 1 @@ -84,15 +116,32 @@ function Get-TaefTests $tests } -function List-TaefTests +function List-Tests +{ + $tests = Get-Tests + $tests | Sort-Object -Property Test | Format-Table Test,Description,Type,Filename,Parameters,Architectures,Status -AutoSize | Out-String -Width 512 +} + +function Run-TaefTest { - $tests = Get-TaefTests - $tests | Sort-Object -Property Test | Format-Table Test,Description,Filename,Parameters,Architectures,Status -AutoSize | Out-String -Width 512 + param($test) + + $testFolder = Split-Path -parent $test.TestDef + $tePath = Join-Path $testFolder "te.exe" + $dllFile = Join-Path $testFolder $test.Filename + & $tePath $dllFile $test.Parameters +} + +function Run-PowershellTest +{ + param($test) + + Write-Host "Powershell tests not supported" } -function Run-TaefTests +function Run-Tests { - $tests = Get-TaefTests + $tests = Get-Tests foreach ($test in $tests) { Write-Host "$($test.Filename) - $($test.Description)" @@ -100,10 +149,19 @@ function Run-TaefTests $testEnabled = $test.Status -eq "Enabled" if ($validPlatform -and $testEnabled) { - $testFolder = Split-Path -parent $test.TestDef - $tePath = Join-Path $testFolder "te.exe" - $dllFile = Join-Path $testFolder $test.Filename - & $tePath $dllFile $test.Parameters + if ($test.Type -eq 'TAEF') + { + Run-TaefTest $test + } + elseif ($test.Type -eq 'Powershell') + { + Run-PowershellTest $test + } + else + { + Write-Host "Unknown test type '$test.Type'. Not running." + Exit 1 + } } elseif (-not($validPlatform)) { @@ -118,12 +176,12 @@ function Run-TaefTests if ($List -eq $true) { - $null = List-TaefTests + List-Tests | Out-String } if ($Test -eq $true) { - Run-TaefTests + Run-Tests } $TotalTime = (Get-Date)-$StartTime diff --git a/WasdkStrongNameSign.snk b/WasdkStrongNameSign.snk new file mode 100644 index 0000000000..b8a8d1e871 Binary files /dev/null and b/WasdkStrongNameSign.snk differ diff --git a/WindowsAppRuntime.sln b/WindowsAppRuntime.sln index 906f760725..e9bd3244f5 100644 --- a/WindowsAppRuntime.sln +++ b/WindowsAppRuntime.sln @@ -192,10 +192,19 @@ EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "CS", "CS", "{716C26A0-E6B0-4981-8412-D14A4D410531}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Windows.ApplicationModel.DynamicDependency.Projection", "dev\Projections\CS\Microsoft.Windows.ApplicationModel.DynamicDependency\Microsoft.Windows.ApplicationModel.DynamicDependency.Projection.csproj", "{47D8D21D-F022-4D58-8DB2-8B467756E08C}" + ProjectSection(ProjectDependencies) = postProject + {B73AD907-6164-4294-88FB-F3C9C10DA1F1} = {B73AD907-6164-4294-88FB-F3C9C10DA1F1} + EndProjectSection EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Windows.ApplicationModel.WindowsAppRuntime.Projection", "dev\Projections\CS\Microsoft.Windows.ApplicationModel.WindowsAppRuntime\Microsoft.Windows.ApplicationModel.WindowsAppRuntime.Projection.csproj", "{4782BB2A-2968-44B4-867C-5FAEB7A51C6B}" + ProjectSection(ProjectDependencies) = postProject + {B73AD907-6164-4294-88FB-F3C9C10DA1F1} = {B73AD907-6164-4294-88FB-F3C9C10DA1F1} + EndProjectSection EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Windows.AppLifecycle.Projection", "dev\Projections\CS\Microsoft.Windows.AppLifecycle\Microsoft.Windows.AppLifecycle.Projection.csproj", "{D417EDBE-D783-484F-83F3-710DEC7CB585}" + ProjectSection(ProjectDependencies) = postProject + {B73AD907-6164-4294-88FB-F3C9C10DA1F1} = {B73AD907-6164-4294-88FB-F3C9C10DA1F1} + EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "WindowsAppRuntime.Test.Singleton.Msix", "test\DynamicDependency\data\WindowsAppRuntime.Test.Singleton.Msix\WindowsAppRuntime.Test.Singleton.Msix.vcxproj", "{8F2C21F1-47AB-428C-A110-EE33FD7D9493}" EndProject @@ -220,10 +229,19 @@ EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.WindowsAppRuntime.Bootstrap.Net", "dev\Bootstrap\CS\Microsoft.WindowsAppRuntime.Bootstrap.Net\Microsoft.WindowsAppRuntime.Bootstrap.Net.csproj", "{D6574FD6-8D13-4412-9FCB-308D44063CDA}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Windows.System.Power.Projection", "dev\Projections\CS\Microsoft.Windows.System.Power\Microsoft.Windows.System.Power.Projection.csproj", "{63ACBA4F-385A-4D04-98AD-263FED501A19}" + ProjectSection(ProjectDependencies) = postProject + {B73AD907-6164-4294-88FB-F3C9C10DA1F1} = {B73AD907-6164-4294-88FB-F3C9C10DA1F1} + EndProjectSection EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Windows.System.Projection", "dev\Projections\CS\Microsoft.Windows.System\Microsoft.Windows.System.Projection.csproj", "{85E9BB46-7841-4732-A039-9C902B71DEC3}" + ProjectSection(ProjectDependencies) = postProject + {B73AD907-6164-4294-88FB-F3C9C10DA1F1} = {B73AD907-6164-4294-88FB-F3C9C10DA1F1} + EndProjectSection EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Windows.PushNotifications.Projection", "dev\Projections\CS\Microsoft.Windows.PushNotifications.Projection\Microsoft.Windows.PushNotifications.Projection.csproj", "{F1F2F3A6-A7DE-45D1-9E96-E28171FD3147}" + ProjectSection(ProjectDependencies) = postProject + {B73AD907-6164-4294-88FB-F3C9C10DA1F1} = {B73AD907-6164-4294-88FB-F3C9C10DA1F1} + EndProjectSection EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Deployment", "Deployment", "{68E63911-6283-4212-BFFE-3F972AF8F835}" EndProject @@ -301,6 +319,9 @@ EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "AppNotifications", "dev\AppNotifications\AppNotifications.vcxitems", "{B4824897-88E0-4927-8FB9-E60106F01ED9}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Windows.AppNotifications.Projection", "dev\Projections\CS\Microsoft.Windows.AppNotifications.Projection\Microsoft.Windows.AppNotifications.Projection.csproj", "{2385A443-A1C2-4562-8D28-D0AD239EE5E7}" + ProjectSection(ProjectDependencies) = postProject + {B73AD907-6164-4294-88FB-F3C9C10DA1F1} = {B73AD907-6164-4294-88FB-F3C9C10DA1F1} + EndProjectSection EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Common", "Common", "{82A73181-EA4A-431A-B82B-BE6734604CC9}" EndProject @@ -344,6 +365,9 @@ EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "AppNotificationBuilderTests", "test\AppNotificationBuilderTests\AppNotificationBuilderTests.vcxproj", "{131DE0C4-AA1E-4649-B5BC-7B43508FA93A}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Windows.Security.AccessControl.Projection", "dev\Projections\CS\Microsoft.Windows.Security.AccessControl.Projection\Microsoft.Windows.Security.AccessControl.Projection.csproj", "{E6D59245-696F-4D13-ACF6-7ECE6E653367}" + ProjectSection(ProjectDependencies) = postProject + {B73AD907-6164-4294-88FB-F3C9C10DA1F1} = {B73AD907-6164-4294-88FB-F3C9C10DA1F1} + EndProjectSection EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "API", "API", "{0D6B1FF3-A075-4194-9FC0-AF7BB89D0519}" EndProject @@ -401,6 +425,9 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Test_DeploymentManagerAutoI EndProjectSection EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Windows.AppNotifications.Builder.Projection", "dev\Projections\CS\Microsoft.Windows.AppNotifications.Builder.Projection\Microsoft.Windows.AppNotifications.Builder.Projection.csproj", "{50BF3E96-3050-4053-B012-BF6993483DA5}" + ProjectSection(ProjectDependencies) = postProject + {B73AD907-6164-4294-88FB-F3C9C10DA1F1} = {B73AD907-6164-4294-88FB-F3C9C10DA1F1} + EndProjectSection EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "NotificationTests", "NotificationTests", "{1FDC307C-2DB7-4B40-8F18-F1057E9E0969}" EndProject @@ -626,6 +653,9 @@ EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "KozaniRemoteManagerLauncher", "KozaniRemoteManagerLauncher", "{C5408A09-CDB4-41C1-8766-7677757EB7F2}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "KozaniRemoteManagerLauncher", "dev\Kozani\KozaniRemoteManagerLauncher\KozaniRemoteManagerLauncher.vcxproj", "{45C50DA4-F2C7-4A4B-8493-50E5DF17B527}" + ProjectSection(ProjectDependencies) = postProject + {B73AD907-6164-4294-88FB-F3C9C10DA1F1} = {B73AD907-6164-4294-88FB-F3C9C10DA1F1} + EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "KozaniRemoteManager.Msix", "test\Kozani\data\KozaniRemoteManager.Msix\KozaniRemoteManager.Msix.vcxproj", "{A18E00C4-3668-4289-ABFC-D1DF330DA6BF}" EndProject @@ -633,6 +663,46 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "KozaniProtocol", "KozaniPro EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "KozaniProtocol", "dev\Kozani\KozaniProtocol\KozaniProtocol.vcxproj", "{3F28C3ED-2548-4530-8B6C-832FAE0E993D}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "PackageManager", "PackageManager", "{380C8BE1-1868-4860-BD32-ADCD8683285D}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "API", "API", "{CC969A0B-9B01-479D-A563-C9866BCC6F83}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PackageManager", "dev\PackageManager\API\PackageManager.vcxitems", "{8A9A0C85-65A8-4BCA-A49E-45FC4FDBC7D2}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "PackageManager", "PackageManager", "{B03C7C69-0A52-4553-B465-04C995161E42}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "API", "API", "{4B85FB26-28B6-4072-85C2-DB7B5FEB98BE}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PackageManagerTests", "test\PackageManager\API\PackageManagerTests.vcxproj", "{4A38CB80-3580-4960-9B31-3301058B7AFE}" + ProjectSection(ProjectDependencies) = postProject + {09DDAE21-397F-4263-8561-7F2FF28127CF} = {09DDAE21-397F-4263-8561-7F2FF28127CF} + {4626E11F-A7A4-41A2-B22D-5A108BC369AC} = {4626E11F-A7A4-41A2-B22D-5A108BC369AC} + {58E95711-A12F-4C0E-A978-C6B4A0842AC8} = {58E95711-A12F-4C0E-A978-C6B4A0842AC8} + {66D0D8B1-FAF4-4C6A-8303-07F3BA356FE3} = {66D0D8B1-FAF4-4C6A-8303-07F3BA356FE3} + {B73AD907-6164-4294-88FB-F3C9C10DA1F1} = {B73AD907-6164-4294-88FB-F3C9C10DA1F1} + {D0A1DFB8-8CEE-4CFC-B57B-B7C574B411C2} = {D0A1DFB8-8CEE-4CFC-B57B-B7C574B411C2} + {F2946790-DAF7-4DFF-A754-BA471A12E494} = {F2946790-DAF7-4DFF-A754-BA471A12E494} + {FBAE1876-C50A-4EFC-A686-3008B6438731} = {FBAE1876-C50A-4EFC-A686-3008B6438731} + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "data", "data", "{6213B1A3-E854-498F-AAFA-4CFC1E71023E}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "PackageManager.Test.F.Red.Msix", "PackageManager.Test.F.Red.Msix", "{5188EBDF-87AE-4CA1-AA44-AD743583FF2D}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PackageManager.Test.F.Red.Msix", "test\PackageManager\data\PackageManager.Test.F.Red.Msix\PackageManager.Test.F.Red.Msix.vcxproj", "{F2946790-DAF7-4DFF-A754-BA471A12E494}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "PackageManager.Test.F.Green.Msix", "PackageManager.Test.F.Green.Msix", "{266AE21F-0D59-4422-A95C-4B3D2BA32A4C}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PackageManager.Test.F.Green.msix", "test\PackageManager\data\PackageManager.Test.F.Green.msix\PackageManager.Test.F.Green.msix.vcxproj", "{4626E11F-A7A4-41A2-B22D-5A108BC369AC}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "PackageManager.Test.F.Blue.Msix", "PackageManager.Test.F.Blue.Msix", "{39A17DBB-F1DB-4D0C-B90E-D5F9BEC2283A}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PackageManager.Test.F.Blue.msix", "test\PackageManager\data\PackageManager.Test.F.Blue.msix\PackageManager.Test.F.Blue.msix.vcxproj", "{FBAE1876-C50A-4EFC-A686-3008B6438731}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "PackageManager.Test.F.Redder.Msix", "PackageManager.Test.F.Redder.Msix", "{B6B68924-6A0B-457E-AD53-018696EC8889}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PackageManager.Test.F.Redder.msix", "test\PackageManager\data\PackageManager.Test.F.Redder.msix\PackageManager.Test.F.Redder.msix.vcxproj", "{D0A1DFB8-8CEE-4CFC-B57B-B7C574B411C2}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -2147,8 +2217,8 @@ Global {FD0CC14A-ED4B-4936-B68B-F31E58372E32}.Release|ARM64.Build.0 = Release|x64 {FD0CC14A-ED4B-4936-B68B-F31E58372E32}.Release|x64.ActiveCfg = Release|x64 {FD0CC14A-ED4B-4936-B68B-F31E58372E32}.Release|x64.Build.0 = Release|x64 - {FD0CC14A-ED4B-4936-B68B-F31E58372E32}.Release|x86.ActiveCfg = Release|Any CPU - {FD0CC14A-ED4B-4936-B68B-F31E58372E32}.Release|x86.Build.0 = Release|Any CPU + {FD0CC14A-ED4B-4936-B68B-F31E58372E32}.Release|x86.ActiveCfg = Release|x64 + {FD0CC14A-ED4B-4936-B68B-F31E58372E32}.Release|x86.Build.0 = Release|x64 {4B4667B2-94DB-4A19-8270-0FDB1676C27B}.Debug|Any CPU.ActiveCfg = Debug|x64 {4B4667B2-94DB-4A19-8270-0FDB1676C27B}.Debug|Any CPU.Build.0 = Debug|x64 {4B4667B2-94DB-4A19-8270-0FDB1676C27B}.Debug|ARM64.ActiveCfg = Debug|ARM64 @@ -2243,6 +2313,86 @@ Global {3F28C3ED-2548-4530-8B6C-832FAE0E993D}.Release|x64.Build.0 = Release|x64 {3F28C3ED-2548-4530-8B6C-832FAE0E993D}.Release|x86.ActiveCfg = Release|Win32 {3F28C3ED-2548-4530-8B6C-832FAE0E993D}.Release|x86.Build.0 = Release|Win32 + {4A38CB80-3580-4960-9B31-3301058B7AFE}.Debug|Any CPU.ActiveCfg = Debug|x64 + {4A38CB80-3580-4960-9B31-3301058B7AFE}.Debug|Any CPU.Build.0 = Debug|x64 + {4A38CB80-3580-4960-9B31-3301058B7AFE}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {4A38CB80-3580-4960-9B31-3301058B7AFE}.Debug|ARM64.Build.0 = Debug|ARM64 + {4A38CB80-3580-4960-9B31-3301058B7AFE}.Debug|x64.ActiveCfg = Debug|x64 + {4A38CB80-3580-4960-9B31-3301058B7AFE}.Debug|x64.Build.0 = Debug|x64 + {4A38CB80-3580-4960-9B31-3301058B7AFE}.Debug|x86.ActiveCfg = Debug|Win32 + {4A38CB80-3580-4960-9B31-3301058B7AFE}.Debug|x86.Build.0 = Debug|Win32 + {4A38CB80-3580-4960-9B31-3301058B7AFE}.Release|Any CPU.ActiveCfg = Release|x64 + {4A38CB80-3580-4960-9B31-3301058B7AFE}.Release|Any CPU.Build.0 = Release|x64 + {4A38CB80-3580-4960-9B31-3301058B7AFE}.Release|ARM64.ActiveCfg = Release|ARM64 + {4A38CB80-3580-4960-9B31-3301058B7AFE}.Release|ARM64.Build.0 = Release|ARM64 + {4A38CB80-3580-4960-9B31-3301058B7AFE}.Release|x64.ActiveCfg = Release|x64 + {4A38CB80-3580-4960-9B31-3301058B7AFE}.Release|x64.Build.0 = Release|x64 + {4A38CB80-3580-4960-9B31-3301058B7AFE}.Release|x86.ActiveCfg = Release|Win32 + {4A38CB80-3580-4960-9B31-3301058B7AFE}.Release|x86.Build.0 = Release|Win32 + {F2946790-DAF7-4DFF-A754-BA471A12E494}.Debug|Any CPU.ActiveCfg = Debug|x64 + {F2946790-DAF7-4DFF-A754-BA471A12E494}.Debug|Any CPU.Build.0 = Debug|x64 + {F2946790-DAF7-4DFF-A754-BA471A12E494}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {F2946790-DAF7-4DFF-A754-BA471A12E494}.Debug|ARM64.Build.0 = Debug|ARM64 + {F2946790-DAF7-4DFF-A754-BA471A12E494}.Debug|x64.ActiveCfg = Debug|x64 + {F2946790-DAF7-4DFF-A754-BA471A12E494}.Debug|x64.Build.0 = Debug|x64 + {F2946790-DAF7-4DFF-A754-BA471A12E494}.Debug|x86.ActiveCfg = Debug|Win32 + {F2946790-DAF7-4DFF-A754-BA471A12E494}.Debug|x86.Build.0 = Debug|Win32 + {F2946790-DAF7-4DFF-A754-BA471A12E494}.Release|Any CPU.ActiveCfg = Release|x64 + {F2946790-DAF7-4DFF-A754-BA471A12E494}.Release|Any CPU.Build.0 = Release|x64 + {F2946790-DAF7-4DFF-A754-BA471A12E494}.Release|ARM64.ActiveCfg = Release|ARM64 + {F2946790-DAF7-4DFF-A754-BA471A12E494}.Release|ARM64.Build.0 = Release|ARM64 + {F2946790-DAF7-4DFF-A754-BA471A12E494}.Release|x64.ActiveCfg = Release|x64 + {F2946790-DAF7-4DFF-A754-BA471A12E494}.Release|x64.Build.0 = Release|x64 + {F2946790-DAF7-4DFF-A754-BA471A12E494}.Release|x86.ActiveCfg = Release|Win32 + {F2946790-DAF7-4DFF-A754-BA471A12E494}.Release|x86.Build.0 = Release|Win32 + {4626E11F-A7A4-41A2-B22D-5A108BC369AC}.Debug|Any CPU.ActiveCfg = Debug|x64 + {4626E11F-A7A4-41A2-B22D-5A108BC369AC}.Debug|Any CPU.Build.0 = Debug|x64 + {4626E11F-A7A4-41A2-B22D-5A108BC369AC}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {4626E11F-A7A4-41A2-B22D-5A108BC369AC}.Debug|ARM64.Build.0 = Debug|ARM64 + {4626E11F-A7A4-41A2-B22D-5A108BC369AC}.Debug|x64.ActiveCfg = Debug|x64 + {4626E11F-A7A4-41A2-B22D-5A108BC369AC}.Debug|x64.Build.0 = Debug|x64 + {4626E11F-A7A4-41A2-B22D-5A108BC369AC}.Debug|x86.ActiveCfg = Debug|Win32 + {4626E11F-A7A4-41A2-B22D-5A108BC369AC}.Debug|x86.Build.0 = Debug|Win32 + {4626E11F-A7A4-41A2-B22D-5A108BC369AC}.Release|Any CPU.ActiveCfg = Release|x64 + {4626E11F-A7A4-41A2-B22D-5A108BC369AC}.Release|Any CPU.Build.0 = Release|x64 + {4626E11F-A7A4-41A2-B22D-5A108BC369AC}.Release|ARM64.ActiveCfg = Release|ARM64 + {4626E11F-A7A4-41A2-B22D-5A108BC369AC}.Release|ARM64.Build.0 = Release|ARM64 + {4626E11F-A7A4-41A2-B22D-5A108BC369AC}.Release|x64.ActiveCfg = Release|x64 + {4626E11F-A7A4-41A2-B22D-5A108BC369AC}.Release|x64.Build.0 = Release|x64 + {4626E11F-A7A4-41A2-B22D-5A108BC369AC}.Release|x86.ActiveCfg = Release|Win32 + {4626E11F-A7A4-41A2-B22D-5A108BC369AC}.Release|x86.Build.0 = Release|Win32 + {FBAE1876-C50A-4EFC-A686-3008B6438731}.Debug|Any CPU.ActiveCfg = Debug|x64 + {FBAE1876-C50A-4EFC-A686-3008B6438731}.Debug|Any CPU.Build.0 = Debug|x64 + {FBAE1876-C50A-4EFC-A686-3008B6438731}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {FBAE1876-C50A-4EFC-A686-3008B6438731}.Debug|ARM64.Build.0 = Debug|ARM64 + {FBAE1876-C50A-4EFC-A686-3008B6438731}.Debug|x64.ActiveCfg = Debug|x64 + {FBAE1876-C50A-4EFC-A686-3008B6438731}.Debug|x64.Build.0 = Debug|x64 + {FBAE1876-C50A-4EFC-A686-3008B6438731}.Debug|x86.ActiveCfg = Debug|Win32 + {FBAE1876-C50A-4EFC-A686-3008B6438731}.Debug|x86.Build.0 = Debug|Win32 + {FBAE1876-C50A-4EFC-A686-3008B6438731}.Release|Any CPU.ActiveCfg = Release|x64 + {FBAE1876-C50A-4EFC-A686-3008B6438731}.Release|Any CPU.Build.0 = Release|x64 + {FBAE1876-C50A-4EFC-A686-3008B6438731}.Release|ARM64.ActiveCfg = Release|ARM64 + {FBAE1876-C50A-4EFC-A686-3008B6438731}.Release|ARM64.Build.0 = Release|ARM64 + {FBAE1876-C50A-4EFC-A686-3008B6438731}.Release|x64.ActiveCfg = Release|x64 + {FBAE1876-C50A-4EFC-A686-3008B6438731}.Release|x64.Build.0 = Release|x64 + {FBAE1876-C50A-4EFC-A686-3008B6438731}.Release|x86.ActiveCfg = Release|Win32 + {FBAE1876-C50A-4EFC-A686-3008B6438731}.Release|x86.Build.0 = Release|Win32 + {D0A1DFB8-8CEE-4CFC-B57B-B7C574B411C2}.Debug|Any CPU.ActiveCfg = Debug|x64 + {D0A1DFB8-8CEE-4CFC-B57B-B7C574B411C2}.Debug|Any CPU.Build.0 = Debug|x64 + {D0A1DFB8-8CEE-4CFC-B57B-B7C574B411C2}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {D0A1DFB8-8CEE-4CFC-B57B-B7C574B411C2}.Debug|ARM64.Build.0 = Debug|ARM64 + {D0A1DFB8-8CEE-4CFC-B57B-B7C574B411C2}.Debug|x64.ActiveCfg = Debug|x64 + {D0A1DFB8-8CEE-4CFC-B57B-B7C574B411C2}.Debug|x64.Build.0 = Debug|x64 + {D0A1DFB8-8CEE-4CFC-B57B-B7C574B411C2}.Debug|x86.ActiveCfg = Debug|Win32 + {D0A1DFB8-8CEE-4CFC-B57B-B7C574B411C2}.Debug|x86.Build.0 = Debug|Win32 + {D0A1DFB8-8CEE-4CFC-B57B-B7C574B411C2}.Release|Any CPU.ActiveCfg = Release|x64 + {D0A1DFB8-8CEE-4CFC-B57B-B7C574B411C2}.Release|Any CPU.Build.0 = Release|x64 + {D0A1DFB8-8CEE-4CFC-B57B-B7C574B411C2}.Release|ARM64.ActiveCfg = Release|ARM64 + {D0A1DFB8-8CEE-4CFC-B57B-B7C574B411C2}.Release|ARM64.Build.0 = Release|ARM64 + {D0A1DFB8-8CEE-4CFC-B57B-B7C574B411C2}.Release|x64.ActiveCfg = Release|x64 + {D0A1DFB8-8CEE-4CFC-B57B-B7C574B411C2}.Release|x64.Build.0 = Release|x64 + {D0A1DFB8-8CEE-4CFC-B57B-B7C574B411C2}.Release|x86.ActiveCfg = Release|Win32 + {D0A1DFB8-8CEE-4CFC-B57B-B7C574B411C2}.Release|x86.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -2436,6 +2586,21 @@ Global {A18E00C4-3668-4289-ABFC-D1DF330DA6BF} = {9CE0ED94-078A-405F-8599-BFC2D8D6E537} {82197F64-3A88-4C48-AEF9-7E62E71D75BB} = {84F66485-4391-41C7-89CB-D5006EDF1383} {3F28C3ED-2548-4530-8B6C-832FAE0E993D} = {82197F64-3A88-4C48-AEF9-7E62E71D75BB} + {380C8BE1-1868-4860-BD32-ADCD8683285D} = {448ED2E5-0B37-4D97-9E6B-8C10A507976A} + {CC969A0B-9B01-479D-A563-C9866BCC6F83} = {380C8BE1-1868-4860-BD32-ADCD8683285D} + {8A9A0C85-65A8-4BCA-A49E-45FC4FDBC7D2} = {CC969A0B-9B01-479D-A563-C9866BCC6F83} + {B03C7C69-0A52-4553-B465-04C995161E42} = {8630F7AA-2969-4DC9-8700-9B468C1DC21D} + {4B85FB26-28B6-4072-85C2-DB7B5FEB98BE} = {B03C7C69-0A52-4553-B465-04C995161E42} + {4A38CB80-3580-4960-9B31-3301058B7AFE} = {4B85FB26-28B6-4072-85C2-DB7B5FEB98BE} + {6213B1A3-E854-498F-AAFA-4CFC1E71023E} = {B03C7C69-0A52-4553-B465-04C995161E42} + {5188EBDF-87AE-4CA1-AA44-AD743583FF2D} = {6213B1A3-E854-498F-AAFA-4CFC1E71023E} + {F2946790-DAF7-4DFF-A754-BA471A12E494} = {5188EBDF-87AE-4CA1-AA44-AD743583FF2D} + {266AE21F-0D59-4422-A95C-4B3D2BA32A4C} = {6213B1A3-E854-498F-AAFA-4CFC1E71023E} + {4626E11F-A7A4-41A2-B22D-5A108BC369AC} = {266AE21F-0D59-4422-A95C-4B3D2BA32A4C} + {39A17DBB-F1DB-4D0C-B90E-D5F9BEC2283A} = {6213B1A3-E854-498F-AAFA-4CFC1E71023E} + {FBAE1876-C50A-4EFC-A686-3008B6438731} = {39A17DBB-F1DB-4D0C-B90E-D5F9BEC2283A} + {B6B68924-6A0B-457E-AD53-018696EC8889} = {B03C7C69-0A52-4553-B465-04C995161E42} + {D0A1DFB8-8CEE-4CFC-B57B-B7C574B411C2} = {B6B68924-6A0B-457E-AD53-018696EC8889} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {4B3D7591-CFEC-4762-9A07-ABE99938FB77} @@ -2454,6 +2619,7 @@ Global dev\Kozani\Common\Common.vcxitems*{829cdb09-eefe-4188-a045-3fc6be7bd96b}*SharedItemsImports = 4 dev\Common\Common.vcxitems*{8828053c-d6ec-4744-8624-f8c676c2d4df}*SharedItemsImports = 9 dev\Licensing\Licensing.vcxitems*{885a43fa-052d-4b0d-a2dc-13ee15796435}*SharedItemsImports = 9 + dev\PackageManager\API\PackageManager.vcxitems*{8a9a0c85-65a8-4bca-a49e-45fc4fdbc7d2}*SharedItemsImports = 9 test\inc\inc.vcxitems*{8e52d7ea-a200-4a6b-ba74-8efb49468caf}*SharedItemsImports = 4 dev\Kozani\Common\Common.vcxitems*{a11c6664-f26a-4e71-b440-2e4e1ba09a93}*SharedItemsImports = 4 dev\AppNotifications\AppNotifications.vcxitems*{b4824897-88e0-4927-8fb9-e60106f01ed9}*SharedItemsImports = 9 @@ -2461,6 +2627,7 @@ Global dev\Common\Common.vcxitems*{b73ad907-6164-4294-88fb-f3c9c10da1f1}*SharedItemsImports = 4 dev\DynamicDependency\API\DynamicDependency.vcxitems*{b73ad907-6164-4294-88fb-f3c9c10da1f1}*SharedItemsImports = 4 dev\Licensing\Licensing.vcxitems*{b73ad907-6164-4294-88fb-f3c9c10da1f1}*SharedItemsImports = 4 + dev\PackageManager\API\PackageManager.vcxitems*{b73ad907-6164-4294-88fb-f3c9c10da1f1}*SharedItemsImports = 4 dev\PowerNotifications\PowerNotifications.vcxitems*{b73ad907-6164-4294-88fb-f3c9c10da1f1}*SharedItemsImports = 4 dev\UndockedRegFreeWinRT\UndockedRegFreeWinRT.vcxitems*{b73ad907-6164-4294-88fb-f3c9c10da1f1}*SharedItemsImports = 4 dev\PowerNotifications\PowerNotifications.vcxitems*{b75c1b22-553c-40e4-b38e-6ab4d01fdb9d}*SharedItemsImports = 9 diff --git a/build/AzurePipelinesTemplates/WindowsAppSDK-BuildBinaries-Steps.yml b/build/AzurePipelinesTemplates/WindowsAppSDK-BuildBinaries-Steps.yml index 271df68e72..3ee7d5fdc7 100644 --- a/build/AzurePipelinesTemplates/WindowsAppSDK-BuildBinaries-Steps.yml +++ b/build/AzurePipelinesTemplates/WindowsAppSDK-BuildBinaries-Steps.yml @@ -38,6 +38,7 @@ steps: - task: 333b11bd-d341-40d9-afcf-b32d5ce6f23b@2 displayName: RestoreNuGetPackages + retryCountOnTaskFailure: 10 inputs: restoreSolution: build/packages.config feedsToUse: config diff --git a/build/AzurePipelinesTemplates/WindowsAppSDK-BuildMRT-Steps.yml b/build/AzurePipelinesTemplates/WindowsAppSDK-BuildMRT-Steps.yml index 701463aafc..3f003fa029 100644 --- a/build/AzurePipelinesTemplates/WindowsAppSDK-BuildMRT-Steps.yml +++ b/build/AzurePipelinesTemplates/WindowsAppSDK-BuildMRT-Steps.yml @@ -47,6 +47,7 @@ steps: - ${{ if not( parameters.RunPrefast ) }}: - task: PowerShell@2 name: BuildBinaries + retryCountOnTaskFailure: 10 inputs: filePath: 'BuildAll.ps1' arguments: -Platform "$(buildPlatform)" -Configuration "$(buildConfiguration)" -AzureBuildStep "BuildMRT" diff --git a/build/AzurePipelinesTemplates/WindowsAppSDK-BuildTransportPackage-Stage.yml b/build/AzurePipelinesTemplates/WindowsAppSDK-BuildTransportPackage-Stage.yml index ed4356a52d..96c341f0e4 100644 --- a/build/AzurePipelinesTemplates/WindowsAppSDK-BuildTransportPackage-Stage.yml +++ b/build/AzurePipelinesTemplates/WindowsAppSDK-BuildTransportPackage-Stage.yml @@ -2,6 +2,9 @@ parameters: - name: "PublishToMaestro" type: boolean default: False +- name: "PublishPackage" + type: boolean + default: False - name: "IgnoreFailures" type: boolean default: False @@ -163,6 +166,7 @@ stages: parameters: SignOutput: ${{ parameters.SignOutput }} IsOneBranch: ${{ parameters.IsOneBranch }} + PublishPackage: ${{ parameters.PublishPackage }} # Build WinAppSDK and Run Integration Test from TestAll.ps1 - job: WinAppSDKIntegrationBuildAndTest @@ -174,7 +178,7 @@ stages: name: 'ProjectReunionESPool-2022' variables: WindowsAppSDKTransportPackageVersion: $[ dependencies.NugetPackage.outputs['SetVersion.packageVersion'] ] - VersionWithDevTag: $[format('{0}.{1}.{2}-{3}.{4}.{5}', variables['major'], variables['minor'], variables['patch'], 'dev', variables['versionDate'], variables['versionCounter'])] + VersionWithDevTag: $[format('{0}.{1}.{2}-{3}', variables['major'], variables['minor'], variables['versionDate'], 'dev')] ob_outputDirectory: '$(REPOROOT)\out' ob_artifactBaseName: "WindowsAppSDKNugetPackage" steps: diff --git a/build/AzurePipelinesTemplates/WindowsAppSDK-PackNuget-Steps.yml b/build/AzurePipelinesTemplates/WindowsAppSDK-PackNuget-Steps.yml index e5fd2da6ee..cb10ed5a19 100644 --- a/build/AzurePipelinesTemplates/WindowsAppSDK-PackNuget-Steps.yml +++ b/build/AzurePipelinesTemplates/WindowsAppSDK-PackNuget-Steps.yml @@ -2,6 +2,9 @@ parameters: - name: "SignOutput" type: boolean default: False +- name: "PublishPackage" + type: boolean + default: False - name: "IsOneBranch" type: boolean default: True @@ -154,7 +157,7 @@ steps: displayName: MoveToOutputDirectory inputs: SourceFolder: '$(build.artifactStagingDirectory)\FullNuget' - TargetFolder: '$(ob_outputDirectory)\TransportPackage' + TargetFolder: '$(ob_outputDirectory)' - ${{ if not( parameters.IsOneBranch ) }}: - task: PublishBuildArtifacts@1 @@ -162,13 +165,14 @@ steps: PathtoPublish: '$(ob_outputDirectory)' artifactName: '$(ob_artifactBaseName)' -# this mysterious guid fixes the "NuGetCommand@2 is ambiguous" error :-( -- task: 333b11bd-d341-40d9-afcf-b32d5ce6f23b@2 - displayName: 'NuGet push to ProjectReunion.nuget.internal' - inputs: - command: 'push' - packagesToPush: '$(ob_outputDirectory)\TransportPackage\*.nupkg' - verbosityPush: 'Detailed' - nuGetFeedType: 'internal' - #Note: The project qualifier is always required when using a feed name. Also, do not use organization scoped feeds. - publishVstsFeed: 'ProjectReunion/Project.Reunion.nuget.internal' \ No newline at end of file +- ${{ if eq(parameters.PublishPackage, 'true') }}: + # this mysterious guid fixes the "NuGetCommand@2 is ambiguous" error :-( + - task: 333b11bd-d341-40d9-afcf-b32d5ce6f23b@2 + displayName: 'NuGet push to ProjectReunion.nuget.internal' + inputs: + command: 'push' + packagesToPush: '$(ob_outputDirectory)\*.nupkg' + verbosityPush: 'Detailed' + nuGetFeedType: 'internal' + #Note: The project qualifier is always required when using a feed name. Also, do not use organization scoped feeds. + publishVstsFeed: 'ProjectReunion/Project.Reunion.nuget.internal' \ No newline at end of file diff --git a/build/AzurePipelinesTemplates/WindowsAppSDK-RunTests-Steps.yml b/build/AzurePipelinesTemplates/WindowsAppSDK-RunTests-Steps.yml index efd3462651..8210a16bfd 100644 --- a/build/AzurePipelinesTemplates/WindowsAppSDK-RunTests-Steps.yml +++ b/build/AzurePipelinesTemplates/WindowsAppSDK-RunTests-Steps.yml @@ -1,10 +1,10 @@ parameters: buildPlatform: '' buildConfiguration: '' - ImageName: '' TaefSelect: '*' BinaryCompatSwitch: '' testLocale: '' + steps: - task: powershell@2 displayName: 'DevCheck: Setup/Verify development environment' diff --git a/build/AzurePipelinesTemplates/WindowsAppSDK-RunTestsInPipeline-Job.yml b/build/AzurePipelinesTemplates/WindowsAppSDK-RunTestsInPipeline-Job.yml index 1c846355f3..af0b02eecb 100644 --- a/build/AzurePipelinesTemplates/WindowsAppSDK-RunTestsInPipeline-Job.yml +++ b/build/AzurePipelinesTemplates/WindowsAppSDK-RunTestsInPipeline-Job.yml @@ -53,11 +53,6 @@ jobs: buildPlatform: x64 buildConfiguration: release testLocale: ja-JP - 21H1_x64fre: - imageName: Windows.10.Enterprise.21h1 - buildPlatform: x64 - buildConfiguration: release - testLocale: en-US 21H2_MS_x64fre: imageName: Windows.11.Enterprise.MultiSession.21h2 buildPlatform: x64 @@ -68,11 +63,6 @@ jobs: buildPlatform: x86 buildConfiguration: release testLocale: en-US - co_refresh_x64fre: - imageName: co_refresh - buildPlatform: x64 - buildConfiguration: release - testLocale: en-US rs_prerelease_x64fre: imageName: rs_prerelease buildPlatform: x64 @@ -95,11 +85,6 @@ jobs: buildPlatform: arm64 buildConfiguration: release testLocale: en-US - Server22_DC_arm64fre: - imageName: Windows.11.Server2022.DataCenter.arm64 - buildPlatform: arm64 - buildConfiguration: release - testLocale: en-US pool: type: windows isCustom: true diff --git a/build/AzurePipelinesTemplates/WindowsAppSDK-SetupBuildEnvironment-Steps.yml b/build/AzurePipelinesTemplates/WindowsAppSDK-SetupBuildEnvironment-Steps.yml index 7f7f78ae71..e91f722390 100644 --- a/build/AzurePipelinesTemplates/WindowsAppSDK-SetupBuildEnvironment-Steps.yml +++ b/build/AzurePipelinesTemplates/WindowsAppSDK-SetupBuildEnvironment-Steps.yml @@ -4,15 +4,10 @@ parameters: default: True steps: -- task: UseDotNet@2 - displayName: Use .NET Core SDK 5 - inputs: - version: 5.0.407 - - task: UseDotNet@2 displayName: Use .NET Core SDK 6 inputs: - version: 6.0.401 + version: 6.0.414 # Extract the build revision number from Build.BuildNumber. This is needed to pass to build-nupkg. # This relies on the format of the pipeline name being of the format: $(date:yyMM).$(date:dd)$(rev:rrr) diff --git a/build/CopyFilesToStagingDir.ps1 b/build/CopyFilesToStagingDir.ps1 index 73d84a35b4..86d240c80a 100644 --- a/build/CopyFilesToStagingDir.ps1 +++ b/build/CopyFilesToStagingDir.ps1 @@ -39,15 +39,16 @@ PublishFile $OverrideDir\PushNotifications-Override.json $FullPublishDir\ PublishFile $FullBuildOutput\WindowsAppRuntime_DLL\Microsoft.WindowsAppRuntime.dll $FullPublishDir\Microsoft.WindowsAppRuntime\ PublishFile $FullBuildOutput\WindowsAppRuntime_DLL\Microsoft.WindowsAppRuntime.pdb $FullPublishDir\Microsoft.WindowsAppRuntime\ PublishFile $FullBuildOutput\WindowsAppRuntime_DLL\Microsoft.WindowsAppRuntime.lib $FullPublishDir\Microsoft.WindowsAppRuntime\ +PublishFile $FullBuildOutput\WindowsAppRuntime_DLL\StrippedWinMD\Microsoft.Windows.ApplicationModel.DynamicDependency.winmd $FullPublishDir\Microsoft.WindowsAppRuntime\ +PublishFile $FullBuildOutput\WindowsAppRuntime_DLL\StrippedWinMD\Microsoft.Windows.ApplicationModel.WindowsAppRuntime.winmd $FullPublishDir\Microsoft.WindowsAppRuntime\ PublishFile $FullBuildOutput\WindowsAppRuntime_DLL\StrippedWinMD\Microsoft.Windows.AppLifecycle.winmd $FullPublishDir\Microsoft.WindowsAppRuntime\ -PublishFile $FullBuildOutput\WindowsAppRuntime_DLL\StrippedWinMD\Microsoft.Windows.AppNotifications.winmd $FullPublishDir\Microsoft.WindowsAppRuntime\ PublishFile $FullBuildOutput\WindowsAppRuntime_DLL\StrippedWinMD\Microsoft.Windows.AppNotifications.Builder.winmd $FullPublishDir\Microsoft.WindowsAppRuntime\ +PublishFile $FullBuildOutput\WindowsAppRuntime_DLL\StrippedWinMD\Microsoft.Windows.AppNotifications.winmd $FullPublishDir\Microsoft.WindowsAppRuntime\ +PublishFile $FullBuildOutput\WindowsAppRuntime_DLL\StrippedWinMD\Microsoft.Windows.Management.Deployment.winmd $FullPublishDir\Microsoft.WindowsAppRuntime\ PublishFile $FullBuildOutput\WindowsAppRuntime_DLL\StrippedWinMD\Microsoft.Windows.PushNotifications.winmd $FullPublishDir\Microsoft.WindowsAppRuntime\ -PublishFile $FullBuildOutput\WindowsAppRuntime_DLL\StrippedWinMD\Microsoft.Windows.ApplicationModel.DynamicDependency.winmd $FullPublishDir\Microsoft.WindowsAppRuntime\ -PublishFile $FullBuildOutput\WindowsAppRuntime_DLL\StrippedWinMD\Microsoft.Windows.ApplicationModel.WindowsAppRuntime.winmd $FullPublishDir\Microsoft.WindowsAppRuntime\ -PublishFile $FullBuildOutput\WindowsAppRuntime_DLL\StrippedWinMD\Microsoft.Windows.System.winmd $FullPublishDir\Microsoft.WindowsAppRuntime\ -PublishFile $FullBuildOutput\WindowsAppRuntime_DLL\StrippedWinMD\Microsoft.Windows.System.Power.winmd $FullPublishDir\Microsoft.WindowsAppRuntime\ PublishFile $FullBuildOutput\WindowsAppRuntime_DLL\StrippedWinMD\Microsoft.Windows.Security.AccessControl.winmd $FullPublishDir\Microsoft.WindowsAppRuntime\ +PublishFile $FullBuildOutput\WindowsAppRuntime_DLL\StrippedWinMD\Microsoft.Windows.System.Power.winmd $FullPublishDir\Microsoft.WindowsAppRuntime\ +PublishFile $FullBuildOutput\WindowsAppRuntime_DLL\StrippedWinMD\Microsoft.Windows.System.winmd $FullPublishDir\Microsoft.WindowsAppRuntime\ PublishFile $FullBuildOutput\WindowsAppRuntime_DLL\MsixDynamicDependency.h $FullPublishDir\Microsoft.WindowsAppRuntime\ PublishFile $FullBuildOutput\WindowsAppRuntime_DLL\wil_msixdynamicdependency.h $FullPublishDir\Microsoft.WindowsAppRuntime\ PublishFile $FullBuildOutput\WindowsAppRuntime_DLL\Security.AccessControl.h $FullPublishDir\Microsoft.WindowsAppRuntime\ @@ -56,7 +57,6 @@ PublishFile $FullBuildOutput\RestartAgent\RestartAgent.pdb $FullPublishDir\Micro PublishFile $FullBuildOutput\DeploymentAgent\DeploymentAgent.exe $FullPublishDir\Microsoft.WindowsAppRuntime\ PublishFile $FullBuildOutput\DeploymentAgent\DeploymentAgent.pdb $FullPublishDir\Microsoft.WindowsAppRuntime\ - # PublishFile $FullBuildOutput\DynamicDependency.DataStore\DynamicDependency.DataStore.exe $FullPublishDir\DynamicDependency.DataStore\ PublishFile $FullBuildOutput\DynamicDependency.DataStore\DynamicDependency.DataStore.pdb $FullPublishDir\DynamicDependency.DataStore\ @@ -104,18 +104,18 @@ PublishFile $FullBuildOutput\Microsoft.Windows.ApplicationModel.WindowsAppRuntim PublishFile $FullBuildOutput\Microsoft.Windows.ApplicationModel.WindowsAppRuntime.Projection\Microsoft.Windows.ApplicationModel.WindowsAppRuntime.Projection.pdb $NugetDir\lib\net6.0-windows10.0.17763.0 PublishFile $FullBuildOutput\Microsoft.Windows.AppLifecycle.Projection\Microsoft.Windows.AppLifecycle.Projection.dll $NugetDir\lib\net6.0-windows10.0.17763.0 PublishFile $FullBuildOutput\Microsoft.Windows.AppLifecycle.Projection\Microsoft.Windows.AppLifecycle.Projection.pdb $NugetDir\lib\net6.0-windows10.0.17763.0 -PublishFile $FullBuildOutput\Microsoft.Windows.AppNotifications.Projection\Microsoft.Windows.AppNotifications.Projection.dll $NugetDir\lib\net6.0-windows10.0.17763.0 -PublishFile $FullBuildOutput\Microsoft.Windows.AppNotifications.Projection\Microsoft.Windows.AppNotifications.Projection.pdb $NugetDir\lib\net6.0-windows10.0.17763.0 PublishFile $FullBuildOutput\Microsoft.Windows.AppNotifications.Builder.Projection\Microsoft.Windows.AppNotifications.Builder.Projection.dll $NugetDir\lib\net6.0-windows10.0.17763.0 PublishFile $FullBuildOutput\Microsoft.Windows.AppNotifications.Builder.Projection\Microsoft.Windows.AppNotifications.Builder.Projection.pdb $NugetDir\lib\net6.0-windows10.0.17763.0 +PublishFile $FullBuildOutput\Microsoft.Windows.AppNotifications.Projection\Microsoft.Windows.AppNotifications.Projection.dll $NugetDir\lib\net6.0-windows10.0.17763.0 +PublishFile $FullBuildOutput\Microsoft.Windows.AppNotifications.Projection\Microsoft.Windows.AppNotifications.Projection.pdb $NugetDir\lib\net6.0-windows10.0.17763.0 PublishFile $FullBuildOutput\Microsoft.Windows.PushNotifications.Projection\Microsoft.Windows.PushNotifications.Projection.dll $NugetDir\lib\net6.0-windows10.0.17763.0 PublishFile $FullBuildOutput\Microsoft.Windows.PushNotifications.Projection\Microsoft.Windows.PushNotifications.Projection.pdb $NugetDir\lib\net6.0-windows10.0.17763.0 -PublishFile $FullBuildOutput\Microsoft.Windows.System.Projection\Microsoft.Windows.System.Projection.dll $NugetDir\lib\net6.0-windows10.0.17763.0 -PublishFile $FullBuildOutput\Microsoft.Windows.System.Projection\Microsoft.Windows.System.Projection.pdb $NugetDir\lib\net6.0-windows10.0.17763.0 -PublishFile $FullBuildOutput\Microsoft.Windows.System.Power.Projection\Microsoft.Windows.System.Power.Projection.dll $NugetDir\lib\net6.0-windows10.0.17763.0 -PublishFile $FullBuildOutput\Microsoft.Windows.System.Power.Projection\Microsoft.Windows.System.Power.Projection.pdb $NugetDir\lib\net6.0-windows10.0.17763.0 PublishFile $FullBuildOutput\Microsoft.Windows.Security.AccessControl.Projection\Microsoft.Windows.Security.AccessControl.Projection.dll $NugetDir\lib\net6.0-windows10.0.17763.0 PublishFile $FullBuildOutput\Microsoft.Windows.Security.AccessControl.Projection\Microsoft.Windows.Security.AccessControl.Projection.pdb $NugetDir\lib\net6.0-windows10.0.17763.0 +PublishFile $FullBuildOutput\Microsoft.Windows.System.Power.Projection\Microsoft.Windows.System.Power.Projection.dll $NugetDir\lib\net6.0-windows10.0.17763.0 +PublishFile $FullBuildOutput\Microsoft.Windows.System.Power.Projection\Microsoft.Windows.System.Power.Projection.pdb $NugetDir\lib\net6.0-windows10.0.17763.0 +PublishFile $FullBuildOutput\Microsoft.Windows.System.Projection\Microsoft.Windows.System.Projection.dll $NugetDir\lib\net6.0-windows10.0.17763.0 +PublishFile $FullBuildOutput\Microsoft.Windows.System.Projection\Microsoft.Windows.System.Projection.pdb $NugetDir\lib\net6.0-windows10.0.17763.0 # # Dynamic Dependency build overrides @@ -174,15 +174,16 @@ PublishFile $FullBuildOutput\WindowsAppRuntime_MSIXInstallFromPath\WindowsAppRun PublishFile $FullBuildOutput\WindowsAppRuntime_MSIXInstallFromPath\WindowsAppRuntime_MSIXInstallFromPath.pdb $NugetDir\tools\$Platform # # WinMD for UWP apps +PublishFile $FullBuildOutput\WindowsAppRuntime_DLL\StrippedWinMD\Microsoft.Windows.ApplicationModel.DynamicDependency.winmd $NugetDir\lib\uap10.0 +PublishFile $FullBuildOutput\WindowsAppRuntime_DLL\StrippedWinMD\Microsoft.Windows.ApplicationModel.WindowsAppRuntime.winmd $NugetDir\lib\uap10.0 PublishFile $FullBuildOutput\WindowsAppRuntime_DLL\StrippedWinMD\Microsoft.Windows.AppLifecycle.winmd $NugetDir\lib\uap10.0 -PublishFile $FullBuildOutput\WindowsAppRuntime_DLL\StrippedWinMD\Microsoft.Windows.AppNotifications.winmd $NugetDir\lib\uap10.0 PublishFile $FullBuildOutput\WindowsAppRuntime_DLL\StrippedWinMD\Microsoft.Windows.AppNotifications.Builder.winmd $NugetDir\lib\uap10.0 +PublishFile $FullBuildOutput\WindowsAppRuntime_DLL\StrippedWinMD\Microsoft.Windows.AppNotifications.winmd $NugetDir\lib\uap10.0 +PublishFile $FullBuildOutput\WindowsAppRuntime_DLL\StrippedWinMD\Microsoft.Windows.Management.Deployment.winmd $NugetDir\lib\uap10.0 PublishFile $FullBuildOutput\WindowsAppRuntime_DLL\StrippedWinMD\Microsoft.Windows.PushNotifications.winmd $NugetDir\lib\uap10.0 -PublishFile $FullBuildOutput\WindowsAppRuntime_DLL\StrippedWinMD\Microsoft.Windows.ApplicationModel.DynamicDependency.winmd $NugetDir\lib\uap10.0 -PublishFile $FullBuildOutput\WindowsAppRuntime_DLL\StrippedWinMD\Microsoft.Windows.ApplicationModel.WindowsAppRuntime.winmd $NugetDir\lib\uap10.0 -PublishFile $FullBuildOutput\WindowsAppRuntime_DLL\StrippedWinMD\Microsoft.Windows.System.winmd $NugetDir\lib\uap10.0 -PublishFile $FullBuildOutput\WindowsAppRuntime_DLL\StrippedWinMD\Microsoft.Windows.System.Power.winmd $NugetDir\lib\uap10.0 PublishFile $FullBuildOutput\WindowsAppRuntime_DLL\StrippedWinMD\Microsoft.Windows.Security.AccessControl.winmd $NugetDir\lib\uap10.0 +PublishFile $FullBuildOutput\WindowsAppRuntime_DLL\StrippedWinMD\Microsoft.Windows.System.Power.winmd $NugetDir\lib\uap10.0 +PublishFile $FullBuildOutput\WindowsAppRuntime_DLL\StrippedWinMD\Microsoft.Windows.System.winmd $NugetDir\lib\uap10.0 # # Bootstrap Auto-Initializer Files PublishFile $FullBuildOutput\WindowsAppRuntime_BootstrapDLL\MddBootstrapAutoInitializer.cpp $NugetDir\include diff --git a/build/NuSpecs/AppxManifest.xml b/build/NuSpecs/AppxManifest.xml index ef35e49436..a4c68722d5 100644 --- a/build/NuSpecs/AppxManifest.xml +++ b/build/NuSpecs/AppxManifest.xml @@ -27,6 +27,8 @@ Microsoft.WindowsAppRuntime.dll + + @@ -34,7 +36,7 @@ - + @@ -47,6 +49,40 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -64,19 +100,6 @@ - - - - - - - - - - - - - diff --git a/build/NuSpecs/Microsoft.WindowsAppSDK.Bootstrap.CS.targets b/build/NuSpecs/Microsoft.WindowsAppSDK.Bootstrap.CS.targets index 07f0ccdd5c..1a7f16ab5e 100644 --- a/build/NuSpecs/Microsoft.WindowsAppSDK.Bootstrap.CS.targets +++ b/build/NuSpecs/Microsoft.WindowsAppSDK.Bootstrap.CS.targets @@ -8,13 +8,14 @@ $(DefineConstants);MICROSOFT_WINDOWSAPPSDK_BOOTSTRAP_AUTO_INITIALIZE_OPTIONS_ONERROR_FAILFAST $(DefineConstants);MICROSOFT_WINDOWSAPPSDK_BOOTSTRAP_AUTO_INITIALIZE_OPTIONS_ONNOMATCH_SHOWUI $(DefineConstants);MICROSOFT_WINDOWSAPPSDK_BOOTSTRAP_AUTO_INITIALIZE_OPTIONS_ONPACKAGEIDENTITY_NOOP + true - - - - - - + + + + + + diff --git a/build/NuSpecs/Microsoft.WindowsAppSDK.DeploymentManager.CS.targets b/build/NuSpecs/Microsoft.WindowsAppSDK.DeploymentManager.CS.targets index 4524c2766a..d4bda4c0b7 100644 --- a/build/NuSpecs/Microsoft.WindowsAppSDK.DeploymentManager.CS.targets +++ b/build/NuSpecs/Microsoft.WindowsAppSDK.DeploymentManager.CS.targets @@ -4,13 +4,14 @@ $(DefineConstants);MICROSOFT_WINDOWSAPPSDK_DEPLOYMENTMANAGER_AUTO_INITIALIZE_OPTIONS_DEFAULT $(DefineConstants);MICROSOFT_WINDOWSAPPSDK_DEPLOYMENTMANAGER_AUTO_INITIALIZE_OPTIONS_NONE $(DefineConstants);MICROSOFT_WINDOWSAPPSDK_DEPLOYMENTMANAGER_AUTO_INITIALIZE_OPTIONS_ONERRORSHOWUI + true - - - - - - + + + + + + diff --git a/build/NuSpecs/Microsoft.WindowsAppSDK.Foundation.targets b/build/NuSpecs/Microsoft.WindowsAppSDK.Foundation.targets index 11a6d03861..73434d043d 100644 --- a/build/NuSpecs/Microsoft.WindowsAppSDK.Foundation.targets +++ b/build/NuSpecs/Microsoft.WindowsAppSDK.Foundation.targets @@ -1,4 +1,4 @@ - + @@ -13,4 +13,8 @@ + + + + diff --git a/build/ProjectReunion-BuildFoundation.yml b/build/ProjectReunion-BuildFoundation.yml index f741dc5448..84f5510b8f 100644 --- a/build/ProjectReunion-BuildFoundation.yml +++ b/build/ProjectReunion-BuildFoundation.yml @@ -11,4 +11,5 @@ stages: parameters: PublishToMaestro: False SignOutput: False - IsOneBranch: False \ No newline at end of file + IsOneBranch: False + PublishPackage: False \ No newline at end of file diff --git a/build/ProjectReunion-CI.yml b/build/ProjectReunion-CI.yml index 40ed8edb4a..85114d6b5f 100644 --- a/build/ProjectReunion-CI.yml +++ b/build/ProjectReunion-CI.yml @@ -55,16 +55,17 @@ jobs: targetType: filePath filePath: tools\VerifyCopyrightHeaders.ps1 -- job: Build +- job: BuildBinaries pool: vmImage: 'windows-2022' timeoutInMinutes: 120 strategy: maxParallel: 10 matrix: - Debug_x86: - buildPlatform: 'x86' - buildConfiguration: 'Debug' + # TODO: Reenable when LNK2019 error is fixed Bug#46043382 + # Debug_x86: + # buildPlatform: 'x86' + # buildConfiguration: 'Debug' Release_x86: buildPlatform: 'x86' buildConfiguration: 'Release' @@ -84,6 +85,8 @@ jobs: - task: NuGetToolInstaller@1 - template: AzurePipelinesTemplates\WindowsAppSDK-SetupBuildEnvironment-Steps.yml + parameters: + IsOneBranch: false - task: PowerShell@2 name: BuildBinaries @@ -91,19 +94,27 @@ jobs: filePath: 'BuildAll.ps1' arguments: -Platform "$(buildPlatform)" -Configuration "$(buildConfiguration)" -AzureBuildStep "BuildBinaries" + - task: CopyFiles@2 + displayName: MoveToOutputDirectory + inputs: + SourceFolder: '$(build.SourcesDirectory)\packages' + TargetFolder: '$(build.SourcesDirectory)\BuildOutput\packages' + - task: PublishBuildArtifacts@1 displayName: 'Publish artifact: Full Nuget' inputs: PathtoPublish: '$(build.SourcesDirectory)\BuildOutput' - artifactName: 'BuildOutput' + artifactName: 'FoundationBinaries_$(buildConfiguration)_$(buildPlatform)' -- job: BuildAnyCPU +- job: BuildBinaries_release_anycpu pool: vmImage: 'windows-2022' steps: - task: NuGetToolInstaller@1 - template: AzurePipelinesTemplates\WindowsAppSDK-SetupBuildEnvironment-Steps.yml + parameters: + IsOneBranch: false - task: PowerShell@2 name: BuildBinaries @@ -115,7 +126,7 @@ jobs: displayName: 'Publish artifact: Full Nuget' inputs: PathtoPublish: '$(build.SourcesDirectory)\BuildOutput' - artifactName: 'BuildOutput' + artifactName: 'FoundationBinaries_Release_AnyCPU' - job: BuildMRT pool: @@ -132,96 +143,42 @@ jobs: Release_Arm64: buildPlatform: 'ARM64' buildConfiguration: 'Release' + variables: + ob_artifactBaseName: "MrtBinaries_$(buildConfiguration)_$(buildPlatform)" # For BuildMRT to publish t steps: - task: NuGetToolInstaller@1 - template: AzurePipelinesTemplates\WindowsAppSDK-BuildMRT-Steps.yml + parameters: + IsOneBranch: false - - task: PublishBuildArtifacts@1 - displayName: 'Publish BuildOutput' - inputs: - artifactName: BuildOutput - PathtoPublish: '$(buildOutputDir)' - -# We no longer run MRT tests in Helix here, due to dwindling Helix support. But one MRT test suite -# is still being run in WindowsAppSDK-BuildMRT-Steps.yml. - -- job: StageAndPack +- job: Test pool: vmImage: 'windows-2022' - timeoutInMinutes: 120 + strategy: + maxParallel: 10 + matrix: + Release_x86: + buildPlatform: 'x86' + buildConfiguration: 'Release' + testLocale: en-US + Release_x64: + buildPlatform: 'x64' + buildConfiguration: 'Release' + testLocale: en-US + Release_Arm64: + buildPlatform: 'ARM64' + buildConfiguration: 'Release' + testLocale: en-US dependsOn: - - Build - - BuildMRT + - BuildBinaries + - BuildBinaries_release_anycpu + - BuildMRT + variables: + testPayloadArtifactDir: $(Build.SourcesDirectory)\BuildOutput\$(buildConfiguration)\$(buildPlatform) steps: - - task: DownloadBuildArtifacts@0 - inputs: - artifactName: BuildOutput - downloadPath: '$(Build.SourcesDirectory)' - - - task: PowerShell@2 - name: StageFiles - inputs: - filePath: 'BuildAll.ps1' - arguments: -Platform "x86,x64,arm64" -Configuration "release" -AzureBuildStep "StageFiles" - - - task: PowerShell@2 - name: SetVersion - displayName: Update metapackage version - inputs: - targetType: 'inline' - script: | - $packageVersion = '$(version)' - $pipelineType = '$(PipelineType)' - $sourceBranchName = '$(Build.SourceBranchName)' - if ($sourceBranchName -eq 'main' -or $sourceBranchName -eq 'develop') - { - $packageVersion = $packageVersion + '.' + $sourceBranchName + '.' + $pipelineType - } - Write-Host "##vso[task.setvariable variable=packageVersion;]$packageVersion" - Write-Host $packageVersion - [xml]$publicNuspec = Get-Content -Path $(Build.SourcesDirectory)\build\NuSpecs\Microsoft.WindowsAppSDK.Foundation.nuspec - $publicNuspec.package.metadata.version = $packageVersion - Set-Content -Value $publicNuspec.OuterXml $(Build.SourcesDirectory)\build\NuSpecs\Microsoft.WindowsAppSDK.Foundation.nuspec - - task: PowerShell@2 - name: PackNuget - inputs: - filePath: 'BuildAll.ps1' - arguments: -Platform "x64" -Configuration "release" -AzureBuildStep "PackNuget" -OutputDirectory "$(build.artifactStagingDirectory)\FullNuget" -PackageVersion "$(packageVersion)" - - - task: BinSkim@3 - inputs: - InputType: 'Basic' - Function: 'analyze' - AnalyzeTarget: '$(build.SourcesDirectory)\BuildOutput\FullNuget\*.dll;$(build.SourcesDirectory)\BuildOutput\FullNuget\*.exe' - AnalyzeVerbose: true - - - task: PostAnalysis@1 - inputs: - AllTools: false - APIScan: false - BinSkim: true - BinSkimBreakOn: 'Error' - CodesignValidation: false - CredScan: false - FortifySCA: false - FxCop: false - ModernCop: false - PoliCheck: false - RoslynAnalyzers: false - SDLNativeRules: false - Semmle: false - TSLint: false - ToolLogsNotFoundAction: 'Standard' - - - task: PublishBuildArtifacts@1 - displayName: 'Publish artifact: NugetContent' - inputs: - PathtoPublish: '$(Build.SourcesDirectory)\BuildOutput\FullNuget' - artifactName: 'NugetContent' - - - task: PublishBuildArtifacts@1 - displayName: 'Publish artifact: TransportPackage' - inputs: - PathtoPublish: '$(build.artifactStagingDirectory)\FullNuget' - artifactName: 'TransportPackage' + - template: AzurePipelinesTemplates\WindowsAppSDK-RunTests-Steps.yml + parameters: + buildPlatform: $(buildPlatform) + buildConfiguration: $(buildConfiguration) + testLocale: $(testLocale) diff --git a/build/WindowsAppSDK-CommonVariables.yml b/build/WindowsAppSDK-CommonVariables.yml index 0445b50b0f..32e2f8a0b5 100644 --- a/build/WindowsAppSDK-CommonVariables.yml +++ b/build/WindowsAppSDK-CommonVariables.yml @@ -13,7 +13,7 @@ variables: Codeql.Enabled: true # CodeQL runs every 3 days on the default branch for all languages its applicable to in that pipeline. - channel: 'preview' + channel: 'experimental' rerunPassesRequiredToAvoidFailure: 5 versionDate: $[format('{0:yyyyMMdd}', pipeline.startTime)] versionCounter: $[counter(variables['versionDate'], 0)] diff --git a/build/WindowsAppSDK-Foundation-Nightly.yml b/build/WindowsAppSDK-Foundation-Nightly.yml index 3c2d7b38c0..7ecd4ff3ef 100644 --- a/build/WindowsAppSDK-Foundation-Nightly.yml +++ b/build/WindowsAppSDK-Foundation-Nightly.yml @@ -76,4 +76,5 @@ extends: parameters: PublishToMaestro: ${{ parameters.PublishToMaestro }} IgnoreFailures: ${{ parameters.IgnoreFailures }} - SignOutput: ${{ parameters.SignOutput }} \ No newline at end of file + SignOutput: ${{ parameters.SignOutput }} + PublishPackage: true \ No newline at end of file diff --git a/build/WindowsAppSDK-Foundation-PR.yml b/build/WindowsAppSDK-Foundation-PR.yml index b97204c142..e982969d97 100644 --- a/build/WindowsAppSDK-Foundation-PR.yml +++ b/build/WindowsAppSDK-Foundation-PR.yml @@ -51,5 +51,6 @@ extends: stages: - template: AzurePipelinesTemplates\WindowsAppSDK-BuildTransportPackage-Stage.yml@self parameters: - PublishToMaestro: False - SignOutput: False \ No newline at end of file + PublishToMaestro: false + SignOutput: false + PublishPackage: false \ No newline at end of file diff --git a/build/WindowsAppSDK-Foundation-Release.yml b/build/WindowsAppSDK-Foundation-Release.yml index b8f74fe2f6..38f2caeeec 100644 --- a/build/WindowsAppSDK-Foundation-Release.yml +++ b/build/WindowsAppSDK-Foundation-Release.yml @@ -64,4 +64,5 @@ extends: parameters: PublishToMaestro: ${{ parameters.PublishToMaestro }} IgnoreFailures: ${{ parameters.IgnoreFailures }} - SignOutput: ${{ parameters.SignOutput }} \ No newline at end of file + SignOutput: ${{ parameters.SignOutput }} + PublishPackage: true \ No newline at end of file diff --git a/build/WindowsAppSDK-Versions.yml b/build/WindowsAppSDK-Versions.yml index faf7fe6fb3..2d35180d18 100644 --- a/build/WindowsAppSDK-Versions.yml +++ b/build/WindowsAppSDK-Versions.yml @@ -1,5 +1,5 @@ variables: # Version Control major: "1" - minor: "4" + minor: "5" patch: "0" diff --git a/dev/Common/AppModel.Identity.h b/dev/Common/AppModel.Identity.h index d975c4e82f..fa0f646b29 100644 --- a/dev/Common/AppModel.Identity.h +++ b/dev/Common/AppModel.Identity.h @@ -1,4 +1,4 @@ -// Copyright (c) Microsoft Corporation and Contributors. +// Copyright (c) Microsoft Corporation and Contributors. // Licensed under the MIT License. #ifndef __APPMODEL_IDENTITY_H @@ -6,6 +6,9 @@ #include +#include +#include + namespace AppModel::Identity { inline bool IsPackagedProcess() @@ -46,6 +49,34 @@ constexpr PCWSTR GetCurrentArchitectureAsString() #endif } +constexpr PCWSTR GetArchitectureAsString(const std::uint32_t architecture) +{ + switch (architecture) + { + case PROCESSOR_ARCHITECTURE_AMD64: return L"x64"; + case PROCESSOR_ARCHITECTURE_ARM: return L"arm"; + case PROCESSOR_ARCHITECTURE_ARM64: return L"arm64"; + case PROCESSOR_ARCHITECTURE_IA32_ON_ARM64: return L"x86onArm64"; + case PROCESSOR_ARCHITECTURE_INTEL: return L"x86"; + case PROCESSOR_ARCHITECTURE_NEUTRAL: return L"neutral"; + case PROCESSOR_ARCHITECTURE_UNKNOWN: return L"unknown"; + default: THROW_HR_MSG(E_UNEXPECTED, "Unknown architecture 0x%X", architecture); + } +} + +constexpr PCWSTR GetArchitectureAsString(const winrt::Windows::System::ProcessorArchitecture architecture) +{ + static_assert(static_cast(winrt::Windows::System::ProcessorArchitecture::Arm) == static_cast(PROCESSOR_ARCHITECTURE_ARM), "winrt::Windows::System::ProcessorArchitecture::Arm != PROCESSOR_ARCHITECTURE_ARM"); + static_assert(static_cast(winrt::Windows::System::ProcessorArchitecture::Arm64) == static_cast(PROCESSOR_ARCHITECTURE_ARM64), "winrt::Windows::System::ProcessorArchitecture::Arm64 != PROCESSOR_ARCHITECTURE_ARM64"); + static_assert(static_cast(winrt::Windows::System::ProcessorArchitecture::Neutral) == static_cast(PROCESSOR_ARCHITECTURE_NEUTRAL), "winrt::Windows::System::ProcessorArchitecture::Neutral != PROCESSOR_ARCHITECTURE_NEUTRAL"); + static_assert(static_cast(winrt::Windows::System::ProcessorArchitecture::Unknown) == static_cast(PROCESSOR_ARCHITECTURE_UNKNOWN), "winrt::Windows::System::ProcessorArchitecture::Unknown != PROCESSOR_ARCHITECTURE_UNKNOWN"); + static_assert(static_cast(winrt::Windows::System::ProcessorArchitecture::X64) == static_cast(PROCESSOR_ARCHITECTURE_AMD64), "winrt::Windows::System::ProcessorArchitecture::X64 != PROCESSOR_ARCHITECTURE_AMD64"); + static_assert(static_cast(winrt::Windows::System::ProcessorArchitecture::X86) == static_cast(PROCESSOR_ARCHITECTURE_INTEL), "winrt::Windows::System::ProcessorArchitecture::X86 != PROCESSOR_ARCHITECTURE_INTEL"); + static_assert(static_cast(winrt::Windows::System::ProcessorArchitecture::X86OnArm64) == static_cast(PROCESSOR_ARCHITECTURE_IA32_ON_ARM64), "winrt::Windows::System::ProcessorArchitecture::X86OnArm64 != PROCESSOR_ARCHITECTURE_IA32_ON_ARM64"); + + return GetArchitectureAsString(static_cast(architecture)); +} + inline winrt::Windows::System::ProcessorArchitecture ParseArchitecture(_In_ PCWSTR architecture) { if (CompareStringOrdinal(architecture, -1, L"x64", -1, TRUE) == CSTR_EQUAL) @@ -109,6 +140,109 @@ inline winrt::Windows::System::ProcessorArchitecture ParseShortArchitecture(_In_ } } +class PackageVersion : public PACKAGE_VERSION +{ +public: + PackageVersion(const PackageVersion&) = default; + + // Create an instance with the value `major.minor.build.revision`. + PackageVersion(std::uint16_t major, std::uint16_t minor = 0, std::uint16_t build = 0, std::uint16_t revision = 0) : + PACKAGE_VERSION() + { + Major = major; + Minor = minor; + Build = build; + Revision = revision; + } + + // Create an instance from a version as a uint64. + PackageVersion(std::uint64_t version = 0) + { + Version = version; + } + + template + PackageVersion(TVersion const& t) : + PackageVersion(t.Major, t.Minor, t.Build, t.Revision) + { + } + +#if defined(WINRT_Windows_ApplicationModel_2_H) + PackageVersion(winrt::Windows::ApplicationModel::PackageVersion packageVersion) : + PACKAGE_VERSION() + { + Major = packageVersion.Major; + Minor = packageVersion.Minor; + Build = packageVersion.Build; + Revision = packageVersion.Revision; + } +#endif // defined(WINRT_Windows_ApplicationModel_2_H) + + PackageVersion& operator=(const PackageVersion&) = default; + + // Return the version as a uint64. + std::uint64_t ToVersion() const + { + return Version; + } + +#if defined(____x_ABI_CWindows_CApplicationModel_CIPackageId_INTERFACE_DEFINED__) + ABI::Windows::ApplicationModel::PackageVersion ToPackageVersion() const + { + return ABI::Windows::ApplicationModel::PackageVersion{ Major, Minor, Build, Revision }; + } +#endif // defined(____x_ABI_CWindows_CApplicationModel_CIPackageId_INTERFACE_DEFINED__) + +#if defined(WINRT_Windows_ApplicationModel_2_H) + winrt::Windows::ApplicationModel::PackageVersion ToWinrtPackageVersion() const + { + return winrt::Windows::ApplicationModel::PackageVersion{ Major, Minor, Build, Revision }; + } +#endif // defined(WINRT_Windows_ApplicationModel_2_H) + +#if defined(_XSTRING_) + // Return the string as a formatted value "major.minor.build.revision". + std::wstring ToString() const + { + return ToString(Major, Minor, Build, Revision); + } + + static std::wstring ToString(std::uint16_t major, std::uint16_t minor, std::uint16_t build, std::uint16_t revision) + { +#if (__cplusplus >= 202002L) || (defined(_MSVC_LANG) && (_MSVC_LANG >= 202002L)) + return std::format(L"{}.{}.{}.{}", major, minor, build, revision); +#else + return std::to_wstring(major) + L"." + std::to_wstring(minor) + L"." + std::to_wstring(build) + L"." + std::to_wstring(revision); +#endif + } +#endif defined(_XSTRING_) +}; + +inline bool operator==(const PackageVersion& packageVersion1, const PackageVersion& packageVersion2) +{ + return packageVersion1.Version == packageVersion2.Version; +} +inline bool operator!=(const PackageVersion& packageVersion1, const PackageVersion& packageVersion2) +{ + return packageVersion1.Version != packageVersion2.Version; +} +inline bool operator<(const PackageVersion& packageVersion1, const PackageVersion& packageVersion2) +{ + return packageVersion1.Version < packageVersion2.Version; +} +inline bool operator<=(const PackageVersion& packageVersion1, const PackageVersion& packageVersion2) +{ + return packageVersion1.Version <= packageVersion2.Version; +} +inline bool operator>(const PackageVersion& packageVersion1, const PackageVersion& packageVersion2) +{ + return packageVersion1.Version > packageVersion2.Version; +} +inline bool operator>=(const PackageVersion& packageVersion1, const PackageVersion& packageVersion2) +{ + return packageVersion1.Version >= packageVersion2.Version; +} + inline bool IsValidVersionShortTag( const std::wstring& versionShortTag) { diff --git a/dev/Common/AppModel.Package.h b/dev/Common/AppModel.Package.h index 1dd596db3b..772091840a 100644 --- a/dev/Common/AppModel.Package.h +++ b/dev/Common/AppModel.Package.h @@ -1,4 +1,4 @@ -// Copyright (c) Microsoft Corporation and Contributors. +// Copyright (c) Microsoft Corporation and Contributors. // Licensed under the MIT License. #ifndef __APPMODEL_PACKAGE_H @@ -6,6 +6,8 @@ #include +#include + namespace AppModel::Package { /// Find all Main+Framework packages in a package family registered to the current user @@ -52,6 +54,31 @@ inline PACKAGE_VERSION ToPackageVersion(winrt::Windows::ApplicationModel::Packag to.Revision = from.Revision; return to; } + +inline std::tuple ParsePackageFullName(PCWSTR packageFullName) +{ + BYTE buffer[ + sizeof(PACKAGE_ID) + + sizeof(WCHAR) * (PACKAGE_NAME_MAX_LENGTH + 1) + + sizeof(WCHAR) * (PACKAGE_VERSION_MAX_LENGTH + 1) + + sizeof(WCHAR) * (PACKAGE_ARCHITECTURE_MAX_LENGTH + 1) + + sizeof(WCHAR) * (PACKAGE_RESOURCEID_MAX_LENGTH + 1) + + sizeof(WCHAR) * (PACKAGE_PUBLISHERID_MAX_LENGTH + 1)]{}; + UINT32 bufferLength{ ARRAYSIZE(buffer) }; + THROW_IF_WIN32_ERROR_MSG(::PackageIdFromFullName(packageFullName, PACKAGE_INFORMATION_BASIC, &bufferLength, buffer), "%ls", packageFullName); + const auto& packageId{ *reinterpret_cast(buffer) }; + + WCHAR packageFamilyName[PACKAGE_FAMILY_NAME_MAX_LENGTH + 1]{}; + UINT32 packageFamilyNameLength{ ARRAYSIZE(packageFamilyName) }; + THROW_IF_WIN32_ERROR_MSG(::PackageFamilyNameFromId(&packageId, &packageFamilyNameLength, packageFamilyName), "%ls", packageFullName); + + return { std::wstring(packageId.name), packageId.version, packageId.processorArchitecture, std::wstring(packageId.resourceId ? packageId.resourceId : L""), std::wstring(packageId.publisherId), std::wstring(packageFamilyName) }; +} + +inline std::tuple ParsePackageFullName(const std::wstring& packageFullName) +{ + return ParsePackageFullName(packageFullName.c_str()); +} } #endif // __APPMODEL_PACKAGE_H diff --git a/dev/Common/Common.vcxitems b/dev/Common/Common.vcxitems index e3bb682e8b..1de21b01e5 100644 --- a/dev/Common/Common.vcxitems +++ b/dev/Common/Common.vcxitems @@ -29,5 +29,6 @@ + \ No newline at end of file diff --git a/dev/Common/Common.vcxitems.filters b/dev/Common/Common.vcxitems.filters index 1fccf173f1..7a346b9426 100644 --- a/dev/Common/Common.vcxitems.filters +++ b/dev/Common/Common.vcxitems.filters @@ -41,6 +41,9 @@ Header Files + + Header Files + diff --git a/dev/Common/TerminalVelocityFeatures-PackageManager.h b/dev/Common/TerminalVelocityFeatures-PackageManager.h new file mode 100644 index 0000000000..99edf97bbd --- /dev/null +++ b/dev/Common/TerminalVelocityFeatures-PackageManager.h @@ -0,0 +1,32 @@ +// Copyright (c) Microsoft Corporation and Contributors. +// Licensed under the MIT License. + +// THIS FILE IS AUTOMATICALLY GENERATED; DO NOT EDIT IT + +// INPUT FILE: dev\common\TerminalVelocityFeatures-PackageManager.xml +// OPTIONS: -Channel Experimental -Language C++ -Namespace Microsoft.Windows.Management.Deployment -Path dev\common\TerminalVelocityFeatures-PackageManager.xml -Output dev\common\TerminalVelocityFeatures-PackageManager.h + +#if defined(__midlrt) +namespace features +{ + feature_name Feature_PackageManager = { DisabledByDefault, FALSE }; +} +#endif // defined(__midlrt) + +// Feature constants +#define WINDOWSAPPRUNTIME_MICROSOFT_WINDOWS_MANAGEMENT_DEPLOYMENT_FEATURE_PACKAGEMANAGER_ENABLED 1 + +#if defined(__cplusplus) + +namespace Microsoft::Windows::Management::Deployment +{ + +__pragma(detect_mismatch("ODR_violation_WINDOWSAPPRUNTIME_MICROSOFT_WINDOWS_MANAGEMENT_DEPLOYMENT_FEATURE_PACKAGEMANAGER_ENABLED_mismatch", "AlwaysEnabled")) +struct Feature_PackageManager +{ + static constexpr bool IsEnabled() { return WINDOWSAPPRUNTIME_MICROSOFT_WINDOWS_MANAGEMENT_DEPLOYMENT_FEATURE_PACKAGEMANAGER_ENABLED == 1; } +}; + +} // namespace Microsoft.Windows.Management.Deployment + +#endif // defined(__cplusplus) diff --git a/dev/Common/TerminalVelocityFeatures-PackageManager.xml b/dev/Common/TerminalVelocityFeatures-PackageManager.xml new file mode 100644 index 0000000000..932aa39394 --- /dev/null +++ b/dev/Common/TerminalVelocityFeatures-PackageManager.xml @@ -0,0 +1,20 @@ + + + + + + + + + + Feature_PackageManager + Package Management APIs + AlwaysEnabled + + Preview + Stable + + + diff --git a/dev/Common/winrt_WindowsAppRuntime.h b/dev/Common/winrt_WindowsAppRuntime.h new file mode 100644 index 0000000000..d986617997 --- /dev/null +++ b/dev/Common/winrt_WindowsAppRuntime.h @@ -0,0 +1,33 @@ +// Copyright (c) Microsoft Corporation and Contributors. +// Licensed under the MIT License. + +#ifndef __WINRT_WINDOWS_APP_RUNTIME_H +#define __WINRT_WINDOWS_APP_RUNTIME_H + +namespace winrt +{ + // Per https://docs.microsoft.com/windows/uwp/cpp-and-winrt-apis/interop-winrt-abi#convert_from_abi-function + template + T convert_from_abi(::IUnknown* from) + { + T to{ nullptr }; // `T` is a projected type. + + winrt::check_hresult(from->QueryInterface(winrt::guid_of(), + winrt::put_abi(to))); + + return to; + } + + template + T convert_from_abi(::IInspectable* from) + { + T to{ nullptr }; // `T` is a projected type. + + winrt::check_hresult(from->QueryInterface(winrt::guid_of(), + winrt::put_abi(to))); + + return to; + } +} + +#endif // __WINRT_WINDOWS_APP_RUNTIME_H \ No newline at end of file diff --git a/dev/DeploymentAgent/packages.config b/dev/DeploymentAgent/packages.config index 2305cb7181..9ba3aa91dd 100644 --- a/dev/DeploymentAgent/packages.config +++ b/dev/DeploymentAgent/packages.config @@ -1,5 +1,5 @@  - + diff --git a/dev/DynamicDependency/API/DataStore.cpp b/dev/DynamicDependency/API/DataStore.cpp index 50d18dfab9..65ba3a97e8 100644 --- a/dev/DynamicDependency/API/DataStore.cpp +++ b/dev/DynamicDependency/API/DataStore.cpp @@ -6,7 +6,7 @@ #include "DataStore.h" #include "DynamicDependencyDataStore_h.h" -#include "winrt_msixdynamicdependency.h" +#include "winrt_WindowsAppRuntime.h" #include diff --git a/dev/DynamicDependency/API/DynamicDependency.vcxitems b/dev/DynamicDependency/API/DynamicDependency.vcxitems index 091653b2b9..e5f3fa55ae 100644 --- a/dev/DynamicDependency/API/DynamicDependency.vcxitems +++ b/dev/DynamicDependency/API/DynamicDependency.vcxitems @@ -23,6 +23,7 @@ + @@ -46,6 +47,7 @@ + @@ -60,7 +62,6 @@ - @@ -70,6 +71,7 @@ + diff --git a/dev/DynamicDependency/API/DynamicDependency.vcxitems.filters b/dev/DynamicDependency/API/DynamicDependency.vcxitems.filters index 587277fc02..293f21384c 100644 --- a/dev/DynamicDependency/API/DynamicDependency.vcxitems.filters +++ b/dev/DynamicDependency/API/DynamicDependency.vcxitems.filters @@ -50,6 +50,9 @@ Source Files + + Source Files + Source Files @@ -127,6 +130,9 @@ Header Files + + Header Files + Header Files @@ -148,9 +154,6 @@ Header Files - - Header Files - diff --git a/dev/DynamicDependency/API/MddWin11.cpp b/dev/DynamicDependency/API/MddWin11.cpp new file mode 100644 index 0000000000..cca5dad052 --- /dev/null +++ b/dev/DynamicDependency/API/MddWin11.cpp @@ -0,0 +1,256 @@ +// Copyright (c) Microsoft Corporation and Contributors. +// Licensed under the MIT License. + +#include "pch.h" + +#include + +#include "MddWin11.h" + +namespace MddCore::Win11 +{ +static HMODULE g_dllApisetAppmodelRuntime_1_6{}; +static decltype(&::TryCreatePackageDependency) g_win11TryCreatePackageDependency{}; +static decltype(&::DeletePackageDependency) g_win11DeletePackageDependency{}; +static decltype(&::AddPackageDependency) g_win11AddPackageDependency{}; +static decltype(&::RemovePackageDependency) g_win11RemovePackageDependency{}; +static decltype(&::GetResolvedPackageFullNameForPackageDependency) g_win11GetResolvedPackageFullNameForPackageDependency{}; +static decltype(&::GetIdForPackageDependencyContext) g_win11GetIdForPackageDependencyContext{}; +static decltype(&::GetPackageGraphRevisionId) g_win11GetPackageGraphRevisionId{}; + +constexpr PackageDependencyLifetimeKind ToLifetimeKind(MddPackageDependencyLifetimeKind lifetimeKind) +{ + switch (lifetimeKind) + { + case MddPackageDependencyLifetimeKind::Process: return PackageDependencyLifetimeKind_Process; + case MddPackageDependencyLifetimeKind::FilePath: return PackageDependencyLifetimeKind_FilePath; + case MddPackageDependencyLifetimeKind::RegistryKey: return PackageDependencyLifetimeKind_RegistryKey; + default: THROW_HR_MSG(E_UNEXPECTED, "Unknown MddPackageDependencyLifetimeKind (%d)", lifetimeKind); + }; +} + +constexpr PackageDependencyLifetimeKind ToLifetimeKind(winrt::Microsoft::Windows::ApplicationModel::DynamicDependency::PackageDependencyLifetimeArtifactKind lifetimeKind) +{ + switch (lifetimeKind) + { + case winrt::Microsoft::Windows::ApplicationModel::DynamicDependency::PackageDependencyLifetimeArtifactKind::Process: return PackageDependencyLifetimeKind_Process; + case winrt::Microsoft::Windows::ApplicationModel::DynamicDependency::PackageDependencyLifetimeArtifactKind::FilePath: return PackageDependencyLifetimeKind_FilePath; + case winrt::Microsoft::Windows::ApplicationModel::DynamicDependency::PackageDependencyLifetimeArtifactKind::RegistryKey: return PackageDependencyLifetimeKind_RegistryKey; + default: THROW_HR_MSG(E_UNEXPECTED, "Unknown winrt::Microsoft::Windows::ApplicationModel::DynamicDependency::PackageDependencyLifetimeKind (%d)", lifetimeKind); + }; +} +} + +HRESULT WINAPI MddWin11Initialize() noexcept +{ + if (!MddCore::Win11::IsSupported()) + { + return S_OK; + } + + HMODULE dllApisetAppmodelRuntime_1_6{ LoadLibraryExW(L"api-ms-win-appmodel-runtime-l1-1-6.dll", nullptr, 0) }; + FAIL_FAST_HR_IF_NULL(HRESULT_FROM_WIN32(GetLastError()), dllApisetAppmodelRuntime_1_6); + + auto win11TryCreatePackageDependency{ GetProcAddressByFunctionDeclaration(dllApisetAppmodelRuntime_1_6, TryCreatePackageDependency) }; + RETURN_HR_IF_NULL(HRESULT_FROM_WIN32(GetLastError()), win11TryCreatePackageDependency); + auto win11DeletePackageDependency{ GetProcAddressByFunctionDeclaration(dllApisetAppmodelRuntime_1_6, DeletePackageDependency) }; + RETURN_HR_IF_NULL(HRESULT_FROM_WIN32(GetLastError()), win11DeletePackageDependency); + auto win11AddPackageDependency{ GetProcAddressByFunctionDeclaration(dllApisetAppmodelRuntime_1_6, AddPackageDependency) }; + RETURN_HR_IF_NULL(HRESULT_FROM_WIN32(GetLastError()), win11AddPackageDependency); + auto win11RemovePackageDependency{ GetProcAddressByFunctionDeclaration(dllApisetAppmodelRuntime_1_6, RemovePackageDependency) }; + RETURN_HR_IF_NULL(HRESULT_FROM_WIN32(GetLastError()), win11RemovePackageDependency); + auto win11GetResolvedPackageFullNameForPackageDependency{ GetProcAddressByFunctionDeclaration(dllApisetAppmodelRuntime_1_6, GetResolvedPackageFullNameForPackageDependency) }; + RETURN_HR_IF_NULL(HRESULT_FROM_WIN32(GetLastError()), win11GetResolvedPackageFullNameForPackageDependency); + auto win11GetIdForPackageDependencyContext{ GetProcAddressByFunctionDeclaration(dllApisetAppmodelRuntime_1_6, GetIdForPackageDependencyContext) }; + RETURN_HR_IF_NULL(HRESULT_FROM_WIN32(GetLastError()), win11GetIdForPackageDependencyContext); + auto win11GetPackageGraphRevisionId{ GetProcAddressByFunctionDeclaration(dllApisetAppmodelRuntime_1_6, GetPackageGraphRevisionId) }; + RETURN_HR_IF_NULL(HRESULT_FROM_WIN32(GetLastError()), win11GetPackageGraphRevisionId); + + MddCore::Win11::g_dllApisetAppmodelRuntime_1_6 = dllApisetAppmodelRuntime_1_6; + MddCore::Win11::g_win11TryCreatePackageDependency = win11TryCreatePackageDependency; + MddCore::Win11::g_win11DeletePackageDependency = win11DeletePackageDependency; + MddCore::Win11::g_win11AddPackageDependency = win11AddPackageDependency; + MddCore::Win11::g_win11RemovePackageDependency = win11RemovePackageDependency; + MddCore::Win11::g_win11GetResolvedPackageFullNameForPackageDependency = win11GetResolvedPackageFullNameForPackageDependency; + MddCore::Win11::g_win11GetIdForPackageDependencyContext = win11GetIdForPackageDependencyContext; + MddCore::Win11::g_win11GetPackageGraphRevisionId = win11GetPackageGraphRevisionId; + return S_OK; +} + +HRESULT WINAPI MddWin11Shutdown() noexcept +{ + if (MddCore::Win11::g_dllApisetAppmodelRuntime_1_6) + { + MddCore::Win11::g_win11TryCreatePackageDependency = nullptr; + MddCore::Win11::g_win11DeletePackageDependency = nullptr; + MddCore::Win11::g_win11AddPackageDependency = nullptr; + MddCore::Win11::g_win11RemovePackageDependency = nullptr; + MddCore::Win11::g_win11GetResolvedPackageFullNameForPackageDependency = nullptr; + MddCore::Win11::g_win11GetIdForPackageDependencyContext = nullptr; + MddCore::Win11::g_win11GetPackageGraphRevisionId = nullptr; + FreeLibrary(MddCore::Win11::g_dllApisetAppmodelRuntime_1_6); + MddCore::Win11::g_dllApisetAppmodelRuntime_1_6 = nullptr; + } + return S_OK; +} + +bool MddCore::Win11::IsSupported() +{ + static bool s_isSupported{ WindowsVersion::IsWindows11_22H2OrGreater() }; + return s_isSupported; +} + +HRESULT MddCore::Win11::TryCreatePackageDependency( + PSID user, + const winrt::hstring& packageFamilyName, + const winrt::Windows::ApplicationModel::PackageVersion& minVersion, + winrt::Microsoft::Windows::ApplicationModel::DynamicDependency::PackageDependencyProcessorArchitectures packageDependencyProcessorArchitectures, + winrt::Microsoft::Windows::ApplicationModel::DynamicDependency::CreatePackageDependencyOptions const& options, + _Outptr_result_maybenull_ PWSTR* packageDependencyId) +{ + PCWSTR win11PackageFamilyName{ packageFamilyName.c_str() }; + + const ::AppModel::Identity::PackageVersion minPackageVersion{ minVersion }; + const PACKAGE_VERSION win11MinVersion{ minPackageVersion }; + + auto win11PackageDependencyProcessorArchitectures{ PackageDependencyProcessorArchitectures_None }; + WI_SetFlagIf(win11PackageDependencyProcessorArchitectures, PackageDependencyProcessorArchitectures_Neutral, WI_IsFlagSet(packageDependencyProcessorArchitectures, winrt::Microsoft::Windows::ApplicationModel::DynamicDependency::PackageDependencyProcessorArchitectures::Neutral)); + WI_SetFlagIf(win11PackageDependencyProcessorArchitectures, PackageDependencyProcessorArchitectures_X86, WI_IsFlagSet(packageDependencyProcessorArchitectures, winrt::Microsoft::Windows::ApplicationModel::DynamicDependency::PackageDependencyProcessorArchitectures::X86)); + WI_SetFlagIf(win11PackageDependencyProcessorArchitectures, PackageDependencyProcessorArchitectures_X64, WI_IsFlagSet(packageDependencyProcessorArchitectures, winrt::Microsoft::Windows::ApplicationModel::DynamicDependency::PackageDependencyProcessorArchitectures::X64)); + WI_SetFlagIf(win11PackageDependencyProcessorArchitectures, PackageDependencyProcessorArchitectures_Arm, WI_IsFlagSet(packageDependencyProcessorArchitectures, winrt::Microsoft::Windows::ApplicationModel::DynamicDependency::PackageDependencyProcessorArchitectures::Arm)); + WI_SetFlagIf(win11PackageDependencyProcessorArchitectures, PackageDependencyProcessorArchitectures_Arm64, WI_IsFlagSet(packageDependencyProcessorArchitectures, winrt::Microsoft::Windows::ApplicationModel::DynamicDependency::PackageDependencyProcessorArchitectures::Arm64)); + WI_SetFlagIf(win11PackageDependencyProcessorArchitectures, PackageDependencyProcessorArchitectures_X86A64, WI_IsFlagSet(packageDependencyProcessorArchitectures, winrt::Microsoft::Windows::ApplicationModel::DynamicDependency::PackageDependencyProcessorArchitectures::X86OnArm64)); + + const auto win11LifetimeKind{ ToLifetimeKind(options.LifetimeArtifactKind()) }; + + PCWSTR win11LifetimeArtifact{ options.LifetimeArtifact().c_str() }; + + auto win11Options{ CreatePackageDependencyOptions_None }; + WI_SetFlagIf(win11Options, CreatePackageDependencyOptions_DoNotVerifyDependencyResolution, !options.VerifyDependencyResolution()); + //TODO CreatePackageDependencyOptions_ScopeIsSystem + + RETURN_IF_FAILED(g_win11TryCreatePackageDependency(user, win11PackageFamilyName, win11MinVersion, + win11PackageDependencyProcessorArchitectures, win11LifetimeKind, win11LifetimeArtifact, + win11Options, packageDependencyId)); + return S_OK; +} + +HRESULT MddCore::Win11::TryCreatePackageDependency( + PSID user, + _In_ PCWSTR packageFamilyName, + PACKAGE_VERSION minVersion, + MddPackageDependencyProcessorArchitectures packageDependencyProcessorArchitectures, + MddPackageDependencyLifetimeKind lifetimeKind, + PCWSTR lifetimeArtifact, + MddCreatePackageDependencyOptions options, + _Outptr_result_maybenull_ PWSTR* packageDependencyId) +{ + const ::AppModel::Identity::PackageVersion win11MinVersion{ minVersion }; + + auto win11PackageDependencyProcessorArchitectures{ PackageDependencyProcessorArchitectures_None }; + WI_SetFlagIf(win11PackageDependencyProcessorArchitectures, PackageDependencyProcessorArchitectures_Neutral, WI_IsFlagSet(packageDependencyProcessorArchitectures, MddPackageDependencyProcessorArchitectures::Neutral)); + WI_SetFlagIf(win11PackageDependencyProcessorArchitectures, PackageDependencyProcessorArchitectures_X86, WI_IsFlagSet(packageDependencyProcessorArchitectures, MddPackageDependencyProcessorArchitectures::X86)); + WI_SetFlagIf(win11PackageDependencyProcessorArchitectures, PackageDependencyProcessorArchitectures_X64, WI_IsFlagSet(packageDependencyProcessorArchitectures, MddPackageDependencyProcessorArchitectures::X64)); + WI_SetFlagIf(win11PackageDependencyProcessorArchitectures, PackageDependencyProcessorArchitectures_Arm, WI_IsFlagSet(packageDependencyProcessorArchitectures, MddPackageDependencyProcessorArchitectures::Arm)); + WI_SetFlagIf(win11PackageDependencyProcessorArchitectures, PackageDependencyProcessorArchitectures_Arm64, WI_IsFlagSet(packageDependencyProcessorArchitectures, MddPackageDependencyProcessorArchitectures::Arm64)); + WI_SetFlagIf(win11PackageDependencyProcessorArchitectures, PackageDependencyProcessorArchitectures_X86A64, WI_IsFlagSet(packageDependencyProcessorArchitectures, MddPackageDependencyProcessorArchitectures::X86OnArm64)); + + const auto win11LifetimeKind{ ToLifetimeKind(lifetimeKind) }; + + auto win11Options{ CreatePackageDependencyOptions_None }; + WI_SetFlagIf(win11Options, CreatePackageDependencyOptions_DoNotVerifyDependencyResolution, WI_IsFlagSet(options, MddCreatePackageDependencyOptions::DoNotVerifyDependencyResolution)); + WI_SetFlagIf(win11Options, CreatePackageDependencyOptions_ScopeIsSystem, WI_IsFlagSet(options, MddCreatePackageDependencyOptions::ScopeIsSystem)); + + RETURN_IF_FAILED(g_win11TryCreatePackageDependency(user, packageFamilyName, win11MinVersion, + win11PackageDependencyProcessorArchitectures, win11LifetimeKind, lifetimeArtifact, + win11Options, packageDependencyId)); + return S_OK; +} + +void MddCore::Win11::DeletePackageDependency( + const winrt::hstring& packageDependencyId) +{ + DeletePackageDependency(packageDependencyId.c_str()); +} + +void MddCore::Win11::DeletePackageDependency( + _In_ PCWSTR packageDependencyId) +{ + (void)LOG_IF_FAILED(g_win11DeletePackageDependency(packageDependencyId)); +} + +HRESULT MddCore::Win11::AddPackageDependency( + const winrt::hstring& packageDependencyId, + winrt::Microsoft::Windows::ApplicationModel::DynamicDependency::AddPackageDependencyOptions const& options, + _Out_ MDD_PACKAGEDEPENDENCY_CONTEXT* packageDependencyContext, + _Outptr_opt_result_maybenull_ PWSTR* packageFullName) +{ + PCWSTR win11PackageDependencyId{ packageDependencyId.c_str() }; + + const auto win11Rank{ options.Rank() }; + + auto win11Options{ AddPackageDependencyOptions_None }; + WI_SetFlagIf(win11Options, AddPackageDependencyOptions_PrependIfRankCollision, options.PrependIfRankCollision()); + + static_assert(sizeof(MDD_PACKAGEDEPENDENCY_CONTEXT) == sizeof(PACKAGEDEPENDENCY_CONTEXT)); + auto win11PackageDependencyContext{ reinterpret_cast(packageDependencyContext) }; + + RETURN_IF_FAILED(g_win11AddPackageDependency(win11PackageDependencyId, win11Rank, win11Options, win11PackageDependencyContext, packageFullName)); + return S_OK; +} + +HRESULT MddCore::Win11::AddPackageDependency( + _In_ PCWSTR packageDependencyId, + INT32 rank, + MddAddPackageDependencyOptions options, + _Out_ MDD_PACKAGEDEPENDENCY_CONTEXT* packageDependencyContext, + _Outptr_opt_result_maybenull_ PWSTR* packageFullName) +{ + auto win11Options{ AddPackageDependencyOptions_None }; + WI_SetFlagIf(win11Options, AddPackageDependencyOptions_PrependIfRankCollision, WI_IsFlagSet(options, MddAddPackageDependencyOptions::PrependIfRankCollision)); + + static_assert(sizeof(MDD_PACKAGEDEPENDENCY_CONTEXT) == sizeof(PACKAGEDEPENDENCY_CONTEXT)); + auto win11PackageDependencyContext{ reinterpret_cast(packageDependencyContext) }; + + RETURN_IF_FAILED(g_win11AddPackageDependency(packageDependencyId, rank, win11Options, win11PackageDependencyContext, packageFullName)); + return S_OK; +} + +void MddCore::Win11::RemovePackageDependency( + winrt::Microsoft::Windows::ApplicationModel::DynamicDependency::PackageDependencyContextId packageDependencyContextId) +{ + return RemovePackageDependency(ToContext(packageDependencyContextId)); +} + +void MddCore::Win11::RemovePackageDependency( + _In_ MDD_PACKAGEDEPENDENCY_CONTEXT packageDependencyContext) +{ + static_assert(sizeof(MDD_PACKAGEDEPENDENCY_CONTEXT) == sizeof(PACKAGEDEPENDENCY_CONTEXT)); + auto win11PackageDependencyContext{ reinterpret_cast(packageDependencyContext) }; + + g_win11RemovePackageDependency(win11PackageDependencyContext); +} + +HRESULT MddCore::Win11::GetResolvedPackageFullNameForPackageDependency( + _In_ PCWSTR packageDependencyId, + _Outptr_result_maybenull_ PWSTR* packageFullName) +{ + RETURN_IF_FAILED(g_win11GetResolvedPackageFullNameForPackageDependency(packageDependencyId, packageFullName)); + return S_OK; +} + +HRESULT MddCore::Win11::GetIdForPackageDependencyContext( + _In_ MDD_PACKAGEDEPENDENCY_CONTEXT packageDependencyContext, + _Outptr_result_maybenull_ PWSTR* packageDependencyId) +{ + static_assert(sizeof(MDD_PACKAGEDEPENDENCY_CONTEXT) == sizeof(PACKAGEDEPENDENCY_CONTEXT)); + auto win11PackageDependencyContext{ reinterpret_cast(packageDependencyContext) }; + + RETURN_IF_FAILED(g_win11GetIdForPackageDependencyContext(win11PackageDependencyContext, packageDependencyId)); + return S_OK; +} + +UINT32 MddCore::Win11::GetPackageGraphRevisionId() +{ + return g_win11GetPackageGraphRevisionId(); +} diff --git a/dev/DynamicDependency/API/MddWin11.h b/dev/DynamicDependency/API/MddWin11.h new file mode 100644 index 0000000000..8b0f6bef92 --- /dev/null +++ b/dev/DynamicDependency/API/MddWin11.h @@ -0,0 +1,82 @@ +// Copyright (c) Microsoft Corporation and Contributors. +// Licensed under the MIT License. + +#if !defined(MDDWIN11DYNAMICDEPENDENCY_H) +#define MDDWIN11DYNAMICDEPENDENCY_H + +#include +#include + +HRESULT WINAPI MddWin11Initialize() noexcept; + +HRESULT WINAPI MddWin11Shutdown() noexcept; + +namespace MddCore::Win11 +{ +bool IsSupported(); + +HRESULT TryCreatePackageDependency( + PSID user, + const winrt::hstring& packageFamilyName, + const winrt::Windows::ApplicationModel::PackageVersion& minVersion, + winrt::Microsoft::Windows::ApplicationModel::DynamicDependency::PackageDependencyProcessorArchitectures packageDependencyProcessorArchitectures, + winrt::Microsoft::Windows::ApplicationModel::DynamicDependency::CreatePackageDependencyOptions const& options, + _Outptr_result_maybenull_ PWSTR* packageDependencyId); + +HRESULT TryCreatePackageDependency( + PSID user, + _In_ PCWSTR packageFamilyName, + PACKAGE_VERSION minVersion, + MddPackageDependencyProcessorArchitectures packageDependencyProcessorArchitectures, + MddPackageDependencyLifetimeKind lifetimeKind, + PCWSTR lifetimeArtifact, + MddCreatePackageDependencyOptions options, + _Outptr_result_maybenull_ PWSTR* packageDependencyId); + +void DeletePackageDependency( + const winrt::hstring& packageDependencyId); + +void DeletePackageDependency( + _In_ PCWSTR packageDependencyId); + +HRESULT AddPackageDependency( + const winrt::hstring& packageDependencyId, + winrt::Microsoft::Windows::ApplicationModel::DynamicDependency::AddPackageDependencyOptions const& options, + _Out_ MDD_PACKAGEDEPENDENCY_CONTEXT* packageDependencyContext, + _Outptr_opt_result_maybenull_ PWSTR* packageFullName); + +HRESULT AddPackageDependency( + _In_ PCWSTR packageDependencyId, + std::int32_t rank, + MddAddPackageDependencyOptions options, + _Out_ MDD_PACKAGEDEPENDENCY_CONTEXT* packageDependencyContext, + _Outptr_opt_result_maybenull_ PWSTR* packageFullName); + +void RemovePackageDependency( + winrt::Microsoft::Windows::ApplicationModel::DynamicDependency::PackageDependencyContextId packageDependencyContextId); + +void RemovePackageDependency( + _In_ MDD_PACKAGEDEPENDENCY_CONTEXT packageDependencyContext); + +HRESULT GetResolvedPackageFullNameForPackageDependency( + _In_ PCWSTR packageDependencyId, + _Outptr_result_maybenull_ PWSTR* packageFullName); + +HRESULT GetIdForPackageDependencyContext( + _In_ MDD_PACKAGEDEPENDENCY_CONTEXT packageDependencyContext, + _Outptr_result_maybenull_ PWSTR* packageDependencyId); + +UINT32 GetPackageGraphRevisionId(); + +inline winrt::Microsoft::Windows::ApplicationModel::DynamicDependency::PackageDependencyContextId ToContextId(MDD_PACKAGEDEPENDENCY_CONTEXT context) +{ + return winrt::Microsoft::Windows::ApplicationModel::DynamicDependency::PackageDependencyContextId{ static_cast(reinterpret_cast(context)) }; +} + +inline MDD_PACKAGEDEPENDENCY_CONTEXT ToContext(winrt::Microsoft::Windows::ApplicationModel::DynamicDependency::PackageDependencyContextId contextId) +{ + return reinterpret_cast(static_cast(contextId.Id)); +} +} + +#endif // MDDWIN11DYNAMICDEPENDENCY_H diff --git a/dev/DynamicDependency/API/winrt_msixdynamicdependency.h b/dev/DynamicDependency/API/winrt_msixdynamicdependency.h deleted file mode 100644 index 394d6022dc..0000000000 --- a/dev/DynamicDependency/API/winrt_msixdynamicdependency.h +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright (c) Microsoft Corporation and Contributors. -// Licensed under the MIT License. - -#pragma once - -namespace winrt -{ - // Per https://docs.microsoft.com/windows/uwp/cpp-and-winrt-apis/interop-winrt-abi#convert_from_abi-function - template - T convert_from_abi(::IUnknown* from) - { - T to{ nullptr }; // `T` is a projected type. - - winrt::check_hresult(from->QueryInterface(winrt::guid_of(), - winrt::put_abi(to))); - - return to; - } -} diff --git a/dev/DynamicDependency/Powershell/Add-PackageDependency.ps1 b/dev/DynamicDependency/Powershell/Add-PackageDependency.ps1 new file mode 100644 index 0000000000..2360e510a4 --- /dev/null +++ b/dev/DynamicDependency/Powershell/Add-PackageDependency.ps1 @@ -0,0 +1,71 @@ +# Copyright (c) Microsoft Corporation and Contributors. +# Licensed under the MIT License. + +<# +.SYNOPSIS + Add to the current process' package graph. + +.DESCRIPTION + Add a run-time reference for the package dependency created earlier via + the TryCreate-PackageDependency cmdlet, with the specified options. After + successful completion you can use content from the package. + +.PARAMETER PackageDependencyId + ID of the package dependency to be resolved and added to the invoking + process' package graph. This parameter must match a package dependency + defined by the TryCreate-PackageDependency cmdlet for the calling + user or the system (via the TryCreate-PackageDependencyOptions -ScopeIsSystem option). + +.PARAMETER Rank + The rank to add the resolved package to the caller's package graph. + For more information, see https://learn.microsoft.com/windows/win32/api/appmodel/nf-appmodel-addpackagedependency#remarks + +.PARAMETER PrependIfRankCollision + If multiple packages are present in the package graph with the same rank, + the resolved package is added before others of the same rank. For more + information, see https://learn.microsoft.com/windows/win32/api/appmodel/ne-appmodel-addpackagedependencyoptions + +.LINK + https://learn.microsoft.com/windows/win32/api/appmodel/nf-appmodel-addpackagedependency +#> +[CmdletBinding(SupportsShouldProcess=$true)] +param( + [Parameter(Mandatory=$true)] + [string]$PackageDependencyId, + + [int]$Rank=0, + + [switch]$PrependIfRankCollision +) + +Set-StrictMode -Version 3.0 + +$ErrorActionPreference = "Stop" + +# Import the MSIX Dynamic Dependency module +if (-not (Get-Module | Where-Object {$_.Name -eq 'MsixDynamicDependency'})) +{ + $module = Join-Path $PSScriptRoot 'MsixDynamicDependency.psm1' + Import-Module -Name $module -ErrorAction Stop +} + +$options = [Microsoft.Windows.ApplicationModel.DynamicDependency.AddPackageDependencyOptions]::None +if ($PrependIfRankCollision -eq $true) +{ + $options = $options -bor [Microsoft.Windows.ApplicationModel.DynamicDependency.AddPackageDependencyOptions]::PrependIfRankCollision +} + +$packageDependencyContext = [IntPtr]0 +$packageFullName = "" +$hr = [Microsoft.Windows.ApplicationModel.DynamicDependency.PackageDependency]::Add( + $PackageDependencyId, $Rank, $options, [ref] $packageDependencyContext, [ref] $packageFullName) +if ($hr -lt 0) +{ + $win32ex = [System.ComponentModel.Win32Exception]::new($hr) + Write-Error "Error 0x$($hr.ToString('X')): $($win32ex.Message)" -ErrorAction Stop +} + +$o = New-Object System.Object +$o | Add-Member -type NoteProperty -name "PackageDependencyContext" -value $packageDependencyContext +$o | Add-Member -type NoteProperty -name "PackageFullName" -value $packageFullName +$o diff --git a/dev/DynamicDependency/Powershell/Delete-PackageDependency.ps1 b/dev/DynamicDependency/Powershell/Delete-PackageDependency.ps1 new file mode 100644 index 0000000000..d52bdaafde --- /dev/null +++ b/dev/DynamicDependency/Powershell/Delete-PackageDependency.ps1 @@ -0,0 +1,36 @@ +# Copyright (c) Microsoft Corporation and Contributors. +# Licensed under the MIT License. + +<# +.SYNOPSIS + Delete the package dependency. + +.PARAMETER + The ID of the package dependency to remove. + +.LINK + https://learn.microsoft.com/windows/win32/api/appmodel/nf-appmodel-deletepackagedependency +#> +[CmdletBinding(SupportsShouldProcess=$true)] +param( + [Parameter(Mandatory=$true)] + [string]$PackageDependencyId +) + +Set-StrictMode -Version 3.0 + +$ErrorActionPreference = "Stop" + +# Import the MSIX Dynamic Dependency module +if (-not (Get-Module | Where-Object {$_.Name -eq 'MsixDynamicDependency'})) +{ + $module = Join-Path $PSScriptRoot 'MsixDynamicDependency.psm1' + Import-Module -Name $module -ErrorAction Stop +} + +$hr = [Microsoft.Windows.ApplicationModel.DynamicDependency.PackageDependency]::Delete($PackageDependencyId) +if ($hr -lt 0) +{ + $win32ex = [System.ComponentModel.Win32Exception]::new($hr) + Write-Error "Error 0x$($hr.ToString('X')): $($win32ex.Message)" -ErrorAction Stop +} diff --git a/dev/DynamicDependency/Powershell/Get-PackageDependencyIdForContext.ps1 b/dev/DynamicDependency/Powershell/Get-PackageDependencyIdForContext.ps1 new file mode 100644 index 0000000000..b5670630b2 --- /dev/null +++ b/dev/DynamicDependency/Powershell/Get-PackageDependencyIdForContext.ps1 @@ -0,0 +1,40 @@ +# Copyright (c) Microsoft Corporation and Contributors. +# Licensed under the MIT License. + +<# +.SYNOPSIS + Return the package dependency for the specified context handle. + +.PARAMETER PackageDependencyContext + The handle of the package dependency. + +.LINK + https://learn.microsoft.com/windows/win32/api/appmodel/nf-appmodel-getidforpackagedependencycontext +#> +[CmdletBinding(SupportsShouldProcess=$true)] +param( + [Parameter(Mandatory=$true)] + [int64]$PackageDependencyContext +) + +Set-StrictMode -Version 3.0 + +$ErrorActionPreference = "Stop" + +# Import the MSIX Dynamic Dependency module +if (-not (Get-Module | Where-Object {$_.Name -eq 'MsixDynamicDependency'})) +{ + $module = Join-Path $PSScriptRoot 'MsixDynamicDependency.psm1' + Import-Module -Name $module -ErrorAction Stop +} + +$packageDependencyId = "" +$hr = [Microsoft.Windows.ApplicationModel.DynamicDependency.PackageDependency]::GetIdForContext( + $PackageDependencyContext, [ref] $packageDependencyId) +if ($hr -lt 0) +{ + $win32ex = [System.ComponentModel.Win32Exception]::new($hr) + Write-Error "Error 0x$($hr.ToString('X')): $($win32ex.Message)" -ErrorAction Stop +} + +$packageDependencyId diff --git a/dev/DynamicDependency/Powershell/Get-PackageDependencyResolved.ps1 b/dev/DynamicDependency/Powershell/Get-PackageDependencyResolved.ps1 new file mode 100644 index 0000000000..c0d8ceb32e --- /dev/null +++ b/dev/DynamicDependency/Powershell/Get-PackageDependencyResolved.ps1 @@ -0,0 +1,46 @@ +# Copyright (c) Microsoft Corporation and Contributors. +# Licensed under the MIT License. + +<# +.SYNOPSIS + Return the package full name if the package dependency is resolved. + +.DESCRIPTION + Return the package full name that would be used if the package dependency + were to be resolved. + + This does not add the package to the invoking process' package graph. + +.PARAMETER PackageDependencyId + The ID of the resolved package dependency. + +.LINK + https://learn.microsoft.com/windows/win32/api/appmodel/nf-appmodel-getresolvedpackagefullnameforpackagedependency +#> +[CmdletBinding(SupportsShouldProcess=$true)] +param( + [Parameter(Mandatory=$true)] + [string]$PackageDependencyId +) + +Set-StrictMode -Version 3.0 + +$ErrorActionPreference = "Stop" + +# Import the MSIX Dynamic Dependency module +if (-not (Get-Module | Where-Object {$_.Name -eq 'MsixDynamicDependency'})) +{ + $module = Join-Path $PSScriptRoot 'MsixDynamicDependency.psm1' + Import-Module -Name $module -ErrorAction Stop +} + +$packageFullName = "" +$hr = [Microsoft.Windows.ApplicationModel.DynamicDependency.PackageDependency]::GetResolvedPackageFullName( + $PackageDependencyId, [ref] $packageFullName) +if ($hr -lt 0) +{ + $win32ex = [System.ComponentModel.Win32Exception]::new($hr) + Write-Error "Error 0x$($hr.ToString('X')): $($win32ex.Message)" -ErrorAction Stop +} + +$packageFullName diff --git a/dev/DynamicDependency/Powershell/Get-PackageGraphRevisionId.ps1 b/dev/DynamicDependency/Powershell/Get-PackageGraphRevisionId.ps1 new file mode 100644 index 0000000000..a9bb8fcffe --- /dev/null +++ b/dev/DynamicDependency/Powershell/Get-PackageGraphRevisionId.ps1 @@ -0,0 +1,23 @@ +# Copyright (c) Microsoft Corporation and Contributors. +# Licensed under the MIT License. + +<# +.SYNOPSIS +TODO +#> +[CmdletBinding(SupportsShouldProcess=$true)] +param( +) + +Set-StrictMode -Version 3.0 + +$ErrorActionPreference = "Stop" + +# Import the MSIX Dynamic Dependency module +if (-not (Get-Module | Where-Object {$_.Name -eq 'MsixDynamicDependency'})) +{ + $module = Join-Path $PSScriptRoot 'MsixDynamicDependency.psm1' + Import-Module -Name $module -ErrorAction Stop +} + +[Microsoft.Windows.ApplicationModel.DynamicDependency.PackageGraph]::RevisionId diff --git a/dev/DynamicDependency/Powershell/MsixDynamicDependency.psm1 b/dev/DynamicDependency/Powershell/MsixDynamicDependency.psm1 new file mode 100644 index 0000000000..2590b6c6f2 --- /dev/null +++ b/dev/DynamicDependency/Powershell/MsixDynamicDependency.psm1 @@ -0,0 +1,341 @@ +# Copyright (c) Microsoft Corporation and Contributors. +# Licensed under the MIT License. + +<# +.SYNOPSIS +Functions to use Windows' Dynamic Dependency API. + +.DESCRIPTION +TBD + +.INPUTS +None + +.OUTPUTS +None + +.NOTES + Version : 0.1.0 +#> + +Add-Type -TypeDefinition @" +using System; +using System.Runtime.InteropServices; + +namespace Microsoft.Windows.ApplicationModel.DynamicDependency +{ + public enum CreatePackageDependencyOptions + { + None = 0, + + // Disable dependency resolution when pinning a package dependency. + DoNotVerifyDependencyResolution = 0x00000001, + + // Define the package dependency for the system, accessible to all users + // (default is the package dependency is defined for a specific user). + // This option requires the caller has adminitrative privileges. + ScopeIsSystem = 0x00000002, + } + + public enum PackageDependencyLifetimeKind + { + // The current process is the lifetime artifact. The package dependency + // is implicitly deleted when the process terminates. + Process = 0, + + // The lifetime artifact is an absolute filename or path. + // The package dependency is implicitly deleted when this is deleted. + FilePath = 1, + + // The lifetime artifact is a registry key in the format + // 'root\\subkey' where root is one of the following: HKLM, HKCU, HKCR, HKU. + // The package dependency is implicitly deleted when this is deleted. + RegistryKey = 2, + } + + public enum AddPackageDependencyOptions + { + None = 0, + PrependIfRankCollision = 0x00000001, + }; + + public class Rank + { + public const int Default = 0; + } + + public enum PackageDependencyProcessorArchitectures + { + None = 0, + Neutral = 0x00000001, + X86 = 0x00000002, + X64 = 0x00000004, + Arm = 0x00000008, + Arm64 = 0x00000010, + X86A64 = 0x00000020, + }; + + public class PackageDependency + { + [DllImport("kernelbase.dll", EntryPoint="GetProcessHeap", ExactSpelling=true, SetLastError=true)] + public static extern IntPtr kernel32_GetProcessHeap(); + + [DllImport("kernelbase.dll", EntryPoint="HeapFree", ExactSpelling=true, SetLastError=true)] + private static extern bool kernel32_HeapFree(IntPtr hHeap, uint dwFlags, IntPtr lpMem); + + private static bool HeapFree(IntPtr p) + { + return kernel32_HeapFree(kernel32_GetProcessHeap(), 0, p); + } + + // Define a package dependency. The criteria for a PackageDependency + // (package family name, minimum version, etc) + // may match multiple packages, but ensures Deployment won't remove + // a package if it's the only one satisfying the PackageDependency. + // + // @note A package matching a PackageDependency pin can still be removed + // as long as there's another package that satisfies the PackageDependency. + // For example, if Fwk-v1 is installed and a PackageDependency specifies + // MinVersion=1 and then Fwk-v2 is installed, Deployment could remove + // Fwk-v1 because Fwk-v2 will satisfy the PackageDependency. After Fwk-v1 + // is removed Deployment won't remove Fwk-v2 because it's the only package + // satisfying the PackageDependency. Thus Fwk-v1 and Fwk-v2 (and any other + // package matching the PackageDependency) are 'loosely pinned'. Deployment + // guarantees it won't remove a package if it would make a PackageDependency + // unsatisfied. + // + // A PackageDependency specifies criteria (package family, minimum version, etc) + // and not a specific package. Deployment reserves the right to use a different + // package (e.g. higher version) to satisfy the PackageDependency if/when + // one becomes available. + // + // @param user the user scope of the package dependency. If NULL the caller's + // user context is used. MUST be NULL if CreatePackageDependencyOptions_ScopeIsSystem + // is specified + // @param lifetimeArtifact MUST be NULL if lifetimeKind=Process + // @param packageDependencyId allocated via HeapAlloc; use HeapFree to deallocate + // + // @note TryCreatePackageDependency() fails if the PackageDependency cannot be resolved to a specific + // package. This package resolution check is skipped if + // CreatePackageDependencyOptions_DoNotVerifyDependencyResolution is specified. This is useful + // for installers running as user contexts other than the target user (e.g. installers + // running as LocalSystem). + [DllImport("kernelbase.dll", ExactSpelling=true, CharSet=CharSet.Unicode)] + private static extern int TryCreatePackageDependency( + /*PSID*/ IntPtr user, + string packageFamilyName, + /*PACKAGE_VERSION*/ long minVersion, + /*PackageDependencyProcessorArchitectures*/ int packageDependencyProcessorArchitectures, + /*PackageDependencyLifetimeKind*/ int lifetimeKind, + string lifetimeArtifact, + /*CreatePackageDependencyOptions*/ int options, + /*_Outptr_result_maybenull_ PWSTR* */ out IntPtr packageDependencyId); + + public static int TryCreate( + string packageFamilyName, + long minVersion, + /*PackageDependencyProcessorArchitectures*/ int packageDependencyProcessorArchitectures, + /*PackageDependencyLifetimeKind*/ int lifetimeKind, + string lifetimeArtifact, + /*CreatePackageDependencyOptions*/ int options, + /*_Outptr_result_maybenull_ PWSTR* */ out string packageDependencyId) + { + packageDependencyId = null; + + IntPtr pdi = IntPtr.Zero; + int hr = TryCreatePackageDependency(IntPtr.Zero, packageFamilyName, minVersion, packageDependencyProcessorArchitectures, + lifetimeKind, lifetimeArtifact, options, out pdi); + if (hr >= 0) + { + packageDependencyId = Marshal.PtrToStringUni(pdi); + } + if (pdi != IntPtr.Zero) + { + HeapFree(pdi); + } + return hr; + } + + // Undefine a package dependency. Removing a pin on a PackageDependency is typically done at uninstall-time. + // This implicitly occurs if the package dependency's 'lifetime artifact' (specified via TryCreatePackageDependency) + // is deleted. Packages that are not referenced by other packages and have no pins are elegible to be removed. + // + // @warn DeletePackageDependency() requires the caller have administrative privileges + // if the package dependency was pinned with CreatePackageDependencyOptions_ScopeIsSystem. + [DllImport("kernelbase.dll", ExactSpelling=true, CharSet=CharSet.Unicode)] + private static extern int DeletePackageDependency( + string packageDependencyId); + + public static int Delete( + string packageDependencyId) + { + return DeletePackageDependency(packageDependencyId); + } + + // Resolve a previously-pinned PackageDependency to a specific package and + // add it to the invoking process' package graph. Once the dependency has + // been added other code-loading methods (LoadLibrary, CoCreateInstance, etc) + // can find the binaries in the resolved package. + // + // Package resolution is specific to a user and can return different values + // for different users on a system. + // + // Each successful AddPackageDependency() adds the resolve packaged to the + // calling process' package graph, even if already present. There is no + // duplicate 'detection' or 'filtering' applied by the API (multiple + // references from a package is not harmful). Once resolution is complete + // the package dependency stays resolved for that user until the last reference across + // all processes for that user is removed via RemovePackageDependency (or + // process termination). + // + // AddPackageDependency() adds the resolved package to the caller's package graph, + // per the rank specified. A process' package graph is a list of packages sorted by + // rank in ascending order (-infinity...0...+infinity). If package(s) are present in the + // package graph with the same rank as the call to AddPackageDependency the resolved + // package is (by default) added after others of the same rank. To add a package + // before others of the same rank, specify AddPackageDependencyOptions_PrependIfRankCollision. + // + // Every AddPackageDependency can be balanced by a RemovePackageDependency + // to remove the entry from the package graph. If the process terminates all package + // references are removed, but any pins stay behind. + // + // AddPackageDependency adds the resolved package to the process' package + // graph, per the rank and options parameters. The process' package + // graph is used to search for DLLs (per Dynamic-Link Library Search Order), + // WinRT objects and other resources; the caller can now load DLLs, activate + // WinRT objects and use other resources from the framework package until + // RemovePackageDependency is called. The packageDependencyId parameter + // must match a package dependency defined for the calling user or the + // system (i.e. pinned with CreatePackageDependencyOptions_ScopeIsSystem) else + // an error is returned. + // + // @param packageDependencyContext valid until passed to RemovePackageDependency() + // @param packageFullName allocated via HeapAlloc; use HeapFree to deallocate + [DllImport("kernelbase.dll", ExactSpelling=true, CharSet=CharSet.Unicode)] + private static extern int AddPackageDependency( + string packageDependencyId, + int rank, + /*AddPackageDependencyOptions*/ int options, + /*_Out_ PACKAGEDEPENDENCY_CONTEXT* */ out IntPtr packageDependencyContext, + /*_Outptr_opt_result_maybenull_ PWSTR* */ out IntPtr packageFullName); + + public static int Add( + string packageDependencyId, + int rank, + /*AddPackageDependencyOptions*/ int options, + /*_Out_ PACKAGEDEPENDENCY_CONTEXT* */ out IntPtr packageDependencyContext, + out string packageFullName) + { + packageDependencyContext = IntPtr.Zero; + packageFullName = null; + + IntPtr pdc = IntPtr.Zero; + IntPtr pfn = IntPtr.Zero; + int hr = AddPackageDependency(packageDependencyId, rank, options, out pdc, out pfn); + if (hr >= 0) + { + packageDependencyContext = pdc; + packageFullName = Marshal.PtrToStringUni(pfn); + } + if (pfn != IntPtr.Zero) + { + HeapFree(pfn); + } + return hr; + } + + // Remove a resolved PackageDependency from the current process' package graph + // (i.e. undo AddPackageDependency). Used at runtime (i.e. the moral equivalent + // of Windows' RemoveDllDirectory()). + // + // @note This does not unload loaded resources (DLLs etc). After removing + // a package dependency any files loaded from the package can continue + // to be used; future file resolution will fail to see the removed + // package dependency. + [DllImport("kernelbase.dll", ExactSpelling=true, CharSet=CharSet.Unicode)] + private static extern int RemovePackageDependency( + /*PACKAGEDEPENDENCY_CONTEXT*/ IntPtr packageDependencyContext); + + public static int Remove( + IntPtr packageDependencyContext) + { + return RemovePackageDependency(packageDependencyContext); + } + + // Return the package full name that would be used if the + // PackageDependency were to be resolved. Does not add the + // package to the process graph. + // + // @param packageFullName allocated via HeapAlloc; use HeapFree to deallocate. + // If the package dependency cannot be resolved the function + // succeeds but packageFullName is nullptr. + [DllImport("kernelbase.dll", ExactSpelling=true, CharSet=CharSet.Unicode)] + private static extern int GetResolvedPackageFullNameForPackageDependency( + string packageDependencyId, + /*_Outptr_result_maybenull_ PWSTR* */ out IntPtr packageFullName); + + public static int GetResolvedPackageFullName( + string packageDependencyId, + out string packageFullName) + { + packageFullName = null; + + IntPtr pfn = IntPtr.Zero; + int hr = GetResolvedPackageFullNameForPackageDependency(packageDependencyId, out pfn); + if (hr >= 0) + { + packageFullName = Marshal.PtrToStringUni(pfn); + } + if (pfn != IntPtr.Zero) + { + HeapFree(pfn); + } + return hr; + } + + // Return the package dependency for the context. + // + // @param packageDependencyId allocated via HeapAlloc; use HeapFree to deallocate. + // If the package dependency context cannot be resolved + // the function succeeds but packageDependencyId is nullptr. + [DllImport("kernelbase.dll", ExactSpelling=true, CharSet=CharSet.Unicode)] + private static extern int GetIdForPackageDependencyContext( + /*PACKAGEDEPENDENCY_CONTEXT*/ IntPtr packageDependencyContext, + /*_Outptr_result_maybenull_ PWSTR* */ out IntPtr packageDependencyId); + + public static int GetIdForContext( + /*PACKAGEDEPENDENCY_CONTEXT*/ IntPtr packageDependencyContext, + /*_Outptr_result_maybenull_ PWSTR* */ out string packageDependencyId) + { + packageDependencyId = null; + + IntPtr pdi = IntPtr.Zero; + int hr = GetIdForPackageDependencyContext(packageDependencyContext, out pdi); + if (hr >= 0) + { + packageDependencyId = Marshal.PtrToStringUni(pdi); + } + if (pdi != IntPtr.Zero) + { + HeapFree(pdi); + } + return hr; + } + } + + public class PackageGraph + { + // Returns the package graph's current revision ID. + [DllImport("kernelbase.dll")] + private static extern uint GetPackageGraphRevisionId(); + + public static uint RevisionId + { + get + { + return GetPackageGraphRevisionId(); + } + } + } +} +"@ diff --git a/dev/DynamicDependency/Powershell/Remove-PackageDependency.ps1 b/dev/DynamicDependency/Powershell/Remove-PackageDependency.ps1 new file mode 100644 index 0000000000..583600f910 --- /dev/null +++ b/dev/DynamicDependency/Powershell/Remove-PackageDependency.ps1 @@ -0,0 +1,37 @@ +# Copyright (c) Microsoft Corporation and Contributors. +# Licensed under the MIT License. + +<# +.SYNOPSIS + Remove a resolved package dependency from the current process' package graph. + +.PARAMETER PackageDependencyContext + The handle of the package dependency to remove. + +.LINK + https://learn.microsoft.com/windows/win32/api/appmodel/nf-appmodel-removepackagedependency +#> +[CmdletBinding(SupportsShouldProcess=$true)] +param( + [Parameter(Mandatory=$true)] + [int64]$PackageDependencyContext +) + +Set-StrictMode -Version 3.0 + +$ErrorActionPreference = "Stop" + +# Import the MSIX Dynamic Dependency module +if (-not (Get-Module | Where-Object {$_.Name -eq 'MsixDynamicDependency'})) +{ + $module = Join-Path $PSScriptRoot 'MsixDynamicDependency.psm1' + Import-Module -Name $module -ErrorAction Stop +} + +$context = [IntPtr]$PackageDependencyContext +$hr = [Microsoft.Windows.ApplicationModel.DynamicDependency.PackageDependency]::Remove($context) +if ($hr -lt 0) +{ + $win32ex = [System.ComponentModel.Win32Exception]::new($hr) + Write-Error "Error 0x$($hr.ToString('X')): $($win32ex.Message)" -ErrorAction Stop +} diff --git a/dev/DynamicDependency/Powershell/TryCreate-PackageDependency.ps1 b/dev/DynamicDependency/Powershell/TryCreate-PackageDependency.ps1 new file mode 100644 index 0000000000..f92153acc4 --- /dev/null +++ b/dev/DynamicDependency/Powershell/TryCreate-PackageDependency.ps1 @@ -0,0 +1,100 @@ +# Copyright (c) Microsoft Corporation and Contributors. +# Licensed under the MIT License. + +<# +.SYNOPSIS + Dynamically create a package dependency. + +.DESCRIPTION + Create a package dependency, using package family name, minimum version, + and additional criteria. + +.PARAMETER PackageDependencyId + ID of the package dependency to be resolved and added to the invoking + process' package graph. This parameter must match a package dependency + defined by the TryCreate-PackageDependency cmdlet for the calling + user or the system (via the TryCreate-PackageDependencyOptions -ScopeIsSystem option). + +.PARAMETER MinVersion + The minimum version of the target package on which to take a dependency. + +.PARAMETER NoVerifyDependencyResolution + Disables dependency resolution when pinning a package dependency. This is + useful for installers running as user contexts other than the target user + (for example, installers running as LocalSystem). + +.PARAMETER System + Defines the package dependency for the system, accessible to all users (by + default, the package dependency is defined for a specific user). This + option requires the caller has administrative privileges. + +.PARAMETER LifetimeKind + The type of artifact to use to define the lifetime of the package + dependency. For more information, see + https://learn.microsoft.com/windows/win32/api/appmodel/nf-appmodel-trycreatepackagedependency#remarks + +.PARAMETER LifetimeArtifact + The name of the artifact used to define the lifetime of the package + dependency. N/A -LifetimeKind=Process. For more information, see + https://learn.microsoft.com/windows/win32/api/appmodel/nf-appmodel-trycreatepackagedependency#remarks + +.LINK + https://learn.microsoft.com/windows/win32/api/appmodel/nf-appmodel-addpackagedependency +#> +[CmdletBinding(SupportsShouldProcess=$true)] +param( + [Parameter(Mandatory=$true)] + [string]$PackageFamilyName, + + [long]$MinVersion, + + [switch]$NoVerifyDependencyResolution, + [switch]$System, + + [ValidateSet('Process', 'File', 'Registry')] + [string]$LifetimeKind, + [string]$LifetimeArtifact +) + +Set-StrictMode -Version 3.0 + +$ErrorActionPreference = "Stop" + +# Import the MSIX Dynamic Dependency module +if (-not (Get-Module | Where-Object {$_.Name -eq 'MsixDynamicDependency'})) +{ + $module = Join-Path $PSScriptRoot 'MsixDynamicDependency.psm1' + Import-Module -Name $module -ErrorAction Stop +} + +$options = [Microsoft.Windows.ApplicationModel.DynamicDependency.CreatePackageDependencyOptions]::None +if ($NoVerifyDependencyResolution -eq $true) +{ + $options = $options -bor [Microsoft.Windows.ApplicationModel.DynamicDependency.CreatePackageDependencyOptions]::DoNotVerifyDependencyResolution +} +if ($System -eq $true) +{ + $options = $options -bor [Microsoft.Windows.ApplicationModel.DynamicDependency.CreatePackageDependencyOptions]::ScopeIsSystem +} + +$lifetime = [Microsoft.Windows.ApplicationModel.DynamicDependency.PackageDependencyLifetimeKind]::Process +if ($LifetimeKind -eq 'File') +{ + $lifetime = [Microsoft.Windows.ApplicationModel.DynamicDependency.PackageDependencyLifetimeKind]::FilePath +} +elseif ($LifetimeKind -eq 'Registry') +{ + $lifetime = [Microsoft.Windows.ApplicationModel.DynamicDependency.PackageDependencyLifetimeKind]::RegistryKey +} + +$architectures = [Microsoft.Windows.ApplicationModel.DynamicDependency.PackageDependencyProcessorArchitectures]::None +$pdid = "" +$hr = [Microsoft.Windows.ApplicationModel.DynamicDependency.PackageDependency]::TryCreate( + $PackageFamilyName, $MinVersion, $architectures, $lifetime, $LifetimeArtifact, $options, [ref] $pdid) +if ($hr -lt 0) +{ + $win32ex = [System.ComponentModel.Win32Exception]::new($hr) + Write-Error "Error 0x$($hr.ToString('X')): $($win32ex.Message)" -ErrorAction Stop +} + +$pdid diff --git a/dev/Kozani/Common/KozaniDvc-Constants.h b/dev/Kozani/Common/KozaniDvc-Constants.h index 2716d7d659..f91a633e93 100644 --- a/dev/Kozani/Common/KozaniDvc-Constants.h +++ b/dev/Kozani/Common/KozaniDvc-Constants.h @@ -6,6 +6,4 @@ namespace Microsoft::Kozani::DVC::Constants { const char ConnectionIdSwitch[] = "-connectionId"; - - const WCHAR RemoteDesktopClientExe[] = L"mstsc.exe"; } \ No newline at end of file diff --git a/dev/Kozani/Common/KozaniDvcProtocol.cpp b/dev/Kozani/Common/KozaniDvcProtocol.cpp index 8feeaf1b36..a47db90115 100644 --- a/dev/Kozani/Common/KozaniDvcProtocol.cpp +++ b/dev/Kozani/Common/KozaniDvcProtocol.cpp @@ -2,30 +2,15 @@ // Licensed under the MIT License. #include +#include #include "KozaniDvcProtocol.h" namespace Microsoft::Kozani::DvcProtocol { - bool IsEmptyPayloadProtocolDataUnitType(Dvc::ProtocolDataUnit::DataType type) + std::string CreatePdu(UINT64 activityId, Dvc::ProtocolDataUnit::DataType type, const std::string& payload) { - switch (type) - { - case Dvc::ProtocolDataUnit::AppTerminationNotice: - return true; - } - - return false; - } - - std::string CreatePdu(UINT64 activityId, Dvc::ProtocolDataUnit::DataType type, const std::string& payload = std::string()) - { - if (!IsEmptyPayloadProtocolDataUnitType(type)) - { - // Payload data of the Pdu should not be empty. It catches a failure condition when empty string is returned - // from a failed SerializeAsString call before calling into this method. - THROW_HR_IF(KOZANI_E_PDU_SERIALIZATION, payload.empty()); - } - + // Do not check payload.empty() because if the payload message only contains default values, it can be empty after SerializeAsString(). + Dvc::ProtocolDataUnit pdu; pdu.set_activity_id(activityId); pdu.set_type(type); @@ -36,8 +21,9 @@ namespace Microsoft::Kozani::DvcProtocol } std::string rawPdu{ pdu.SerializeAsString() }; - THROW_HR_IF(KOZANI_E_PDU_SERIALIZATION, rawPdu.empty()); + // rawPdu should never be empty as the activityId must not be default value (0). + THROW_HR_IF(KOZANI_E_PDU_SERIALIZATION, rawPdu.empty()); return rawPdu; } @@ -53,15 +39,43 @@ namespace Microsoft::Kozani::DvcProtocol switch (args.Kind()) { case winrt::Windows::ApplicationModel::Activation::ActivationKind::Launch: - auto specificArgs{ args.as() }; - if (!specificArgs.Arguments().empty()) { - const std::string argsUtf8{ ::Microsoft::Utf8::ToUtf8(specificArgs.Arguments().c_str()) }; - Dvc::LaunchActivationArgs launchArgs; - launchArgs.set_arguments(std::move(argsUtf8)); - return launchArgs.SerializeAsString(); + auto specificArgs{ args.as() }; + if (!specificArgs.Arguments().empty()) + { + const std::string argsUtf8{ ::Microsoft::Utf8::ToUtf8(specificArgs.Arguments().c_str()) }; + Dvc::LaunchActivationArgs launchArgs; + launchArgs.set_arguments(std::move(argsUtf8)); + return launchArgs.SerializeAsString(); + } + break; + } + + case winrt::Windows::ApplicationModel::Activation::ActivationKind::File: + { + auto specificArgs{ args.as() }; + const std::string verbUtf8{ ::Microsoft::Utf8::ToUtf8(specificArgs.Verb().c_str()) }; + Dvc::FileActivationArgs fileArgs; + fileArgs.set_verb(std::move(verbUtf8)); + + auto files{ specificArgs.Files() }; + for (auto const& file : specificArgs.Files()) + { + const std::string filePathUtf8{ ::Microsoft::Utf8::ToUtf8(file.Path().c_str()) }; + fileArgs.add_file_paths(std::move(filePathUtf8)); + } + + return fileArgs.SerializeAsString(); + } + case winrt::Windows::ApplicationModel::Activation::ActivationKind::Protocol: + { + auto specificArgs{ args.as() }; + const std::string uriUtf8{ ::Microsoft::Utf8::ToUtf8(specificArgs.Uri().AbsoluteUri().c_str())}; + Dvc::ProtocolActivationArgs protocolArgs; + protocolArgs.set_uri(std::move(uriUtf8)); + + return protocolArgs.SerializeAsString(); } - break; } return std::string(); } @@ -70,16 +84,16 @@ namespace Microsoft::Kozani::DvcProtocol UINT64 activityId, PCWSTR appUserModelId, winrt::Windows::ApplicationModel::Activation::ActivationKind activationKind, - winrt::Windows::ApplicationModel::Activation::IActivatedEventArgs& args) + const std::string& serializedArgs) { Dvc::ActivateAppRequest activateAppRequest; activateAppRequest.set_activation_kind(static_cast(activationKind)); const std::string appUserModelIdUtf8{ ::Microsoft::Utf8::ToUtf8(appUserModelId) }; activateAppRequest.set_app_user_model_id(std::move(appUserModelIdUtf8)); - if (args) + if (!serializedArgs.empty()) { - activateAppRequest.set_arguments(SerializeActivatedEventArgs(args)); + activateAppRequest.set_arguments(serializedArgs); } return CreatePdu(activityId, Dvc::ProtocolDataUnit::ActivateAppRequest, activateAppRequest.SerializeAsString()); diff --git a/dev/Kozani/Common/KozaniDvcProtocol.h b/dev/Kozani/Common/KozaniDvcProtocol.h index 6b9a2a8234..cdb75ba87c 100644 --- a/dev/Kozani/Common/KozaniDvcProtocol.h +++ b/dev/Kozani/Common/KozaniDvcProtocol.h @@ -3,6 +3,7 @@ #pragma once +#include #include #include #include @@ -13,7 +14,7 @@ namespace Microsoft::Kozani::DvcProtocol { const char DvcChannelName[] = "KozaniDvc"; - std::string CreatePdu(UINT64 activityId, Dvc::ProtocolDataUnit::DataType type, const std::string& payload); + std::string CreatePdu(UINT64 activityId, Dvc::ProtocolDataUnit::DataType type, const std::string& payload = std::string()); std::string CreateConnectionAckPdu(PCSTR connectionId, UINT64 activityId); @@ -23,7 +24,7 @@ namespace Microsoft::Kozani::DvcProtocol UINT64 activityId, PCWSTR appUserModelId, winrt::Windows::ApplicationModel::Activation::ActivationKind activationKind, - winrt::Windows::ApplicationModel::Activation::IActivatedEventArgs& args); + const std::string& serializedArgs); std::string CreateActivateAppResultPdu( UINT64 activityId, diff --git a/dev/Kozani/Common/Logging.h b/dev/Kozani/Common/Logging.h index 2e7ba64fa1..a1ea414173 100644 --- a/dev/Kozani/Common/Logging.h +++ b/dev/Kozani/Common/Logging.h @@ -7,9 +7,11 @@ // According to https://learn.microsoft.com/en-us/windows/win32/com/codes-in-facility-itf, all the COM-defined FACILITY_ITF codes have a code value // in the range of 0x0000-0x01FF. It is recommended that only code values in the range of 0x0200-0xFFFF be used for 3rd party FACILITY_ITF codes. -// Success HRESULT used for Kozani information logging purpose. -// 0x00040201 (262657) -constexpr HRESULT KOZANI_S_INFO{ MAKE_HRESULT(SEVERITY_SUCCESS, FACILITY_ITF, 0x0201) }; +// HRESULT used for Kozani information logging purpose. Note that it does NOT mean there is an error. WIL logging requires a failure HRESULT as the input +// to the LOG_HR_MSG() macro. Passing in a successful HRESULT to the macro will cause fail fast crash in Debug build, or it will log XS_STATUS_ASSERTION_FAILURE +// in released build. So it has to be a failure HRESULT, although it does not mean failure in this case. +// 0x80040201 (-2147220991) +constexpr HRESULT KOZANI_E_INFO{ MAKE_HRESULT(SEVERITY_ERROR, FACILITY_ITF, 0x0201) }; // Bad/malformatted PDU that cannot be parsed successfully. // 0x80040202 (-2147220990) @@ -22,3 +24,45 @@ constexpr HRESULT KOZANI_E_UNSUPPORTED_ACTIVATION_KIND{ MAKE_HRESULT(SEVERITY_ER // Bad/malformatted PDU that cannot be parsed successfully. // 0x80040204 (-2147220988) constexpr HRESULT KOZANI_E_PDU_SERIALIZATION{ MAKE_HRESULT(SEVERITY_ERROR, FACILITY_ITF, 0x0204) }; + +#if RESULT_DIAGNOSTICS_LEVEL > 3 + +#define TRACELOGGING_FAILURE_CONTEXT(failure) \ + TraceLoggingHResult(failure.hr, "HResult"), \ + TraceLoggingString(failure.pszFile, "File"), \ + TraceLoggingUInt32(failure.uLineNumber, "LineNumber"), \ + TraceLoggingString(failure.pszFunction, "Function"), \ + TraceLoggingWideString(failure.pszMessage, "Message"), \ + TraceLoggingString(failure.pszCallContext, "CallingContext"), \ + TraceLoggingString(failure.pszModule, "Module"), \ + TraceLoggingPointer(failure.returnAddress, "Site"), \ + TraceLoggingString(failure.pszCode, "Code") \ + +#else + +#define TRACELOGGING_FAILURE_CONTEXT(failure) \ + TraceLoggingHResult(failure.hr, "HResult"), \ + TraceLoggingString(failure.pszFile, "File"), \ + TraceLoggingUInt32(failure.uLineNumber, "LineNumber"), \ + TraceLoggingWideString(failure.pszMessage, "Message") \ + +#endif + +template +void __stdcall TraceFailureFromProvider(const wil::FailureInfo& failure) WI_NOEXCEPT +{ + if (failure.hr == KOZANI_E_INFO) + { + TraceLoggingWrite( + TProvider::Provider(), + "Info", + TRACELOGGING_FAILURE_CONTEXT(failure)); + } + else + { + TraceLoggingWrite( + TProvider::Provider(), + "Failure", + TRACELOGGING_FAILURE_CONTEXT(failure)); + } +} diff --git a/dev/Kozani/KozaniAppGraph/packages.config b/dev/Kozani/KozaniAppGraph/packages.config index 14efb7baf5..cd05427e9c 100644 --- a/dev/Kozani/KozaniAppGraph/packages.config +++ b/dev/Kozani/KozaniAppGraph/packages.config @@ -3,6 +3,6 @@ - + diff --git a/dev/Kozani/KozaniHostRuntime/KozaniHostRuntime.vcxproj b/dev/Kozani/KozaniHostRuntime/KozaniHostRuntime.vcxproj index be045d3361..4f37ec3f1c 100644 --- a/dev/Kozani/KozaniHostRuntime/KozaniHostRuntime.vcxproj +++ b/dev/Kozani/KozaniHostRuntime/KozaniHostRuntime.vcxproj @@ -92,7 +92,7 @@ - (MSBuildThisFileDirectory);$(OutDir)\..\WindowsAppRuntime_DLL;$(RepoRoot)\dev\WindowsAppRuntime_Insights;$(RepoRoot)\dev\common;$(IntDir);%(AdditionalIncludeDirectories) + (MSBuildThisFileDirectory);$(OutDir)\..\WindowsAppRuntime_DLL;$(RepoRoot)\dev\WindowsAppRuntime_Insights;$(RepoRoot)\dev\common;$(IntDir);$(OutDir)..\KozaniManagerProxyStub;$(RepoRoot)\dev\Kozani\common;%(AdditionalIncludeDirectories) Use pch.h KOZANIHOSTRUNTIMEDLL_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) @@ -186,6 +186,11 @@ $(RepoRoot)\dev\Common;$(RepoRoot);%(AdditionalIncludeDirectories) + + + {400ed5ec-4530-4adb-8dce-9d1e6708a1f5} + + @@ -208,4 +213,4 @@ - + \ No newline at end of file diff --git a/dev/Kozani/KozaniHostRuntime/KozaniHostRuntime.vcxproj.filters b/dev/Kozani/KozaniHostRuntime/KozaniHostRuntime.vcxproj.filters index ac929245b8..c88628f9f2 100644 --- a/dev/Kozani/KozaniHostRuntime/KozaniHostRuntime.vcxproj.filters +++ b/dev/Kozani/KozaniHostRuntime/KozaniHostRuntime.vcxproj.filters @@ -27,6 +27,9 @@ Header Files + + Header Files + @@ -59,4 +62,7 @@ Resource Files - + + + + \ No newline at end of file diff --git a/dev/Kozani/KozaniHostRuntime/framework.h b/dev/Kozani/KozaniHostRuntime/framework.h index 4c430d5b39..296665aad1 100644 --- a/dev/Kozani/KozaniHostRuntime/framework.h +++ b/dev/Kozani/KozaniHostRuntime/framework.h @@ -21,8 +21,10 @@ #include #include +#include #include #include +#include #include #include diff --git a/dev/Kozani/KozaniHostRuntime/main.cpp b/dev/Kozani/KozaniHostRuntime/main.cpp index dd3f63d8e8..5f76ad67e4 100644 --- a/dev/Kozani/KozaniHostRuntime/main.cpp +++ b/dev/Kozani/KozaniHostRuntime/main.cpp @@ -3,11 +3,210 @@ #include "pch.h" +#include + // Including this file once per binary will automatically opt WIL error handling macros into calling RoOriginateError when they // begin logging a new error. This greatly improves the debuggability of errors that propagate before a failfast. #include +#include +#include "winrt/Microsoft.Kozani.ManagerRuntime.h" + +#include "Logging.h" + +// Uncomment to enable wait for debugger when the local variant app is launched. We can attach debugger to the KozaniHostRuntime.exe while it is waiting. +//#define WAIT_FOR_DEBUGGER + +using namespace winrt; using namespace winrt::Windows::Foundation; +using namespace winrt::Windows::Foundation::Collections; +using namespace winrt::Windows::Storage; +using namespace winrt::Windows::ApplicationModel; +using namespace winrt::Windows::ApplicationModel::Activation; +using namespace winrt::Windows::Data::Xml::Dom; + +constexpr PCWSTR c_kozaniSettingsFolderName{ L"KozaniSettings" }; +constexpr PCWSTR c_rdpFileName{ L"connection.rdp" }; +constexpr PCWSTR c_additionalSettingsFileName{ L"AdditionalSettings.txt" }; +constexpr PCWSTR c_manifestFileName{ L"AppxManifest.xml" }; + +enum KozaniStatus +{ + None = 0, + Activated = 1, + Failed = 2, + Closed = 3 +}; + +struct KozaniStatusCallbackHandler : winrt::implements +{ + KozaniStatusCallbackHandler(PCWSTR aumid) : m_aumid(aumid) + { + m_eventExitProcess.create(); + } + +#pragma region IKozaniStatusCallback_methods + STDMETHODIMP OnActivated(DWORD pid, boolean isNewInstance) + { + LOG_HR_MSG(KOZANI_E_INFO, "[ActivationSuccess] IKozaniStausCallback::OnActivated is called. Remote app aumid = %ls, pid = %u, isNewInstance = %u", + m_aumid.c_str(), pid, isNewInstance); + + m_remoteAppProcessId = pid; + m_status = KozaniStatus::Activated; + + if (!isNewInstance) + { + // This activation does not launch a new app process. Exit this process as there is already another one tracking the remote process. + // Example: Calculator app has single process for multiple app windows. + m_eventExitProcess.SetEvent(); + } + return S_OK; + } + + STDMETHODIMP OnActivationFailed( + DWORD errorCode, + PCWSTR errorMessage) + { + LOG_HR_MSG(KOZANI_E_INFO, "[ActivationFailed] IKozaniStausCallback::OnActivationFailed is called. Remote app aumid = %ls, errorCode = 0x%x, errorMessage: %s", + m_aumid.c_str(), errorCode, errorMessage); + + m_status = KozaniStatus::Failed; + m_eventExitProcess.SetEvent(); + return S_OK; + } + + STDMETHODIMP OnClosed() + { + LOG_HR_MSG(KOZANI_E_INFO, "[App Terminated] IKozaniStausCallback::OnClosed is called. Remote app aumid = %ls, pid=%u", + m_aumid.c_str(), m_remoteAppProcessId); + + m_status = KozaniStatus::Closed; + m_eventExitProcess.SetEvent(); + return S_OK; + } +#pragma endregion IKozaniStatusCallback_methods + + bool WaitForExitProcessEvent(DWORD timeout) + { + return m_eventExitProcess.wait(timeout); + } + + KozaniStatus GetStatus() + { + return m_status; + } + +private: + std::wstring m_aumid; + DWORD m_remoteAppProcessId{}; + KozaniStatus m_status{}; + wil::unique_event m_eventExitProcess; +}; + +void LogArgs(int argc, PWSTR* argv) +{ + TraceLoggingWrite(Microsoft_Kozani_HostRuntime_TraceLogger::Provider(), "argc", + TraceLoggingValue(argc, "argc")); + for (int i = 0; i < argc; i++) + { + TraceLoggingWrite(Microsoft_Kozani_HostRuntime_TraceLogger::Provider(), "argv", + TraceLoggingValue(i, "index"), + TraceLoggingValue(argv[i], "argv")); + } +} + +// Remote app AUMID is stored in an app extension of the local variant package (LVP). The app extension name is formatted as: +// com.microsoft.kozani.localvariant.remoteapp. +// and the app extension Id is the package-relative application identifier (PRAID) of the LVP app being activated. +// : we replace the '_' character in the package family name with '-' as '_' is not allowed in the app extension name. +// +// For example: +// +// +// +// Microsoft.WindowsCalculator_8wekyb3d8bbwe!App +// +// +// +winrt::hstring GetRemoteAumid() +{ + WCHAR lvpAumid[APPLICATION_USER_MODEL_ID_MAX_LENGTH + 1]{}; + UINT32 lvpAumidLength{ ARRAYSIZE(lvpAumid) }; + THROW_IF_WIN32_ERROR(GetCurrentApplicationUserModelId(&lvpAumidLength, lvpAumid)); + + WCHAR lvpFamilyName[PACKAGE_FAMILY_NAME_MAX_LENGTH + 1]{}; + WCHAR lvpPraid[PACKAGE_RELATIVE_APPLICATION_ID_MAX_LENGTH + 1]{}; + UINT32 lvpFamilyNameLength{ ARRAYSIZE(lvpFamilyName) }; + UINT32 lvpPraidLength{ ARRAYSIZE(lvpPraid) }; + THROW_IF_WIN32_ERROR(ParseApplicationUserModelId(lvpAumid, &lvpFamilyNameLength, lvpFamilyName, &lvpPraidLength, lvpPraid)); + + // Replace '_' in the family name with '-' as '_' cannot be used in the app extension name. + for (UINT32 i = 0; i < lvpFamilyNameLength; i++) + { + if (lvpFamilyName[i] == L'_') + { + lvpFamilyName[i] = L'-'; + break; + } + } + + std::wstring appExtensionName{ L"com.microsoft.kozani.localvariant.remoteapp." }; + appExtensionName += lvpFamilyName; + + auto catalog{ AppExtensions::AppExtensionCatalog::Open(appExtensionName.c_str()) }; + IVectorView appExtensions{ catalog.FindAllAsync().get() }; + for (const auto appExtension : appExtensions) + { + if (appExtension.Id() == lvpPraid) + { + const auto properties{ appExtension.GetExtensionPropertiesAsync().get() }; + const auto property{ properties.Lookup(L"RemoteAppAumid").as>() }; + const auto remoteAumid{ winrt::unbox_value(property.Lookup(L"#text")) }; + return remoteAumid; + } + } + + THROW_WIN32_MSG(ERROR_NOT_FOUND, "Cannot find remote app aumid from app extension with name: %ls, Id: %ls", appExtensionName.c_str(), lvpPraid); +} + +void GetConfigurationFiles(std::wstring& rdpFilePath, std::wstring& additionalSettingsFilePath) +{ + StorageFolder localFolder{ ApplicationData::Current().LocalFolder() }; + // This hostRuntime exe should run with the identity of the hosted app (localvariant) package that activated + // Logging the AppData local folder path thus indicates the identity of the hosted app. + TraceLoggingWrite(Microsoft_Kozani_HostRuntime_TraceLogger::Provider(), "localFolder", + TraceLoggingValue(localFolder.Path().c_str(), "path")); + + auto settingsFolder{ localFolder.GetFolderAsync(c_kozaniSettingsFolderName).get() }; + auto rdpFile{ settingsFolder.GetFileAsync(c_rdpFileName).get() }; + THROW_HR_IF(HRESULT_FROM_WIN32(ERROR_INVALID_DATA), !rdpFile.IsOfType(StorageItemTypes::File)); + + rdpFilePath = rdpFile.Path(); + + auto additionalSettingsFile{ settingsFolder.TryGetItemAsync(c_additionalSettingsFileName).get() }; + if (additionalSettingsFile) + { + THROW_HR_IF(HRESULT_FROM_WIN32(ERROR_INVALID_DATA), !additionalSettingsFile.IsOfType(StorageItemTypes::File)); + additionalSettingsFilePath = additionalSettingsFile.Path(); + } + else + { + additionalSettingsFilePath.clear(); + } +} + +#ifdef WAIT_FOR_DEBUGGER +void WaitForDebugger() +{ + while (!IsDebuggerPresent()) + { + Sleep(3000); + } +} +#endif int APIENTRY wWinMain( HINSTANCE /*hInstance*/, @@ -15,10 +214,43 @@ int APIENTRY wWinMain( PWSTR /*pCmdLine*/, int /*nCmdShow*/) try { - int argc{}; - const wil::unique_hlocal_ptr argv{ CommandLineToArgvW(GetCommandLineW(), &argc) }; - wprintf(L"argc: %d\nargv[0]: %ls\n", argc, argv[0]); + wil::SetResultLoggingCallback(&TraceFailureFromProvider); + winrt::init_apartment(); + +#ifdef WAIT_FOR_DEBUGGER + WaitForDebugger(); +#endif + + winrt::hstring remoteAumid{ GetRemoteAumid() }; + LOG_HR_MSG(KOZANI_E_INFO, "remoteAumid=%ls", remoteAumid.c_str()); + + std::wstring rdpFilePath; + std::wstring additionalSettingsFilePath; + GetConfigurationFiles(rdpFilePath, additionalSettingsFilePath); + LOG_HR_MSG(KOZANI_E_INFO, "rdpFilePath=%ls, additionalSettingsFilePath=%ls", rdpFilePath.c_str(), additionalSettingsFilePath.c_str()); + + auto activatedEventArgs{ AppInstance::GetActivatedEventArgs() }; + auto runtimeManager{ winrt::Microsoft::Kozani::ManagerRuntime::ManagerRuntimeManager::Create() }; + auto statusCallback{ winrt::make_self(remoteAumid.c_str()) }; + + runtimeManager.ActivateRemoteApplication( + activatedEventArgs.Kind(), + remoteAumid.c_str(), + rdpFilePath.c_str(), + GetCurrentProcessId(), + activatedEventArgs, + statusCallback.as(), + additionalSettingsFilePath.c_str()); + + // Release the IManagerRuntimeManager object so the host runtime does not hold on to it while waiting for process termination event. + // In case this process is killed by the user (i.e., from Task Manager), holding the IManagerRuntimeManager object will leak the ref count + // and prevent KozaniManager.exe from exiting after all remote apps are closed. + runtimeManager = nullptr; + + statusCallback->WaitForExitProcessEvent(INFINITE); + TraceLoggingWrite(Microsoft_Kozani_HostRuntime_TraceLogger::Provider(), "Exiting instance"); + winrt::uninit_apartment(); return S_OK; } CATCH_RETURN() diff --git a/dev/Kozani/KozaniHostRuntime/packages.config b/dev/Kozani/KozaniHostRuntime/packages.config index 14efb7baf5..cd05427e9c 100644 --- a/dev/Kozani/KozaniHostRuntime/packages.config +++ b/dev/Kozani/KozaniHostRuntime/packages.config @@ -3,6 +3,6 @@ - + diff --git a/dev/Kozani/KozaniManager/ConnectionManager.cpp b/dev/Kozani/KozaniManager/ConnectionManager.cpp index 2196a4987f..569cf33dcc 100644 --- a/dev/Kozani/KozaniManager/ConnectionManager.cpp +++ b/dev/Kozani/KozaniManager/ConnectionManager.cpp @@ -35,6 +35,8 @@ namespace Microsoft::Kozani::Manager if (requestInfo->statusCallback) { + // The following call can fail with RPC_E_SERVER_UNAVAILABLE (0x800706BA) if the statusCallback client is hosted in the + // process that has been terminated. Ignore the failure - best effort to deliver the status update. (void)requestInfo->statusCallback->OnClosed(); requestInfo->statusCallback.reset(); } @@ -42,14 +44,7 @@ namespace Microsoft::Kozani::Manager switch (requestInfo->status) { case RequestStatus::Connecting: - for (auto it = connectionManager->m_requestsPendingConnection.begin(); it != connectionManager->m_requestsPendingConnection.end(); it++) - { - if (requestInfo == *it) - { - connectionManager->m_requestsPendingConnection.erase(it); - break; - } - } + connectionManager->RemoveRequestFromPendingConnectionList(requestInfo); break; case RequestStatus::Connected: @@ -70,13 +65,10 @@ namespace Microsoft::Kozani::Manager FAIL_FAST_MSG("Unhandled RequestStatus: %u", requestInfo->status); } - // ActivityId_Unknown (0) is reserved for uninitialized state (ConnectionAck has not been received from DVC server yet) and will not be in m_activityMap. - if (requestInfo->activityId != ActivationRequestInfo::ActivityId_Unknown) - { - connectionManager->m_activityMap.erase(requestInfo->activityId); - } + requestInfo->status = RequestStatus::Closed; + requestInfo->statusReporter->SetStatus(RequestStatus::Closed); - connectionManager->m_activationRequests.erase(requestInfo->listPosition); + connectionManager->RemoveRequest(requestInfo, true /* removeFromMainList */); } CATCH_LOG_RETURN() @@ -156,11 +148,14 @@ namespace Microsoft::Kozani::Manager requestInfo->connectionId = std::move(connectionId); requestInfo->activationKind = activationKind; requestInfo->appUserModelId.assign(appUserModelId); - requestInfo->args = activatedEventArgs; - requestInfo->statusCallback = statusCallback; - requestInfo->statusReporter = std::make_shared(); + if (activatedEventArgs) + { + requestInfo->serializedActivationArgs = DvcProtocol::SerializeActivatedEventArgs(activatedEventArgs); + } + requestInfo->statusCallback = statusCallback; + requestInfo->statusReporter = std::make_shared(); requestInfo->connectionManager = this; if (associatedLocalProcessHandle) @@ -170,8 +165,6 @@ namespace Microsoft::Kozani::Manager { THROW_LAST_ERROR_MSG("RegisterWaitForSingleObject failed. Cannot track lifetime of the associated local proess pid=%u", associatedLocalProcessId); } - - requestInfo->associatedLocalProcessHandle = std::move(associatedLocalProcessHandle); } m_requestsPendingConnection.push_back(requestInfo); @@ -181,6 +174,23 @@ namespace Microsoft::Kozani::Manager return requestInfo->statusReporter; } + void ConnectionManager::CleanupActivationRequest(_In_ const ActivationRequestStatusReporter* statusReporter) + { + auto lock{ m_requestsLock.lock_exclusive() }; + + for (auto& request : m_activationRequests) + { + // Locate the request object based on its statusReporter pointer. + if (request.statusReporter.get() == statusReporter) + { + bool localProcessTerminationCallbackPending{}; + const HRESULT hrDisableProcessLifetimeTracker{ LOG_IF_FAILED(DisableProcessLifetimeTracker(&request, localProcessTerminationCallbackPending)) }; + RemoveRequest(&request, SUCCEEDED(hrDisableProcessLifetimeTracker) && !localProcessTerminationCallbackPending); + break; + } + } + } + void ConnectionManager::ProcessProtocolDataUnit( _In_reads_(size) BYTE* data, UINT32 size, @@ -299,7 +309,7 @@ namespace Microsoft::Kozani::Manager errorMessage = L"Failed to process DVC server connection."; } - ProcessAppActivationFailure(hrOnDvcServerConnected, activityId, requestInfo, errorMessage.c_str()); + ProcessAppActivationFailure(hrOnDvcServerConnected, requestInfo, errorMessage.c_str()); } THROW_HR(hrOnDvcServerConnected); @@ -333,78 +343,110 @@ namespace Microsoft::Kozani::Manager ActivationRequestInfo* requestInfo{ iter->second }; if (SUCCEEDED(activateAppResult.hresult())) { - requestInfo->status = RequestStatus::AppActivationSucceeded; - requestInfo->statusReporter->SetStatus(RequestStatus::AppActivationSucceeded); + if (activateAppResult.is_new_instance()) + { + requestInfo->status = RequestStatus::AppActivationSucceeded; + requestInfo->statusReporter->SetStatus(RequestStatus::AppActivationSucceeded); - if (requestInfo->statusCallback != nullptr) + if (requestInfo->statusCallback != nullptr) + { + LOG_IF_FAILED(requestInfo->statusCallback->OnActivated(activateAppResult.process_id(), activateAppResult.is_new_instance())); + } + } + else { - (void)requestInfo->statusCallback->OnActivated(activateAppResult.process_id(), activateAppResult.is_new_instance()); + // We no longer need to track the associated local process as the remote app activation does not create a new remote process. + bool localProcessTerminationCallbackPending{}; + const HRESULT hrDisableProcessLifetimeTracker{ LOG_IF_FAILED(DisableProcessLifetimeTracker(requestInfo, localProcessTerminationCallbackPending)) }; + + requestInfo->status = RequestStatus::Closed; + requestInfo->statusReporter->SetStatus(RequestStatus::Closed); + + if (requestInfo->statusCallback != nullptr) + { + LOG_IF_FAILED(requestInfo->statusCallback->OnActivated(activateAppResult.process_id(), activateAppResult.is_new_instance())); + requestInfo->statusCallback.reset(); + } + + // No longer need to track the request so remove it from the tracking mechanism. We only remove the requestInfo object from + // main list (owning storage) if it is safe to do so: after the process lifetime tracker is successfully disabled and there + // are no pending process termination callbacks. Otherwise, the callbacks will need to access the object. We will delay the + // cleanup later in the next remote app termination with MinCleanupDelay, or during the local process termination callback. + RemoveRequest(requestInfo, SUCCEEDED(hrDisableProcessLifetimeTracker) && !localProcessTerminationCallbackPending); } } else { std::wstring errorMessage{ ::Microsoft::Utf8::ToUtf16(activateAppResult.error_message()) }; - ProcessAppActivationFailure(activateAppResult.hresult(), pdu.activity_id(), requestInfo, errorMessage.c_str()); + ProcessAppActivationFailure(activateAppResult.hresult(), requestInfo, errorMessage.c_str()); } } // Must be called with m_requestsLock.lock_exclusive() done in caller. void ConnectionManager::ProcessAppActivationFailure( HRESULT hrActivation, - uint64_t activityId, _In_ ActivationRequestInfo* requestInfo, _In_ PCWSTR errorMessage) { + // We no longer need to track the associated local process as remote app activation failed. + // Disabling the associated local process tracker also prevents unnecessary handling if the associated local process + // is terminated due to us calling IKozaniStatusCallback::OnActivationFailed() to report the failure to our client, + // which may cause it to terminate the associated local process. + bool localProcessTerminationCallbackPending{}; + const HRESULT hrDisableProcessLifetimeTracker{ LOG_IF_FAILED(DisableProcessLifetimeTracker(requestInfo, localProcessTerminationCallbackPending)) }; + + // Change status to Failed AFTER disabling local process lifetime tracker to avoid triggering the local process to exit + // before the tracker is disabled. + requestInfo->status = RequestStatus::Failed; requestInfo->statusReporter->SetStatus(RequestStatus::Failed); + if (requestInfo->statusCallback != nullptr) { - (void)requestInfo->statusCallback->OnActivationFailed(hrActivation, errorMessage); + LOG_IF_FAILED(requestInfo->statusCallback->OnActivationFailed(hrActivation, errorMessage)); + requestInfo->statusCallback.reset(); } - // Remove the request from all tracking mechanism. - m_activityMap.erase(activityId); - m_activationRequests.erase(requestInfo->listPosition); + // Remove the request from all tracking mechanism. We only remove the requestInfo object from + // main list (owning storage) if it is safe to do so: after the process lifetime tracker is successfully disabled and there + // are no pending process termination callbacks. Otherwise, the callbacks will need to access the object. We will delay the + // cleanup later in the next remote app termination with MinCleanupDelay, or during the local process termination callback. + RemoveRequest(requestInfo, SUCCEEDED(hrDisableProcessLifetimeTracker) && !localProcessTerminationCallbackPending); } - void ConnectionManager::DisableProcessLifetimeTracker(uint64_t activityId) + // Must be called with m_requestsLock.lock_exclusive() done in caller. + HRESULT ConnectionManager::DisableProcessLifetimeTracker(ActivationRequestInfo* requestInfo, _Out_ bool& callbackPending) noexcept try { - auto lock{ m_requestsLock.lock_exclusive() }; - if (m_closing) - { - // We are closing, no more processing. - return; - } - - auto iter{ m_activityMap.find(activityId) }; - if (iter == m_activityMap.end()) - { - return; - } - - ActivationRequestInfo* requestInfo{ iter->second }; + callbackPending = false; if (requestInfo->processLifetimeTrackerHandle) { - requestInfo->processLifetimeTrackerDisabled = true; + BOOL unregisterWaitSuccess{ UnregisterWait(requestInfo->processLifetimeTrackerHandle.get()) }; + if (!unregisterWaitSuccess) + { + DWORD error{ GetLastError() }; + if (error == ERROR_IO_PENDING) + { + // If there are outstanding callbacks when UnregisterWait is called, UnregisterWait unregisters the wait on the callback functions + // and fails with the ERROR_IO_PENDING error code. The error code does not indicate that the function has failed, and the function + // does not need to be called again. + callbackPending = true; + } + else + { + RETURN_WIN32_MSG(error, "UnregisterWait failed"); + } + } - // Call UnregisterWaitEx with INVALID_HANDLE_VALUE so it will wait for any pending callback to finish before returning. - // Release the m_requestsLock before calling blocking UnregisterWaitEx, which will deadlock if the other thread calling the - // ProcessTerminationCallback function is trying to get the lock. We are safe here as requestInfo->processLifetimeTrackerDisabled - // is set to true above, which will prevent the process lifetime tracker thread from modifying the requestInfo object. - lock.reset(); - THROW_IF_WIN32_BOOL_FALSE(UnregisterWaitEx(requestInfo->processLifetimeTrackerHandle.get(), INVALID_HANDLE_VALUE)); + requestInfo->processLifetimeTrackerDisabled = true; + requestInfo->processLifetimeTrackerDisabledTime = GetTickCount64(); requestInfo->processLifetimeTrackerHandle.release(); } + return S_OK; } + CATCH_RETURN() void ConnectionManager::ProcessAppTerminationNotice(_In_ const Dvc::ProtocolDataUnit& pdu) { - // We no longer need to track the associated local process as we know the remote process has been terminated. - // Disabling the associated local process tracker also prevents unnecessary handling if the associated local process - // is terminated due to us calling IKozaniStatusCallback::OnClosed() to report the remote app termination to our client, - // which may cause it to terminate the associated local process. - DisableProcessLifetimeTracker(pdu.activity_id()); - auto lock{ m_requestsLock.lock_exclusive() }; if (m_closing) { @@ -423,6 +465,13 @@ namespace Microsoft::Kozani::Manager ActivationRequestInfo* requestInfo{ iter->second }; + // We no longer need to track the associated local process as we know the remote process has been terminated. + // Disabling the associated local process tracker also prevents unnecessary handling if the associated local process + // is terminated due to us calling IKozaniStatusCallback::OnClosed() to report the remote app termination to our client, + // which may cause it to terminate the associated local process. + bool localProcessTerminationCallbackPending{}; + const HRESULT hrDisableProcessLifetimeTracker{ LOG_IF_FAILED(DisableProcessLifetimeTracker(requestInfo, localProcessTerminationCallbackPending)) }; + requestInfo->status = RequestStatus::Closed; requestInfo->statusReporter->SetStatus(RequestStatus::Closed); @@ -432,14 +481,19 @@ namespace Microsoft::Kozani::Manager requestInfo->statusCallback.reset(); } - m_activityMap.erase(iter); - m_activationRequests.erase(requestInfo->listPosition); + // Remove the request from the tracking mechanism. We only remove the requestInfo object from + // main list (owning storage) if it is safe to do so: after the process lifetime tracker is successfully disabled and there + // are no pending process termination callbacks. Otherwise, the callbacks will need to access the object. We will delay the + // cleanup later in the next remote app termination with MinCleanupDelay, or during the local process termination callback. + RemoveRequest(requestInfo, SUCCEEDED(hrDisableProcessLifetimeTracker) && !localProcessTerminationCallbackPending); + + CleanupOutdatedRequests(); } HRESULT ConnectionManager::SendActivateAppRequest(_In_ ActivationRequestInfo* requestInfo) noexcept try { std::string pdu{ DvcProtocol::CreateActivateAppRequestPdu( - requestInfo->activityId, requestInfo->appUserModelId.c_str(), requestInfo->activationKind, requestInfo->args) }; + requestInfo->activityId, requestInfo->appUserModelId.c_str(), requestInfo->activationKind, requestInfo->serializedActivationArgs) }; RETURN_IF_FAILED(requestInfo->dvcChannel->Write( static_cast(pdu.size()), reinterpret_cast(pdu.data()), nullptr /* pReserved - must be nullptr */)); return S_OK; @@ -469,18 +523,15 @@ namespace Microsoft::Kozani::Manager { if (it->dvcChannel == channel) { - if (it->statusCallback != nullptr) - { - LOG_IF_FAILED(it->statusCallback->OnClosed()); - it->statusCallback.reset(); - } - it = m_activationRequests.erase(it); + CloseRequest(it); } else { it++; } } + + CleanupOutdatedRequests(); } void ConnectionManager::OnRemoteDesktopInitializeConnection(_In_ IWTSVirtualChannelManager* channelManager) @@ -522,17 +573,107 @@ namespace Microsoft::Kozani::Manager { if (it->dvcChannelManager == channelManager) { - if (it->statusCallback != nullptr) - { - LOG_IF_FAILED(it->statusCallback->OnClosed()); - it->statusCallback.reset(); - } - it = m_activationRequests.erase(it); + CloseRequest(it); } else { it++; } } + + CleanupOutdatedRequests(); + } + + // Caller must have m_requestsLock in lock_exclusive() state. + void ConnectionManager::CloseRequest(std::list::iterator& it) + { + // We no longer need to track the associated local process as the request is closed. + // Disabling the associated local process tracker also prevents unnecessary handling if the associated local process + // is terminated due to us calling IKozaniStatusCallback::OnClosed() to report the activation request is closed, + // which may cause it to terminate the associated local process. + bool localProcessTerminationCallbackPending{}; + const HRESULT hrDisableProcessLifetimeTracker{ LOG_IF_FAILED(DisableProcessLifetimeTracker(&(*it), localProcessTerminationCallbackPending)) }; + + if (it->status == RequestStatus::Connecting) + { + RemoveRequestFromPendingConnectionList(&(*it)); + } + + // Report status change AFTER disabling the local process tracker to avoid triggering the local process to exit before the + // tracker is disabled. + it->status = RequestStatus::Closed; + it->statusReporter->SetStatus(RequestStatus::Closed); + + if (it->statusCallback != nullptr) + { + LOG_IF_FAILED(it->statusCallback->OnClosed()); + it->statusCallback.reset(); + } + + if (it->activityId != ActivationRequestInfo::ActivityId_Unknown) + { + m_activityMap.erase(it->activityId); + } + + if (SUCCEEDED(hrDisableProcessLifetimeTracker) && !localProcessTerminationCallbackPending) + { + it = m_activationRequests.erase(it); + } + else + { + it++; + } + } + + // Caller must have m_requestsLock in lock_exclusive() state. + void ConnectionManager::RemoveRequestFromPendingConnectionList(_In_ const ActivationRequestInfo* request) + { + for (auto it = m_requestsPendingConnection.begin(); it != m_requestsPendingConnection.end(); it++) + { + if (request == *it) + { + m_requestsPendingConnection.erase(it); + break; + } + } + } + + // Caller must have m_requestsLock in lock_exclusive() state. + void ConnectionManager::RemoveRequest(_In_ const ActivationRequestInfo* request, bool removeFromMainList) + { + if (request->status == RequestStatus::Connecting) + { + RemoveRequestFromPendingConnectionList(request); + } + + // ActivityId_Unknown (0) is reserved for uninitialized state (ConnectionAck has not been received from DVC server yet) and will not be in m_activityMap. + if (request->activityId != ActivationRequestInfo::ActivityId_Unknown) + { + m_activityMap.erase(request->activityId); + } + + if (removeFromMainList) + { + m_activationRequests.erase(request->listPosition); + } + } + + // Caller must have m_requestsLock in lock_exclusive() state. + void ConnectionManager::CleanupOutdatedRequests() + { + uint64_t currentTickCount{ GetTickCount64() }; + for (auto it = m_activationRequests.begin(); it != m_activationRequests.end();) + { + if (it->processLifetimeTrackerDisabled && (it->status == RequestStatus::Closed || it->status == RequestStatus::Failed)) + { + uint64_t timePassed{ currentTickCount - it->processLifetimeTrackerDisabledTime }; + if (timePassed > ActivationRequestInfo::MinCleanupDelay) + { + it = m_activationRequests.erase(it); + continue; + } + } + it++; + } } } diff --git a/dev/Kozani/KozaniManager/ConnectionManager.h b/dev/Kozani/KozaniManager/ConnectionManager.h index 258b540392..89e6d2eefa 100644 --- a/dev/Kozani/KozaniManager/ConnectionManager.h +++ b/dev/Kozani/KozaniManager/ConnectionManager.h @@ -3,6 +3,8 @@ #pragma once +#include + namespace Microsoft::Kozani::Manager { // Max amount of time we will wait for the DVC plugin to be loaded by the remote desktop client (RDC) since we launches it. @@ -68,12 +70,19 @@ namespace Microsoft::Kozani::Manager { static const uint64_t ActivityId_Unknown{}; + // Minimum cleanup delay after the associated local process lifetime tracker is disabled: 60 seconds. + // When the request status becomes Closed or Failed, we want to unregister the wait handle for tracking the associated local process. + // However, the unregistration can fail with ERROR_IO_PENDING if there is an outstanding callback to be made. In such a case, we cannot + // clean up the ActivationRequestInfo object as it will be accessed from the callback function. We will clean up the object later with + // this minimum delay to allow the callbak to finish. + static const int MinCleanupDelay{ 60 * 1000 }; + uint64_t activityId{}; RequestStatus status{}; std::string connectionId; std::wstring appUserModelId; winrt::Windows::ApplicationModel::Activation::ActivationKind activationKind{}; - winrt::Windows::ApplicationModel::Activation::IActivatedEventArgs args; + std::string serializedActivationArgs; wil::com_ptr statusCallback; wil::com_ptr dvcChannelManager; wil::com_ptr dvcChannel; @@ -81,9 +90,9 @@ namespace Microsoft::Kozani::Manager std::shared_ptr statusReporter; ConnectionManager* connectionManager{}; DWORD associatedLocalProcessId{}; - wil::unique_handle associatedLocalProcessHandle; unique_wait_handle processLifetimeTrackerHandle; bool processLifetimeTrackerDisabled{}; + uint64_t processLifetimeTrackerDisabledTime{}; }; class ConnectionManager @@ -97,6 +106,8 @@ namespace Microsoft::Kozani::Manager _In_ IKozaniStatusCallback* statusCallback, DWORD associatedLocalProcessId); + void CleanupActivationRequest(_In_ const ActivationRequestStatusReporter* statusReporter); + void Close(); void ProcessProtocolDataUnit( @@ -129,17 +140,23 @@ namespace Microsoft::Kozani::Manager void ProcessAppActivationFailure( HRESULT hrActivation, - uint64_t activityId, _In_ ActivationRequestInfo* requestInfo, _In_ PCWSTR errorMessage); - void DisableProcessLifetimeTracker(uint64_t activityId); + HRESULT DisableProcessLifetimeTracker(ActivationRequestInfo* requestInfo, _Out_ bool& callbackPending) noexcept; + void ProcessAppTerminationNotice(_In_ const Dvc::ProtocolDataUnit& pdu); HRESULT SendActivateAppRequest(_In_ ActivationRequestInfo* requestInfo) noexcept; HRESULT SendAppTerminationNotice(_In_ ActivationRequestInfo* requestInfo) noexcept; + void CloseRequest(std::list::iterator& it); + + void RemoveRequestFromPendingConnectionList(_In_ const ActivationRequestInfo* request); + void RemoveRequest(_In_ const ActivationRequestInfo* request, bool removeFromMainList); + void CleanupOutdatedRequests(); + private: std::list m_activationRequests; std::list m_requestsPendingConnection; diff --git a/dev/Kozani/KozaniManager/KozaniManager.vcxproj b/dev/Kozani/KozaniManager/KozaniManager.vcxproj index db99763373..fec423d525 100644 --- a/dev/Kozani/KozaniManager/KozaniManager.vcxproj +++ b/dev/Kozani/KozaniManager/KozaniManager.vcxproj @@ -171,6 +171,9 @@ {400ed5ec-4530-4adb-8dce-9d1e6708a1f5} + + {3f28c3ed-2548-4530-8b6c-832fae0e993d} + diff --git a/dev/Kozani/KozaniManager/KozaniManagerActivity.cpp b/dev/Kozani/KozaniManager/KozaniManagerActivity.cpp index c3d37bac0e..23fe9fb567 100644 --- a/dev/Kozani/KozaniManager/KozaniManagerActivity.cpp +++ b/dev/Kozani/KozaniManager/KozaniManagerActivity.cpp @@ -32,7 +32,7 @@ class KozaniDvcCallback : public Microsoft::WRL::RuntimeClass< // HRESULT STDMETHODCALLTYPE OnDataReceived(ULONG size, _In_reads_(size) BYTE* data) override try { - LOG_HR_MSG(KOZANI_S_INFO, "IWTSVirtualChannelCallback::OnDataReceived(), cbSize = %u, pChannelMgr=0x%p, pChannel=0x%p", + LOG_HR_MSG(KOZANI_E_INFO, "IWTSVirtualChannelCallback::OnDataReceived(), cbSize = %u, pChannelMgr=0x%p, pChannel=0x%p", size, m_channelManager.get(), m_channel.get()); g_connectionManager.ProcessProtocolDataUnit(data, size, m_channelManager.get(), m_channel.get()); @@ -42,7 +42,7 @@ class KozaniDvcCallback : public Microsoft::WRL::RuntimeClass< HRESULT STDMETHODCALLTYPE OnClose() override try { - LOG_HR_MSG(KOZANI_S_INFO, "IWTSVirtualChannelCallback::OnClose() - pChannelMgr=0x%p, pChannel=0x%p", + LOG_HR_MSG(KOZANI_E_INFO, "IWTSVirtualChannelCallback::OnClose() - pChannelMgr=0x%p, pChannel=0x%p", m_channelManager.get(), m_channel.get()); g_connectionManager.OnDvcChannelClose(m_channel.get()); @@ -64,7 +64,7 @@ struct __declspec(uuid(PR_KOZANIDVC_CLSID_STRING)) KozaniDvcImpl WrlFinal : Runt STDMETHODIMP Initialize(IWTSVirtualChannelManager* pChannelMgr) override try { // Called early in MSRDC launch, before a connection to a new remote session. - LOG_HR_MSG(KOZANI_S_INFO, "IWTSPlugin::Initialize() - pChannelMgr=0x%p", pChannelMgr); + LOG_HR_MSG(KOZANI_E_INFO, "IWTSPlugin::Initialize() - pChannelMgr=0x%p", pChannelMgr); m_channelManager = pChannelMgr; @@ -84,14 +84,14 @@ struct __declspec(uuid(PR_KOZANIDVC_CLSID_STRING)) KozaniDvcImpl WrlFinal : Runt STDMETHODIMP Connected() override try { - LOG_HR_MSG(KOZANI_S_INFO, "IWTSPlugin::Connected() - pChannelMgr=0x%p", m_channelManager.get()); + LOG_HR_MSG(KOZANI_E_INFO, "IWTSPlugin::Connected() - pChannelMgr=0x%p", m_channelManager.get()); return S_OK; } CATCH_RETURN() STDMETHODIMP Disconnected(DWORD dwDisconnectCode) override try { - LOG_HR_MSG(KOZANI_S_INFO, "IWTSPlugin::Disconnected() - pChannelMgr=0x%p, dwDisconnectCode = %u", m_channelManager.get(), dwDisconnectCode); + LOG_HR_MSG(KOZANI_E_INFO, "IWTSPlugin::Disconnected() - pChannelMgr=0x%p, dwDisconnectCode = %u", m_channelManager.get(), dwDisconnectCode); g_connectionManager.OnRemoteDesktopDisconnect(m_channelManager.get()); return S_OK; } @@ -99,7 +99,7 @@ struct __declspec(uuid(PR_KOZANIDVC_CLSID_STRING)) KozaniDvcImpl WrlFinal : Runt STDMETHODIMP Terminated() override try { - LOG_HR_MSG(KOZANI_S_INFO, "IWTSPlugin::Terminated() - pChannelMgr=0x%p", m_channelManager.get()); + LOG_HR_MSG(KOZANI_E_INFO, "IWTSPlugin::Terminated() - pChannelMgr=0x%p", m_channelManager.get()); g_connectionManager.OnRemoteDesktopDisconnect(m_channelManager.get()); return S_OK; } @@ -114,7 +114,7 @@ struct __declspec(uuid(PR_KOZANIDVC_CLSID_STRING)) KozaniDvcImpl WrlFinal : Runt _Out_ BOOL* pbAccept, _Out_ IWTSVirtualChannelCallback** ppCallback) override try { - LOG_HR_MSG(KOZANI_S_INFO, "IWTSListenerCallback::OnNewChannelConnection is called! pChannelMgr=0x%p, pChannel=0x%p", + LOG_HR_MSG(KOZANI_E_INFO, "IWTSListenerCallback::OnNewChannelConnection is called! pChannelMgr=0x%p, pChannel=0x%p", m_channelManager.get(), pChannel); auto pConnection = Make(pChannel, m_channelManager.get()); diff --git a/dev/Kozani/KozaniManager/main.cpp b/dev/Kozani/KozaniManager/main.cpp index 31da9e4636..60174a6b13 100644 --- a/dev/Kozani/KozaniManager/main.cpp +++ b/dev/Kozani/KozaniManager/main.cpp @@ -15,6 +15,8 @@ #include +#include + #include #include "KozaniDvc-Constants.h" #include "ConnectionManager.h" @@ -85,23 +87,27 @@ struct __declspec(uuid(PR_KOZANIMANAGER_CLSID_STRING)) KozaniManagerImpl WrlFina { STDMETHODIMP ActivateRemoteApplication( INT32 activationKind, - PCWSTR appUserModelId, - PCWSTR connectionRdpFilePath, - PCWSTR additionalSettingsFilePath, - ::IInspectable* activatedEventArgs, - IKozaniStatusCallback* statusCallback, - DWORD associatedLocalProcessId) noexcept try + _In_ PCWSTR appUserModelId, + _In_ PCWSTR connectionRdpFilePath, + _In_ IKozaniRemoteDesktopClientLauncher* rdcLauncher, + DWORD associatedLocalProcessId, + _In_opt_::IInspectable* activatedEventArgs, + _In_opt_ IKozaniStatusCallback* statusCallback, + _In_opt_ PCWSTR additionalSettingsFilePath) noexcept try { + RETURN_HR_IF_NULL(E_INVALIDARG, appUserModelId); + RETURN_HR_IF_NULL(E_INVALIDARG, connectionRdpFilePath); + RETURN_HR_IF_NULL(E_INVALIDARG, rdcLauncher); + const auto activationKindLocal{ static_cast(activationKind) }; RETURN_HR_IF_MSG(KOZANI_E_UNSUPPORTED_ACTIVATION_KIND, !IsActivationKindSupported(activationKindLocal), "Activation kind: %d", activationKind); winrt::Windows::ApplicationModel::Activation::IActivatedEventArgs args; - if (!activatedEventArgs) + if (activatedEventArgs) { - winrt::com_ptr<::IInspectable> inspectable(activatedEventArgs, winrt::take_ownership_from_abi); - args = inspectable.as(); + args = winrt::convert_from_abi(activatedEventArgs); } std::string connectionId{ GetConnectionId(connectionRdpFilePath) }; @@ -110,16 +116,15 @@ struct __declspec(uuid(PR_KOZANIMANAGER_CLSID_STRING)) KozaniManagerImpl WrlFina std::shared_ptr requestStatusReporter{ g_connectionManager.AddNewActivationRequest(connectionId, activationKindLocal, appUserModelId, args, statusCallback, associatedLocalProcessId) }; - const LONG connectionCountBeforeRDCLaunch{ InterlockedAdd(&g_newConnectionCount, 0) }; + // If failure happens after this point, we will automatically cleanup the new request from tracking mechanism. + auto cleanupRequestOnFailure = wil::scope_exit([&]() + { + g_connectionManager.CleanupActivationRequest(requestStatusReporter.get()); + }); - SHELLEXECUTEINFO shellExecuteInfo{}; - shellExecuteInfo.cbSize = sizeof(shellExecuteInfo); - shellExecuteInfo.fMask = SEE_MASK_NOASYNC; // Will wait for ShellExecuteEx to finish launching the remote desktop client. - shellExecuteInfo.lpFile = Dvc::Constants::RemoteDesktopClientExe; - shellExecuteInfo.lpParameters = connectionRdpFilePath; - shellExecuteInfo.nShow = SW_NORMAL; + const LONG connectionCountBeforeRDCLaunch{ InterlockedAdd(&g_newConnectionCount, 0) }; - RETURN_IF_WIN32_BOOL_FALSE_MSG(ShellExecuteEx(&shellExecuteInfo), "ShellExecuteEx failed to launch %ls", Dvc::Constants::RemoteDesktopClientExe); + RETURN_IF_FAILED(rdcLauncher->Launch(connectionRdpFilePath, nullptr)); // Wait for request status change or time out to ensure this module is alive for RDC to load the DVC plugin hosted by the module. // If the module is exiting while RDC is loading the DVC plugin, the DVC loading will fail and RDC will ignore the failure and @@ -141,6 +146,7 @@ struct __declspec(uuid(PR_KOZANIMANAGER_CLSID_STRING)) KozaniManagerImpl WrlFina // finish cannot be determined. The user may take some time to enter the password to login and the login can take time // to finish depending on the server's workload. The IKozaniStatusCallback object will be used by the DVC to communicate // any issues in this longer process. + cleanupRequestOnFailure.release(); return S_OK; } } @@ -159,6 +165,8 @@ struct __declspec(uuid(PR_KOZANIMANAGER_CLSID_STRING)) KozaniManagerImpl WrlFina RETURN_HR(E_APPLICATION_ACTIVATION_TIMED_OUT); } + // No failures before returning - disable the auto cleanup on failure logic. + cleanupRequestOnFailure.release(); return S_OK; } CATCH_RETURN() @@ -168,6 +176,10 @@ struct __declspec(uuid(PR_KOZANIMANAGER_CLSID_STRING)) KozaniManagerImpl WrlFina switch (kind) { case winrt::Windows::ApplicationModel::Activation::ActivationKind::Launch: + [[fallthrough]]; + case winrt::Windows::ApplicationModel::Activation::ActivationKind::File: + [[fallthrough]]; + case winrt::Windows::ApplicationModel::Activation::ActivationKind::Protocol: return true; } @@ -185,6 +197,9 @@ void EndOfTheLine() int WINAPI WinMain(HINSTANCE /*hInstance*/, HINSTANCE /*hPrevInstance*/, PSTR /*lpCmdLine*/, int /*nCmdShow*/) { + // Hook up wil logging MACROs to trace provider. + wil::SetResultLoggingCallback(&TraceFailureFromProvider); + // Verify that the version of the library that we linked against is // compatible with the version of the headers we compiled against. GOOGLE_PROTOBUF_VERIFY_VERSION; diff --git a/dev/Kozani/KozaniManager/packages.config b/dev/Kozani/KozaniManager/packages.config index ba003992c7..8d63d7f888 100644 --- a/dev/Kozani/KozaniManager/packages.config +++ b/dev/Kozani/KozaniManager/packages.config @@ -3,7 +3,7 @@ - + diff --git a/dev/Kozani/KozaniManager/pch.h b/dev/Kozani/KozaniManager/pch.h index aeb83e0f15..3628c2b6e9 100644 --- a/dev/Kozani/KozaniManager/pch.h +++ b/dev/Kozani/KozaniManager/pch.h @@ -36,6 +36,7 @@ #include +#include "KozaniManagerTracelogging.h" #include "KozaniProtobufMessages.h" #include "KozaniDvcProtocol.h" #include "Logging.h" diff --git a/dev/Kozani/KozaniManagerInterface/KozaniManagerInterface.idl b/dev/Kozani/KozaniManagerInterface/KozaniManagerInterface.idl index 79421278f3..cb752270dd 100644 --- a/dev/Kozani/KozaniManagerInterface/KozaniManagerInterface.idl +++ b/dev/Kozani/KozaniManagerInterface/KozaniManagerInterface.idl @@ -19,6 +19,16 @@ interface IKozaniStatusCallback : IInspectable HRESULT OnClosed(); }; +[object] +[uuid(43665c78-faf6-4534-9411-321147fc80ea)] +[pointer_default(unique)] +interface IKozaniRemoteDesktopClientLauncher : IUnknown +{ + HRESULT Launch( + [in, string] LPCWSTR connectionRdpFilePath, + [in, string, unique] LPCWSTR userName); +}; + [object] [uuid(5882f14f-f954-4af9-bbeb-a7c1a2a6357e)] [pointer_default(unique)] @@ -28,8 +38,10 @@ interface IKozaniManager : IUnknown INT32 activationKind, [in, string] LPCWSTR appUserModelId, [in, string] LPCWSTR connectionRdpFilePath, - [in, string] LPCWSTR additionalSettingsFilePath, - [in] IInspectable* activatedEventArgs, - [in] IKozaniStatusCallback* statusCallback, - DWORD associatedLocalProcessId); + [in] IKozaniRemoteDesktopClientLauncher* rdcLauncher, + DWORD associatedLocalProcessId, // Use 0 if the remote app is not associated with a local process (no tracking local process for lifetime management). + [in, unique] IInspectable* activatedEventArgs, // optional - can be nullptr if there are no activatedEventArgs + [in, unique] IKozaniStatusCallback* statusCallback, // optional - can be nullptr if the caller does not need status update callbacks + [in, string, unique] LPCWSTR additionalSettingsFilePath // optional - can be nullptr if the additional settings file does not exist + ); }; diff --git a/dev/Kozani/KozaniManagerRuntime/KozaniManagerRuntime.idl b/dev/Kozani/KozaniManagerRuntime/KozaniManagerRuntime.idl index 7329be07ee..b5a7cffb6e 100644 --- a/dev/Kozani/KozaniManagerRuntime/KozaniManagerRuntime.idl +++ b/dev/Kozani/KozaniManagerRuntime/KozaniManagerRuntime.idl @@ -15,10 +15,10 @@ namespace Microsoft.Kozani.ManagerRuntime Windows.ApplicationModel.Activation.ActivationKind activationKind, String appUserModelId, String connectionRdpFilePath, - String additionalSettingsFilePath, - Windows.ApplicationModel.Activation.IActivatedEventArgs args, // optional, can be nullptr - IInspectable statusCallback, - UInt32 associatedLocalProcessId // optional, use 0 if you don't want the remote app lifetime to be tied to the lifetime of an associated local process + UInt32 associatedLocalProcessId, // optional, use 0 if you don't want the remote app lifetime to be tied to the lifetime of an associated local process + Windows.ApplicationModel.Activation.IActivatedEventArgs args, // optional - can be nullptr if there are no activatedEventArgs for Launch ActivationKind + IInspectable statusCallback, // optional - can be nullptr if the caller does not need status update callbacks + String additionalSettingsFilePath // optional - can be empty String if the additional settings file does not exist ); }; } diff --git a/dev/Kozani/KozaniManagerRuntime/KozaniManagerRuntime.vcxproj b/dev/Kozani/KozaniManagerRuntime/KozaniManagerRuntime.vcxproj index c6a3bf3240..4f9f83ecd7 100644 --- a/dev/Kozani/KozaniManagerRuntime/KozaniManagerRuntime.vcxproj +++ b/dev/Kozani/KozaniManagerRuntime/KozaniManagerRuntime.vcxproj @@ -92,7 +92,7 @@ - (MSBuildThisFileDirectory);$(OutDir)..\KozaniManagerProxyStub;$(OutDir)\..\WindowsAppRuntime_DLL;$(RepoRoot)\dev\WindowsAppRuntime_Insights;$(RepoRoot)\dev\common;$(IntDir);%(AdditionalIncludeDirectories) + (MSBuildThisFileDirectory);$(OutDir)..\KozaniManagerProxyStub;$(OutDir)\..\WindowsAppRuntime_DLL;$(RepoRoot)\dev\WindowsAppRuntime_Insights;$(RepoRoot)\dev\common;$(IntDir);$(RepoRoot)\dev\Kozani\common;%(AdditionalIncludeDirectories) Use pch.h KOZANIMANAGERRUNTIMEDLL_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) diff --git a/dev/Kozani/KozaniManagerRuntime/KozaniManagerRuntime.vcxproj.filters b/dev/Kozani/KozaniManagerRuntime/KozaniManagerRuntime.vcxproj.filters index c120a9f8e2..95a6c26388 100644 --- a/dev/Kozani/KozaniManagerRuntime/KozaniManagerRuntime.vcxproj.filters +++ b/dev/Kozani/KozaniManagerRuntime/KozaniManagerRuntime.vcxproj.filters @@ -71,4 +71,7 @@ Resource Files - + + + + \ No newline at end of file diff --git a/dev/Kozani/KozaniManagerRuntime/M.K.MR.ManagerRuntimeManager.cpp b/dev/Kozani/KozaniManagerRuntime/M.K.MR.ManagerRuntimeManager.cpp index eded8cdd46..eb5ac32d20 100644 --- a/dev/Kozani/KozaniManagerRuntime/M.K.MR.ManagerRuntimeManager.cpp +++ b/dev/Kozani/KozaniManagerRuntime/M.K.MR.ManagerRuntimeManager.cpp @@ -2,13 +2,31 @@ // Licensed under the MIT License. See LICENSE in the project root for license information. #include "pch.h" - #include "M.K.MR.ManagerRuntimeManager.h" - #include "ManagerRuntimeManager.g.cpp" namespace winrt::Microsoft::Kozani::ManagerRuntime::implementation { + constexpr PCWSTR c_remoteDesktopClientExe = L"mstsc.exe"; + + struct KozaniRemoteDesktopClientLauncher : winrt::implements + { + STDMETHODIMP Launch(_In_ PCWSTR connectionRdpFilePath, _In_opt_ PCWSTR /* userName */) + { + RETURN_HR_IF_NULL(E_INVALIDARG, connectionRdpFilePath); + + SHELLEXECUTEINFO shellExecuteInfo{}; + shellExecuteInfo.cbSize = sizeof(shellExecuteInfo); + shellExecuteInfo.fMask = SEE_MASK_NOASYNC; // Will wait for ShellExecuteEx to finish launching the remote desktop client. + shellExecuteInfo.lpFile = c_remoteDesktopClientExe; + shellExecuteInfo.lpParameters = connectionRdpFilePath; + shellExecuteInfo.nShow = SW_NORMAL; + + RETURN_IF_WIN32_BOOL_FALSE_MSG(ShellExecuteEx(&shellExecuteInfo), "ShellExecuteEx failed to launch %ls", c_remoteDesktopClientExe); + return S_OK; + } + }; + ManagerRuntimeManager::ManagerRuntimeManager() { m_kozaniManager = wil::CoCreateInstance(CLSCTX_LOCAL_SERVER); @@ -23,18 +41,27 @@ namespace winrt::Microsoft::Kozani::ManagerRuntime::implementation Windows::ApplicationModel::Activation::ActivationKind activationKind, winrt::hstring appUserModelId, winrt::hstring connectionRdpFilePath, - winrt::hstring additionalSettingsFilePath, + UINT32 associatedLocalProcessId, Windows::ApplicationModel::Activation::IActivatedEventArgs args, IInspectable statusCallback, - UINT32 associatedLocalProcessId) + winrt::hstring additionalSettingsFilePath) { + // The purpose of IKozaniRemoteDesktopClientLauncher is to allow the caller of the IKozaniManager::ActivateRemoteApplication API + // to launch remote desktop client (RDC) in its process. The COM server hosting the IKozaniManager APIs is a background process, + // which may not be able to launch the RDC to desktop foreground. From experiments we've found that if the caller process is a + // foregrounddoes process (e.g., just got activated from Start Menu) but does not display a window (process with no UIs), launching + // RDC from its process will show the RDC in foreground, while launching RDC in the IKozaniManager APIs COM server process will + // have the RDC window in background with flashing icon on the taskbar. + auto rdcLauncher{ winrt::make_self() }; + winrt::check_hresult(m_kozaniManager->ActivateRemoteApplication( static_cast(activationKind), appUserModelId.c_str(), connectionRdpFilePath.c_str(), - additionalSettingsFilePath.c_str(), - reinterpret_cast<::IInspectable*>(winrt::get_abi(args)), - reinterpret_cast<::IKozaniStatusCallback*>(winrt::get_abi(statusCallback)), - associatedLocalProcessId)); + reinterpret_cast<::IKozaniRemoteDesktopClientLauncher*>(winrt::get_abi(rdcLauncher)), + associatedLocalProcessId, + args.as<::IInspectable>().get(), + statusCallback.as<::IKozaniStatusCallback>().get(), + additionalSettingsFilePath.c_str())); } } diff --git a/dev/Kozani/KozaniManagerRuntime/M.K.MR.ManagerRuntimeManager.h b/dev/Kozani/KozaniManagerRuntime/M.K.MR.ManagerRuntimeManager.h index eeaf2ad0e9..446301a917 100644 --- a/dev/Kozani/KozaniManagerRuntime/M.K.MR.ManagerRuntimeManager.h +++ b/dev/Kozani/KozaniManagerRuntime/M.K.MR.ManagerRuntimeManager.h @@ -18,10 +18,10 @@ namespace winrt::Microsoft::Kozani::ManagerRuntime::implementation Windows::ApplicationModel::Activation::ActivationKind activationKind, winrt::hstring appUserModelId, winrt::hstring connectionRdpFilePath, - winrt::hstring additionalSettingsFilePath, + UINT32 associatedLocalProcessId, Windows::ApplicationModel::Activation::IActivatedEventArgs args, IInspectable statusCallback, - UINT32 associatedLocalProcessId); + winrt::hstring additionalSettingsFilePath); private: wil::com_ptr m_kozaniManager; diff --git a/dev/Kozani/KozaniManagerRuntime/dllmain.cpp b/dev/Kozani/KozaniManagerRuntime/dllmain.cpp index 2da5b862d4..3cc4d89335 100644 --- a/dev/Kozani/KozaniManagerRuntime/dllmain.cpp +++ b/dev/Kozani/KozaniManagerRuntime/dllmain.cpp @@ -12,6 +12,8 @@ BOOL APIENTRY DllMain(HMODULE hmodule, DWORD reason, LPVOID reserved) switch (reason) { case DLL_PROCESS_ATTACH: + // Hook up wil logging MACROs to trace provider. + wil::SetResultLoggingCallback(&TraceFailureFromProvider); DisableThreadLibraryCalls(hmodule); case DLL_THREAD_ATTACH: case DLL_THREAD_DETACH: diff --git a/dev/Kozani/KozaniManagerRuntime/packages.config b/dev/Kozani/KozaniManagerRuntime/packages.config index 14efb7baf5..cd05427e9c 100644 --- a/dev/Kozani/KozaniManagerRuntime/packages.config +++ b/dev/Kozani/KozaniManagerRuntime/packages.config @@ -3,6 +3,6 @@ - + diff --git a/dev/Kozani/KozaniManagerRuntime/pch.h b/dev/Kozani/KozaniManagerRuntime/pch.h index be289b02c9..e0a5cd8dae 100644 --- a/dev/Kozani/KozaniManagerRuntime/pch.h +++ b/dev/Kozani/KozaniManagerRuntime/pch.h @@ -16,5 +16,6 @@ #include "framework.h" #include "KozaniManagerRuntimeActivity.h" #include "KozaniManagerRuntimeTraceLogging.h" +#include "Logging.h" #endif //PCH_H diff --git a/dev/Kozani/KozaniPackage/packages.config b/dev/Kozani/KozaniPackage/packages.config index 14efb7baf5..cd05427e9c 100644 --- a/dev/Kozani/KozaniPackage/packages.config +++ b/dev/Kozani/KozaniPackage/packages.config @@ -3,6 +3,6 @@ - + diff --git a/dev/Kozani/KozaniProtocol/Kozani.DVC.proto b/dev/Kozani/KozaniProtocol/Kozani.DVC.proto index 4ef02b3b46..8993e951f8 100644 --- a/dev/Kozani/KozaniProtocol/Kozani.DVC.proto +++ b/dev/Kozani/KozaniProtocol/Kozani.DVC.proto @@ -65,3 +65,14 @@ message LaunchActivationArgs { string arguments = 1; } + +message FileActivationArgs +{ + string verb = 1; + repeated string file_paths = 2; +} + +message ProtocolActivationArgs +{ + string uri = 1; +} \ No newline at end of file diff --git a/dev/Kozani/KozaniRemoteManager/ConnectionManager.cpp b/dev/Kozani/KozaniRemoteManager/ConnectionManager.cpp index 6337149279..d43b354273 100644 --- a/dev/Kozani/KozaniRemoteManager/ConnectionManager.cpp +++ b/dev/Kozani/KozaniRemoteManager/ConnectionManager.cpp @@ -42,7 +42,7 @@ namespace Microsoft::Kozani::KozaniRemoteManager } CATCH_LOG_RETURN() - void ConnectionManager::Connect(PCSTR connectionId) + void ConnectionManager::Connect(PCSTR connectionId, IKozaniApplicationLauncher* appLauncher) { auto lock{ std::unique_lock(m_dvcServerLock) }; @@ -88,7 +88,7 @@ namespace Microsoft::Kozani::KozaniRemoteManager } } - m_dvcServer->SendConnectionAck(connectionId); + m_dvcServer->ProcessClientConnection(connectionId, appLauncher); } // Report error from DVC server object. Called from the DVC server object encounting error. diff --git a/dev/Kozani/KozaniRemoteManager/ConnectionManager.h b/dev/Kozani/KozaniRemoteManager/ConnectionManager.h index 8c46b3d038..0b1a6355be 100644 --- a/dev/Kozani/KozaniRemoteManager/ConnectionManager.h +++ b/dev/Kozani/KozaniRemoteManager/ConnectionManager.h @@ -15,7 +15,7 @@ namespace Microsoft::Kozani::KozaniRemoteManager ~ConnectionManager() noexcept; - void Connect(PCSTR connectionId); + void Connect(_In_ PCSTR connectionId, _In_ IKozaniApplicationLauncher* appLauncher); void ReportDvcServerError(HRESULT hr); private: diff --git a/dev/Kozani/KozaniRemoteManager/KozaniDvcServer.cpp b/dev/Kozani/KozaniRemoteManager/KozaniDvcServer.cpp index 7c45d3a631..36af192dac 100644 --- a/dev/Kozani/KozaniRemoteManager/KozaniDvcServer.cpp +++ b/dev/Kozani/KozaniRemoteManager/KozaniDvcServer.cpp @@ -4,7 +4,6 @@ #pragma once #include "pch.h" -#include #include #include @@ -83,6 +82,16 @@ namespace Microsoft::Kozani::KozaniRemoteManager return S_OK; } + void KozaniDvcServer::ProcessClientConnection(_In_ PCSTR connectionId, _In_ IKozaniApplicationLauncher* appLauncher) + { + { + auto lock{ m_appLauncherLock.lock_exclusive() }; + m_appLauncher = appLauncher; + } + + SendConnectionAck(connectionId); + } + void KozaniDvcServer::OpenDvc() { auto lock{ std::unique_lock(m_dvcLock) }; @@ -151,13 +160,13 @@ namespace Microsoft::Kozani::KozaniRemoteManager } HANDLE events[]{ m_dvcThreadExit.get(), readComplete.get() }; - LOG_HR_MSG(KOZANI_S_INFO, "[DVC] Listener thread starting to wait"); + LOG_HR_MSG(KOZANI_E_INFO, "[DVC] Listener thread starting to wait"); // When we reach this point, the DVC listener thread has passed setup phase and is running. m_dvcThreadStarted.SetEvent(); const DWORD result{ WaitForMultipleObjects(ARRAYSIZE(events), events, FALSE, INFINITE) }; - LOG_HR_MSG(KOZANI_S_INFO, "[DVC] Listener thread wait completed (result=0x%x)", result); + LOG_HR_MSG(KOZANI_E_INFO, "[DVC] Listener thread wait completed (result=0x%x)", result); if (result == WAIT_FAILED) { hr = HRESULT_FROM_WIN32(GetLastError()); @@ -170,7 +179,7 @@ namespace Microsoft::Kozani::KozaniRemoteManager case WAIT_OBJECT_0: { // Thread exit handle signaled. - LOG_HR_MSG(KOZANI_S_INFO, "[DVC] Thread exit event handled"); + LOG_HR_MSG(KOZANI_E_INFO, "[DVC] Thread exit event handled"); return S_OK; } @@ -346,6 +355,10 @@ namespace Microsoft::Kozani::KozaniRemoteManager connectionManager.m_activityMap.erase(pdu.activity_id()); } + + wchar_t textBuffer[300]{}; + swprintf(textBuffer, ARRAYSIZE(textBuffer), L"Error code: 0x%x, message: %hs", hr, errorMessage.c_str()); + MessageBox(nullptr, textBuffer, L"Error", MB_ICONERROR); } } CATCH_LOG_RETURN() @@ -386,16 +399,19 @@ namespace Microsoft::Kozani::KozaniRemoteManager } } - wil::com_ptr aam; - HRESULT hrCoCreateInstance{ CoCreateInstance(CLSID_ApplicationActivationManager, nullptr, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&aam)) }; - if (FAILED(hrCoCreateInstance)) + std::wstring appUserModelId{ ::Microsoft::Utf8::ToUtf16(activateAppRequest.app_user_model_id()) }; + DWORD processId{}; + + wil::com_ptr appLauncher; { - errorMessage = "Failed to CoCreateInstance CLSID_ApplicationActivationManager."; - RETURN_HR(hrCoCreateInstance); + // Lock and assign m_appLauncher to local com_ptr appLauncher, which adds ref count of the IKozaniApplicationLauncher object to + // keep it alive through this method. m_appLauncher can be replaced with a different object and deref in another thread when there is another + // client connection coming in. Do not hold the lock during app activation so if the current activation takes a long time it will not block + // subsequent activation requests. + auto lock{ m_appLauncherLock.lock_shared() }; + appLauncher = m_appLauncher; } - std::wstring appUserModelId{ ::Microsoft::Utf8::ToUtf16(activateAppRequest.app_user_model_id()) }; - DWORD processId{}; switch (activateAppRequest.activation_kind()) { case Dvc::ActivationKind::Launch: @@ -412,8 +428,8 @@ namespace Microsoft::Kozani::KozaniRemoteManager launchArgs = ::Microsoft::Utf8::ToUtf16(args.arguments()); } - - HRESULT hrActivateApp{ aam->ActivateApplication(appUserModelId.c_str(), launchArgs.c_str(), AO_NONE, &processId) }; + + HRESULT hrActivateApp{ appLauncher->Launch(appUserModelId.c_str(), launchArgs.c_str(), &processId) }; if (FAILED(hrActivateApp)) { errorMessage = "Failed to Activate app."; @@ -423,11 +439,11 @@ namespace Microsoft::Kozani::KozaniRemoteManager break; case Dvc::ActivationKind::File: - // ToDo: https://task.ms/43963854 support FTA launch. + RETURN_IF_FAILED(ProcessFileActivationRequest(appLauncher.get(), appUserModelId, activateAppRequest, processId, errorMessage)); break; case Dvc::ActivationKind::Protocol: - // ToDo: https://task.ms/43963854 support protocol launch. + RETURN_IF_FAILED(ProcessProtocolActivationRequest(appLauncher.get(), appUserModelId, activateAppRequest, processId, errorMessage)); break; default: @@ -482,6 +498,7 @@ namespace Microsoft::Kozani::KozaniRemoteManager { const DWORD errorOpenProcess{ LOG_LAST_ERROR_MSG("ProcessId: %u", processId) }; + //connectionManager.m_processIdMap.erase(processId); connectionManager.m_activityMap.erase(iter); errorMessage = "Failed to OpenProcess after the app is activated. The app may have crashed. Process Id: " + std::to_string(processId); RETURN_WIN32(errorOpenProcess); @@ -512,6 +529,101 @@ namespace Microsoft::Kozani::KozaniRemoteManager } CATCH_RETURN() + HRESULT KozaniDvcServer::ProcessFileActivationRequest( + _In_ IKozaniApplicationLauncher* appLauncher, + const std::wstring& appUserModelId, + const Dvc::ActivateAppRequest& activateAppRequest, + _Out_ DWORD& processId, + _Out_ std::string& errorMessage) noexcept try + { + if (activateAppRequest.arguments().empty()) + { + errorMessage = "Arguments for File activation cannot be empty"; + RETURN_WIN32(ERROR_INVALID_DATA); + } + + Dvc::FileActivationArgs args; + if (!args.ParseFromString(activateAppRequest.arguments())) + { + errorMessage = "Failed to parse File activation arguments"; + RETURN_WIN32(ERROR_INVALID_DATA); + } + + int filePathsCount{ args.file_paths_size() }; + + // There should be at least 1 file path in the FileActivationArgs for file activation to work. + RETURN_HR_IF(HRESULT_FROM_WIN32(ERROR_INVALID_DATA), filePathsCount <= 0); + + std::vector filePathArray; + wistd::unique_ptr filePaths{ new PCWSTR[filePathsCount] }; + RETURN_IF_NULL_ALLOC(filePaths); + + PCWSTR* pFilePaths{ filePaths.get() }; + ZeroMemory(pFilePaths, sizeof(PCWSTR) * filePathsCount); + + for (int i = 0; i < filePathsCount; i++) + { + std::wstring clientLocalPath{ ::Microsoft::Utf8::ToUtf16(args.file_paths(i)) }; + + filePathArray.emplace_back(GetRedirectedClientPath(clientLocalPath)); + pFilePaths[i] = filePathArray.back().c_str(); + } + + KozaniAppType appType{ GetAppType(appUserModelId) }; + std::wstring verb{ ::Microsoft::Utf8::ToUtf16(args.verb()) }; + HRESULT hrActivateApp{ appLauncher->LaunchFiles(appUserModelId.c_str(), verb.c_str(), filePathsCount, pFilePaths, &appType, &processId) }; + if (FAILED(hrActivateApp)) + { + errorMessage = "Failed to activate app for file "; + std::string path{ ::Microsoft::Utf8::ToUtf8(pFilePaths[0]) }; + errorMessage += path; + RETURN_HR(hrActivateApp); + } + + UpdateAppTypeIfNeeded(appUserModelId, appType); + return S_OK; + } + CATCH_RETURN() + + HRESULT KozaniDvcServer::ProcessProtocolActivationRequest( + _In_ IKozaniApplicationLauncher* appLauncher, + const std::wstring& appUserModelId, + const Dvc::ActivateAppRequest& activateAppRequest, + _Out_ DWORD& processId, + _Out_ std::string& errorMessage) noexcept try + { + processId = 0; + errorMessage.clear(); + + if (activateAppRequest.arguments().empty()) + { + errorMessage = "Arguments for Protocol activation cannot be empty"; + RETURN_WIN32(ERROR_INVALID_DATA); + } + + Dvc::ProtocolActivationArgs args; + if (!args.ParseFromString(activateAppRequest.arguments())) + { + errorMessage = "Failed to parse Protocol activation arguments"; + RETURN_WIN32(ERROR_INVALID_DATA); + } + + KozaniAppType appType{ GetAppType(appUserModelId) }; + std::wstring uri{ ::Microsoft::Utf8::ToUtf16(args.uri()) }; + HRESULT hrActivateApp{ appLauncher->LaunchUri(appUserModelId.c_str(), uri.c_str(), &appType, &processId) }; + if (FAILED(hrActivateApp)) + { + errorMessage = "Failed to activate app for URI: "; + std::string uriUtf8{ ::Microsoft::Utf8::ToUtf8(uri) }; + errorMessage += uriUtf8; + RETURN_HR(hrActivateApp); + } + + UpdateAppTypeIfNeeded(appUserModelId, appType); + return S_OK; + } + CATCH_RETURN() + HRESULT KozaniDvcServer::ProcessAppTerminationNotice(_In_ Dvc::ProtocolDataUnit& pdu) noexcept try { ConnectionManager& connectionManager{ KozaniRemoteManagerModule::GetConnectionManagerInstance() }; @@ -549,6 +661,23 @@ namespace Microsoft::Kozani::KozaniRemoteManager } CATCH_RETURN() + // Convert local path from the remote client to a path that can be addressed by the remote desktop server. Local drives of the client have been + // rediected to the server so the server can directly access them. For example, local path "C:\data\MyFile.txt" will be redirected to the server + // side with addressable path "\\tsclient\C\data\MyFile.txt" + std::wstring KozaniDvcServer::GetRedirectedClientPath(const std::wstring& localPath) + { + // UNC paths are not redirected so we return it as it is. + if (localPath.starts_with(L"\\\\")) + { + return localPath; + } + + std::wstring redirectedPath{ L"\\\\tsclient\\" }; + redirectedPath += localPath[0]; + redirectedPath += localPath.substr(2); + return redirectedPath; + } + bool KozaniDvcServer::IsActivationKindSupported(Dvc::ActivationKind kind) { switch (kind) @@ -581,7 +710,7 @@ namespace Microsoft::Kozani::KozaniRemoteManager m_dvcListenerThread = std::thread(&KozaniDvcServer::ProcessDvcIncomingDataThreadFunc, this); HANDLE events[] = { m_dvcThreadStarted.get(), m_dvcThreadExit.get() }; - LOG_HR_MSG(KOZANI_S_INFO, "[StartDvcListenerThread] Waiting for listener thread starting status"); + LOG_HR_MSG(KOZANI_E_INFO, "[StartDvcListenerThread] Waiting for listener thread starting status"); // Wait for listerner thread to start successfully. Wait no longer than 5s. DWORD result = WaitForMultipleObjects(ARRAYSIZE(events), events, FALSE, 5000); @@ -591,7 +720,7 @@ namespace Microsoft::Kozani::KozaniRemoteManager { case WAIT_OBJECT_0: // Thread successfully started and is running. - LOG_HR_MSG(KOZANI_S_INFO, "[StartDvcListenerThread] Listener thread successfully started"); + LOG_HR_MSG(KOZANI_E_INFO, "[StartDvcListenerThread] Listener thread successfully started"); return; case WAIT_OBJECT_0 + 1: @@ -715,4 +844,38 @@ namespace Microsoft::Kozani::KozaniRemoteManager std::string pdu{ CreateAppTerminationNoticePdu(activityId) }; SendDvcProtocolData(pdu.c_str(), static_cast(pdu.size())); } + + // Look up the type of the app from the m_appTypeMap as an optimization, as the launcher finds the type of the app (UWP or packaged desktop app) + // by different activation API behaviors. At first, the app type is unknown for a particular AUMID. Once it is activated for file or protocol, + // the appLauncher returns the app type, so we can cache in the map for faster activation next time. + KozaniAppType KozaniDvcServer::GetAppType(const std::wstring& appUserModelId) + { + auto lock{ m_appTypeMapLock.lock_shared() }; + + KozaniAppType appType{ KozaniAppType_Unknown }; + auto iter{ m_appTypeMap.find(appUserModelId) }; + if (iter != m_appTypeMap.end()) + { + appType = iter->second; + } + return appType; + } + + void KozaniDvcServer::UpdateAppTypeIfNeeded(const std::wstring& appUserModelId, KozaniAppType appType) + { + auto lock{ m_appTypeMapLock.lock_exclusive() }; + + auto iter{ m_appTypeMap.find(appUserModelId) }; + if (iter != m_appTypeMap.end()) + { + if (iter->second != appType) + { + iter->second = appType; + } + } + else + { + m_appTypeMap[appUserModelId] = appType; + } + } } diff --git a/dev/Kozani/KozaniRemoteManager/KozaniDvcServer.h b/dev/Kozani/KozaniRemoteManager/KozaniDvcServer.h index 6574a56d73..d5eadbde24 100644 --- a/dev/Kozani/KozaniRemoteManager/KozaniDvcServer.h +++ b/dev/Kozani/KozaniRemoteManager/KozaniDvcServer.h @@ -3,6 +3,7 @@ #pragma once +#include #include "KozaniDvcProtocol.h" #include "KozaniRemoteManagerTraceLogging.h" @@ -43,7 +44,7 @@ namespace Microsoft::Kozani::KozaniRemoteManager // Enable error reporting to ConnectionManager. Called only after ConnectionManager has successfully created this object. HRESULT EnableConnectionManagerReporting(); - void SendConnectionAck(PCSTR connectionId); + void ProcessClientConnection(_In_ PCSTR connectionId, _In_ IKozaniApplicationLauncher* appLauncher); void SendAppTerminationNotice(uint64_t activityId); private: @@ -70,8 +71,24 @@ namespace Microsoft::Kozani::KozaniRemoteManager _Out_ bool& appActivatedAndTracked, _Out_ std::string& errorMessage) noexcept; + HRESULT ProcessFileActivationRequest( + _In_ IKozaniApplicationLauncher* appLauncher, + const std::wstring& appUserModelId, + const Dvc::ActivateAppRequest& activateAppRequest, + _Out_ DWORD& processId, + _Out_ std::string& errorMessage) noexcept; + + HRESULT ProcessProtocolActivationRequest( + _In_ IKozaniApplicationLauncher* appLauncher, + const std::wstring& appUserModelId, + const Dvc::ActivateAppRequest& activateAppRequest, + _Out_ DWORD& processId, + _Out_ std::string& errorMessage) noexcept; + HRESULT ProcessAppTerminationNotice(_In_ Dvc::ProtocolDataUnit& pdu) noexcept; + std::wstring GetRedirectedClientPath(const std::wstring& localPath); + bool IsActivationKindSupported(Dvc::ActivationKind kind); void OpenDvc(); @@ -80,6 +97,7 @@ namespace Microsoft::Kozani::KozaniRemoteManager void ReportDvcWriterError(HRESULT errorCode); void SendDvcProtocolData(const char* data, UINT32 size); + void SendConnectionAck(PCSTR connectionId); void SendActivateAppResult( uint64_t activityId, HRESULT hr, @@ -87,6 +105,9 @@ namespace Microsoft::Kozani::KozaniRemoteManager bool isNewInstance, _In_ const std::string& errorMessage = std::string()); + KozaniAppType GetAppType(const std::wstring& appUserModelId); + void UpdateAppTypeIfNeeded(const std::wstring& appUserModelId, KozaniAppType appType); + private: wil::srwlock m_errorReportingLock; std::recursive_mutex m_dvcLock; @@ -97,5 +118,11 @@ namespace Microsoft::Kozani::KozaniRemoteManager bool m_errorReportingEnabled{}; HRESULT m_errorFromDvcListener{}; HRESULT m_errorFromDvcWriter{}; + + wil::srwlock m_appLauncherLock; + wil::com_ptr m_appLauncher; + + wil::srwlock m_appTypeMapLock; + std::map m_appTypeMap; }; } diff --git a/dev/Kozani/KozaniRemoteManager/KozaniRemoteManager.vcxproj b/dev/Kozani/KozaniRemoteManager/KozaniRemoteManager.vcxproj index abb4e0f26a..9dc988e14a 100644 --- a/dev/Kozani/KozaniRemoteManager/KozaniRemoteManager.vcxproj +++ b/dev/Kozani/KozaniRemoteManager/KozaniRemoteManager.vcxproj @@ -166,6 +166,9 @@ + + {3f28c3ed-2548-4530-8b6c-832fae0e993d} + {B9933E40-5A7C-482E-9FF3-FC06C1A7B37E} diff --git a/dev/Kozani/KozaniRemoteManager/main.cpp b/dev/Kozani/KozaniRemoteManager/main.cpp index 724226ae1b..20320908c2 100644 --- a/dev/Kozani/KozaniRemoteManager/main.cpp +++ b/dev/Kozani/KozaniRemoteManager/main.cpp @@ -5,8 +5,6 @@ #include "..\KozaniRemoteManager\KozaniRemoteManager-Constants.h" -#include - // Including this file once per binary will automatically opt WIL error handling macros into calling RoOriginateError when they // begin logging a new error. This greatly improves the debuggability of errors that propagate before a failfast. #include @@ -44,13 +42,11 @@ namespace KozaniRemoteManagerModule } }; - - struct __declspec(uuid(PR_KOZANIREMOTEMANAGER_CLSID_STRING)) KozaniRemoteManagerImpl WrlFinal : RuntimeClass, IKozaniRemoteManager> { - STDMETHODIMP Connect(_In_ PCSTR connectionId) noexcept try + STDMETHODIMP Connect(_In_ PCSTR connectionId, IKozaniApplicationLauncher* appLauncher) noexcept try { - g_connectionManager.Connect(connectionId); + g_connectionManager.Connect(connectionId, appLauncher); return S_OK; } CATCH_RETURN() @@ -66,6 +62,9 @@ void EndOfTheLine() int WINAPI WinMain(HINSTANCE /*hInstance*/, HINSTANCE /*hPrevInstance*/, PSTR /*lpCmdLine*/, int /*nCmdShow*/) { + // Hook up wil logging MACROs to trace provider. + wil::SetResultLoggingCallback(&TraceFailureFromProvider); + RETURN_IF_FAILED(::CoInitializeEx(nullptr, COINITBASE_MULTITHREADED)); wil::unique_event endOfTheLine(::CreateEventW(nullptr, TRUE, FALSE, nullptr)); diff --git a/dev/Kozani/KozaniRemoteManager/packages.config b/dev/Kozani/KozaniRemoteManager/packages.config index ba003992c7..8d63d7f888 100644 --- a/dev/Kozani/KozaniRemoteManager/packages.config +++ b/dev/Kozani/KozaniRemoteManager/packages.config @@ -3,7 +3,7 @@ - + diff --git a/dev/Kozani/KozaniRemoteManager/pch.h b/dev/Kozani/KozaniRemoteManager/pch.h index 9d937e645c..daa9b1ea95 100644 --- a/dev/Kozani/KozaniRemoteManager/pch.h +++ b/dev/Kozani/KozaniRemoteManager/pch.h @@ -31,4 +31,5 @@ #include -#include "Logging.h" \ No newline at end of file +#include +#include "Logging.h" diff --git a/dev/Kozani/KozaniRemoteManagerInterface/KozaniRemoteManagerInterface.idl b/dev/Kozani/KozaniRemoteManagerInterface/KozaniRemoteManagerInterface.idl index 3df36ddf69..ca3ca92391 100644 --- a/dev/Kozani/KozaniRemoteManagerInterface/KozaniRemoteManagerInterface.idl +++ b/dev/Kozani/KozaniRemoteManagerInterface/KozaniRemoteManagerInterface.idl @@ -4,6 +4,38 @@ import "oaidl.idl"; import "ocidl.idl"; +typedef [v1_enum] enum KozaniAppType +{ + KozaniAppType_Unknown = 0, + KozaniAppType_PackagedDesktopApp = 1, + KozaniAppType_UWP = 2 +} KozaniAppType; + +[object] +[uuid(0b86ddd1-faba-40dc-b92b-9f29654a97b2)] +[pointer_default(unique)] +interface IKozaniApplicationLauncher : IUnknown +{ + HRESULT Launch( + [in, string] LPCWSTR appUserModelId, + [in, string, unique] LPCWSTR arguments, + [out] DWORD* processId); + + HRESULT LaunchFiles( + [in, string] LPCWSTR appUserModelId, + [in, string] LPCWSTR verb, + UINT32 fileCount, + [in, string, size_is(fileCount)] LPCWSTR* filePaths, + [in, out] KozaniAppType* appType, + [out] DWORD* processId); + + HRESULT LaunchUri( + [in, string] LPCWSTR appUserModelId, + [in, string] LPCWSTR uri, + [in, out] KozaniAppType* appType, + [out] DWORD* processId); +}; + [object] [uuid(30599ceb-631f-468f-bdd6-febc5bb12b81)] [pointer_default(unique)] @@ -11,5 +43,5 @@ interface IKozaniRemoteManager : IUnknown { // Connects to client DVC by opening a DVC channel with Kozani_DVC name and sends back an ACK message with connectionId // to link the connection to the client request. - HRESULT Connect([in, string] LPCSTR connectionId); + HRESULT Connect([in, string] LPCSTR connectionId, [in] IKozaniApplicationLauncher* appLauncher); }; diff --git a/dev/Kozani/KozaniRemoteManagerLauncher/main.cpp b/dev/Kozani/KozaniRemoteManagerLauncher/main.cpp index 288a2db9a9..ff28a929e6 100644 --- a/dev/Kozani/KozaniRemoteManagerLauncher/main.cpp +++ b/dev/Kozani/KozaniRemoteManagerLauncher/main.cpp @@ -2,19 +2,434 @@ // Licensed under the MIT License. #include "pch.h" +#include // Including this file once per binary will automatically opt WIL error handling macros into calling RoOriginateError when they // begin logging a new error. This greatly improves the debuggability of errors that propagate before a failfast. #include +#include +#include +#include #include #include "KozaniDvc-Constants.h" +using namespace Microsoft::WRL; using namespace winrt::Windows::Foundation; using namespace Microsoft::Kozani::DVC; +wil::unique_event g_exitProcess; + +struct KozaniApplicationLauncher : winrt::implements +{ +private: + enum AssociationType + { + File = 0, + Protocol + }; + + const PCWSTR c_registeredPackagedApplicationsPath{ L"SOFTWARE\\RegisteredApplications\\PackagedApps" }; + const PCWSTR c_fileAssociationsKeyName{ L"FileAssociations" }; + const PCWSTR c_protocolAssociationsKeyName{ L"URLAssociations" }; + +public: + STDMETHODIMP Launch(_In_ PCWSTR appUserModelId, _In_opt_ PCWSTR arguments, _Out_ DWORD* processId) noexcept try + { + RETURN_HR_IF_NULL(E_INVALIDARG, appUserModelId); + RETURN_HR_IF_NULL(E_INVALIDARG, processId); + + *processId = 0; + +#ifdef MEASURE_PERF + DWORD startTime = GetTickCount(); +#endif + + wil::com_ptr aam; + RETURN_IF_FAILED(CoCreateInstance(CLSID_ApplicationActivationManager, nullptr, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&aam))); + RETURN_IF_FAILED(aam->ActivateApplication(appUserModelId, arguments, AO_NONE, processId)); + +#ifdef MEASURE_PERF + MessageBox(nullptr, std::format(L"Activation costs - aam: {}ms", GetTickCount() - startTime).c_str(), L"Perf", MB_OK); +#endif + + return S_OK; + } + CATCH_RETURN() + + STDMETHODIMP LaunchFiles( + _In_ PCWSTR appUserModelId, + _In_ PCWSTR verb, + UINT32 fileCount, + _In_count_(fileCount) PCWSTR* filePaths, + _Inout_ KozaniAppType* appType, + _Out_ DWORD* processId) noexcept try + { + RETURN_HR_IF_NULL(E_INVALIDARG, appUserModelId); + RETURN_HR_IF_NULL(E_INVALIDARG, processId); + RETURN_HR_IF_NULL(E_INVALIDARG, filePaths); + RETURN_HR_IF(E_INVALIDARG, fileCount == 0); + + *processId = 0; + +#ifdef MEASURE_PERF + DWORD aamCost{}; + DWORD shellExeCost{}; + DWORD findProcessCost{}; + DWORD startTime = GetTickCount(); +#endif + + // If appType is KozaniAppType_Unknown, we try to activate it as KozaniAppType_PackagedDesktopApp. If we activate a PackagedDesktopApp + // using IApplicationActivationManager, it will fail and try to repair the registration of the app unnecessarily, also causing forced + // shutdown of the app if it is already running. + if (*appType == KozaniAppType_Unknown || *appType == KozaniAppType_PackagedDesktopApp) + { + RETURN_IF_FAILED(ShellExecuteAssociationHandler(appUserModelId, AssociationType::File, filePaths[0], verb, processId)); + +#ifdef MEASURE_PERF + shellExeCost = GetTickCount() - startTime; +#endif + + if (*processId == 0) + { + // If the app is UWP, ShellExecute will not return its process handle and pid will be 0. Correct the appType so the next time + // it is launched, we will use the IApplicationActivationManager API, which will return pid for UWPs. + *appType = KozaniAppType_UWP; + +#ifdef MEASURE_PERF + DWORD findProcessStartTime = GetTickCount(); +#endif + + // Try to find the process Id of the process that has the same AUMID as the app we just launched, from all running processes. + // Best effort only and will not fail the call if we fail to find the pid. + LOG_IF_FAILED(FindProcessIdFromSnapshot(appUserModelId, processId)); + +#ifdef MEASURE_PERF + findProcessCost = GetTickCount() - findProcessStartTime; +#endif + } + else if (*appType == KozaniAppType_Unknown) + { + *appType = KozaniAppType_PackagedDesktopApp; + } + } + else if (*appType == KozaniAppType_UWP) + { + // IApplicationActivationManager file activation only works for UWP apps. + if (FAILED_LOG(LaunchFilesByActivationManager(appUserModelId, verb, fileCount, filePaths, processId))) + { +#ifdef MEASURE_PERF + DWORD aamTime = GetTickCount(); + aamCost = aamTime - startTime; +#endif + + // The incoming appType may not be correct. Fall back to using ShellExecute if LaunchFilesByActivationManager fails. + // ShellExecute can only launch one file a time. + RETURN_IF_FAILED(ShellExecuteAssociationHandler(appUserModelId, AssociationType::File, filePaths[0], verb, processId)); + if (*processId != 0) + { + *appType = KozaniAppType_PackagedDesktopApp; + } + else + { + LOG_IF_FAILED(FindProcessIdFromSnapshot(appUserModelId, processId)); + } + +#ifdef MEASURE_PERF + shellExeCost = GetTickCount() - aamTime; +#endif + } + else + { +#ifdef MEASURE_PERF + aamCost = GetTickCount() - startTime; +#endif + } + } + else + { + // Invalid KozaniAppType enum value. + RETURN_HR(E_INVALIDARG); + } + +#ifdef MEASURE_PERF + MessageBox(nullptr, std::format(L"Activation costs - aam: {}ms, shellexec: {}ms, FindProcess: {}ms, pid: {}", + aamCost, shellExeCost, findProcessCost, *processId).c_str(), L"Perf", MB_OK); +#endif + return S_OK; + } + CATCH_RETURN() + + STDMETHODIMP LaunchUri(_In_ PCWSTR appUserModelId, _In_ PCWSTR uri, _Inout_ KozaniAppType* appType, _Out_ DWORD* processId) noexcept try + { + RETURN_HR_IF_NULL(E_INVALIDARG, appUserModelId); + RETURN_HR_IF_NULL(E_INVALIDARG, uri); + RETURN_HR_IF_NULL(E_INVALIDARG, processId); + + *processId = 0; + +#ifdef MEASURE_PERF + DWORD aamCost{}; + DWORD shellExeCost{}; + DWORD startTime = GetTickCount(); +#endif + + // If appType is KozaniAppType_Unknown, we try to activate it as KozaniAppType_PackagedDesktopApp. If we activate a PackagedDesktopApp + // using IApplicationActivationManager, it will fail and try to repair the registration of the app unnecessarily, also causing forced + // shutdown of the app if it is already running. + if (*appType == KozaniAppType_Unknown || *appType == KozaniAppType_PackagedDesktopApp) + { + RETURN_IF_FAILED(ShellExecuteAssociationHandler(appUserModelId, AssociationType::Protocol, uri, nullptr /* verb */, processId)); + +#ifdef MEASURE_PERF + shellExeCost = GetTickCount() - startTime; +#endif + + if (*processId == 0) + { + // If the app is UWP, ShellExecute will not return its process handle and pid will be 0. Correct the appType so the next time + // it is launched, we will use the IApplicationActivationManager API, which will return pid for UWPs. + *appType = KozaniAppType_UWP; + + // Try to find the process Id of the process that has the same AUMID as the app we just launched, from all running processes. + // Best effort only and will not fail the call if we fail to find the pid. + LOG_IF_FAILED(FindProcessIdFromSnapshot(appUserModelId, processId)); + } + } + else if (*appType == KozaniAppType_UWP) + { + // IApplicationActivationManager protocol activation only works for UWP apps. The reason we don't try IApplicationActivationManager first + // when the app type is unknown is it will crash the existing running app process if it is not UWP. + if (FAILED_LOG(LaunchUriByActivationManager(appUserModelId, uri, processId))) + { +#ifdef MEASURE_PERF + DWORD aamTime = GetTickCount(); + aamCost = aamTime - startTime; +#endif + + // The incoming appType may not be correct. Fall back to using ShellExecute if LaunchFilesByActivationManager fails. + RETURN_IF_FAILED(ShellExecuteAssociationHandler(appUserModelId, AssociationType::Protocol, uri, nullptr /* verb */, processId)); + if (*processId != 0) + { + *appType = KozaniAppType_PackagedDesktopApp; + } + else + { + LOG_IF_FAILED(FindProcessIdFromSnapshot(appUserModelId, processId)); + } + +#ifdef MEASURE_PERF + shellExeCost = GetTickCount() - aamTime; +#endif + } + else + { +#ifdef MEASURE_PERF + aamCost = GetTickCount() - startTime; +#endif + } + } + else + { + // Invalid KozaniAppType enum value. + RETURN_HR(E_INVALIDARG); + } + +#ifdef MEASURE_PERF + MessageBox(nullptr, std::format(L"Activation costs - aam: {}ms, shellexec: {}ms, pid: {}", aamCost, shellExeCost, *processId).c_str(), L"Perf", MB_OK); +#endif + return S_OK; + } + CATCH_RETURN() + + ULONG __stdcall Release() noexcept override + { + ULONG refCount{ winrt::implements::Release() }; + if (refCount == 0) + { + g_exitProcess.SetEvent(); + } + return refCount; + } + +private: + HRESULT LaunchFilesByActivationManager( + _In_ PCWSTR appUserModelId, + _In_ PCWSTR verb, + UINT32 fileCount, + _In_count_(fileCount) PCWSTR* filePaths, + _Out_ DWORD* processId) noexcept try + { + wil::com_ptr aam; + RETURN_IF_FAILED(CoCreateInstance(CLSID_ApplicationActivationManager, nullptr, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&aam))); + + wistd::unique_ptr filePathList(new PIDLIST_ABSOLUTE[fileCount]); + RETURN_IF_NULL_ALLOC(filePathList); + + PIDLIST_ABSOLUTE* pidlistFilePaths{ filePathList.get() }; + ZeroMemory(pidlistFilePaths, sizeof(PIDLIST_ABSOLUTE)* fileCount); + + auto freeFilePathList{ wil::scope_exit([&]() + { + for (UINT32 i = 0; i < fileCount; i++) + { + if (pidlistFilePaths[i]) + { + CoTaskMemFree(pidlistFilePaths[i]); + } + } + }) }; + + for (UINT32 i = 0; i < fileCount; i++) + { + RETURN_IF_FAILED(SHParseDisplayName(filePaths[i], nullptr, &pidlistFilePaths[i], 0, nullptr)); + } + + wil::com_ptr filePathArray; + RETURN_IF_FAILED(SHCreateShellItemArrayFromIDLists(fileCount, const_cast(pidlistFilePaths), &filePathArray)); + + RETURN_IF_FAILED(aam->ActivateForFile(appUserModelId, filePathArray.get(), verb, processId)); + return S_OK; + } + CATCH_RETURN() + + HRESULT LaunchUriByActivationManager(_In_ PCWSTR appUserModelId, _In_ PCWSTR uri, _Out_ DWORD* processId) noexcept try + { + wil::com_ptr aam; + RETURN_IF_FAILED(CoCreateInstance(CLSID_ApplicationActivationManager, nullptr, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&aam))); + + wil::com_ptr shellItem; + RETURN_IF_FAILED(SHCreateItemFromParsingName(uri, nullptr, IID_PPV_ARGS(&shellItem))); + + wil::com_ptr shellItemArray; + RETURN_IF_FAILED(SHCreateShellItemArrayFromShellItem(shellItem.get(), IID_PPV_ARGS(&shellItemArray))); + + RETURN_IF_FAILED(aam->ActivateForProtocol(appUserModelId, shellItemArray.get(), processId)); + + return S_OK; + } + CATCH_RETURN() + + std::wstring GetAppAssociationProgId( + _In_ PCWSTR appUserModelId, + AssociationType associationType, + _In_ PCWSTR associationKeyword) + { + wil::unique_hkey appsKey; + THROW_IF_WIN32_ERROR(RegOpenKeyEx(HKEY_CURRENT_USER, c_registeredPackagedApplicationsPath, 0, KEY_READ, wil::out_param(appsKey))); + + std::wstring stringValue; + stringValue.resize(MAX_PATH); + + // The PackagedApps key contains AUMID -> AssociaitonInfoRegPath key/value pairs. We can look up the path to the registry key storing the + // app's association info by its AUMID. For example: + // Microsoft.SkypeApp_kzf8qxf38zg5c!App = Software\Classes\Local Settings\Software\Microsoft\Windows\CurrentVersion\AppModel\Repository\Packages\Microsoft.SkypeApp_15.99.3202.0_x64__kzf8qxf38zg5c\App\Capabilities + DWORD bufferSize{ static_cast(stringValue.size() * sizeof(wchar_t)) }; + THROW_IF_WIN32_ERROR(RegGetValue(appsKey.get(), nullptr, appUserModelId, RRF_RT_REG_SZ, nullptr, stringValue.data(), &bufferSize)); + + // Under the association info key, there are subkeys based on association types. Each assocation type subkey contains AssociationKeyword -> ProgId key/value pairs. + // For example: + // ...\Capabilities + // \FileAssociations + // .txt = AppX4ztfk9wxr86nxmzzq47px0nh0e58b8fw + // \URLAssociations + // tel = AppX5mseefwz6s981bhyy79d4wwmcper2jyg + wil::unique_hkey associationInfoKey; + THROW_IF_WIN32_ERROR(RegOpenKeyEx(HKEY_CURRENT_USER, stringValue.c_str(), 0, KEY_READ, wil::out_param(associationInfoKey))); + + stringValue.clear(); + stringValue.resize(MAX_PATH); + PCWSTR associationTypeKeyName{ (associationType == AssociationType::File) ? c_fileAssociationsKeyName : c_protocolAssociationsKeyName }; + THROW_IF_WIN32_ERROR(RegGetValue(associationInfoKey.get(), associationTypeKeyName, associationKeyword, RRF_RT_REG_SZ, nullptr, stringValue.data(), &bufferSize)); + + return stringValue; + } + + HRESULT ShellExecuteAssociationHandler( + _In_ PCWSTR appUserModelId, + AssociationType associationType, + _In_ PCWSTR launchTarget, + _In_opt_ PCWSTR verb, + _Out_ DWORD* processId) noexcept try + { + std::wstring associationKeyword; + if (associationType == AssociationType::File) + { + associationKeyword = std::filesystem::path(launchTarget).extension(); + } + else + { + PCWSTR schemeEnd{ wcschr(launchTarget, L':') }; + RETURN_HR_IF_NULL_MSG(E_INVALIDARG, schemeEnd, "Invalid URI: %ls", launchTarget); + + associationKeyword.assign(launchTarget, schemeEnd - launchTarget); + } + + std::wstring progId{ GetAppAssociationProgId(appUserModelId, associationType, associationKeyword.c_str()) }; + + SHELLEXECUTEINFO shellExecuteInfo{}; + shellExecuteInfo.cbSize = sizeof(shellExecuteInfo); + shellExecuteInfo.fMask = SEE_MASK_NOASYNC | SEE_MASK_NOCLOSEPROCESS | SEE_MASK_CLASSNAME; + shellExecuteInfo.lpVerb = verb; + shellExecuteInfo.lpFile = launchTarget; + shellExecuteInfo.lpClass = progId.c_str(); + + shellExecuteInfo.nShow = SW_SHOWNORMAL; + + RETURN_IF_WIN32_BOOL_FALSE(ShellExecuteEx(&shellExecuteInfo)); + if (shellExecuteInfo.hProcess != nullptr) + { + *processId = GetProcessId(shellExecuteInfo.hProcess); + RETURN_LAST_ERROR_IF(*processId == 0); + } + + return S_OK; + } + CATCH_RETURN() + + HRESULT FindProcessIdFromSnapshot(_In_ PCWSTR appUserModelId, _Out_ DWORD* processId) noexcept try + { + PROCESSENTRY32 entry; + entry.dwSize = sizeof(PROCESSENTRY32); + + wil::unique_handle snapshot{ CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0) }; + RETURN_LAST_ERROR_IF(!snapshot); + + RETURN_IF_WIN32_BOOL_FALSE(Process32First(snapshot.get(), &entry)); + + wchar_t aumidBuffer[APPLICATION_USER_MODEL_ID_MAX_LENGTH]{}; + do + { + wil::unique_handle process{ OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, entry.th32ProcessID) }; + if (process) + { + wil::unique_handle token; + if (OpenProcessToken(process.get(), TOKEN_QUERY, &token)) + { + UINT32 aumidBufferLength = ARRAYSIZE(aumidBuffer); + if (ERROR_SUCCESS == GetApplicationUserModelIdFromToken(token.get(), &aumidBufferLength, aumidBuffer)) + { + if (_wcsicmp(appUserModelId, aumidBuffer) == 0) + { + *processId = entry.th32ProcessID; + return S_OK; + } + } + } + } + } + while (Process32Next(snapshot.get(), &entry)); + + RETURN_WIN32(ERROR_NOT_FOUND); + } + CATCH_RETURN() +}; + int main(int argc, char* argv[]) try { + // Hook up wil logging MACROs to trace provider. + wil::SetResultLoggingCallback(&TraceFailureFromProvider); + if (argc < 3) { return E_INVALIDARG; @@ -27,8 +442,26 @@ int main(int argc, char* argv[]) try auto uninitOnExit = wil::CoInitializeEx(); + g_exitProcess.create(); + + auto appLauncher{ winrt::make_self() }; + PCSTR connectionId = argv[2]; auto remoteManager = wil::CoCreateInstance(CLSCTX_LOCAL_SERVER); - return remoteManager->Connect(connectionId); + RETURN_IF_FAILED(remoteManager->Connect(connectionId, appLauncher.get())); + + appLauncher = nullptr; + + // Wait up to 30s for KozaniRemoteManager to call back to activate app before exiting the process. + // If the KozaniApplicationLauncher object this process handed out is released earlier than that it will exit sooner. + g_exitProcess.wait(30000); + + // If a debugger is attached to this process, wait forever so it does not terminate the process during debugging. + if (IsDebuggerPresent()) + { + g_exitProcess.wait(INFINITE); + } + + return S_OK; } CATCH_RETURN() diff --git a/dev/Kozani/KozaniRemoteManagerLauncher/packages.config b/dev/Kozani/KozaniRemoteManagerLauncher/packages.config index 14efb7baf5..cd05427e9c 100644 --- a/dev/Kozani/KozaniRemoteManagerLauncher/packages.config +++ b/dev/Kozani/KozaniRemoteManagerLauncher/packages.config @@ -3,6 +3,6 @@ - + diff --git a/dev/Kozani/KozaniRemoteManagerLauncher/pch.h b/dev/Kozani/KozaniRemoteManagerLauncher/pch.h index f06e603567..5a5a4f09fb 100644 --- a/dev/Kozani/KozaniRemoteManagerLauncher/pch.h +++ b/dev/Kozani/KozaniRemoteManagerLauncher/pch.h @@ -16,5 +16,6 @@ #include "framework.h" #include "KozaniRemoteManagerLauncherActivity.h" #include "KozaniRemoteManagerLauncherTraceLogging.h" +#include "Logging.h" #endif //PCH_H diff --git a/dev/Kozani/KozaniSendToLocal/packages.config b/dev/Kozani/KozaniSendToLocal/packages.config index 14efb7baf5..cd05427e9c 100644 --- a/dev/Kozani/KozaniSendToLocal/packages.config +++ b/dev/Kozani/KozaniSendToLocal/packages.config @@ -3,6 +3,6 @@ - + diff --git a/dev/Kozani/KozaniSendToRemote/packages.config b/dev/Kozani/KozaniSendToRemote/packages.config index 14efb7baf5..cd05427e9c 100644 --- a/dev/Kozani/KozaniSendToRemote/packages.config +++ b/dev/Kozani/KozaniSendToRemote/packages.config @@ -3,6 +3,6 @@ - + diff --git a/dev/Kozani/KozaniSettings/packages.config b/dev/Kozani/KozaniSettings/packages.config index 14efb7baf5..cd05427e9c 100644 --- a/dev/Kozani/KozaniSettings/packages.config +++ b/dev/Kozani/KozaniSettings/packages.config @@ -3,6 +3,6 @@ - + diff --git a/dev/Kozani/MakeMSIX/packages.config b/dev/Kozani/MakeMSIX/packages.config index 14efb7baf5..cd05427e9c 100644 --- a/dev/Kozani/MakeMSIX/packages.config +++ b/dev/Kozani/MakeMSIX/packages.config @@ -3,6 +3,6 @@ - + diff --git a/dev/MRTCore/mrt/Core/unittests/packages.config b/dev/MRTCore/mrt/Core/unittests/packages.config index f11cc64c3e..1861ca894b 100644 --- a/dev/MRTCore/mrt/Core/unittests/packages.config +++ b/dev/MRTCore/mrt/Core/unittests/packages.config @@ -1,4 +1,4 @@  - + diff --git a/dev/MRTCore/mrt/Microsoft.Windows.ApplicationModel.Resources/UnpackagedTests/packages.config b/dev/MRTCore/mrt/Microsoft.Windows.ApplicationModel.Resources/UnpackagedTests/packages.config index e827484f00..11a9dacfc8 100644 --- a/dev/MRTCore/mrt/Microsoft.Windows.ApplicationModel.Resources/UnpackagedTests/packages.config +++ b/dev/MRTCore/mrt/Microsoft.Windows.ApplicationModel.Resources/UnpackagedTests/packages.config @@ -1,4 +1,4 @@  - + diff --git a/dev/MRTCore/mrt/Microsoft.Windows.ApplicationModel.Resources/src/packages.config b/dev/MRTCore/mrt/Microsoft.Windows.ApplicationModel.Resources/src/packages.config index 11a32940bf..9b45da6a85 100644 --- a/dev/MRTCore/mrt/Microsoft.Windows.ApplicationModel.Resources/src/packages.config +++ b/dev/MRTCore/mrt/Microsoft.Windows.ApplicationModel.Resources/src/packages.config @@ -3,5 +3,5 @@ - + diff --git a/dev/MRTCore/mrt/mrm/UnitTests/packages.config b/dev/MRTCore/mrt/mrm/UnitTests/packages.config index ef4201b12e..3a3c1cd7e9 100644 --- a/dev/MRTCore/mrt/mrm/UnitTests/packages.config +++ b/dev/MRTCore/mrt/mrm/UnitTests/packages.config @@ -1,5 +1,5 @@  - + diff --git a/dev/PackageManager/API/M.W.M.D.AddPackageOptions.cpp b/dev/PackageManager/API/M.W.M.D.AddPackageOptions.cpp new file mode 100644 index 0000000000..42566d9061 --- /dev/null +++ b/dev/PackageManager/API/M.W.M.D.AddPackageOptions.cpp @@ -0,0 +1,171 @@ +// Copyright (c) Microsoft Corporation and Contributors. +// Licensed under the MIT License. + +#include "pch.h" + +#include + +#include "M.W.M.D.AddPackageOptions.h" +#include "Microsoft.Windows.Management.Deployment.AddPackageOptions.g.cpp" + +namespace winrt::Microsoft::Windows::Management::Deployment::implementation +{ + winrt::Microsoft::Windows::Management::Deployment::PackageVolume AddPackageOptions::TargetVolume() + { + return m_targetVolume; + } + void AddPackageOptions::TargetVolume(winrt::Microsoft::Windows::Management::Deployment::PackageVolume const& value) + { + m_targetVolume = value; + } + winrt::Windows::Foundation::Collections::IVector AddPackageOptions::DependencyPackageUris() + { + if (!m_dependencyPackageUris) + { + m_dependencyPackageUris = winrt::single_threaded_vector(); + } + return m_dependencyPackageUris; + } + winrt::Windows::Foundation::Collections::IVector AddPackageOptions::OptionalPackageFamilyNames() + { + if (!m_optionalPackageFamilyNames) + { + m_optionalPackageFamilyNames = winrt::single_threaded_vector(); + } + return m_optionalPackageFamilyNames; + } + winrt::Windows::Foundation::Collections::IVector AddPackageOptions::OptionalPackageUris() + { + if (!m_optionalPackageUris) + { + m_optionalPackageUris = winrt::single_threaded_vector(); + } + return m_optionalPackageUris; + } + winrt::Windows::Foundation::Collections::IVector AddPackageOptions::RelatedPackageUris() + { + if (!m_relatedPackageUris) + { + m_relatedPackageUris = winrt::single_threaded_vector(); + } + return m_relatedPackageUris; + } + winrt::Windows::Foundation::Uri AddPackageOptions::ExternalLocationUri() + { + return m_externalLocationUri; + } + void AddPackageOptions::ExternalLocationUri(winrt::Windows::Foundation::Uri const& value) + { + m_externalLocationUri = value; + } + winrt::Microsoft::Windows::Management::Deployment::StubPackageOption AddPackageOptions::StubPackageOption() + { + return m_stubPackageOption; + } + void AddPackageOptions::StubPackageOption(winrt::Microsoft::Windows::Management::Deployment::StubPackageOption const& value) + { + m_stubPackageOption = value; + } + bool AddPackageOptions::AllowUnsigned() + { + return m_allowUnsigned; + } + void AddPackageOptions::AllowUnsigned(bool value) + { + m_allowUnsigned = value; + } + bool AddPackageOptions::DeveloperMode() + { + return m_developerMode; + } + void AddPackageOptions::DeveloperMode(bool value) + { + m_developerMode = value; + } + bool AddPackageOptions::ForceAppShutdown() + { + return m_forceAppShutdown; + } + void AddPackageOptions::ForceAppShutdown(bool value) + { + m_forceAppShutdown = value; + } + bool AddPackageOptions::ForceTargetAppShutdown() + { + return m_forceTargetAppShutdown; + } + void AddPackageOptions::ForceTargetAppShutdown(bool value) + { + m_forceTargetAppShutdown = value; + } + bool AddPackageOptions::ForceUpdateFromAnyVersion() + { + return m_forceUpdateFromAnyVersion; + } + void AddPackageOptions::ForceUpdateFromAnyVersion(bool value) + { + m_forceUpdateFromAnyVersion = value; + } + bool AddPackageOptions::InstallAllResources() + { + return m_installAllResources; + } + void AddPackageOptions::InstallAllResources(bool value) + { + m_installAllResources = value; + } + bool AddPackageOptions::RequiredContentGroupOnly() + { + return m_requiredContentGroupOnly; + } + void AddPackageOptions::RequiredContentGroupOnly(bool value) + { + m_requiredContentGroupOnly = value; + } + bool AddPackageOptions::RetainFilesOnFailure() + { + return m_retainFilesOnFailure; + } + void AddPackageOptions::RetainFilesOnFailure(bool value) + { + m_retainFilesOnFailure = value; + } + bool AddPackageOptions::StageInPlace() + { + return m_stageInPlace; + } + void AddPackageOptions::StageInPlace(bool value) + { + m_stageInPlace = value; + } + bool AddPackageOptions::DeferRegistrationWhenPackagesAreInUse() + { + return m_deferRegistrationWhenPackagesAreInUse; + } + void AddPackageOptions::DeferRegistrationWhenPackagesAreInUse(bool value) + { + m_deferRegistrationWhenPackagesAreInUse = value; + } + bool AddPackageOptions::IsExpectedDigestsSupported() + { + // Requires Windows >= 10.0.22621.0 (aka Win11 22H2) + return WindowsVersion::IsWindows11_22H2OrGreater(); + } + winrt::Windows::Foundation::Collections::IMap AddPackageOptions::ExpectedDigests() + { + return m_expectedDigests; + } + bool AddPackageOptions::IsLimitToExistingPackagesSupported() + { + // Requires Windows >= 10.0.22621.0 (aka Win11 22H2) + return WindowsVersion::IsWindows11_22H2OrGreater(); + } + bool AddPackageOptions::LimitToExistingPackages() + { + return m_limitToExistingPackages; + } + void AddPackageOptions::LimitToExistingPackages(bool value) + { + m_limitToExistingPackages = value; + } +} diff --git a/dev/PackageManager/API/M.W.M.D.AddPackageOptions.h b/dev/PackageManager/API/M.W.M.D.AddPackageOptions.h new file mode 100644 index 0000000000..a0a438473e --- /dev/null +++ b/dev/PackageManager/API/M.W.M.D.AddPackageOptions.h @@ -0,0 +1,78 @@ +// Copyright (c) Microsoft Corporation and Contributors. +// Licensed under the MIT License. + +#pragma once + +#include "Microsoft.Windows.Management.Deployment.AddPackageOptions.g.h" + +namespace winrt::Microsoft::Windows::Management::Deployment::implementation +{ + struct AddPackageOptions : AddPackageOptionsT + { + AddPackageOptions() = default; + + winrt::Microsoft::Windows::Management::Deployment::PackageVolume TargetVolume(); + void TargetVolume(winrt::Microsoft::Windows::Management::Deployment::PackageVolume const& value); + winrt::Windows::Foundation::Collections::IVector DependencyPackageUris(); + winrt::Windows::Foundation::Collections::IVector OptionalPackageFamilyNames(); + winrt::Windows::Foundation::Collections::IVector OptionalPackageUris(); + winrt::Windows::Foundation::Collections::IVector RelatedPackageUris(); + winrt::Windows::Foundation::Uri ExternalLocationUri(); + void ExternalLocationUri(winrt::Windows::Foundation::Uri const& value); + winrt::Microsoft::Windows::Management::Deployment::StubPackageOption StubPackageOption(); + void StubPackageOption(winrt::Microsoft::Windows::Management::Deployment::StubPackageOption const& value); + bool AllowUnsigned(); + void AllowUnsigned(bool value); + bool DeveloperMode(); + void DeveloperMode(bool value); + bool ForceAppShutdown(); + void ForceAppShutdown(bool value); + bool ForceTargetAppShutdown(); + void ForceTargetAppShutdown(bool value); + bool ForceUpdateFromAnyVersion(); + void ForceUpdateFromAnyVersion(bool value); + bool InstallAllResources(); + void InstallAllResources(bool value); + bool RequiredContentGroupOnly(); + void RequiredContentGroupOnly(bool value); + bool RetainFilesOnFailure(); + void RetainFilesOnFailure(bool value); + bool StageInPlace(); + void StageInPlace(bool value); + bool IsDeferRegistrationWhenPackagesAreInUseSupported(); + bool DeferRegistrationWhenPackagesAreInUse(); + void DeferRegistrationWhenPackagesAreInUse(bool value); + bool IsExpectedDigestsSupported(); + winrt::Windows::Foundation::Collections::IMap ExpectedDigests(); + bool IsLimitToExistingPackagesSupported(); + bool LimitToExistingPackages(); + void LimitToExistingPackages(bool value); + + private: + winrt::Microsoft::Windows::Management::Deployment::PackageVolume m_targetVolume{}; + winrt::Windows::Foundation::Collections::IVector m_dependencyPackageUris{}; + winrt::Windows::Foundation::Collections::IVector m_optionalPackageFamilyNames{}; + winrt::Windows::Foundation::Collections::IVector m_optionalPackageUris{}; + winrt::Windows::Foundation::Collections::IVector m_relatedPackageUris{}; + winrt::Windows::Foundation::Uri m_externalLocationUri{ nullptr }; + winrt::Microsoft::Windows::Management::Deployment::StubPackageOption m_stubPackageOption{}; + bool m_allowUnsigned{}; + bool m_developerMode{}; + bool m_forceAppShutdown{}; + bool m_forceTargetAppShutdown{}; + bool m_forceUpdateFromAnyVersion{}; + bool m_installAllResources{}; + bool m_requiredContentGroupOnly{}; + bool m_retainFilesOnFailure{}; + bool m_stageInPlace{}; + bool m_deferRegistrationWhenPackagesAreInUse{}; + winrt::Windows::Foundation::Collections::IMap m_expectedDigests; + bool m_limitToExistingPackages{}; + }; +} +namespace winrt::Microsoft::Windows::Management::Deployment::factory_implementation +{ + struct AddPackageOptions : AddPackageOptionsT + { + }; +} diff --git a/dev/PackageManager/API/M.W.M.D.AddPackageSetOptions.cpp b/dev/PackageManager/API/M.W.M.D.AddPackageSetOptions.cpp new file mode 100644 index 0000000000..6b6927aa37 --- /dev/null +++ b/dev/PackageManager/API/M.W.M.D.AddPackageSetOptions.cpp @@ -0,0 +1,35 @@ +// Copyright (c) Microsoft Corporation and Contributors. +// Licensed under the MIT License. + +#include "pch.h" + +#include "M.W.M.D.AddPackageSetOptions.h" +#include "Microsoft.Windows.Management.Deployment.AddPackageSetOptions.g.cpp" + +namespace winrt::Microsoft::Windows::Management::Deployment::implementation +{ + winrt::Microsoft::Windows::Management::Deployment::DeploymentProcessingModel AddPackageSetOptions::DeploymentProcessingModel() + { + return m_deploymentProcessingModel; + } + void AddPackageSetOptions::DeploymentProcessingModel(winrt::Microsoft::Windows::Management::Deployment::DeploymentProcessingModel const& value) + { + m_deploymentProcessingModel = value; + } + winrt::Microsoft::Windows::Management::Deployment::DeploymentPriority AddPackageSetOptions::DeploymentPriority() + { + return m_deploymentPriority; + } + void AddPackageSetOptions::DeploymentPriority(winrt::Microsoft::Windows::Management::Deployment::DeploymentPriority const& value) + { + m_deploymentPriority = value; + } + winrt::Microsoft::Windows::Management::Deployment::AddPackageOptions AddPackageSetOptions::AddPackageOptions() + { + return m_addPackageOptions; + } + void AddPackageSetOptions::AddPackageOptions(winrt::Microsoft::Windows::Management::Deployment::AddPackageOptions const& value) + { + m_addPackageOptions = value; + } +} diff --git a/dev/PackageManager/API/M.W.M.D.AddPackageSetOptions.h b/dev/PackageManager/API/M.W.M.D.AddPackageSetOptions.h new file mode 100644 index 0000000000..86b8fea9b8 --- /dev/null +++ b/dev/PackageManager/API/M.W.M.D.AddPackageSetOptions.h @@ -0,0 +1,32 @@ +// Copyright (c) Microsoft Corporation and Contributors. +// Licensed under the MIT License. + +#pragma once + +#include "Microsoft.Windows.Management.Deployment.AddPackageSetOptions.g.h" + +namespace winrt::Microsoft::Windows::Management::Deployment::implementation +{ + struct AddPackageSetOptions : AddPackageSetOptionsT + { + AddPackageSetOptions() = default; + + winrt::Microsoft::Windows::Management::Deployment::DeploymentProcessingModel DeploymentProcessingModel(); + void DeploymentProcessingModel(winrt::Microsoft::Windows::Management::Deployment::DeploymentProcessingModel const& value); + winrt::Microsoft::Windows::Management::Deployment::DeploymentPriority DeploymentPriority(); + void DeploymentPriority(winrt::Microsoft::Windows::Management::Deployment::DeploymentPriority const& value); + winrt::Microsoft::Windows::Management::Deployment::AddPackageOptions AddPackageOptions(); + void AddPackageOptions(winrt::Microsoft::Windows::Management::Deployment::AddPackageOptions const& value); + + private: + winrt::Microsoft::Windows::Management::Deployment::DeploymentProcessingModel m_deploymentProcessingModel{}; + winrt::Microsoft::Windows::Management::Deployment::DeploymentPriority m_deploymentPriority{ winrt::Microsoft::Windows::Management::Deployment::DeploymentPriority::Normal }; + winrt::Microsoft::Windows::Management::Deployment::AddPackageOptions m_addPackageOptions{}; + }; +} +namespace winrt::Microsoft::Windows::Management::Deployment::factory_implementation +{ + struct AddPackageSetOptions : AddPackageSetOptionsT + { + }; +} diff --git a/dev/PackageManager/API/M.W.M.D.EnsureIsReadyOptions.cpp b/dev/PackageManager/API/M.W.M.D.EnsureIsReadyOptions.cpp new file mode 100644 index 0000000000..4b44c8b2c5 --- /dev/null +++ b/dev/PackageManager/API/M.W.M.D.EnsureIsReadyOptions.cpp @@ -0,0 +1,29 @@ +// Copyright (c) Microsoft Corporation and Contributors. +// Licensed under the MIT License. + +#include "pch.h" + +#include + +#include "M.W.M.D.EnsureIsReadyOptions.h" +#include "Microsoft.Windows.Management.Deployment.EnsureIsReadyOptions.g.cpp" + +namespace winrt::Microsoft::Windows::Management::Deployment::implementation +{ + winrt::Microsoft::Windows::Management::Deployment::DeploymentProcessingModel EnsureIsReadyOptions::DeploymentProcessingModel() + { + return m_deploymentProcessingModel; + } + void EnsureIsReadyOptions::DeploymentProcessingModel(winrt::Microsoft::Windows::Management::Deployment::DeploymentProcessingModel const& value) + { + m_deploymentProcessingModel = value; + } + winrt::Microsoft::Windows::Management::Deployment::DeploymentPriority EnsureIsReadyOptions::DeploymentPriority() + { + return m_deploymentPriority; + } + void EnsureIsReadyOptions::DeploymentPriority(winrt::Microsoft::Windows::Management::Deployment::DeploymentPriority const& value) + { + m_deploymentPriority = value; + } +} diff --git a/dev/PackageManager/API/M.W.M.D.EnsureIsReadyOptions.h b/dev/PackageManager/API/M.W.M.D.EnsureIsReadyOptions.h new file mode 100644 index 0000000000..9b0fe6c04c --- /dev/null +++ b/dev/PackageManager/API/M.W.M.D.EnsureIsReadyOptions.h @@ -0,0 +1,29 @@ +// Copyright (c) Microsoft Corporation and Contributors. +// Licensed under the MIT License. + +#pragma once + +#include "Microsoft.Windows.Management.Deployment.EnsureIsReadyOptions.g.h" + +namespace winrt::Microsoft::Windows::Management::Deployment::implementation +{ + struct EnsureIsReadyOptions : EnsureIsReadyOptionsT + { + EnsureIsReadyOptions() = default; + + winrt::Microsoft::Windows::Management::Deployment::DeploymentProcessingModel DeploymentProcessingModel(); + void DeploymentProcessingModel(winrt::Microsoft::Windows::Management::Deployment::DeploymentProcessingModel const& value); + winrt::Microsoft::Windows::Management::Deployment::DeploymentPriority DeploymentPriority(); + void DeploymentPriority(winrt::Microsoft::Windows::Management::Deployment::DeploymentPriority const& value); + + private: + winrt::Microsoft::Windows::Management::Deployment::DeploymentProcessingModel m_deploymentProcessingModel{}; + winrt::Microsoft::Windows::Management::Deployment::DeploymentPriority m_deploymentPriority{ winrt::Microsoft::Windows::Management::Deployment::DeploymentPriority::Normal }; + }; +} +namespace winrt::Microsoft::Windows::Management::Deployment::factory_implementation +{ + struct EnsureIsReadyOptions : EnsureIsReadyOptionsT + { + }; +} diff --git a/dev/PackageManager/API/M.W.M.D.FindPackageSetOptions.cpp b/dev/PackageManager/API/M.W.M.D.FindPackageSetOptions.cpp new file mode 100644 index 0000000000..d1f49eb744 --- /dev/null +++ b/dev/PackageManager/API/M.W.M.D.FindPackageSetOptions.cpp @@ -0,0 +1,18 @@ +// Copyright (c) Microsoft Corporation and Contributors. +// Licensed under the MIT License. + +#include "pch.h" +#include "M.W.M.D.FindPackageSetOptions.h" +#include "Microsoft.Windows.Management.Deployment.FindPackageSetOptions.g.cpp" + +namespace winrt::Microsoft::Windows::Management::Deployment::implementation +{ + bool FindPackageSetOptions::TODO_MustHaveAtLeastOneInterfaceOrStaticFactoryPlaceholder() + { + throw hresult_not_implemented(); + } + void FindPackageSetOptions::TODO_MustHaveAtLeastOneInterfaceOrStaticFactoryPlaceholder(bool value) + { + throw hresult_not_implemented(); + } +} diff --git a/dev/PackageManager/API/M.W.M.D.FindPackageSetOptions.h b/dev/PackageManager/API/M.W.M.D.FindPackageSetOptions.h new file mode 100644 index 0000000000..a4251fef49 --- /dev/null +++ b/dev/PackageManager/API/M.W.M.D.FindPackageSetOptions.h @@ -0,0 +1,23 @@ +// Copyright (c) Microsoft Corporation and Contributors. +// Licensed under the MIT License. + +#pragma once + +#include "Microsoft.Windows.Management.Deployment.FindPackageSetOptions.g.h" + +namespace winrt::Microsoft::Windows::Management::Deployment::implementation +{ + struct FindPackageSetOptions : FindPackageSetOptionsT + { + FindPackageSetOptions() = default; + + bool TODO_MustHaveAtLeastOneInterfaceOrStaticFactoryPlaceholder(); + void TODO_MustHaveAtLeastOneInterfaceOrStaticFactoryPlaceholder(bool value); + }; +} +namespace winrt::Microsoft::Windows::Management::Deployment::factory_implementation +{ + struct FindPackageSetOptions : FindPackageSetOptionsT + { + }; +} diff --git a/dev/PackageManager/API/M.W.M.D.PackageDeploymentManager.cpp b/dev/PackageManager/API/M.W.M.D.PackageDeploymentManager.cpp new file mode 100644 index 0000000000..73c2088b8b --- /dev/null +++ b/dev/PackageManager/API/M.W.M.D.PackageDeploymentManager.cpp @@ -0,0 +1,584 @@ +// Copyright (c) Microsoft Corporation and Contributors. +// Licensed under the MIT License. + +#include "pch.h" +#include "M.W.M.D.PackageDeploymentManager.h" +#include "Microsoft.Windows.Management.Deployment.PackageDeploymentManager.g.cpp" + +#include "M.W.M.D.PackageDeploymentResult.h" +#include "M.W.M.D.PackageDeploymentProgress.h" +#include "M.W.M.D.PackageVolumeManager.h" +#include "MsixPackageManager.h" +#include "PackageDeploymentResolver.h" + +static_assert(static_cast(winrt::Microsoft::Windows::Management::Deployment::StubPackageOption::Default) == static_cast(winrt::Windows::Management::Deployment::StubPackageOption::Default), + "winrt::Microsoft::Windows::Management::Deployment::StubPackageOption::Default != winrt::Windows::Management::Deployment::StubPackageOption::Default"); +static_assert(static_cast(winrt::Microsoft::Windows::Management::Deployment::StubPackageOption::InstallFull) == static_cast(winrt::Windows::Management::Deployment::StubPackageOption::InstallFull), + "winrt::Microsoft::Windows::Management::Deployment::StubPackageOption::InstallFull != winrt::Windows::Management::Deployment::StubPackageOption::InstallFull"); +static_assert(static_cast(winrt::Microsoft::Windows::Management::Deployment::StubPackageOption::InstallStub) == static_cast(winrt::Windows::Management::Deployment::StubPackageOption::InstallStub), + "winrt::Microsoft::Windows::Management::Deployment::StubPackageOption::InstallStub != winrt::Windows::Management::Deployment::StubPackageOption::InstallStub"); +static_assert(static_cast(winrt::Microsoft::Windows::Management::Deployment::StubPackageOption::UsePreference) == static_cast(winrt::Windows::Management::Deployment::StubPackageOption::UsePreference), + "winrt::Microsoft::Windows::Management::Deployment::StubPackageOption::UsePreference != winrt::Windows::Management::Deployment::StubPackageOption::UsePreference"); + +namespace winrt::Microsoft::Windows::Management::Deployment::implementation +{ + winrt::Microsoft::Windows::Management::Deployment::PackageDeploymentManager PackageDeploymentManager::GetDefault() + { + return winrt::make(); + } + bool PackageDeploymentManager::IsPackageSetReady(winrt::Microsoft::Windows::Management::Deployment::PackageSet const& packageSet) + { + Validate(packageSet); + + for (const winrt::Microsoft::Windows::Management::Deployment::PackageSetItem& packageSetItem : packageSet.PackageSetItems()) + { + if (!IsReady(packageSetItem)) + { + (void)LOG_HR_MSG(MSIXPACKAGEMANAGER_E_PACKAGE_SCAN_FAILED, + "Id=%ls PackageFamilyName=%ls MinVersion=%hu.%hu.%hu.%hu ArchitectureFilter:0x%X", + packageSetItem.Id().c_str(), + packageSetItem.PackageFamilyName().c_str(), + packageSetItem.MinVersion().Major, + packageSetItem.MinVersion().Minor, + packageSetItem.MinVersion().Build, + packageSetItem.MinVersion().Revision, + packageSetItem.ProcessorArchitectureFilter()); + return false; + } + } + return true; + } + bool PackageDeploymentManager::IsPackageSetReadyById(hstring const& packageSetId) + { + throw hresult_not_implemented(); + } + winrt::Windows::Foundation::IAsyncOperationWithProgress + PackageDeploymentManager::EnsurePackageSetIsReadyAsync(winrt::Microsoft::Windows::Management::Deployment::PackageSet packageSet, winrt::Microsoft::Windows::Management::Deployment::EnsureIsReadyOptions options) + { + //TODO auto logTelemetry{ PackageDeploymentTelemetry::CreateChannelAsync::Start(g_telemetryHelper, remoteId) }; + + auto strong = get_strong(); + + auto cancellation{ co_await winrt::get_cancellation_token() }; + cancellation.enable_propagation(true); + + //TODO logTelemetry.IgnoreCurrentThread(); + + // Allow to register the progress and complete handler + co_await resume_background(); + + //TODO auto logTelemetryContinuation = logTelemetry.ContinueOnCurrentThread(); + + auto progress{ co_await winrt::get_progress_token() }; + auto packageDeploymentProgress{ + winrt::make< + winrt::Microsoft::Windows::Management::Deployment::implementation::PackageDeploymentProgress>( + PackageDeploymentProgressStatus::Queued, 0) }; + progress(packageDeploymentProgress); + + // Check parameter(s) + Validate(packageSet); + + // Is there any work to do? + packageDeploymentProgress.status(PackageDeploymentProgressStatus::InProgress); + const double c_progressPercentageStartOfIsReady{ 0.01 }; + packageDeploymentProgress.percentage(c_progressPercentageStartOfIsReady); + progress(packageDeploymentProgress); + if (IsPackageSetReady(packageSet)) + { + co_return winrt::make( + PackageDeploymentStatus::CompletedSuccess, S_OK, true, /*TODO*/winrt::guid{}); + } + + const double c_progressPercentageStartOfInstalls{ 0.10 }; + packageDeploymentProgress.percentage(c_progressPercentageStartOfInstalls); + progress(packageDeploymentProgress); + auto packageSetItems{ packageSet.PackageSetItems() }; + const double progressIncrementPerPackageSetItem{ (1.0 - c_progressPercentageStartOfInstalls) / packageSetItems.Size() }; + for (const winrt::Microsoft::Windows::Management::Deployment::PackageSetItem& packageSetItem : packageSetItems) + { + try + { + EnsureIsReadyAsync(packageSetItem, options); + packageDeploymentProgress.percentage(packageDeploymentProgress.percentage() + progressIncrementPerPackageSetItem); + progress(packageDeploymentProgress); + } + catch (...) + { + auto exception{ hresult_error(to_hresult(), take_ownership_from_abi) }; + co_return winrt::make( + PackageDeploymentStatus::CompletedFailure, exception.code(), false, /*TODO*/winrt::guid{}); + } + } + + co_return winrt::make( + PackageDeploymentStatus::CompletedSuccess, S_OK, true, /*TODO*/winrt::guid{}); + + //TODO logTelemetry.Stop(); + } + winrt::Windows::Foundation::IAsyncOperationWithProgress + PackageDeploymentManager::EnsurePackageSetIsReadyByIdAsync(hstring packageSetId, winrt::Microsoft::Windows::Management::Deployment::EnsureIsReadyOptions options) + { + throw hresult_not_implemented(); + } + winrt::Windows::Foundation::IAsyncOperationWithProgress + PackageDeploymentManager::AddPackageAsync(hstring package, winrt::Microsoft::Windows::Management::Deployment::AddPackageOptions options) + { + const winrt::Windows::Foundation::Uri packageUri{ package }; + const auto packageAbsoluteUri{ packageUri.AbsoluteUri() }; + if (!packageAbsoluteUri.empty()) + { + const std::wstring packageAsString{ package.c_str() }; + if (packageAsString.ends_with(L".appinstaller")) + { + //TODO: return AddPackageByAppInstallerFileAsync(packageUri); + } + else + { + return AddPackageByUriAsync(packageUri, options); + } + } + THROW_HR_MSG(E_INVALIDARG, "%ls", package.c_str()); + } + winrt::Windows::Foundation::IAsyncOperationWithProgress + PackageDeploymentManager::AddPackageByUriAsync(winrt::Windows::Foundation::Uri packageUri, winrt::Microsoft::Windows::Management::Deployment::AddPackageOptions options) + { + //TODO auto logTelemetry{ PackageDeploymentTelemetry::CreateChannelAsync::Start(g_telemetryHelper, remoteId) }; + + auto strong = get_strong(); + + auto cancellation{ co_await winrt::get_cancellation_token() }; + cancellation.enable_propagation(true); + + //TODO logTelemetry.IgnoreCurrentThread(); + + // Allow to register the progress and complete handler + co_await resume_background(); + + //TODO auto logTelemetryContinuation = logTelemetry.ContinueOnCurrentThread(); + + auto progress{ co_await winrt::get_progress_token() }; + auto packageDeploymentProgress{ + winrt::make< + winrt::Microsoft::Windows::Management::Deployment::implementation::PackageDeploymentProgress>( + PackageDeploymentProgressStatus::Queued, 0) }; + progress(packageDeploymentProgress); + + // Check parameter(s) + //TODO Validate(packageSet); + + winrt::Windows::Management::Deployment::AddPackageOptions addOptions{ ToOptions(options) }; + try + { + AddAsync(packageUri, addOptions); + } + catch (...) + { + auto exception{ hresult_error(to_hresult(), take_ownership_from_abi) }; + co_return winrt::make( + PackageDeploymentStatus::CompletedFailure, exception.code(), false, /*TODO*/winrt::guid{}); + } + + co_return winrt::make( + PackageDeploymentStatus::CompletedSuccess, S_OK, true, /*TODO*/winrt::guid{}); + + //TODO logTelemetry.Stop(); + } + winrt::Windows::Foundation::IAsyncOperationWithProgress + PackageDeploymentManager::AddPackageSetAsync(winrt::Microsoft::Windows::Management::Deployment::PackageSet packageSet, winrt::Microsoft::Windows::Management::Deployment::AddPackageSetOptions options) + { + //TODO auto logTelemetry{ PackageDeploymentTelemetry::CreateChannelAsync::Start(g_telemetryHelper, remoteId) }; + + auto strong = get_strong(); + + auto cancellation{ co_await winrt::get_cancellation_token() }; + cancellation.enable_propagation(true); + + //TODO logTelemetry.IgnoreCurrentThread(); + + // Allow to register the progress and complete handler + co_await resume_background(); + + //TODO auto logTelemetryContinuation = logTelemetry.ContinueOnCurrentThread(); + + auto progress{ co_await winrt::get_progress_token() }; + auto packageDeploymentProgress{ + winrt::make< + winrt::Microsoft::Windows::Management::Deployment::implementation::PackageDeploymentProgress>( + PackageDeploymentProgressStatus::Queued, 0) }; + progress(packageDeploymentProgress); + + // Check parameter(s) + Validate(packageSet); + + packageDeploymentProgress.status(PackageDeploymentProgressStatus::InProgress); + const double c_progressPercentageStartOfInstalls{ 0.10 }; + packageDeploymentProgress.percentage(c_progressPercentageStartOfInstalls); + progress(packageDeploymentProgress); + auto packageSetItems{ packageSet.PackageSetItems() }; + const double progressIncrementPerPackageSetItem{ (1.0 - c_progressPercentageStartOfInstalls) / packageSetItems.Size() }; + for (const winrt::Microsoft::Windows::Management::Deployment::PackageSetItem& packageSetItem : packageSetItems) + { + try + { + AddAsync(packageSetItem, options); + packageDeploymentProgress.percentage(packageDeploymentProgress.percentage() + progressIncrementPerPackageSetItem); + progress(packageDeploymentProgress); + } + catch (...) + { + auto exception{ hresult_error(to_hresult(), take_ownership_from_abi) }; + co_return winrt::make( + PackageDeploymentStatus::CompletedFailure, exception.code(), false, /*TODO*/winrt::guid{}); + } + } + + co_return winrt::make( + PackageDeploymentStatus::CompletedSuccess, S_OK, true, /*TODO*/winrt::guid{}); + + //TODO logTelemetry.Stop(); + } + winrt::Windows::Foundation::IAsyncOperationWithProgress + PackageDeploymentManager::AddPackageSetByIdAsync(hstring packageSetId, winrt::Microsoft::Windows::Management::Deployment::AddPackageSetOptions options) + { + throw hresult_not_implemented(); + } + winrt::Windows::Foundation::IAsyncOperationWithProgress + PackageDeploymentManager::RemovePackageAsync(hstring package, winrt::Microsoft::Windows::Management::Deployment::RemovePackageOptions options) + { + if (VerifyPackageFamilyName(package.c_str()) == ERROR_SUCCESS) + { + return RemovePackageByFamilyNameAsync(package, options); + } + else if (VerifyPackageFullName(package.c_str()) == ERROR_SUCCESS) + { + return RemovePackageByFullNameAsync(package, options); + } + THROW_HR_MSG(E_INVALIDARG, "%ls", package.c_str()); + } + winrt::Windows::Foundation::IAsyncOperationWithProgress + PackageDeploymentManager::RemovePackageByFullNameAsync(hstring packageFullName, winrt::Microsoft::Windows::Management::Deployment::RemovePackageOptions options) + { + throw hresult_not_implemented(); + } + winrt::Windows::Foundation::IAsyncOperationWithProgress + PackageDeploymentManager::RemovePackageByFamilyNameAsync(hstring packageFamilyName, winrt::Microsoft::Windows::Management::Deployment::RemovePackageOptions options) + { + throw hresult_not_implemented(); + } + winrt::Windows::Foundation::IAsyncOperationWithProgress + PackageDeploymentManager::RemovePackageSetAsync(winrt::Microsoft::Windows::Management::Deployment::PackageSet packageSet, winrt::Microsoft::Windows::Management::Deployment::RemovePackageOptions options) + { + throw hresult_not_implemented(); + } + winrt::Windows::Foundation::IAsyncOperationWithProgress + PackageDeploymentManager::RemovePackageSetByIdAsync(hstring packageSetId, winrt::Microsoft::Windows::Management::Deployment::RemovePackageOptions options) + { + throw hresult_not_implemented(); + } + + bool PackageDeploymentManager::IsReady(winrt::Microsoft::Windows::Management::Deployment::PackageSetItem const& packageSetItem) + { + const AppModel::Identity::PackageVersion minVersion{ packageSetItem.MinVersion() }; + const auto processorArchitectureFilter{ packageSetItem.ProcessorArchitectureFilter() }; + return ::Microsoft::Windows::ApplicationModel::PackageDeploymentResolver::FindAny(m_packageManager, packageSetItem.PackageFamilyName(), minVersion, processorArchitectureFilter); + } + + void PackageDeploymentManager::Validate(winrt::Microsoft::Windows::Management::Deployment::PackageSet const& packageSet) const + { + THROW_HR_IF(E_INVALIDARG, packageSet.Id().empty()); + const auto& packageSetItems{ packageSet.PackageSetItems() }; + THROW_HR_IF(E_INVALIDARG, packageSetItems.Size() == 0); + for (const winrt::Microsoft::Windows::Management::Deployment::PackageSetItem& packageSetItem : packageSetItems) + { + Validate(packageSetItem); + } + } + + void PackageDeploymentManager::Validate(winrt::Microsoft::Windows::Management::Deployment::PackageSetItem const& packageSetItem) const + { + const auto packageFamilyName{ packageSetItem.PackageFamilyName() }; + THROW_IF_WIN32_ERROR_MSG(VerifyPackageFamilyName(packageFamilyName.c_str()), "PackageFamilyName:%ls", packageFamilyName.c_str()); + + const auto packageUri{ packageSetItem.PackageUri() }; + THROW_HR_IF_NULL_MSG(E_INVALIDARG, packageUri, "PackageUri:"); + } + + void PackageDeploymentManager::EnsureIsReadyAsync(winrt::Microsoft::Windows::Management::Deployment::PackageSetItem const& packageSetItem, winrt::Microsoft::Windows::Management::Deployment::EnsureIsReadyOptions const& options) + { + if (IsReady(packageSetItem)) + { + return; + } + + auto packageUri{ packageSetItem.PackageUri() }; + winrt::Windows::Management::Deployment::AddPackageOptions addOptions{ ToOptions(options) }; + auto deploymentOperation{ m_packageManager.AddPackageByUriAsync(packageUri, addOptions) }; + deploymentOperation.get(); + try + { + const auto deploymentResult{ deploymentOperation.GetResults() }; + if (deploymentOperation.Status() == winrt::Windows::Foundation::AsyncStatus::Error) + { + const winrt::hresult hr{ static_cast(deploymentOperation.ErrorCode()) }; + THROW_IF_FAILED_MSG(hr, "%ls", packageUri.ToString().c_str()); + const winrt::hresult extendedHr{ deploymentResult.ExtendedErrorCode() }; + THROW_IF_FAILED_MSG(extendedHr, "%ls", packageUri.ToString().c_str()); + FAIL_FAST_HR_MSG(E_UNEXPECTED, "%ls", packageUri.ToString().c_str()); + } + else if (deploymentOperation.Status() == winrt::Windows::Foundation::AsyncStatus::Canceled) + { + THROW_WIN32_MSG(ERROR_CANCELLED, "%ls", packageUri.ToString().c_str()); + } + FAIL_FAST_HR_IF_MSG(E_UNEXPECTED, deploymentOperation.Status() != winrt::Windows::Foundation::AsyncStatus::Completed, "%ls", packageUri.ToString().c_str()); + } + catch (...) + { + auto exception{ hresult_error(to_hresult(), take_ownership_from_abi) }; + THROW_HR_MSG(exception.code(), "%ls", packageUri.ToString().c_str()); + } + } + + void PackageDeploymentManager::AddAsync(winrt::Microsoft::Windows::Management::Deployment::PackageSetItem const& packageSetItem, winrt::Microsoft::Windows::Management::Deployment::AddPackageSetOptions const& options) + { + auto packageUri{ packageSetItem.PackageUri() }; + winrt::Windows::Management::Deployment::AddPackageOptions addOptions{ ToOptions(options) }; + AddAsync(packageUri, addOptions); + } + + void PackageDeploymentManager::AddAsync(winrt::Windows::Foundation::Uri const& packageUri, winrt::Windows::Management::Deployment::AddPackageOptions const& addOptions) + { + auto deploymentOperation{ m_packageManager.AddPackageByUriAsync(packageUri, addOptions) }; + deploymentOperation.get(); + try + { + const auto deploymentResult{ deploymentOperation.GetResults() }; + if (deploymentOperation.Status() == winrt::Windows::Foundation::AsyncStatus::Error) + { + const winrt::hresult hr{ static_cast(deploymentOperation.ErrorCode()) }; + if (hr == HRESULT_FROM_WIN32(ERROR_INSTALL_PACKAGE_DOWNGRADE)) + { + // Newer version already installed. Success! + (void)LOG_HR_MSG(HRESULT_FROM_WIN32(ERROR_INSTALL_PACKAGE_DOWNGRADE), "%ls", deploymentResult.ErrorText().c_str()); + return; + } + THROW_IF_FAILED_MSG(hr, "%ls", packageUri.ToString().c_str()); + const winrt::hresult extendedHr{ deploymentResult.ExtendedErrorCode() }; + THROW_IF_FAILED_MSG(extendedHr, "%ls", packageUri.ToString().c_str()); + FAIL_FAST_HR_MSG(E_UNEXPECTED, "%ls", packageUri.ToString().c_str()); + } + else if (deploymentOperation.Status() == winrt::Windows::Foundation::AsyncStatus::Canceled) + { + THROW_WIN32_MSG(ERROR_CANCELLED, "%ls", packageUri.ToString().c_str()); + } + FAIL_FAST_HR_IF_MSG(E_UNEXPECTED, deploymentOperation.Status() != winrt::Windows::Foundation::AsyncStatus::Completed, "%ls", packageUri.ToString().c_str()); + } + catch (...) + { + auto exception{ hresult_error(to_hresult(), take_ownership_from_abi) }; + THROW_HR_MSG(exception.code(), "%ls", packageUri.ToString().c_str()); + } + } + + winrt::Windows::Management::Deployment::PackageVolume PackageDeploymentManager::ToPackageVolume(winrt::Microsoft::Windows::Management::Deployment::PackageVolume const& packageVolume) const + { + if (packageVolume) + { + const auto name{ packageVolume.Name() }; + if (!name.empty()) + { + auto toPackageVolume{ m_packageManager.FindPackageVolume(name) }; + return toPackageVolume; + } + } + return nullptr; + } + + winrt::Windows::Management::Deployment::AddPackageOptions PackageDeploymentManager::ToOptions(winrt::Microsoft::Windows::Management::Deployment::AddPackageOptions const& options) const + { + if (!options) + { + return winrt::Windows::Management::Deployment::AddPackageOptions(); + } + + winrt::Windows::Management::Deployment::AddPackageOptions toOptions; + const auto targetVolume{ options.TargetVolume() }; + if (targetVolume) + { + const auto toPackageVolume{ ToPackageVolume(targetVolume) }; + if (toPackageVolume) + { + toOptions.TargetVolume(toPackageVolume); + } + } + for (const auto uri : options.DependencyPackageUris()) + { + toOptions.DependencyPackageUris().Append(uri); + } + for (const auto packageFamilyName : options.OptionalPackageFamilyNames()) + { + toOptions.OptionalPackageFamilyNames().Append(packageFamilyName); + } + for (const auto uri : options.OptionalPackageUris()) + { + toOptions.OptionalPackageUris().Append(uri); + } + for (const auto uri : options.RelatedPackageUris()) + { + toOptions.RelatedPackageUris().Append(uri); + } + toOptions.ExternalLocationUri(options.ExternalLocationUri()); + toOptions.StubPackageOption(static_cast(options.StubPackageOption())); + toOptions.AllowUnsigned(options.AllowUnsigned()); + toOptions.DeveloperMode(options.DeveloperMode()); + toOptions.ForceAppShutdown(options.ForceAppShutdown()); + toOptions.ForceTargetAppShutdown(options.ForceTargetAppShutdown()); + toOptions.ForceUpdateFromAnyVersion(options.ForceUpdateFromAnyVersion()); + toOptions.InstallAllResources(options.InstallAllResources()); + toOptions.RequiredContentGroupOnly(options.RequiredContentGroupOnly()); + toOptions.RetainFilesOnFailure(options.RetainFilesOnFailure()); + toOptions.StageInPlace(options.StageInPlace()); + toOptions.DeferRegistrationWhenPackagesAreInUse(options.DeferRegistrationWhenPackagesAreInUse()); + if (options.IsExpectedDigestsSupported()) + { + const auto expectedDigests{ options.ExpectedDigests() }; + if (expectedDigests) + { + auto toExpectedDigests{ toOptions.ExpectedDigests() }; + for (const auto expectedDigest : expectedDigests) + { + toExpectedDigests.Insert(expectedDigest.Key(), expectedDigest.Value()); + } + } + } + if (options.IsLimitToExistingPackagesSupported()) + { + toOptions.LimitToExistingPackages(options.LimitToExistingPackages()); + } + return toOptions; + } + + winrt::Windows::Management::Deployment::AddPackageOptions PackageDeploymentManager::ToOptions(winrt::Microsoft::Windows::Management::Deployment::AddPackageSetOptions const& options) const + { + return ToOptions(options.AddPackageOptions()); + } + + winrt::Windows::Management::Deployment::StagePackageOptions PackageDeploymentManager::ToOptions(winrt::Microsoft::Windows::Management::Deployment::StagePackageOptions const& options) const + { + winrt::Windows::Management::Deployment::StagePackageOptions toOptions; + const auto targetVolume{ options.TargetVolume() }; + if (targetVolume) + { + const auto toPackageVolume{ ToPackageVolume(targetVolume) }; + if (toPackageVolume) + { + toOptions.TargetVolume(toPackageVolume); + } + } + for (const auto uri : options.DependencyPackageUris()) + { + toOptions.DependencyPackageUris().Append(uri); + } + for (const auto packageFamilyName : options.OptionalPackageFamilyNames()) + { + toOptions.OptionalPackageFamilyNames().Append(packageFamilyName); + } + for (const auto uri : options.OptionalPackageUris()) + { + toOptions.OptionalPackageUris().Append(uri); + } + for (const auto uri : options.RelatedPackageUris()) + { + toOptions.RelatedPackageUris().Append(uri); + } + toOptions.ExternalLocationUri(options.ExternalLocationUri()); + toOptions.StubPackageOption(static_cast(options.StubPackageOption())); + toOptions.DeveloperMode(options.DeveloperMode()); + toOptions.ForceUpdateFromAnyVersion(options.ForceUpdateFromAnyVersion()); + toOptions.InstallAllResources(options.InstallAllResources()); + toOptions.RequiredContentGroupOnly(options.RequiredContentGroupOnly()); + toOptions.StageInPlace(options.StageInPlace()); + toOptions.AllowUnsigned(options.AllowUnsigned()); + if (options.IsExpectedDigestsSupported()) + { + const auto expectedDigests{ options.ExpectedDigests() }; + if (expectedDigests) + { + auto toExpectedDigests{ toOptions.ExpectedDigests() }; + for (const auto expectedDigest : expectedDigests) + { + toExpectedDigests.Insert(expectedDigest.Key(), expectedDigest.Value()); + } + } + } + return toOptions; + } + + winrt::Windows::Management::Deployment::RegisterPackageOptions PackageDeploymentManager::ToOptions(winrt::Microsoft::Windows::Management::Deployment::RegisterPackageOptions const& options) const + { + winrt::Windows::Management::Deployment::RegisterPackageOptions toOptions; + const auto appDataVolume{ options.AppDataVolume() }; + if (appDataVolume) + { + const auto toPackageVolume{ ToPackageVolume(appDataVolume) }; + if (toPackageVolume) + { + toOptions.AppDataVolume(toPackageVolume); + } + } + for (const auto uri : options.DependencyPackageUris()) + { + toOptions.DependencyPackageUris().Append(uri); + } + for (const auto packageFamilyName : options.OptionalPackageFamilyNames()) + { + toOptions.OptionalPackageFamilyNames().Append(packageFamilyName); + } + toOptions.ExternalLocationUri(options.ExternalLocationUri()); + toOptions.DeveloperMode(options.DeveloperMode()); + toOptions.ForceAppShutdown(options.ForceAppShutdown()); + toOptions.ForceTargetAppShutdown(options.ForceTargetAppShutdown()); + toOptions.ForceUpdateFromAnyVersion(options.ForceUpdateFromAnyVersion()); + toOptions.InstallAllResources(options.InstallAllResources()); + toOptions.StageInPlace(options.StageInPlace()); + toOptions.AllowUnsigned(options.AllowUnsigned()); + toOptions.DeferRegistrationWhenPackagesAreInUse(options.DeferRegistrationWhenPackagesAreInUse()); + if (options.IsExpectedDigestsSupported()) + { + const auto expectedDigests{ options.ExpectedDigests() }; + if (expectedDigests) + { + auto toExpectedDigests{ toOptions.ExpectedDigests() }; + for (const auto expectedDigest : expectedDigests) + { + toExpectedDigests.Insert(expectedDigest.Key(), expectedDigest.Value()); + } + } + } + return toOptions; + } + + winrt::Windows::Management::Deployment::RemovalOptions PackageDeploymentManager::ToOptions(winrt::Microsoft::Windows::Management::Deployment::RemovePackageOptions const& options) const + { + auto toOptions{ winrt::Windows::Management::Deployment::RemovalOptions::None }; + if (options.PreserveApplicationData()) + { + toOptions |= winrt::Windows::Management::Deployment::RemovalOptions::PreserveApplicationData; + } + if (options.PreserveRoamableApplicationData()) + { + toOptions |= winrt::Windows::Management::Deployment::RemovalOptions::PreserveRoamableApplicationData; + } + if (options.RemoveForAllUsers()) + { + toOptions |= winrt::Windows::Management::Deployment::RemovalOptions::RemoveForAllUsers; + } + //TODO DeploymentPriority Priority; + return toOptions; + } + + winrt::Windows::Management::Deployment::AddPackageOptions PackageDeploymentManager::ToOptions(winrt::Microsoft::Windows::Management::Deployment::EnsureIsReadyOptions const& /*options*/) const + { + return winrt::Windows::Management::Deployment::AddPackageOptions(); + } +} diff --git a/dev/PackageManager/API/M.W.M.D.PackageDeploymentManager.h b/dev/PackageManager/API/M.W.M.D.PackageDeploymentManager.h new file mode 100644 index 0000000000..be9c8ed393 --- /dev/null +++ b/dev/PackageManager/API/M.W.M.D.PackageDeploymentManager.h @@ -0,0 +1,53 @@ +// Copyright (c) Microsoft Corporation and Contributors. +// Licensed under the MIT License. + +#pragma once + +#include "Microsoft.Windows.Management.Deployment.PackageDeploymentManager.g.h" + +namespace winrt::Microsoft::Windows::Management::Deployment::implementation +{ + struct PackageDeploymentManager : PackageDeploymentManagerT + { + PackageDeploymentManager() = default; + + static winrt::Microsoft::Windows::Management::Deployment::PackageDeploymentManager GetDefault(); + bool IsPackageSetReady(winrt::Microsoft::Windows::Management::Deployment::PackageSet const& packageSet); + bool IsPackageSetReadyById(hstring const& packageSetId); + winrt::Windows::Foundation::IAsyncOperationWithProgress EnsurePackageSetIsReadyAsync(winrt::Microsoft::Windows::Management::Deployment::PackageSet packageSet, winrt::Microsoft::Windows::Management::Deployment::EnsureIsReadyOptions options); + winrt::Windows::Foundation::IAsyncOperationWithProgress EnsurePackageSetIsReadyByIdAsync(hstring packageSetId, winrt::Microsoft::Windows::Management::Deployment::EnsureIsReadyOptions options); + winrt::Windows::Foundation::IAsyncOperationWithProgress AddPackageAsync(hstring package, winrt::Microsoft::Windows::Management::Deployment::AddPackageOptions options); + winrt::Windows::Foundation::IAsyncOperationWithProgress AddPackageByUriAsync(winrt::Windows::Foundation::Uri packageUri, winrt::Microsoft::Windows::Management::Deployment::AddPackageOptions options); + winrt::Windows::Foundation::IAsyncOperationWithProgress AddPackageSetAsync(winrt::Microsoft::Windows::Management::Deployment::PackageSet packageSet, winrt::Microsoft::Windows::Management::Deployment::AddPackageSetOptions options); + winrt::Windows::Foundation::IAsyncOperationWithProgress AddPackageSetByIdAsync(hstring packageSetId, winrt::Microsoft::Windows::Management::Deployment::AddPackageSetOptions options); + winrt::Windows::Foundation::IAsyncOperationWithProgress RemovePackageAsync(hstring packageFullName, winrt::Microsoft::Windows::Management::Deployment::RemovePackageOptions options); + winrt::Windows::Foundation::IAsyncOperationWithProgress RemovePackageByFullNameAsync(hstring packageFullName, winrt::Microsoft::Windows::Management::Deployment::RemovePackageOptions options); + winrt::Windows::Foundation::IAsyncOperationWithProgress RemovePackageByFamilyNameAsync(hstring packageFamilyName, winrt::Microsoft::Windows::Management::Deployment::RemovePackageOptions options); + winrt::Windows::Foundation::IAsyncOperationWithProgress RemovePackageSetAsync(winrt::Microsoft::Windows::Management::Deployment::PackageSet packageSet, winrt::Microsoft::Windows::Management::Deployment::RemovePackageOptions options); + winrt::Windows::Foundation::IAsyncOperationWithProgress RemovePackageSetByIdAsync(hstring packageSetId, winrt::Microsoft::Windows::Management::Deployment::RemovePackageOptions options); + + private: + bool IsReady(winrt::Microsoft::Windows::Management::Deployment::PackageSetItem const& packageSet); + void Validate(winrt::Microsoft::Windows::Management::Deployment::PackageSet const& packageSet) const; + void Validate(winrt::Microsoft::Windows::Management::Deployment::PackageSetItem const& packageSetItem) const; + void EnsureIsReadyAsync(winrt::Microsoft::Windows::Management::Deployment::PackageSetItem const& packageSetItem, winrt::Microsoft::Windows::Management::Deployment::EnsureIsReadyOptions const& options); + void AddAsync(winrt::Microsoft::Windows::Management::Deployment::PackageSetItem const& packageSetItem, winrt::Microsoft::Windows::Management::Deployment::AddPackageSetOptions const& options); + void AddAsync(winrt::Windows::Foundation::Uri const& packageUri, winrt::Windows::Management::Deployment::AddPackageOptions const& addOptions); + winrt::Windows::Management::Deployment::PackageVolume ToPackageVolume(winrt::Microsoft::Windows::Management::Deployment::PackageVolume const& packageVolume) const; + winrt::Windows::Management::Deployment::AddPackageOptions ToOptions(winrt::Microsoft::Windows::Management::Deployment::AddPackageOptions const& options) const; + winrt::Windows::Management::Deployment::AddPackageOptions ToOptions(winrt::Microsoft::Windows::Management::Deployment::AddPackageSetOptions const& options) const; + winrt::Windows::Management::Deployment::StagePackageOptions ToOptions(winrt::Microsoft::Windows::Management::Deployment::StagePackageOptions const& options) const; + winrt::Windows::Management::Deployment::RegisterPackageOptions ToOptions(winrt::Microsoft::Windows::Management::Deployment::RegisterPackageOptions const& options) const; + winrt::Windows::Management::Deployment::RemovalOptions ToOptions(winrt::Microsoft::Windows::Management::Deployment::RemovePackageOptions const& options) const; + winrt::Windows::Management::Deployment::AddPackageOptions ToOptions(winrt::Microsoft::Windows::Management::Deployment::EnsureIsReadyOptions const& options) const; + + private: + winrt::Windows::Management::Deployment::PackageManager m_packageManager; + }; +} +namespace winrt::Microsoft::Windows::Management::Deployment::factory_implementation +{ + struct PackageDeploymentManager : PackageDeploymentManagerT + { + }; +} diff --git a/dev/PackageManager/API/M.W.M.D.PackageDeploymentProgress.cpp b/dev/PackageManager/API/M.W.M.D.PackageDeploymentProgress.cpp new file mode 100644 index 0000000000..51cb33ba92 --- /dev/null +++ b/dev/PackageManager/API/M.W.M.D.PackageDeploymentProgress.cpp @@ -0,0 +1,34 @@ +// Copyright (c) Microsoft Corporation and Contributors. +// Licensed under the MIT License. + +#include "pch.h" +#include "M.W.M.D.PackageDeploymentProgress.h" +#include "Microsoft.Windows.Management.Deployment.PackageDeploymentProgress.g.cpp" + +namespace winrt::Microsoft::Windows::Management::Deployment::implementation +{ + PackageDeploymentProgress::PackageDeploymentProgress( + winrt::Microsoft::Windows::Management::Deployment::PackageDeploymentProgressStatus const& status, + double percentage) : + m_status(status), + m_percentage(percentage) + { + } + + winrt::Microsoft::Windows::Management::Deployment::PackageDeploymentProgressStatus PackageDeploymentProgress::status() + { + return m_status; + } + void PackageDeploymentProgress::status(winrt::Microsoft::Windows::Management::Deployment::PackageDeploymentProgressStatus const& value) + { + m_status = value; + } + double PackageDeploymentProgress::percentage() + { + return m_percentage; + } + void PackageDeploymentProgress::percentage(double value) + { + m_percentage = value; + } +} diff --git a/dev/PackageManager/API/M.W.M.D.PackageDeploymentProgress.h b/dev/PackageManager/API/M.W.M.D.PackageDeploymentProgress.h new file mode 100644 index 0000000000..21da166ad2 --- /dev/null +++ b/dev/PackageManager/API/M.W.M.D.PackageDeploymentProgress.h @@ -0,0 +1,27 @@ +// Copyright (c) Microsoft Corporation and Contributors. +// Licensed under the MIT License. + +#pragma once + +#include "Microsoft.Windows.Management.Deployment.PackageDeploymentProgress.g.h" + +namespace winrt::Microsoft::Windows::Management::Deployment::implementation +{ + struct PackageDeploymentProgress : PackageDeploymentProgressT + { + PackageDeploymentProgress() = default; + + PackageDeploymentProgress( + winrt::Microsoft::Windows::Management::Deployment::PackageDeploymentProgressStatus const& status, + double percentage); + + winrt::Microsoft::Windows::Management::Deployment::PackageDeploymentProgressStatus status(); + void status(winrt::Microsoft::Windows::Management::Deployment::PackageDeploymentProgressStatus const& value); + double percentage(); + void percentage(double value); + + private: + winrt::Microsoft::Windows::Management::Deployment::PackageDeploymentProgressStatus m_status{}; + double m_percentage{}; + }; +} diff --git a/dev/PackageManager/API/M.W.M.D.PackageDeploymentResult.cpp b/dev/PackageManager/API/M.W.M.D.PackageDeploymentResult.cpp new file mode 100644 index 0000000000..ba5bd56032 --- /dev/null +++ b/dev/PackageManager/API/M.W.M.D.PackageDeploymentResult.cpp @@ -0,0 +1,34 @@ +// Copyright (c) Microsoft Corporation and Contributors. +// Licensed under the MIT License. + +#include "pch.h" +#include "M.W.M.D.PackageDeploymentResult.h" +#include "Microsoft.Windows.Management.Deployment.PackageDeploymentResult.g.cpp" + +namespace winrt::Microsoft::Windows::Management::Deployment::implementation +{ + PackageDeploymentResult::PackageDeploymentResult(winrt::Microsoft::Windows::Management::Deployment::PackageDeploymentStatus status, winrt::hresult const& extendedError, bool isRegistered, winrt::guid const& activityId) : + m_status(status), + m_extendedError(extendedError), + m_isRegistered(isRegistered), + m_activityId(activityId) + { + } + + winrt::Microsoft::Windows::Management::Deployment::PackageDeploymentStatus PackageDeploymentResult::Status() + { + return m_status; + } + winrt::hresult PackageDeploymentResult::ExtendedError() + { + return m_extendedError; + } + bool PackageDeploymentResult::IsRegistered() + { + return m_isRegistered; + } + winrt::guid PackageDeploymentResult::ActivityId() + { + return m_activityId; + } +} diff --git a/dev/PackageManager/API/M.W.M.D.PackageDeploymentResult.h b/dev/PackageManager/API/M.W.M.D.PackageDeploymentResult.h new file mode 100644 index 0000000000..ba865976d0 --- /dev/null +++ b/dev/PackageManager/API/M.W.M.D.PackageDeploymentResult.h @@ -0,0 +1,26 @@ +// Copyright (c) Microsoft Corporation and Contributors. +// Licensed under the MIT License. + +#pragma once + +#include "Microsoft.Windows.Management.Deployment.PackageDeploymentResult.g.h" + +namespace winrt::Microsoft::Windows::Management::Deployment::implementation +{ + struct PackageDeploymentResult : PackageDeploymentResultT + { + PackageDeploymentResult() = default; + PackageDeploymentResult(winrt::Microsoft::Windows::Management::Deployment::PackageDeploymentStatus status, winrt::hresult const& extendedError, bool isRegistered, winrt::guid const& activityId); + + winrt::Microsoft::Windows::Management::Deployment::PackageDeploymentStatus Status(); + winrt::hresult ExtendedError(); + winrt::guid ActivityId(); + bool IsRegistered(); + + private: + PackageDeploymentStatus m_status{}; + winrt::hresult m_extendedError; + bool m_isRegistered{}; + winrt::guid m_activityId{}; + }; +} diff --git a/dev/PackageManager/API/M.W.M.D.PackageRuntimeManager.cpp b/dev/PackageManager/API/M.W.M.D.PackageRuntimeManager.cpp new file mode 100644 index 0000000000..cff2cbf024 --- /dev/null +++ b/dev/PackageManager/API/M.W.M.D.PackageRuntimeManager.cpp @@ -0,0 +1,125 @@ +// Copyright (c) Microsoft Corporation and Contributors. +// Licensed under the MIT License. + +#include "pch.h" +#include "M.W.M.D.PackageRuntimeManager.h" +#include "Microsoft.Windows.Management.Deployment.PackageRuntimeManager.g.cpp" + +#include "M.W.M.D.PackageSetItemRuntimeDisposition.h" +#include "M.W.M.D.PackageSetRuntimeDisposition.h" + +#include +#include +#include + +namespace winrt::Microsoft::Windows::Management::Deployment::implementation +{ + winrt::Microsoft::Windows::Management::Deployment::PackageRuntimeManager PackageRuntimeManager::GetDefault() + { + return winrt::make(); + } + winrt::Microsoft::Windows::Management::Deployment::PackageSetRuntimeDisposition PackageRuntimeManager::AddPackageSet(winrt::Microsoft::Windows::Management::Deployment::PackageSet const& packageSet) + { + winrt::Microsoft::Windows::ApplicationModel::DynamicDependency::CreatePackageDependencyOptions createOptions; + winrt::Microsoft::Windows::ApplicationModel::DynamicDependency::AddPackageDependencyOptions addOptions; + return AddPackageSet(packageSet, createOptions, addOptions); + } + winrt::Microsoft::Windows::Management::Deployment::PackageSetRuntimeDisposition PackageRuntimeManager::AddPackageSet(winrt::Microsoft::Windows::Management::Deployment::PackageSet const& packageSet, winrt::Microsoft::Windows::ApplicationModel::DynamicDependency::CreatePackageDependencyOptions const& createOptions, winrt::Microsoft::Windows::ApplicationModel::DynamicDependency::AddPackageDependencyOptions const& addOptions) + { + // Check parameter(s) + Validate(packageSet); + Validate(createOptions); + Validate(addOptions); + + winrt::Microsoft::Windows::Management::Deployment::PackageSetRuntimeDisposition packageSetRuntimeDisposition; + packageSetRuntimeDisposition.PackageSetId(packageSet.Id()); + auto packageSetItemRuntimeDispositions{ packageSetRuntimeDisposition.PackageSetItemRuntimeDispositions() }; + + const auto packageSetItems{ packageSet.PackageSetItems() }; + for (const winrt::Microsoft::Windows::Management::Deployment::PackageSetItem& packageSetItem : packageSetItems) + { + auto packageSetItemRuntimeDisposition{ AddPackageSetItem(packageSetItem, createOptions, addOptions) }; + packageSetItemRuntimeDispositions.Append(packageSetItemRuntimeDisposition); + } + + return packageSetRuntimeDisposition; + } + winrt::Microsoft::Windows::Management::Deployment::PackageSetRuntimeDisposition PackageRuntimeManager::AddPackageSetById(hstring const& packageSetId) + { + winrt::Microsoft::Windows::ApplicationModel::DynamicDependency::CreatePackageDependencyOptions createOptions; + winrt::Microsoft::Windows::ApplicationModel::DynamicDependency::AddPackageDependencyOptions addOptions; + return AddPackageSetById(packageSetId, createOptions, addOptions); + } + winrt::Microsoft::Windows::Management::Deployment::PackageSetRuntimeDisposition PackageRuntimeManager::AddPackageSetById(hstring const& packageSetId, winrt::Microsoft::Windows::ApplicationModel::DynamicDependency::CreatePackageDependencyOptions const& createOptions, winrt::Microsoft::Windows::ApplicationModel::DynamicDependency::AddPackageDependencyOptions const& addOptions) + { + throw hresult_not_implemented(); + } + void PackageRuntimeManager::RemovePackageSet(winrt::Microsoft::Windows::Management::Deployment::PackageSetRuntimeDisposition const& packageSetRuntimeDisposition) + { + const auto packageSetItemRuntimeDispositions{ packageSetRuntimeDisposition.PackageSetItemRuntimeDispositions() }; + for (const winrt::Microsoft::Windows::Management::Deployment::PackageSetItemRuntimeDisposition& packageSetItemRuntimeDisposition : packageSetItemRuntimeDispositions) + { + RemovePackageSetItem(packageSetItemRuntimeDisposition); + } + } + + winrt::Microsoft::Windows::Management::Deployment::PackageSetItemRuntimeDisposition PackageRuntimeManager::AddPackageSetItem(winrt::Microsoft::Windows::Management::Deployment::PackageSetItem const& packageSetItem, winrt::Microsoft::Windows::ApplicationModel::DynamicDependency::CreatePackageDependencyOptions const& createOptions, winrt::Microsoft::Windows::ApplicationModel::DynamicDependency::AddPackageDependencyOptions const& addOptions) + { + auto createPackageDependencyOptions{ MddCreatePackageDependencyOptions::None }; + WI_SetFlagIf(createPackageDependencyOptions, MddCreatePackageDependencyOptions::DoNotVerifyDependencyResolution, !createOptions.VerifyDependencyResolution()); + wil::unique_process_heap_string packageDependencyId; + THROW_IF_FAILED(MddCore::Win11::TryCreatePackageDependency(nullptr, packageSetItem.PackageFamilyName(), + packageSetItem.MinVersion(), packageSetItem.ProcessorArchitectureFilter(), + createOptions, &packageDependencyId)); + + auto addPackageDependencyOptions{ MddAddPackageDependencyOptions::None }; + WI_SetFlagIf(addPackageDependencyOptions, MddAddPackageDependencyOptions::PrependIfRankCollision, addOptions.PrependIfRankCollision()); + wil::unique_mdd_package_dependency_context mddPackageDependencyContext{}; + wil::unique_process_heap_string packageFullName; + THROW_IF_FAILED(MddCore::Win11::AddPackageDependency(packageDependencyId.get(), addOptions, &mddPackageDependencyContext, &packageFullName)); + + auto packageSetItemRuntimeDisposition{ winrt::make( + packageSetItem.Id(), packageFullName.get(), packageDependencyId.get(), mddPackageDependencyContext.get()) }; + mddPackageDependencyContext.reset(); + return packageSetItemRuntimeDisposition; + } + + void PackageRuntimeManager::RemovePackageSetItem(winrt::Microsoft::Windows::Management::Deployment::PackageSetItemRuntimeDisposition const& packageSetItemRuntimeDisposition) + { + const auto packageDependencyContextId{ packageSetItemRuntimeDisposition.PackageDependencyContextId() }; + MddCore::Win11::RemovePackageDependency(packageDependencyContextId); + + const auto packageDependencyId{ packageSetItemRuntimeDisposition.PackageDependencyId() }; + MddCore::Win11::DeletePackageDependency(packageDependencyId); + } + + void PackageRuntimeManager::Validate(winrt::Microsoft::Windows::Management::Deployment::PackageSet const& packageSet) const + { + THROW_HR_IF(E_INVALIDARG, packageSet.Id().empty()); + const auto& packageSetItems{ packageSet.PackageSetItems() }; + THROW_HR_IF(E_INVALIDARG, packageSetItems.Size() == 0); + for (const winrt::Microsoft::Windows::Management::Deployment::PackageSetItem& packageSetItem : packageSetItems) + { + Validate(packageSetItem); + } + } + + void PackageRuntimeManager::Validate(winrt::Microsoft::Windows::Management::Deployment::PackageSetItem const& packageSetItem) const + { + const auto packageFamilyName{ packageSetItem.PackageFamilyName() }; + THROW_IF_WIN32_ERROR_MSG(VerifyPackageFamilyName(packageFamilyName.c_str()), "PackageFamilyName:%ls", packageFamilyName.c_str()); + + const auto packageUri{ packageSetItem.PackageUri() }; + THROW_HR_IF_NULL_MSG(E_INVALIDARG, packageUri, "PackageUri:"); + } + + void PackageRuntimeManager::Validate(winrt::Microsoft::Windows::ApplicationModel::DynamicDependency::CreatePackageDependencyOptions const& options) const + { + // Nothing to do! + } + + void PackageRuntimeManager::Validate(winrt::Microsoft::Windows::ApplicationModel::DynamicDependency::AddPackageDependencyOptions const& options) const + { + // Nothing to do! + } +} diff --git a/dev/PackageManager/API/M.W.M.D.PackageRuntimeManager.h b/dev/PackageManager/API/M.W.M.D.PackageRuntimeManager.h new file mode 100644 index 0000000000..18e65ad647 --- /dev/null +++ b/dev/PackageManager/API/M.W.M.D.PackageRuntimeManager.h @@ -0,0 +1,34 @@ +// Copyright (c) Microsoft Corporation and Contributors. +// Licensed under the MIT License. + +#pragma once + +#include "Microsoft.Windows.Management.Deployment.PackageRuntimeManager.g.h" + +namespace winrt::Microsoft::Windows::Management::Deployment::implementation +{ + struct PackageRuntimeManager : PackageRuntimeManagerT + { + PackageRuntimeManager() = default; + + static winrt::Microsoft::Windows::Management::Deployment::PackageRuntimeManager GetDefault(); + winrt::Microsoft::Windows::Management::Deployment::PackageSetRuntimeDisposition AddPackageSet(winrt::Microsoft::Windows::Management::Deployment::PackageSet const& packageSet); + winrt::Microsoft::Windows::Management::Deployment::PackageSetRuntimeDisposition AddPackageSet(winrt::Microsoft::Windows::Management::Deployment::PackageSet const& packageSet, winrt::Microsoft::Windows::ApplicationModel::DynamicDependency::CreatePackageDependencyOptions const& createOptions, winrt::Microsoft::Windows::ApplicationModel::DynamicDependency::AddPackageDependencyOptions const& addOptions); + winrt::Microsoft::Windows::Management::Deployment::PackageSetRuntimeDisposition AddPackageSetById(hstring const& packageSetId); + winrt::Microsoft::Windows::Management::Deployment::PackageSetRuntimeDisposition AddPackageSetById(hstring const& packageSetId, winrt::Microsoft::Windows::ApplicationModel::DynamicDependency::CreatePackageDependencyOptions const& createOptions, winrt::Microsoft::Windows::ApplicationModel::DynamicDependency::AddPackageDependencyOptions const& addOptions); + void RemovePackageSet(winrt::Microsoft::Windows::Management::Deployment::PackageSetRuntimeDisposition const& packageSetRuntimeDisposition); + private: + winrt::Microsoft::Windows::Management::Deployment::PackageSetItemRuntimeDisposition AddPackageSetItem(winrt::Microsoft::Windows::Management::Deployment::PackageSetItem const& packageSetItem, winrt::Microsoft::Windows::ApplicationModel::DynamicDependency::CreatePackageDependencyOptions const& createOptions, winrt::Microsoft::Windows::ApplicationModel::DynamicDependency::AddPackageDependencyOptions const& addOptions); + void RemovePackageSetItem(winrt::Microsoft::Windows::Management::Deployment::PackageSetItemRuntimeDisposition const& packageSetItemRuntimeDisposition); + void Validate(winrt::Microsoft::Windows::Management::Deployment::PackageSet const& packageSet) const; + void Validate(winrt::Microsoft::Windows::Management::Deployment::PackageSetItem const& packageSetItem) const; + void Validate(winrt::Microsoft::Windows::ApplicationModel::DynamicDependency::CreatePackageDependencyOptions const& options) const; + void Validate(winrt::Microsoft::Windows::ApplicationModel::DynamicDependency::AddPackageDependencyOptions const& options) const; + }; +} +namespace winrt::Microsoft::Windows::Management::Deployment::factory_implementation +{ + struct PackageRuntimeManager : PackageRuntimeManagerT + { + }; +} diff --git a/dev/PackageManager/API/M.W.M.D.PackageSet.cpp b/dev/PackageManager/API/M.W.M.D.PackageSet.cpp new file mode 100644 index 0000000000..9382a7c428 --- /dev/null +++ b/dev/PackageManager/API/M.W.M.D.PackageSet.cpp @@ -0,0 +1,26 @@ +// Copyright (c) Microsoft Corporation and Contributors. +// Licensed under the MIT License. + +#include "pch.h" +#include "M.W.M.D.PackageSet.h" +#include "Microsoft.Windows.Management.Deployment.PackageSet.g.cpp" + +namespace winrt::Microsoft::Windows::Management::Deployment::implementation +{ + hstring PackageSet::Id() + { + return m_id; + } + void PackageSet::Id(hstring const& value) + { + m_id = value; + } + winrt::Windows::Foundation::Collections::IVector PackageSet::PackageSetItems() + { + if (!m_packageSetItems) + { + m_packageSetItems = winrt::single_threaded_vector(); + } + return m_packageSetItems; + } +} diff --git a/dev/PackageManager/API/M.W.M.D.PackageSet.h b/dev/PackageManager/API/M.W.M.D.PackageSet.h new file mode 100644 index 0000000000..f38581041e --- /dev/null +++ b/dev/PackageManager/API/M.W.M.D.PackageSet.h @@ -0,0 +1,28 @@ +// Copyright (c) Microsoft Corporation and Contributors. +// Licensed under the MIT License. + +#pragma once + +#include "Microsoft.Windows.Management.Deployment.PackageSet.g.h" + +namespace winrt::Microsoft::Windows::Management::Deployment::implementation +{ + struct PackageSet : PackageSetT + { + PackageSet() = default; + + hstring Id(); + void Id(hstring const& value); + winrt::Windows::Foundation::Collections::IVector PackageSetItems(); + + private: + hstring m_id; + winrt::Windows::Foundation::Collections::IVector m_packageSetItems; + }; +} +namespace winrt::Microsoft::Windows::Management::Deployment::factory_implementation +{ + struct PackageSet : PackageSetT + { + }; +} diff --git a/dev/PackageManager/API/M.W.M.D.PackageSetItem.cpp b/dev/PackageManager/API/M.W.M.D.PackageSetItem.cpp new file mode 100644 index 0000000000..ab8623dbfe --- /dev/null +++ b/dev/PackageManager/API/M.W.M.D.PackageSetItem.cpp @@ -0,0 +1,50 @@ +// Copyright (c) Microsoft Corporation and Contributors. +// Licensed under the MIT License. + +#include "pch.h" +#include "M.W.M.D.PackageSetItem.h" +#include "Microsoft.Windows.Management.Deployment.PackageSetItem.g.cpp" + +namespace winrt::Microsoft::Windows::Management::Deployment::implementation +{ + hstring PackageSetItem::Id() + { + return m_id; + } + void PackageSetItem::Id(hstring const& value) + { + m_id = value; + } + hstring PackageSetItem::PackageFamilyName() + { + return m_packageFamilyName; + } + void PackageSetItem::PackageFamilyName(hstring const& value) + { + m_packageFamilyName = value; + } + winrt::Windows::ApplicationModel::PackageVersion PackageSetItem::MinVersion() + { + return m_minVersion; + } + void PackageSetItem::MinVersion(winrt::Windows::ApplicationModel::PackageVersion const& value) + { + m_minVersion = value; + } + winrt::Microsoft::Windows::ApplicationModel::DynamicDependency::PackageDependencyProcessorArchitectures PackageSetItem::ProcessorArchitectureFilter() + { + return m_processorArchitectureFilter; + } + void PackageSetItem::ProcessorArchitectureFilter(winrt::Microsoft::Windows::ApplicationModel::DynamicDependency::PackageDependencyProcessorArchitectures const& value) + { + m_processorArchitectureFilter = value; + } + winrt::Windows::Foundation::Uri PackageSetItem::PackageUri() + { + return m_packageUri; + } + void PackageSetItem::PackageUri(winrt::Windows::Foundation::Uri const& value) + { + m_packageUri = value; + } +} diff --git a/dev/PackageManager/API/M.W.M.D.PackageSetItem.h b/dev/PackageManager/API/M.W.M.D.PackageSetItem.h new file mode 100644 index 0000000000..00e98e04cc --- /dev/null +++ b/dev/PackageManager/API/M.W.M.D.PackageSetItem.h @@ -0,0 +1,40 @@ +// Copyright (c) Microsoft Corporation and Contributors. +// Licensed under the MIT License. + +#pragma once + +#include "Microsoft.Windows.Management.Deployment.PackageSetItem.g.h" + +namespace winrt::Microsoft::Windows::Management::Deployment::implementation +{ + struct PackageSetItem : PackageSetItemT + { + PackageSetItem() = default; + + hstring Id(); + void Id(hstring const& value); + + hstring PackageFamilyName(); + void PackageFamilyName(hstring const& value); + winrt::Windows::ApplicationModel::PackageVersion MinVersion(); + void MinVersion(winrt::Windows::ApplicationModel::PackageVersion const& value); + + winrt::Microsoft::Windows::ApplicationModel::DynamicDependency::PackageDependencyProcessorArchitectures ProcessorArchitectureFilter(); + void ProcessorArchitectureFilter(winrt::Microsoft::Windows::ApplicationModel::DynamicDependency::PackageDependencyProcessorArchitectures const& value); + winrt::Windows::Foundation::Uri PackageUri(); + void PackageUri(winrt::Windows::Foundation::Uri const& value); + + private: + hstring m_id; + hstring m_packageFamilyName; + winrt::Windows::ApplicationModel::PackageVersion m_minVersion{}; + winrt::Microsoft::Windows::ApplicationModel::DynamicDependency::PackageDependencyProcessorArchitectures m_processorArchitectureFilter{}; + winrt::Windows::Foundation::Uri m_packageUri{ nullptr }; + }; +} +namespace winrt::Microsoft::Windows::Management::Deployment::factory_implementation +{ + struct PackageSetItem : PackageSetItemT + { + }; +} diff --git a/dev/PackageManager/API/M.W.M.D.PackageSetItemRuntimeDisposition.cpp b/dev/PackageManager/API/M.W.M.D.PackageSetItemRuntimeDisposition.cpp new file mode 100644 index 0000000000..21fe846d79 --- /dev/null +++ b/dev/PackageManager/API/M.W.M.D.PackageSetItemRuntimeDisposition.cpp @@ -0,0 +1,27 @@ +// Copyright (c) Microsoft Corporation and Contributors. +// Licensed under the MIT License. + +#include "pch.h" + +#include "M.W.M.D.PackageSetItemRuntimeDisposition.h" +#include "Microsoft.Windows.Management.Deployment.PackageSetItemRuntimeDisposition.g.cpp" + +namespace winrt::Microsoft::Windows::Management::Deployment::implementation +{ + hstring PackageSetItemRuntimeDisposition::PackageSetItemId() + { + return m_packageSetItemId; + } + hstring PackageSetItemRuntimeDisposition::PackageFullName() + { + return m_packageFullName; + } + hstring PackageSetItemRuntimeDisposition::PackageDependencyId() + { + return m_packageDependencyId; + } + winrt::Microsoft::Windows::ApplicationModel::DynamicDependency::PackageDependencyContextId PackageSetItemRuntimeDisposition::PackageDependencyContextId() + { + return m_packageDependencyContextId; + } +} diff --git a/dev/PackageManager/API/M.W.M.D.PackageSetItemRuntimeDisposition.h b/dev/PackageManager/API/M.W.M.D.PackageSetItemRuntimeDisposition.h new file mode 100644 index 0000000000..34fec4a95c --- /dev/null +++ b/dev/PackageManager/API/M.W.M.D.PackageSetItemRuntimeDisposition.h @@ -0,0 +1,56 @@ +// Copyright (c) Microsoft Corporation and Contributors. +// Licensed under the MIT License. + +#pragma once + +#include "Microsoft.Windows.Management.Deployment.PackageSetItemRuntimeDisposition.g.h" + +#include "MsixDynamicDependency.h" +#include + +#include "MddWin11.h" + +namespace winrt::Microsoft::Windows::Management::Deployment::implementation +{ + struct PackageSetItemRuntimeDisposition : PackageSetItemRuntimeDispositionT + { + PackageSetItemRuntimeDisposition() = default; + PackageSetItemRuntimeDisposition(winrt::hstring const& packageSetItemId, + winrt::hstring const& packageFullName, + winrt::hstring const& packageDependencyId, + winrt::Microsoft::Windows::ApplicationModel::DynamicDependency::PackageDependencyContextId packageDependencyContextId) : + m_packageSetItemId(packageSetItemId), + m_packageFullName(packageFullName), + m_packageDependencyId(packageDependencyId), + m_packageDependencyContextId(packageDependencyContextId) + { + } + PackageSetItemRuntimeDisposition(winrt::hstring const& packageSetItemId, + winrt::hstring const& packageFullName, + winrt::hstring const& packageDependencyId, + MDD_PACKAGEDEPENDENCY_CONTEXT mddPackageDependencyContext) : + m_packageSetItemId(packageSetItemId), + m_packageFullName(packageFullName), + m_packageDependencyId(packageDependencyId), + m_packageDependencyContextId(MddCore::Win11::ToContextId(mddPackageDependencyContext)) + { + } + + hstring PackageSetItemId(); + hstring PackageFullName(); + hstring PackageDependencyId(); + winrt::Microsoft::Windows::ApplicationModel::DynamicDependency::PackageDependencyContextId PackageDependencyContextId(); + + private: + hstring m_packageSetItemId; + hstring m_packageFullName; + hstring m_packageDependencyId; + winrt::Microsoft::Windows::ApplicationModel::DynamicDependency::PackageDependencyContextId m_packageDependencyContextId; + }; +} +namespace winrt::Microsoft::Windows::Management::Deployment::factory_implementation +{ + struct PackageSetItemRuntimeDisposition : PackageSetItemRuntimeDispositionT + { + }; +} diff --git a/dev/PackageManager/API/M.W.M.D.PackageSetManager.cpp b/dev/PackageManager/API/M.W.M.D.PackageSetManager.cpp new file mode 100644 index 0000000000..96006406b0 --- /dev/null +++ b/dev/PackageManager/API/M.W.M.D.PackageSetManager.cpp @@ -0,0 +1,34 @@ +// Copyright (c) Microsoft Corporation and Contributors. +// Licensed under the MIT License. + +#include "pch.h" +#include "M.W.M.D.PackageSetManager.h" +#include "Microsoft.Windows.Management.Deployment.PackageSetManager.g.cpp" + +namespace winrt::Microsoft::Windows::Management::Deployment::implementation +{ + winrt::Microsoft::Windows::Management::Deployment::PackageSetManager PackageSetManager::GetDefault() + { + throw hresult_not_implemented(); + } + void PackageSetManager::Add(winrt::Microsoft::Windows::Management::Deployment::PackageSet const& packageSet) + { + throw hresult_not_implemented(); + } + void PackageSetManager::Update(winrt::Microsoft::Windows::Management::Deployment::PackageSet const& packageSet) + { + throw hresult_not_implemented(); + } + void PackageSetManager::Remove(hstring const& packageSetId) + { + throw hresult_not_implemented(); + } + winrt::Microsoft::Windows::Management::Deployment::PackageSet PackageSetManager::Get(hstring const& packageSetId) + { + throw hresult_not_implemented(); + } + winrt::Windows::Foundation::Collections::IVector PackageSetManager::Find(winrt::Microsoft::Windows::Management::Deployment::FindPackageSetOptions const& options) + { + throw hresult_not_implemented(); + } +} diff --git a/dev/PackageManager/API/M.W.M.D.PackageSetManager.h b/dev/PackageManager/API/M.W.M.D.PackageSetManager.h new file mode 100644 index 0000000000..192e0f7d29 --- /dev/null +++ b/dev/PackageManager/API/M.W.M.D.PackageSetManager.h @@ -0,0 +1,27 @@ +// Copyright (c) Microsoft Corporation and Contributors. +// Licensed under the MIT License. + +#pragma once + +#include "Microsoft.Windows.Management.Deployment.PackageSetManager.g.h" + +namespace winrt::Microsoft::Windows::Management::Deployment::implementation +{ + struct PackageSetManager : PackageSetManagerT + { + PackageSetManager() = default; + + static winrt::Microsoft::Windows::Management::Deployment::PackageSetManager GetDefault(); + void Add(winrt::Microsoft::Windows::Management::Deployment::PackageSet const& packageSet); + void Update(winrt::Microsoft::Windows::Management::Deployment::PackageSet const& packageSet); + void Remove(hstring const& packageSetId); + winrt::Microsoft::Windows::Management::Deployment::PackageSet Get(hstring const& packageSetId); + winrt::Windows::Foundation::Collections::IVector Find(winrt::Microsoft::Windows::Management::Deployment::FindPackageSetOptions const& options); + }; +} +namespace winrt::Microsoft::Windows::Management::Deployment::factory_implementation +{ + struct PackageSetManager : PackageSetManagerT + { + }; +} diff --git a/dev/PackageManager/API/M.W.M.D.PackageSetRuntimeDisposition.cpp b/dev/PackageManager/API/M.W.M.D.PackageSetRuntimeDisposition.cpp new file mode 100644 index 0000000000..0708139845 --- /dev/null +++ b/dev/PackageManager/API/M.W.M.D.PackageSetRuntimeDisposition.cpp @@ -0,0 +1,27 @@ +// Copyright (c) Microsoft Corporation and Contributors. +// Licensed under the MIT License. + +#include "pch.h" + +#include "M.W.M.D.PackageSetRuntimeDisposition.h" +#include "Microsoft.Windows.Management.Deployment.PackageSetRuntimeDisposition.g.cpp" + +namespace winrt::Microsoft::Windows::Management::Deployment::implementation +{ + hstring PackageSetRuntimeDisposition::PackageSetId() + { + return m_packageSetId; + } + void PackageSetRuntimeDisposition::PackageSetId(hstring const& value) + { + m_packageSetId = value; + } + winrt::Windows::Foundation::Collections::IVector PackageSetRuntimeDisposition::PackageSetItemRuntimeDispositions() + { + if (!m_packageSetItemRuntimeDispositions) + { + m_packageSetItemRuntimeDispositions = winrt::single_threaded_vector(); + } + return m_packageSetItemRuntimeDispositions; + } +} diff --git a/dev/PackageManager/API/M.W.M.D.PackageSetRuntimeDisposition.h b/dev/PackageManager/API/M.W.M.D.PackageSetRuntimeDisposition.h new file mode 100644 index 0000000000..c339c6d611 --- /dev/null +++ b/dev/PackageManager/API/M.W.M.D.PackageSetRuntimeDisposition.h @@ -0,0 +1,39 @@ +// Copyright (c) Microsoft Corporation and Contributors. +// Licensed under the MIT License. + +#pragma once + +#include "M.W.M.D.PackageSetRuntimeDisposition.h" +#include "Microsoft.Windows.Management.Deployment.PackageSetRuntimeDisposition.g.h" + +namespace winrt::Microsoft::Windows::Management::Deployment::implementation +{ + struct PackageSetRuntimeDisposition : PackageSetRuntimeDispositionT + { + PackageSetRuntimeDisposition() = default; +#if 0 + PackageSetRuntimeDisposition(winrt::hstring const& packageSetId) : + m_packageSetId(packageSetId) + { + } + PackageSetRuntimeDisposition(winrt::hstring const& packageSetId, winrt::Windows::Foundation::Collections::IVector& packageSetItemRuntimeDispositions) : + m_packageSetId(packageSetId), + m_packageSetItemRuntimeDispositions(packageSetItemRuntimeDispositions) + { + } +#endif + + hstring PackageSetId(); + void PackageSetId(hstring const& value); + winrt::Windows::Foundation::Collections::IVector PackageSetItemRuntimeDispositions(); + private: + hstring m_packageSetId; + winrt::Windows::Foundation::Collections::IVector m_packageSetItemRuntimeDispositions{}; + }; +} +namespace winrt::Microsoft::Windows::Management::Deployment::factory_implementation +{ + struct PackageSetRuntimeDisposition : PackageSetRuntimeDispositionT + { + }; +} diff --git a/dev/PackageManager/API/M.W.M.D.PackageVolume.cpp b/dev/PackageManager/API/M.W.M.D.PackageVolume.cpp new file mode 100644 index 0000000000..835e8aa25d --- /dev/null +++ b/dev/PackageManager/API/M.W.M.D.PackageVolume.cpp @@ -0,0 +1,57 @@ +// Copyright (c) Microsoft Corporation and Contributors. +// Licensed under the MIT License. + +#include "pch.h" +#include "M.W.M.D.PackageVolume.h" +#include "Microsoft.Windows.Management.Deployment.PackageVolume.g.cpp" + +namespace winrt::Microsoft::Windows::Management::Deployment::implementation +{ + PackageVolume::PackageVolume(winrt::Windows::Management::Deployment::PackageVolume const& value) + { + m_isSystemVolume = value.IsSystemVolume(); + m_mountPoint = value.MountPoint(); + m_name = value.Name(); + m_packageStorePath = value.PackageStorePath(); + m_supportsHardLinks = value.SupportsHardLinks(); + m_isFullTrustPackageSupported = value.IsFullTrustPackageSupported(); + m_isAppxInstallSupported = value.IsAppxInstallSupported(); + //TODO m_packageStatus = value.Status(); + } + bool PackageVolume::IsSystemVolume() + { + return m_isSystemVolume; + } + hstring PackageVolume::MountPoint() + { + return m_mountPoint; + } + hstring PackageVolume::Name() + { + return m_name; + } + hstring PackageVolume::PackageStorePath() + { + return m_packageStorePath; + } + bool PackageVolume::SupportsHardLinks() + { + return m_supportsHardLinks; + } + bool PackageVolume::IsFullTrustPackageSupported() + { + return m_isFullTrustPackageSupported; + } + bool PackageVolume::IsAppxInstallSupported() + { + return m_isAppxInstallSupported; + } + winrt::Microsoft::Windows::Management::Deployment::PackageVolumeStatus PackageVolume::Status() + { + throw hresult_not_implemented(); + } + void PackageVolume::FixMe() + { + throw hresult_not_implemented(); + } +} diff --git a/dev/PackageManager/API/M.W.M.D.PackageVolume.h b/dev/PackageManager/API/M.W.M.D.PackageVolume.h new file mode 100644 index 0000000000..9c09798084 --- /dev/null +++ b/dev/PackageManager/API/M.W.M.D.PackageVolume.h @@ -0,0 +1,41 @@ +// Copyright (c) Microsoft Corporation and Contributors. +// Licensed under the MIT License. + +#pragma once + +#include "Microsoft.Windows.Management.Deployment.PackageVolume.g.h" + +namespace winrt::Microsoft::Windows::Management::Deployment::implementation +{ + struct PackageVolume : PackageVolumeT + { + PackageVolume() = default; + PackageVolume(winrt::Windows::Management::Deployment::PackageVolume const& value); + + bool IsSystemVolume(); + hstring MountPoint(); + hstring Name(); + hstring PackageStorePath(); + bool SupportsHardLinks(); + bool IsFullTrustPackageSupported(); + bool IsAppxInstallSupported(); + winrt::Microsoft::Windows::Management::Deployment::PackageVolumeStatus Status(); + void FixMe(); + + private: + bool m_isSystemVolume{}; + hstring m_mountPoint; + hstring m_name; + hstring m_packageStorePath; + bool m_supportsHardLinks{}; + bool m_isFullTrustPackageSupported{}; + bool m_isAppxInstallSupported{}; + //TODO winrt::Microsoft::Windows::Management::Deployment::PackageVolumeStatus m_status{}; + }; +} +namespace winrt::Microsoft::Windows::Management::Deployment::factory_implementation +{ + struct PackageVolume : PackageVolumeT + { + }; +} diff --git a/dev/PackageManager/API/M.W.M.D.PackageVolumeManager.cpp b/dev/PackageManager/API/M.W.M.D.PackageVolumeManager.cpp new file mode 100644 index 0000000000..8a74361c2a --- /dev/null +++ b/dev/PackageManager/API/M.W.M.D.PackageVolumeManager.cpp @@ -0,0 +1,53 @@ +// Copyright (c) Microsoft Corporation and Contributors. +// Licensed under the MIT License. + +#pragma once + +#include "pch.h" +#include "M.W.M.D.PackageVolumeManager.h" +#include "Microsoft.Windows.Management.Deployment.PackageVolumeManager.g.cpp" + +namespace winrt::Microsoft::Windows::Management::Deployment::implementation +{ + winrt::Windows::Foundation::Collections::IVector PackageVolumeManager::FindPackageVolumes() + { + winrt::Windows::Foundation::Collections::IVector microsoftPackageVolumes{ winrt::single_threaded_vector() }; + + winrt::Windows::Management::Deployment::PackageManager packageManager; + winrt::Windows::Foundation::Collections::IIterable windowsPackageVolumes{ packageManager.FindPackageVolumes() }; + for (winrt::Windows::Management::Deployment::PackageVolume windowsPackageVolume : windowsPackageVolumes) + { + auto microsoftPackageVolume{ winrt::make(windowsPackageVolume) }; + microsoftPackageVolumes.Append(microsoftPackageVolume); + } + return microsoftPackageVolumes; + } + winrt::Microsoft::Windows::Management::Deployment::PackageVolume PackageVolumeManager::FindPackageVolumeByPath(hstring const& path) + { + const auto c_volumePathNameMaxLength{ MAX_PATH }; + wchar_t volumePathName[c_volumePathNameMaxLength]{};//AKA volumeMountPoint + THROW_IF_WIN32_BOOL_FALSE_MSG(::GetVolumePathNameW(path.c_str(), volumePathName, ARRAYSIZE(volumePathName)), "Path:%ls", path.c_str()); + GUID mediaId{}; + const size_t c_volumeNameMaxLength{ 50 }; // "\\?\Volume{GUID}\" == 11 + 11111111-2222-3333-4444-555555555555 + 2 + null-terminator == 11 + 36 + 3 = 50 + wchar_t volumeName[c_volumeNameMaxLength]{}; + THROW_IF_WIN32_BOOL_FALSE_MSG(::GetVolumeNameForVolumeMountPoint(volumePathName, volumeName, ARRAYSIZE(volumeName)), "Path:%ls VolumePathName:%ls", path.c_str(), volumePathName); + const auto volumeNameLength{ wcslen(volumeName) }; + THROW_HR_IF_MSG(E_UNEXPECTED, volumeNameLength == 0, "Path:%ls VolumePathName:%ls", path.c_str(), volumePathName); + const auto offset{ volumeNameLength - 1 }; + if (volumeName[offset] == L'\\') + { + volumeName[offset] = L'\0'; + } + return FindPackageVolumeByName(winrt::hstring{ volumeName }); + } + winrt::Microsoft::Windows::Management::Deployment::PackageVolume PackageVolumeManager::FindPackageVolumeByMediaId(hstring const& mediaId) + { + winrt::Windows::Management::Deployment::PackageManager packageManager; + winrt::Windows::Management::Deployment::PackageVolume windowsPackageVolume{ packageManager.FindPackageVolume(mediaId) }; + return winrt::make(windowsPackageVolume); + } + winrt::Microsoft::Windows::Management::Deployment::PackageVolume PackageVolumeManager::FindPackageVolumeByName(hstring const& name) + { + throw hresult_not_implemented(); + } +} diff --git a/dev/PackageManager/API/M.W.M.D.PackageVolumeManager.h b/dev/PackageManager/API/M.W.M.D.PackageVolumeManager.h new file mode 100644 index 0000000000..94e3db998a --- /dev/null +++ b/dev/PackageManager/API/M.W.M.D.PackageVolumeManager.h @@ -0,0 +1,26 @@ +// Copyright (c) Microsoft Corporation and Contributors. +// Licensed under the MIT License. + +#pragma once + +#include "Microsoft.Windows.Management.Deployment.PackageVolumeManager.g.h" +#include "M.W.M.D.PackageVolume.h" + +namespace winrt::Microsoft::Windows::Management::Deployment::implementation +{ + struct PackageVolumeManager + { + PackageVolumeManager() = default; + + static winrt::Windows::Foundation::Collections::IVector FindPackageVolumes(); + static winrt::Microsoft::Windows::Management::Deployment::PackageVolume FindPackageVolumeByPath(hstring const& path); + static winrt::Microsoft::Windows::Management::Deployment::PackageVolume FindPackageVolumeByMediaId(hstring const& mediaId); + static winrt::Microsoft::Windows::Management::Deployment::PackageVolume FindPackageVolumeByName(hstring const& name); + }; +} +namespace winrt::Microsoft::Windows::Management::Deployment::factory_implementation +{ + struct PackageVolumeManager : PackageVolumeManagerT + { + }; +} diff --git a/dev/PackageManager/API/M.W.M.D.PackageVolumeStatus.cpp b/dev/PackageManager/API/M.W.M.D.PackageVolumeStatus.cpp new file mode 100644 index 0000000000..828c54f668 --- /dev/null +++ b/dev/PackageManager/API/M.W.M.D.PackageVolumeStatus.cpp @@ -0,0 +1,34 @@ +// Copyright (c) Microsoft Corporation and Contributors. +// Licensed under the MIT License. + +#include "pch.h" +#include "M.W.M.D.PackageVolumeStatus.h" +#include "Microsoft.Windows.Management.Deployment.PackageVolumeStatus.g.cpp" + +namespace winrt::Microsoft::Windows::Management::Deployment::implementation +{ + bool PackageVolumeStatus::IsOK() + { + throw hresult_not_implemented(); + } + void PackageVolumeStatus::IsOK(bool value) + { + throw hresult_not_implemented(); + } + bool PackageVolumeStatus::IsOffline() + { + throw hresult_not_implemented(); + } + void PackageVolumeStatus::IsOffline(bool value) + { + throw hresult_not_implemented(); + } + bool PackageVolumeStatus::IsBroken() + { + throw hresult_not_implemented(); + } + void PackageVolumeStatus::IsBroken(bool value) + { + throw hresult_not_implemented(); + } +} diff --git a/dev/PackageManager/API/M.W.M.D.PackageVolumeStatus.h b/dev/PackageManager/API/M.W.M.D.PackageVolumeStatus.h new file mode 100644 index 0000000000..faa8169a91 --- /dev/null +++ b/dev/PackageManager/API/M.W.M.D.PackageVolumeStatus.h @@ -0,0 +1,27 @@ +// Copyright (c) Microsoft Corporation and Contributors. +// Licensed under the MIT License. + +#pragma once + +#include "Microsoft.Windows.Management.Deployment.PackageVolumeStatus.g.h" + +namespace winrt::Microsoft::Windows::Management::Deployment::implementation +{ + struct PackageVolumeStatus : PackageVolumeStatusT + { + PackageVolumeStatus() = default; + + bool IsOK(); + void IsOK(bool value); + bool IsOffline(); + void IsOffline(bool value); + bool IsBroken(); + void IsBroken(bool value); + }; +} +namespace winrt::Microsoft::Windows::Management::Deployment::factory_implementation +{ + struct PackageVolumeStatus : PackageVolumeStatusT + { + }; +} diff --git a/dev/PackageManager/API/M.W.M.D.RegisterPackageOptions.cpp b/dev/PackageManager/API/M.W.M.D.RegisterPackageOptions.cpp new file mode 100644 index 0000000000..8015a759cf --- /dev/null +++ b/dev/PackageManager/API/M.W.M.D.RegisterPackageOptions.cpp @@ -0,0 +1,118 @@ +// Copyright (c) Microsoft Corporation and Contributors. +// Licensed under the MIT License. + +#include "pch.h" + +#include + +#include "M.W.M.D.RegisterPackageOptions.h" +#include "Microsoft.Windows.Management.Deployment.RegisterPackageOptions.g.cpp" + +namespace winrt::Microsoft::Windows::Management::Deployment::implementation +{ + winrt::Microsoft::Windows::Management::Deployment::PackageVolume RegisterPackageOptions::AppDataVolume() + { + return m_appDataVolume; + } + void RegisterPackageOptions::AppDataVolume(winrt::Microsoft::Windows::Management::Deployment::PackageVolume const& value) + { + m_appDataVolume = value; + } + winrt::Windows::Foundation::Collections::IVector RegisterPackageOptions::DependencyPackageUris() + { + if (!m_dependencyPackageUris) + { + m_dependencyPackageUris = winrt::single_threaded_vector(); + } + return m_dependencyPackageUris; + } + winrt::Windows::Foundation::Collections::IVector RegisterPackageOptions::OptionalPackageFamilyNames() + { + if (!m_optionalPackageFamilyNames) + { + m_optionalPackageFamilyNames = winrt::single_threaded_vector(); + } + return m_optionalPackageFamilyNames; + } + winrt::Windows::Foundation::Uri RegisterPackageOptions::ExternalLocationUri() + { + return m_externalLocationUri; + } + void RegisterPackageOptions::ExternalLocationUri(winrt::Windows::Foundation::Uri const& value) + { + m_externalLocationUri = value; + } + bool RegisterPackageOptions::DeveloperMode() + { + return m_developerMode; + } + void RegisterPackageOptions::DeveloperMode(bool value) + { + m_developerMode = value; + } + bool RegisterPackageOptions::ForceAppShutdown() + { + return m_forceAppShutdown; + } + void RegisterPackageOptions::ForceAppShutdown(bool value) + { + m_forceAppShutdown = value; + } + bool RegisterPackageOptions::ForceTargetAppShutdown() + { + return m_forceTargetAppShutdown; + } + void RegisterPackageOptions::ForceTargetAppShutdown(bool value) + { + m_forceTargetAppShutdown = value; + } + bool RegisterPackageOptions::ForceUpdateFromAnyVersion() + { + return m_forceUpdateFromAnyVersion; + } + void RegisterPackageOptions::ForceUpdateFromAnyVersion(bool value) + { + m_forceUpdateFromAnyVersion = value; + } + bool RegisterPackageOptions::InstallAllResources() + { + return m_installAllResources; + } + void RegisterPackageOptions::InstallAllResources(bool value) + { + m_installAllResources = value; + } + bool RegisterPackageOptions::StageInPlace() + { + return m_stageInPlace; + } + void RegisterPackageOptions::StageInPlace(bool value) + { + m_stageInPlace = value; + } + bool RegisterPackageOptions::AllowUnsigned() + { + return m_allowUnsigned; + } + void RegisterPackageOptions::AllowUnsigned(bool value) + { + m_allowUnsigned = value; + } + bool RegisterPackageOptions::DeferRegistrationWhenPackagesAreInUse() + { + return m_deferRegistrationWhenPackagesAreInUse; + } + void RegisterPackageOptions::DeferRegistrationWhenPackagesAreInUse(bool value) + { + m_deferRegistrationWhenPackagesAreInUse = value; + } + bool RegisterPackageOptions::IsExpectedDigestsSupported() + { + // Requires Windows >= 10.0.22621.0 (aka Win11 22H2) + return WindowsVersion::IsWindows11_22H2OrGreater(); + } + winrt::Windows::Foundation::Collections::IMap RegisterPackageOptions::ExpectedDigests() + { + return m_expectedDigests; + } +} diff --git a/dev/PackageManager/API/M.W.M.D.RegisterPackageOptions.h b/dev/PackageManager/API/M.W.M.D.RegisterPackageOptions.h new file mode 100644 index 0000000000..27bb36d673 --- /dev/null +++ b/dev/PackageManager/API/M.W.M.D.RegisterPackageOptions.h @@ -0,0 +1,61 @@ +// Copyright (c) Microsoft Corporation and Contributors. +// Licensed under the MIT License. + +#pragma once + +#include "Microsoft.Windows.Management.Deployment.RegisterPackageOptions.g.h" + +namespace winrt::Microsoft::Windows::Management::Deployment::implementation +{ + struct RegisterPackageOptions : RegisterPackageOptionsT + { + RegisterPackageOptions() = default; + + winrt::Microsoft::Windows::Management::Deployment::PackageVolume AppDataVolume(); + void AppDataVolume(winrt::Microsoft::Windows::Management::Deployment::PackageVolume const& value); + winrt::Windows::Foundation::Collections::IVector DependencyPackageUris(); + winrt::Windows::Foundation::Collections::IVector OptionalPackageFamilyNames(); + winrt::Windows::Foundation::Uri ExternalLocationUri(); + void ExternalLocationUri(winrt::Windows::Foundation::Uri const& value); + bool DeveloperMode(); + void DeveloperMode(bool value); + bool ForceAppShutdown(); + void ForceAppShutdown(bool value); + bool ForceTargetAppShutdown(); + void ForceTargetAppShutdown(bool value); + bool ForceUpdateFromAnyVersion(); + void ForceUpdateFromAnyVersion(bool value); + bool InstallAllResources(); + void InstallAllResources(bool value); + bool StageInPlace(); + void StageInPlace(bool value); + bool AllowUnsigned(); + void AllowUnsigned(bool value); + bool IsDeferRegistrationWhenPackagesAreInUseSupported(); + bool DeferRegistrationWhenPackagesAreInUse(); + void DeferRegistrationWhenPackagesAreInUse(bool value); + bool IsExpectedDigestsSupported(); + winrt::Windows::Foundation::Collections::IMap ExpectedDigests(); + + private: + winrt::Microsoft::Windows::Management::Deployment::PackageVolume m_appDataVolume{}; + winrt::Windows::Foundation::Collections::IVector m_dependencyPackageUris{}; + winrt::Windows::Foundation::Collections::IVector m_optionalPackageFamilyNames{}; + winrt::Windows::Foundation::Uri m_externalLocationUri{ nullptr }; + bool m_developerMode{}; + bool m_forceAppShutdown{}; + bool m_forceTargetAppShutdown{}; + bool m_forceUpdateFromAnyVersion{}; + bool m_installAllResources{}; + bool m_stageInPlace{}; + bool m_allowUnsigned{}; + bool m_deferRegistrationWhenPackagesAreInUse{}; + winrt::Windows::Foundation::Collections::IMap m_expectedDigests; + }; +} +namespace winrt::Microsoft::Windows::Management::Deployment::factory_implementation +{ + struct RegisterPackageOptions : RegisterPackageOptionsT + { + }; +} diff --git a/dev/PackageManager/API/M.W.M.D.RemovePackageOptions.cpp b/dev/PackageManager/API/M.W.M.D.RemovePackageOptions.cpp new file mode 100644 index 0000000000..95cf0b69f6 --- /dev/null +++ b/dev/PackageManager/API/M.W.M.D.RemovePackageOptions.cpp @@ -0,0 +1,43 @@ +// Copyright (c) Microsoft Corporation and Contributors. +// Licensed under the MIT License. + +#include "pch.h" + +#include "M.W.M.D.RemovePackageOptions.h" +#include "Microsoft.Windows.Management.Deployment.RemovePackageOptions.g.cpp" + +namespace winrt::Microsoft::Windows::Management::Deployment::implementation +{ + bool RemovePackageOptions::PreserveApplicationData() + { + return m_preserveApplicationData; + } + void RemovePackageOptions::PreserveApplicationData(bool value) + { + m_preserveApplicationData = value; + } + bool RemovePackageOptions::PreserveRoamableApplicationData() + { + return m_preserveRoamableApplicationData; + } + void RemovePackageOptions::PreserveRoamableApplicationData(bool value) + { + m_preserveRoamableApplicationData = value; + } + bool RemovePackageOptions::RemoveForAllUsers() + { + return m_removeForAllUsers; + } + void RemovePackageOptions::RemoveForAllUsers(bool value) + { + m_removeForAllUsers = value; + } + winrt::Microsoft::Windows::Management::Deployment::DeploymentPriority RemovePackageOptions::Priority() + { + return m_priority; + } + void RemovePackageOptions::Priority(winrt::Microsoft::Windows::Management::Deployment::DeploymentPriority const& value) + { + m_priority = value; + } +} diff --git a/dev/PackageManager/API/M.W.M.D.RemovePackageOptions.h b/dev/PackageManager/API/M.W.M.D.RemovePackageOptions.h new file mode 100644 index 0000000000..523278f5c3 --- /dev/null +++ b/dev/PackageManager/API/M.W.M.D.RemovePackageOptions.h @@ -0,0 +1,35 @@ +// Copyright (c) Microsoft Corporation and Contributors. +// Licensed under the MIT License. + +#pragma once + +#include "Microsoft.Windows.Management.Deployment.RemovePackageOptions.g.h" + +namespace winrt::Microsoft::Windows::Management::Deployment::implementation +{ + struct RemovePackageOptions : RemovePackageOptionsT + { + RemovePackageOptions() = default; + + bool PreserveApplicationData(); + void PreserveApplicationData(bool value); + bool PreserveRoamableApplicationData(); + void PreserveRoamableApplicationData(bool value); + bool RemoveForAllUsers(); + void RemoveForAllUsers(bool value); + winrt::Microsoft::Windows::Management::Deployment::DeploymentPriority Priority(); + void Priority(winrt::Microsoft::Windows::Management::Deployment::DeploymentPriority const& value); + + private: + bool m_preserveApplicationData{}; + bool m_preserveRoamableApplicationData{}; + bool m_removeForAllUsers{}; + winrt::Microsoft::Windows::Management::Deployment::DeploymentPriority m_priority{ winrt::Microsoft::Windows::Management::Deployment::DeploymentPriority::Normal }; + }; +} +namespace winrt::Microsoft::Windows::Management::Deployment::factory_implementation +{ + struct RemovePackageOptions : RemovePackageOptionsT + { + }; +} diff --git a/dev/PackageManager/API/M.W.M.D.StagePackageOptions.cpp b/dev/PackageManager/API/M.W.M.D.StagePackageOptions.cpp new file mode 100644 index 0000000000..a743fb09d7 --- /dev/null +++ b/dev/PackageManager/API/M.W.M.D.StagePackageOptions.cpp @@ -0,0 +1,126 @@ +// Copyright (c) Microsoft Corporation and Contributors. +// Licensed under the MIT License. + +#include "pch.h" + +#include + +#include "M.W.M.D.StagePackageOptions.h" +#include "Microsoft.Windows.Management.Deployment.StagePackageOptions.g.cpp" + +namespace winrt::Microsoft::Windows::Management::Deployment::implementation +{ + winrt::Microsoft::Windows::Management::Deployment::PackageVolume StagePackageOptions::TargetVolume() + { + return m_targetVolume; + } + void StagePackageOptions::TargetVolume(winrt::Microsoft::Windows::Management::Deployment::PackageVolume const& value) + { + m_targetVolume = value; + } + winrt::Windows::Foundation::Collections::IVector StagePackageOptions::DependencyPackageUris() + { + if (!m_dependencyPackageUris) + { + m_dependencyPackageUris = winrt::single_threaded_vector(); + } + return m_dependencyPackageUris; + } + winrt::Windows::Foundation::Collections::IVector StagePackageOptions::OptionalPackageFamilyNames() + { + if (!m_optionalPackageFamilyNames) + { + m_optionalPackageFamilyNames = winrt::single_threaded_vector(); + } + return m_optionalPackageFamilyNames; + } + winrt::Windows::Foundation::Collections::IVector StagePackageOptions::OptionalPackageUris() + { + if (!m_optionalPackageUris) + { + m_optionalPackageUris = winrt::single_threaded_vector(); + } + return m_optionalPackageUris; + } + winrt::Windows::Foundation::Collections::IVector StagePackageOptions::RelatedPackageUris() + { + if (!m_relatedPackageUris) + { + m_relatedPackageUris = winrt::single_threaded_vector(); + } + return m_relatedPackageUris; + } + winrt::Windows::Foundation::Uri StagePackageOptions::ExternalLocationUri() + { + return m_externalLocationUri; + } + void StagePackageOptions::ExternalLocationUri(winrt::Windows::Foundation::Uri const& value) + { + m_externalLocationUri = value; + } + winrt::Microsoft::Windows::Management::Deployment::StubPackageOption StagePackageOptions::StubPackageOption() + { + return m_stubPackageOption; + } + void StagePackageOptions::StubPackageOption(winrt::Microsoft::Windows::Management::Deployment::StubPackageOption const& value) + { + m_stubPackageOption = value; + } + bool StagePackageOptions::DeveloperMode() + { + return m_developerMode; + } + void StagePackageOptions::DeveloperMode(bool value) + { + m_developerMode = value; + } + bool StagePackageOptions::ForceUpdateFromAnyVersion() + { + return m_forceUpdateFromAnyVersion; + } + void StagePackageOptions::ForceUpdateFromAnyVersion(bool value) + { + m_forceUpdateFromAnyVersion = value; + } + bool StagePackageOptions::InstallAllResources() + { + return m_installAllResources; + } + void StagePackageOptions::InstallAllResources(bool value) + { + m_installAllResources = value; + } + bool StagePackageOptions::RequiredContentGroupOnly() + { + return m_requiredContentGroupOnly; + } + void StagePackageOptions::RequiredContentGroupOnly(bool value) + { + m_requiredContentGroupOnly = value; + } + bool StagePackageOptions::StageInPlace() + { + return m_stageInPlace; + } + void StagePackageOptions::StageInPlace(bool value) + { + m_stageInPlace = value; + } + bool StagePackageOptions::AllowUnsigned() + { + return m_allowUnsigned; + } + void StagePackageOptions::AllowUnsigned(bool value) + { + m_allowUnsigned = value; + } + bool StagePackageOptions::IsExpectedDigestsSupported() + { + // Requires Windows >= 10.0.22621.0 (aka Win11 22H2) + return WindowsVersion::IsWindows11_22H2OrGreater(); + } + winrt::Windows::Foundation::Collections::IMap StagePackageOptions::ExpectedDigests() + { + return m_expectedDigests; + } +} diff --git a/dev/PackageManager/API/M.W.M.D.StagePackageOptions.h b/dev/PackageManager/API/M.W.M.D.StagePackageOptions.h new file mode 100644 index 0000000000..5ccd499753 --- /dev/null +++ b/dev/PackageManager/API/M.W.M.D.StagePackageOptions.h @@ -0,0 +1,61 @@ +// Copyright (c) Microsoft Corporation and Contributors. +// Licensed under the MIT License. + +#pragma once + +#include "Microsoft.Windows.Management.Deployment.StagePackageOptions.g.h" + +namespace winrt::Microsoft::Windows::Management::Deployment::implementation +{ + struct StagePackageOptions : StagePackageOptionsT + { + StagePackageOptions() = default; + + winrt::Microsoft::Windows::Management::Deployment::PackageVolume TargetVolume(); + void TargetVolume(winrt::Microsoft::Windows::Management::Deployment::PackageVolume const& value); + winrt::Windows::Foundation::Collections::IVector DependencyPackageUris(); + winrt::Windows::Foundation::Collections::IVector OptionalPackageFamilyNames(); + winrt::Windows::Foundation::Collections::IVector OptionalPackageUris(); + winrt::Windows::Foundation::Collections::IVector RelatedPackageUris(); + void ExternalLocationUri(winrt::Windows::Foundation::Uri const& value); + winrt::Windows::Foundation::Uri ExternalLocationUri(); + winrt::Microsoft::Windows::Management::Deployment::StubPackageOption StubPackageOption(); + void StubPackageOption(winrt::Microsoft::Windows::Management::Deployment::StubPackageOption const& value); + bool DeveloperMode(); + void DeveloperMode(bool value); + bool ForceUpdateFromAnyVersion(); + void ForceUpdateFromAnyVersion(bool value); + bool InstallAllResources(); + void InstallAllResources(bool value); + bool RequiredContentGroupOnly(); + void RequiredContentGroupOnly(bool value); + bool StageInPlace(); + void StageInPlace(bool value); + bool AllowUnsigned(); + void AllowUnsigned(bool value); + bool IsExpectedDigestsSupported(); + winrt::Windows::Foundation::Collections::IMap ExpectedDigests(); + + private: + winrt::Microsoft::Windows::Management::Deployment::PackageVolume m_targetVolume{}; + winrt::Windows::Foundation::Collections::IVector m_dependencyPackageUris{}; + winrt::Windows::Foundation::Collections::IVector m_optionalPackageFamilyNames{}; + winrt::Windows::Foundation::Collections::IVector m_optionalPackageUris{}; + winrt::Windows::Foundation::Collections::IVector m_relatedPackageUris{}; + winrt::Windows::Foundation::Uri m_externalLocationUri{ nullptr }; + winrt::Microsoft::Windows::Management::Deployment::StubPackageOption m_stubPackageOption{}; + bool m_developerMode{}; + bool m_forceUpdateFromAnyVersion{}; + bool m_installAllResources{}; + bool m_requiredContentGroupOnly{}; + bool m_stageInPlace{}; + bool m_allowUnsigned{}; + winrt::Windows::Foundation::Collections::IMap m_expectedDigests; + }; +} +namespace winrt::Microsoft::Windows::Management::Deployment::factory_implementation +{ + struct StagePackageOptions : StagePackageOptionsT + { + }; +} diff --git a/dev/PackageManager/API/MsixPackageManager.h b/dev/PackageManager/API/MsixPackageManager.h new file mode 100644 index 0000000000..c5bb365f42 --- /dev/null +++ b/dev/PackageManager/API/MsixPackageManager.h @@ -0,0 +1,19 @@ +// Copyright (c) Microsoft Corporation and Contributors. +// Licensed under the MIT License. + +#if !defined(MSIXPACKAGEMANAGER_H) +#define MSIXPACKAGEMANAGER_H + +/// MSIX Package Manager: Scanning for an applicable package +#define MSIXPACKAGEMANAGER_E_PACKAGE_SCAN _HRESULT_TYPEDEF_(0x80040301L) + +/// MSIX Package Manager: Found a package but doesn't match the criteria +#define MSIXPACKAGEMANAGER_E_PACKAGE_SCAN_NOT_MATCH _HRESULT_TYPEDEF_(0x80040302L) + +/// MSIX Package Manager: Found a package that does match the criteria +#define MSIXPACKAGEMANAGER_E_PACKAGE_SCAN_MATCH _HRESULT_TYPEDEF_(0x80040303L) + +/// MSIX Package Manager: Found no applicable package matching the criteria +#define MSIXPACKAGEMANAGER_E_PACKAGE_SCAN_FAILED _HRESULT_TYPEDEF_(0x80040304L) + +#endif // MSIXPACKAGEMANAGER_H diff --git a/dev/PackageManager/API/PackageDeploymentResolver.cpp b/dev/PackageManager/API/PackageDeploymentResolver.cpp new file mode 100644 index 0000000000..1a1165f8f9 --- /dev/null +++ b/dev/PackageManager/API/PackageDeploymentResolver.cpp @@ -0,0 +1,272 @@ +// Copyright (c) Microsoft Corporation and Contributors. +// Licensed under the MIT License. + +#include "pch.h" + +#include + +#include "PackageDeploymentResolver.h" + +#include "MsixPackageManager.h" + +namespace Microsoft::Windows::ApplicationModel::PackageDeploymentResolver +{ +winrt::hstring Find( + const winrt::Windows::Management::Deployment::PackageManager& packageManager, + const winrt::hstring& packageFamilyName, + const AppModel::Identity::PackageVersion& minVersion, + const winrt::Microsoft::Windows::ApplicationModel::DynamicDependency::PackageDependencyProcessorArchitectures processorArchitectureFilter, + bool stopOnFirstMatch); + +static winrt::Microsoft::Windows::ApplicationModel::DynamicDependency::PackageDependencyProcessorArchitectures ToPackageDependencyProcessorArchitectures(const winrt::Windows::System::ProcessorArchitecture architecture) +{ + switch (architecture) + { + case winrt::Windows::System::ProcessorArchitecture::X86: return winrt::Microsoft::Windows::ApplicationModel::DynamicDependency::PackageDependencyProcessorArchitectures::X86; + case winrt::Windows::System::ProcessorArchitecture::X64: return winrt::Microsoft::Windows::ApplicationModel::DynamicDependency::PackageDependencyProcessorArchitectures::X64; + case winrt::Windows::System::ProcessorArchitecture::Arm: return winrt::Microsoft::Windows::ApplicationModel::DynamicDependency::PackageDependencyProcessorArchitectures::Arm; + case winrt::Windows::System::ProcessorArchitecture::Arm64: return winrt::Microsoft::Windows::ApplicationModel::DynamicDependency::PackageDependencyProcessorArchitectures::Arm64; + case winrt::Windows::System::ProcessorArchitecture::X86OnArm64: return winrt::Microsoft::Windows::ApplicationModel::DynamicDependency::PackageDependencyProcessorArchitectures::X86OnArm64; + case winrt::Windows::System::ProcessorArchitecture::Neutral: return winrt::Microsoft::Windows::ApplicationModel::DynamicDependency::PackageDependencyProcessorArchitectures::Neutral; + case winrt::Windows::System::ProcessorArchitecture::Unknown: THROW_HR_MSG(E_UNEXPECTED, "Unsupported architecture 0x%X", architecture); + default: THROW_HR_MSG(E_UNEXPECTED, "Unknown architecture 0x%X", architecture); + } +} + +static bool IsArchitectureInArchitectures( + const winrt::Windows::System::ProcessorArchitecture architecture, + const winrt::Microsoft::Windows::ApplicationModel::DynamicDependency::PackageDependencyProcessorArchitectures architectures) +{ + const auto architectureAsArchitectures{ ToPackageDependencyProcessorArchitectures(architecture) }; + return WI_IsAnyFlagSet(architectures, architectureAsArchitectures); +} + +static USHORT GetSystemArchitecture() +{ + USHORT processMachine{ IMAGE_FILE_MACHINE_UNKNOWN }; + USHORT nativeMachine{ IMAGE_FILE_MACHINE_UNKNOWN }; + THROW_IF_WIN32_BOOL_FALSE(::IsWow64Process2(::GetCurrentProcess(), &processMachine, &nativeMachine)); + return nativeMachine; +} + +static winrt::Microsoft::Windows::ApplicationModel::DynamicDependency::PackageDependencyProcessorArchitectures GetSystemSupportedArchitectures(const std::uint16_t nativeMachine) +{ + switch (nativeMachine) + { + case IMAGE_FILE_MACHINE_I386: + return winrt::Microsoft::Windows::ApplicationModel::DynamicDependency::PackageDependencyProcessorArchitectures::Neutral | + winrt::Microsoft::Windows::ApplicationModel::DynamicDependency::PackageDependencyProcessorArchitectures::X86; + case IMAGE_FILE_MACHINE_AMD64: + return winrt::Microsoft::Windows::ApplicationModel::DynamicDependency::PackageDependencyProcessorArchitectures::Neutral | + winrt::Microsoft::Windows::ApplicationModel::DynamicDependency::PackageDependencyProcessorArchitectures::X86 | + winrt::Microsoft::Windows::ApplicationModel::DynamicDependency::PackageDependencyProcessorArchitectures::X64; + case IMAGE_FILE_MACHINE_ARM: + return winrt::Microsoft::Windows::ApplicationModel::DynamicDependency::PackageDependencyProcessorArchitectures::Neutral | + winrt::Microsoft::Windows::ApplicationModel::DynamicDependency::PackageDependencyProcessorArchitectures::X86 | + winrt::Microsoft::Windows::ApplicationModel::DynamicDependency::PackageDependencyProcessorArchitectures::X64 | + winrt::Microsoft::Windows::ApplicationModel::DynamicDependency::PackageDependencyProcessorArchitectures::Arm; + case IMAGE_FILE_MACHINE_ARM64: + return winrt::Microsoft::Windows::ApplicationModel::DynamicDependency::PackageDependencyProcessorArchitectures::Neutral | + winrt::Microsoft::Windows::ApplicationModel::DynamicDependency::PackageDependencyProcessorArchitectures::X86 | + winrt::Microsoft::Windows::ApplicationModel::DynamicDependency::PackageDependencyProcessorArchitectures::X64 | + winrt::Microsoft::Windows::ApplicationModel::DynamicDependency::PackageDependencyProcessorArchitectures::Arm | + winrt::Microsoft::Windows::ApplicationModel::DynamicDependency::PackageDependencyProcessorArchitectures::Arm64 | + winrt::Microsoft::Windows::ApplicationModel::DynamicDependency::PackageDependencyProcessorArchitectures::X86OnArm64; + default: + THROW_HR_MSG(HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED), "nativeMachine=%hu", nativeMachine); + } +} + +static winrt::Microsoft::Windows::ApplicationModel::DynamicDependency::PackageDependencyProcessorArchitectures GetSystemSupportedArchitectures() +{ + const auto nativeMachine{ GetSystemArchitecture() }; + return GetSystemSupportedArchitectures(nativeMachine); +} + +static PCWSTR GetSystemArchitectureAsString(const std::uint16_t nativeMachine) +{ + switch (nativeMachine) + { + case IMAGE_FILE_MACHINE_I386: return L"x86"; + case IMAGE_FILE_MACHINE_AMD64:return L"x64"; + case IMAGE_FILE_MACHINE_ARM: return L"arm"; + case IMAGE_FILE_MACHINE_ARM64:return L"arm64"; + default: THROW_HR_MSG(HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED), "nativeMachine=%hu", nativeMachine); + } +} + +static PCWSTR GetSystemSupportedArchitecturesAsString(const std::uint16_t nativeMachine) +{ + switch (nativeMachine) + { + case IMAGE_FILE_MACHINE_I386: return L"neutral,x86"; + case IMAGE_FILE_MACHINE_AMD64:return L"neutral,x86,x64"; + case IMAGE_FILE_MACHINE_ARM: return L"neutral,x86,arm"; + case IMAGE_FILE_MACHINE_ARM64:return L"neutral,x86,x64,arm,arm64,x86onArm64"; + default: THROW_HR_MSG(HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED), "nativeMachine=%hu", nativeMachine); + } +} + +static PCWSTR GetSystemSupportedArchitecturesAsString() +{ + const auto nativeMachine{ GetSystemArchitecture() }; + return GetSystemSupportedArchitecturesAsString(nativeMachine); +} + +static bool IsArchitectureSupporedByHostMachine( + const winrt::Microsoft::Windows::ApplicationModel::DynamicDependency::PackageDependencyProcessorArchitectures architecture) +{ + const auto supportedArchitectures{ GetSystemSupportedArchitectures() }; + return WI_IsAnyFlagSet(supportedArchitectures, architecture); +} + +static bool IsArchitectureSupporedByHostMachine( + const winrt::Windows::System::ProcessorArchitecture architecture) +{ + const auto architectureAsPackageDependencyProcessorArchitectures{ ToPackageDependencyProcessorArchitectures(architecture) }; + return IsArchitectureSupporedByHostMachine(architectureAsPackageDependencyProcessorArchitectures); +} +} + +winrt::hstring Microsoft::Windows::ApplicationModel::PackageDeploymentResolver::FindBestFit( + const winrt::Windows::Management::Deployment::PackageManager& packageManager, + const winrt::hstring& packageFamilyName, + const AppModel::Identity::PackageVersion& minVersion, + const winrt::Microsoft::Windows::ApplicationModel::DynamicDependency::PackageDependencyProcessorArchitectures processorArchitectureFilter) +{ + return Find(packageManager, packageFamilyName, minVersion, processorArchitectureFilter, false); +} + +bool Microsoft::Windows::ApplicationModel::PackageDeploymentResolver::FindAny( + const winrt::Windows::Management::Deployment::PackageManager& packageManager, + const winrt::hstring& packageFamilyName, + const AppModel::Identity::PackageVersion& minVersion, + const winrt::Microsoft::Windows::ApplicationModel::DynamicDependency::PackageDependencyProcessorArchitectures processorArchitectureFilter) +{ + winrt::hstring packageFullName{ Find(packageManager, packageFamilyName, minVersion, processorArchitectureFilter, true) }; + return !packageFullName.empty(); +} + +winrt::hstring Microsoft::Windows::ApplicationModel::PackageDeploymentResolver::Find( + const winrt::Windows::Management::Deployment::PackageManager& packageManager, + const winrt::hstring& packageFamilyName, + const AppModel::Identity::PackageVersion& minVersion, + const winrt::Microsoft::Windows::ApplicationModel::DynamicDependency::PackageDependencyProcessorArchitectures processorArchitectureFilter, + bool stopOnFirstMatch) +{ + // Find the 'best fit' or 'first matching' package in the family (if any) + winrt::hstring bestFitPackageFullName; + AppModel::Identity::PackageVersion bestFitVersion; + + // Determine the packages in the family that could match + const auto packageTypes{ winrt::Windows::Management::Deployment::PackageTypes::Framework | + winrt::Windows::Management::Deployment::PackageTypes::Main }; + auto packages{ packageManager.FindPackagesForUserWithPackageTypes(winrt::hstring(), packageFamilyName, packageTypes) }; + + // Find the/any match + auto criteria{ wil::str_printf(L"PackageFamilyName=%ls MinVersion=%hu.%hu.%hu.%hu ArchitectureFilter:0x%X", + packageFamilyName.c_str(), + minVersion.Major, minVersion.Minor, + minVersion.Build, minVersion.Revision, + static_cast(processorArchitectureFilter)) }; + (void)LOG_HR_MSG(MSIXPACKAGEMANAGER_E_PACKAGE_SCAN, + "PackageDeploymentResolver: Scanning packages (%ls)", + criteria.get()); + if (packages) + { + for (const winrt::Windows::ApplicationModel::Package& candidate : packages) + { + // Do we already have a higher version under consideration? + auto packageId{ candidate.Id() }; + const AppModel::Identity::PackageVersion candidateVersion{ packageId.Version() }; + if (!bestFitPackageFullName.empty() && (bestFitVersion > candidateVersion)) + { + continue; + } + + // Package version must meet the minVersion filter + auto candidateFullName{ packageId.FullName() }; + if (candidateVersion < minVersion) + { + (void)LOG_HR_MSG(MSIXPACKAGEMANAGER_E_PACKAGE_SCAN_NOT_MATCH, + "PackageDeploymentResolver: %ls not applicable. Version doesn't match MinVersion criteria (%ls)", + candidateFullName.c_str(), criteria.get()); + continue; + } + + // Do we already have a higher version under consideration? + if (!bestFitPackageFullName.empty() && (bestFitVersion > candidateVersion)) + { + continue; + } + + // Package architecture must meet the architecture filter + // Filter=None ==> architecture must match system supported architectures + // Filter!=None => architecture must match one of the specified architectures + const auto candidateArchitecture{ packageId.Architecture() }; + if (processorArchitectureFilter == winrt::Microsoft::Windows::ApplicationModel::DynamicDependency::PackageDependencyProcessorArchitectures::None) + { + const auto nativeMachine{ GetSystemArchitecture() }; + const auto supportedArchitectures{ GetSystemSupportedArchitectures(nativeMachine) }; + if (!IsArchitectureInArchitectures(candidateArchitecture, supportedArchitectures)) + { + (void)LOG_HR_MSG(MSIXPACKAGEMANAGER_E_PACKAGE_SCAN_NOT_MATCH, + "PackageDeploymentResolver: %ls not applicable. Architecture (%ls) doesn't match system supported architectures (0x%X %ls)", + candidateFullName.c_str(), ::AppModel::Identity::GetArchitectureAsString(candidateArchitecture), + static_cast(supportedArchitectures), GetSystemSupportedArchitecturesAsString(nativeMachine)); + continue; + } + } + else + { + if (!IsArchitectureInArchitectures(candidateArchitecture, processorArchitectureFilter)) + { + (void)LOG_HR_MSG(MSIXPACKAGEMANAGER_E_PACKAGE_SCAN_NOT_MATCH, + "PackageDeploymentResolver: %ls not applicable. Architecture (%ls) doesn't match specified architectures (0x%X)", + candidateFullName.c_str(), ::AppModel::Identity::GetArchitectureAsString(candidateArchitecture), + static_cast(processorArchitectureFilter)); + continue; + } + } + + // Package status must be OK to use a package + winrt::hstring currentUser; + auto status{ candidate.Status() }; + if (!status.VerifyIsOK()) + { + (void)LOG_HR_MSG(MSIXPACKAGEMANAGER_E_PACKAGE_SCAN_NOT_MATCH, + "PackageDeploymentResolver: %ls not applicable. Status not OK (%ls)", + candidateFullName.c_str(), criteria.get()); + continue; + } + + // Are we looking for any match? + if (stopOnFirstMatch) + { + (void)LOG_HR_MSG(MSIXPACKAGEMANAGER_E_PACKAGE_SCAN_FAILED, + "PackageDeploymentResolver: Stopping on 1st match %ls (%ls)", + candidateFullName.c_str(), criteria.get()); + return candidateFullName; + } + + // The new candidate is better than the current champion + bestFitPackageFullName = std::move(candidateFullName); + bestFitVersion = candidateVersion; + } + } + + // Did we find what we're looking for? + if (bestFitPackageFullName.empty()) + { + (void)LOG_HR_MSG(MSIXPACKAGEMANAGER_E_PACKAGE_SCAN_FAILED, + "PackageDeploymentResolver: No match (%ls)", + criteria.get()); + } + else + { + (void)LOG_HR_MSG(MSIXPACKAGEMANAGER_E_PACKAGE_SCAN_MATCH, + "PackageDeploymentResolver: %ls is applicable (%ls)", + bestFitPackageFullName.c_str(), criteria.get()); + } + return bestFitPackageFullName; +} diff --git a/dev/PackageManager/API/PackageDeploymentResolver.h b/dev/PackageManager/API/PackageDeploymentResolver.h new file mode 100644 index 0000000000..142a53ed20 --- /dev/null +++ b/dev/PackageManager/API/PackageDeploymentResolver.h @@ -0,0 +1,24 @@ +// Copyright (c) Microsoft Corporation and Contributors. +// Licensed under the MIT License. + +#if !defined(PACKAGERESOLVER_H) +#define PACKAGERESOLVER_H + +namespace Microsoft::Windows::ApplicationModel::PackageDeploymentResolver +{ + // Return the best fit package's full name (or .empty if no match found) + winrt::hstring FindBestFit( + const winrt::Windows::Management::Deployment::PackageManager& packageManager, + const winrt::hstring& packageFamilyName, + const AppModel::Identity::PackageVersion& minVersion, + const winrt::Microsoft::Windows::ApplicationModel::DynamicDependency::PackageDependencyProcessorArchitectures processorArchitectureFilter); + + // Return true if any package meets the criteria + bool FindAny( + const winrt::Windows::Management::Deployment::PackageManager& packageManager, + const winrt::hstring& packageFamilyName, + const AppModel::Identity::PackageVersion& minVersion, + const winrt::Microsoft::Windows::ApplicationModel::DynamicDependency::PackageDependencyProcessorArchitectures processorArchitectureFilter); +} + +#endif // PACKAGERESOLVER_H diff --git a/dev/PackageManager/API/PackageManager.idl b/dev/PackageManager/API/PackageManager.idl new file mode 100644 index 0000000000..ca1db7c62b --- /dev/null +++ b/dev/PackageManager/API/PackageManager.idl @@ -0,0 +1,455 @@ +// Copyright (c) Microsoft Corporation and Contributors. +// Licensed under the MIT License. + +#include + +import "M.AM.DynamicDependency.idl"; + +namespace Microsoft.Windows.Management.Deployment +{ + runtimeclass PackageVolume; + + [feature(Feature_PackageManager)] + [contractversion(1)] + apicontract PackageDeploymentContract{}; + + // How should we handle deployment operations? + [feature(Feature_PackageManager)] + [contract(PackageDeploymentContract, 1)] + enum DeploymentProcessingModel + { + Sequential, + Parallel + }; + + // Do deployment operations need non-default priority? + [feature(Feature_PackageManager)] + [contract(PackageDeploymentContract, 1)] + enum DeploymentPriority + { + // Default? Caller? + Low, + Normal, + Immediate + }; + + [feature(Feature_PackageManager)] + [contract(PackageDeploymentContract, 1)] + runtimeclass PackageVolumeStatus + { + PackageVolumeStatus(); + + Boolean IsOK; + Boolean IsOffline; + Boolean IsBroken; + }; + + [feature(Feature_PackageManager)] + [contract(PackageDeploymentContract, 1)] + runtimeclass PackageVolume + { + PackageVolume(); + + Boolean IsSystemVolume{ get; }; + String MountPoint{ get; }; + String Name{ get; }; + String PackageStorePath{ get; }; + Boolean SupportsHardLinks{ get; }; + Boolean IsFullTrustPackageSupported{ get; }; + Boolean IsAppxInstallSupported{ get; }; + + PackageVolumeStatus Status { get; }; + + void FixMe(); + }; + + [feature(Feature_PackageManager)] + [contract(PackageDeploymentContract, 1)] + runtimeclass PackageVolumeManager + { + static IVector FindPackageVolumes(); + + static PackageVolume FindPackageVolumeByPath(String path); + + static PackageVolume FindPackageVolumeByMediaId(String mediaId); + + static PackageVolume FindPackageVolumeByName(String name); + }; + + [feature(Feature_PackageManager)] + [contract(PackageDeploymentContract, 1)] + runtimeclass PackageSetItem + { + PackageSetItem(); + + // Unique id + String Id; //required + + // Package criteria to identify if a matching package is ready for use and to use at runtime + String PackageFamilyName; //required + Windows.ApplicationModel.PackageVersion MinVersion; //required + Microsoft.Windows.ApplicationModel.DynamicDependency.PackageDependencyProcessorArchitectures ProcessorArchitectureFilter; + + // Source where a package can be retrieved from if/when needed for install, remediation, etc + Windows.Foundation.Uri PackageUri; + + // ??? Additional info potentially needed for deployment operations + //TODO see AddPackageOptions + + // Additional info for runtime use + //TODO see CreatePackageDependencyOptions + //TODO see AddPackageDependencyOptions + } + + [feature(Feature_PackageManager)] + [contract(PackageDeploymentContract, 1)] + runtimeclass PackageSet + { + PackageSet(); + + // Unique id + String Id; + + // Package(s) in the set + IVector PackageSetItems { get; }; + } + + [feature(Feature_PackageManager)] + [contract(PackageDeploymentContract, 1)] + runtimeclass PackageSetItemRuntimeDisposition + { + PackageSetItemRuntimeDisposition(); + + String PackageSetItemId{ get; }; + String PackageFullName{ get; }; + String PackageDependencyId{ get; }; + Microsoft.Windows.ApplicationModel.DynamicDependency.PackageDependencyContextId PackageDependencyContextId{ get; }; + } + + [feature(Feature_PackageManager)] + [contract(PackageDeploymentContract, 1)] + runtimeclass PackageSetRuntimeDisposition + { + PackageSetRuntimeDisposition(); + + String PackageSetId; + IVector PackageSetItemRuntimeDispositions { get; }; + } + + [feature(Feature_PackageManager)] + [contract(PackageDeploymentContract, 1)] + runtimeclass FindPackageSetOptions + { + FindPackageSetOptions(); + + //TODO + Boolean TODO_MustHaveAtLeastOneInterfaceOrStaticFactoryPlaceholder; + } + + [feature(Feature_PackageManager)] + [contract(PackageDeploymentContract, 1)] + runtimeclass PackageSetManager + { + static PackageSetManager GetDefault(); + + void Add(PackageSet packageSet); // Create/Write/Save + void Update(PackageSet packageSet); // Update/Write/Save + void Remove(String packageSetId); // Delete + PackageSet Get(String packageSetId); // Read/Load + IVector Find(FindPackageSetOptions options);// Enumerate + }; + + [feature(Feature_PackageManager)] + [contract(PackageDeploymentContract, 1)] + enum PackageDeploymentStatus + { + InProgress = 0, // The request is in progress + CompletedSuccess = 1, // The request completed successfully + CompletedFailure = 2, // The request failed with some critical internal error. //TODO:Check ExtendedError for HRESULT + }; + + [feature(Feature_PackageManager)] + [contract(PackageDeploymentContract, 1)] + enum PackageDeploymentProgressStatus + { + Queued = 0, // The request is queued + InProgress = 1, // The request is in progress + CompletedSuccess = 2, // The request completed successfully + CompletedFailure = 3, // The request failed with some critical internal error. //TODO:Check ExtendedError for HRESULT + }; + + [feature(Feature_PackageManager)] + [contract(PackageDeploymentContract, 1)] + runtimeclass PackageDeploymentProgress + { + PackageDeploymentProgressStatus status; + Double percentage; + } + + [feature(Feature_PackageManager)] + [contract(PackageDeploymentContract, 1)] + runtimeclass PackageDeploymentResult + { + PackageDeploymentStatus Status { get; }; + HRESULT ExtendedError { get; }; + Boolean IsRegistered{ get; }; + Guid ActivityId { get; }; + } + + [feature(Feature_PackageManager)] + [contract(PackageDeploymentContract, 1)] + enum StubPackageOption + { + Default, + InstallFull, + InstallStub, + UsePreference, + }; + + // Requires Windows >- 10.0.19041.0 (aka 2004 aka 20H1) + [feature(Feature_PackageManager)] + [contract(PackageDeploymentContract, 1)] + runtimeclass AddPackageOptions + { + AddPackageOptions(); + + PackageVolume TargetVolume; + IVector DependencyPackageUris { get; }; + IVector OptionalPackageFamilyNames { get; }; + IVector OptionalPackageUris { get; }; + IVector RelatedPackageUris { get; }; + Windows.Foundation.Uri ExternalLocationUri; + Microsoft.Windows.Management.Deployment.StubPackageOption StubPackageOption; + Boolean AllowUnsigned; + Boolean DeveloperMode; + Boolean ForceAppShutdown; + Boolean ForceTargetAppShutdown; + Boolean ForceUpdateFromAnyVersion; + Boolean InstallAllResources; + Boolean RequiredContentGroupOnly; + Boolean RetainFilesOnFailure; + Boolean StageInPlace; + Boolean DeferRegistrationWhenPackagesAreInUse; + + Boolean IsExpectedDigestsSupported { get; }; // Requires Windows >= 10.0.22621.0 (aka Win11 22H2) + IMap ExpectedDigests{ get; }; + + Boolean IsLimitToExistingPackagesSupported { get; }; // Requires Windows >= 10.0.22621.0 (aka Win11 22H2) + Boolean LimitToExistingPackages; + } + + // Requires Windows >- 10.0.19041.0 (aka 2004 aka 20H1) + [feature(Feature_PackageManager)] + [contract(PackageDeploymentContract, 1)] + runtimeclass AddPackageSetOptions + { + AddPackageSetOptions(); + + DeploymentProcessingModel DeploymentProcessingModel; + DeploymentPriority DeploymentPriority; + AddPackageOptions AddPackageOptions; + } + + // Requires Windows >- 10.0.19041.0 (aka 2004 aka 20H1) + [feature(Feature_PackageManager)] + [contract(PackageDeploymentContract, 1)] + runtimeclass StagePackageOptions + { + StagePackageOptions(); + + PackageVolume TargetVolume; + IVector DependencyPackageUris { get; }; + IVector OptionalPackageFamilyNames { get; }; + IVector OptionalPackageUris { get; }; + IVector RelatedPackageUris { get; }; + Windows.Foundation.Uri ExternalLocationUri; + Microsoft.Windows.Management.Deployment.StubPackageOption StubPackageOption; + Boolean DeveloperMode; + Boolean ForceUpdateFromAnyVersion; + Boolean InstallAllResources; + Boolean RequiredContentGroupOnly; + Boolean StageInPlace; + Boolean AllowUnsigned; + + Boolean IsExpectedDigestsSupported { get; }; // Requires Windows >= 10.0.22621.0 (aka Win11 22H2) + IMap ExpectedDigests{ get; }; + } + + // Requires Windows >- 10.0.19041.0 (aka 2004 aka 20H1) + [feature(Feature_PackageManager)] + [contract(PackageDeploymentContract, 1)] + runtimeclass RegisterPackageOptions + { + RegisterPackageOptions(); + + PackageVolume AppDataVolume; + IVector DependencyPackageUris { get; }; + IVector OptionalPackageFamilyNames { get; }; + Windows.Foundation.Uri ExternalLocationUri; + Boolean DeveloperMode; + Boolean ForceAppShutdown; + Boolean ForceTargetAppShutdown; + Boolean ForceUpdateFromAnyVersion; + Boolean InstallAllResources; + Boolean StageInPlace; + Boolean AllowUnsigned; + Boolean DeferRegistrationWhenPackagesAreInUse; + + Boolean IsExpectedDigestsSupported { get; }; // Requires Windows >= 10.0.22621.0 (aka Win11 22H2) + IMap ExpectedDigests{ get; }; + } + + // Requires Windows >- 10.0.19041.0 (aka 2004 aka 20H1) + [feature(Feature_PackageManager)] + [contract(PackageDeploymentContract, 1)] + runtimeclass RemovePackageOptions + { + RemovePackageOptions(); + + Boolean PreserveApplicationData; + Boolean PreserveRoamableApplicationData; + Boolean RemoveForAllUsers; + DeploymentPriority Priority; + } + + [feature(Feature_PackageManager)] + [contract(PackageDeploymentContract, 1)] + runtimeclass EnsureIsReadyOptions + { + EnsureIsReadyOptions(); + + // Options influencing deployment if/when needed + DeploymentProcessingModel DeploymentProcessingModel; + DeploymentPriority DeploymentPriority; + + // ??? Additional info potentially needed for deployment operations + //TODO see AddPackageOptions + //TODO see RegisterPackageOptions + //TODO see StagePackageOptions + + // Additional info for runtime use + //TODO see CreatePackageDependencyOptions + //TODO see AddPackageDependencyOptions + } + + // The API surface is strongly consistent: + // 1. Modification operations involving incoming packages... + // - PackageAsync (string, options) + // - PackageByUriAsync (uri, options) + // - PackageSetAsync (packageset, options) + // - PackageSetByIdAsync(id, options) + // where + // = Add | Register | Stage + // Parameter string for... + // Add = path | uri + // Register = path | uri | packagefullname | packagefamilyname + // Stage = path | uri + // 2. Modification operations involving existing packages... + // - PackageAsync (string, options) + // - PackageByPackageFamilyNameAsync(string, options) + // - PackageByPackageFullNameAsync (string, options) + // where + // = Deprovision | Provision | Register | Remove + // Parameter string for... + // Deprovision = packagefamilyname + // Provision = packagefamilyname + // Register = packagefamilyname | packagefullname | path\appxmanifest.xml | path containing appxmanifest.xml | file://path/appxmanifest.xml | file://path containing appxmanifest.xml + // Remove = packagefamilyname | packagefullname + // + // TODO: AppInstaller + // TODO: Move + // TODO: Find + // TODO: Properties (Status, StubPreference) + // TODO: RequestAdd + // + [feature(Feature_PackageManager)] + [contract(PackageDeploymentContract, 1)] + runtimeclass PackageDeploymentManager + { + // Get an instance of the manager + static PackageDeploymentManager GetDefault(); + + // Return true if the necessary package(s) are present and available for use + Boolean IsPackageSetReady(PackageSet packageSet); + + Boolean IsPackageSetReadyById(String packageSetId); + + // Check if the necessary package(s) are present + // and available for use and if not then Make It So. + // If the necessary packages(s) are not present on the system + // then make them available (download, install, etc). + // If the necessary packages are present and available this is equivalent to IsReady(id). + Windows.Foundation.IAsyncOperationWithProgress + EnsurePackageSetIsReadyAsync(PackageSet packageSet, EnsureIsReadyOptions options); + + Windows.Foundation.IAsyncOperationWithProgress + EnsurePackageSetIsReadyByIdAsync(String packageSetId, EnsureIsReadyOptions options); + + // Add packages + Windows.Foundation.IAsyncOperationWithProgress + AddPackageAsync(String package, AddPackageOptions options); + + Windows.Foundation.IAsyncOperationWithProgress + AddPackageByUriAsync(Windows.Foundation.Uri packageUri, AddPackageOptions options); + + Windows.Foundation.IAsyncOperationWithProgress + AddPackageSetAsync(PackageSet packageSet, AddPackageSetOptions options); + + Windows.Foundation.IAsyncOperationWithProgress + AddPackageSetByIdAsync(String packageSetId, AddPackageSetOptions options); + + // Remove packages + Windows.Foundation.IAsyncOperationWithProgress + RemovePackageAsync(String package, RemovePackageOptions options); + + Windows.Foundation.IAsyncOperationWithProgress + RemovePackageByFullNameAsync(String packageFullName, RemovePackageOptions options); + + Windows.Foundation.IAsyncOperationWithProgress + RemovePackageByFamilyNameAsync(String packageFamilyName, RemovePackageOptions options); + + Windows.Foundation.IAsyncOperationWithProgress + RemovePackageSetAsync(PackageSet packageSet, RemovePackageOptions options); + + Windows.Foundation.IAsyncOperationWithProgress + RemovePackageSetByIdAsync(String packageSetId, RemovePackageOptions options); + + // Ditto PackageSet operations of Stage, Register, Repair, Reset + } + + [feature(Feature_PackageManager)] + [contract(PackageDeploymentContract, 1)] + runtimeclass PackageRuntimeManager + { + // Get an instance of the manager + static PackageRuntimeManager GetDefault(); + + // Make the package(s) in the package set available to the calling process + // i.e. dynamically add the package(s) in the package set to the caller's package graph. + // This is equivalent to + // FOREACH p IN PackageSetManager.Get(id).PackageSetItems + // pd = TryCreatePackageDependency(p) + // AddPackageDependency(pd) + + Microsoft.Windows.Management.Deployment.PackageSetRuntimeDisposition AddPackageSet( + PackageSet packageSet); + + [method_name("AddPackageSetWithOptions")] + Microsoft.Windows.Management.Deployment.PackageSetRuntimeDisposition AddPackageSet( + PackageSet packageSet, + Microsoft.Windows.ApplicationModel.DynamicDependency.CreatePackageDependencyOptions createOptions, + Microsoft.Windows.ApplicationModel.DynamicDependency.AddPackageDependencyOptions addOptions); + + Microsoft.Windows.Management.Deployment.PackageSetRuntimeDisposition AddPackageSetById( + String packageSetId); + + [method_name("AddPackageSetByIdWithOptions")] + Microsoft.Windows.Management.Deployment.PackageSetRuntimeDisposition AddPackageSetById( + String packageSetId, + Microsoft.Windows.ApplicationModel.DynamicDependency.CreatePackageDependencyOptions createOptions, + Microsoft.Windows.ApplicationModel.DynamicDependency.AddPackageDependencyOptions addOptions); + + void RemovePackageSet( + Microsoft.Windows.Management.Deployment.PackageSetRuntimeDisposition packageSetRuntimeDisposition); + } +} diff --git a/dev/PackageManager/API/PackageManager.vcxitems b/dev/PackageManager/API/PackageManager.vcxitems new file mode 100644 index 0000000000..f2fd326cd5 --- /dev/null +++ b/dev/PackageManager/API/PackageManager.vcxitems @@ -0,0 +1,69 @@ + + + + $(MSBuildAllProjects);$(MSBuildThisFileFullPath) + true + {8a9a0c85-65a8-4bca-a49e-45fc4fdbc7d2} + + + + %(AdditionalIncludeDirectories);$(MSBuildThisFileDirectory) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + %(AdditionalIncludeDirectories);$(RepoRoot)\dev\DynamicDependency\API;%(OutDir) + + + + + + diff --git a/dev/PackageManager/API/PackageManager.vcxitems.filters b/dev/PackageManager/API/PackageManager.vcxitems.filters new file mode 100644 index 0000000000..ebcd8cd73d --- /dev/null +++ b/dev/PackageManager/API/PackageManager.vcxitems.filters @@ -0,0 +1,143 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + + + + diff --git a/dev/PackageManager/API/pch.h b/dev/PackageManager/API/pch.h new file mode 100644 index 0000000000..3dcd1b1b1a --- /dev/null +++ b/dev/PackageManager/API/pch.h @@ -0,0 +1,32 @@ +// Copyright (c) Microsoft Corporation and Contributors. +// Licensed under the MIT License. + +#pragma once + +#include + +#include +#include + +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include +#include +#include +#include + +#include + +#include +#include + +#include "MsixPackageManager.h" diff --git a/dev/PushNotifications/PushNotificationsLongRunningTask/packages.config b/dev/PushNotifications/PushNotificationsLongRunningTask/packages.config index 14efb7baf5..cd05427e9c 100644 --- a/dev/PushNotifications/PushNotificationsLongRunningTask/packages.config +++ b/dev/PushNotifications/PushNotificationsLongRunningTask/packages.config @@ -3,6 +3,6 @@ - + diff --git a/dev/RestartAgent/packages.config b/dev/RestartAgent/packages.config index 2305cb7181..9ba3aa91dd 100644 --- a/dev/RestartAgent/packages.config +++ b/dev/RestartAgent/packages.config @@ -1,5 +1,5 @@  - + diff --git a/dev/VSIX/Directory.Build.props b/dev/VSIX/Directory.Build.props index 857d953ac4..a7568b1781 100644 --- a/dev/VSIX/Directory.Build.props +++ b/dev/VSIX/Directory.Build.props @@ -6,8 +6,8 @@ https://pkgs.dev.azure.com/microsoft/ProjectReunion/_packaging/Project.Reunion.nuget.internal/nuget/v3/index.json - 2.0.220929.3 - 10.0.22621.755 + 2.0.230706.1 + 10.0.22621.756 1.0.220914.1 1.0.0-preview1 diff --git a/dev/VSIX/Extension/Cs/Dev17/WindowsAppSDK.Cs.Extension.Dev17.csproj b/dev/VSIX/Extension/Cs/Dev17/WindowsAppSDK.Cs.Extension.Dev17.csproj index 24a06cd703..e7b4cf8448 100644 --- a/dev/VSIX/Extension/Cs/Dev17/WindowsAppSDK.Cs.Extension.Dev17.csproj +++ b/dev/VSIX/Extension/Cs/Dev17/WindowsAppSDK.Cs.Extension.Dev17.csproj @@ -28,7 +28,7 @@ true {B0F1BA01-DE66-4EF9-9C8B-DBB99FB4DA4B} - + net6.0 @@ -39,11 +39,10 @@ - - - + + + . true - Packages Always @@ -63,15 +62,14 @@ compile; build; native; contentfiles; analyzers; buildtransitive + + runtime; build; native; contentfiles; analyzers; buildtransitive all - - All - All diff --git a/dev/VSIX/Extension/Cs/Dev17/WizardImplementation.cs b/dev/VSIX/Extension/Cs/Dev17/WizardImplementation.cs new file mode 100644 index 0000000000..25119d2c24 --- /dev/null +++ b/dev/VSIX/Extension/Cs/Dev17/WizardImplementation.cs @@ -0,0 +1,141 @@ +// Copyright (c) Microsoft Corporation and Contributors. +// Licensed under the MIT License + +using EnvDTE; +using Microsoft.VisualStudio.ComponentModelHost; +using Microsoft.VisualStudio.Shell; +using Microsoft.VisualStudio.Shell.Interop; +using Microsoft.VisualStudio.TemplateWizard; +using Microsoft.VisualStudio.Threading; +using NuGet.VisualStudio; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using System.Xml.Linq; + +namespace WindowsAppSDK.TemplateUtilities +{ + public class NuGetPackageInstaller : IWizard + { + private string _packageId; + private Project _project; + private IComponentModel _componentModel; + private IVsNuGetProjectUpdateEvents _nugetProjectUpdateEvents; + + public void RunStarted(object automationObject, Dictionary replacementsDictionary, WizardRunKind runKind, object[] customParams) + { + ThreadHelper.ThrowIfNotOnUIThread(); + + _packageId = ExtractPackageId(replacementsDictionary); + _componentModel = (IComponentModel)ServiceProvider.GlobalProvider.GetService(typeof(SComponentModel)); + _nugetProjectUpdateEvents = _componentModel.GetService(); + _nugetProjectUpdateEvents.SolutionRestoreFinished += OnSolutionRestoreFinished; + } + private string ExtractPackageId(Dictionary replacementsDictionary) + { + if (replacementsDictionary.TryGetValue("$wizarddata$", out string wizardDataXml)) + { + XDocument xDoc = XDocument.Parse(wizardDataXml); + XNamespace ns = xDoc.Root.GetDefaultNamespace(); + string packageId = xDoc.Descendants(ns + "package") + .Attributes("id") + .Select(attr => attr.Value) + .FirstOrDefault(); + + if (!string.IsNullOrEmpty(packageId)) + { + return packageId; + } + } + return null; + } + public void ProjectFinishedGenerating(Project project) + { + _project = project; + } + public void BeforeOpeningFile(ProjectItem _) + { + } + public void ProjectItemFinishedGenerating(ProjectItem _) + { + } + public void RunFinished() + { + + } + private void OnSolutionRestoreFinished(IReadOnlyList projects) + { + // Debouncing prevents multiple rapid executions of 'InstallNuGetPackageAsync' + // during solution restore. + _nugetProjectUpdateEvents.SolutionRestoreFinished -= OnSolutionRestoreFinished; + var joinableTaskFactory = new JoinableTaskFactory(ThreadHelper.JoinableTaskContext); + joinableTaskFactory.RunAsync(InstallNuGetPackageAsync); + + } + private Task InstallNuGetPackageAsync() + { + if (string.IsNullOrEmpty(_packageId)) + { + string message = "Failed to install the NuGet package. The package ID provided in the template configuration is either missing or invalid. Please ensure the template is correctly configured with a valid package ID."; + DisplayMessageToUser(message, "Error", OLEMSGICON.OLEMSGICON_CRITICAL); + LogError(message); + return Task.CompletedTask; + } + IVsPackageInstaller installer = _componentModel.GetService(); + try + { + installer.InstallPackage(null, _project, _packageId, "", false); + } + catch (Exception ex) + { + string errorMessage = "Failed to install the Microsoft.WindowsAppSDK package. You can try installing it manually from: https://www.nuget.org/packages/Microsoft.WindowsAppSDK"; + DisplayMessageToUser(errorMessage, "Installation Error", OLEMSGICON.OLEMSGICON_CRITICAL); + + string logMessage = $"Failed to install Microsoft.WindowsAppSDK package. Exception details: \n" + + $"Message: {ex.Message}\n" + + $"Source: {ex.Source}\n" + + $"Stack Trace: {ex.StackTrace}\n" + + $"Target Site: {ex.TargetSite}\n"; + + if (ex.InnerException != null) + { + logMessage += $"Inner Exception Message: {ex.InnerException.Message}\n" + + $"Inner Exception Stack Trace: {ex.InnerException.StackTrace}\n"; + } + LogError(logMessage); + } + + return Task.CompletedTask; + } + private void DisplayMessageToUser(string message, string title, OLEMSGICON icon) + { + ThreadHelper.JoinableTaskFactory.Run(async delegate + { + await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(); + VsShellUtilities.ShowMessageBox( + ServiceProvider.GlobalProvider, + message, + title, + icon, + OLEMSGBUTTON.OLEMSGBUTTON_OK, + OLEMSGDEFBUTTON.OLEMSGDEFBUTTON_FIRST); + }); + } + private void LogError(string message) + { + IVsActivityLog log = ServiceProvider.GlobalProvider.GetService(typeof(SVsActivityLog)) as IVsActivityLog; + if (log != null) + { + log.LogEntry( + (UInt32)__ACTIVITYLOG_ENTRYTYPE.ALE_ERROR, + "WindowsAppSDK.TemplateUtilities", + message); + } + } + public bool ShouldAddProjectItem(string _) + { + return true; + } + } +} diff --git a/dev/VSIX/ItemTemplates/Desktop/CSharp/BlankWindow/WinUI.Desktop.Cs.BlankWindow.vstemplate b/dev/VSIX/ItemTemplates/Desktop/CSharp/BlankWindow/WinUI.Desktop.Cs.BlankWindow.vstemplate index 2ec9e75a60..d3c02065d9 100644 --- a/dev/VSIX/ItemTemplates/Desktop/CSharp/BlankWindow/WinUI.Desktop.Cs.BlankWindow.vstemplate +++ b/dev/VSIX/ItemTemplates/Desktop/CSharp/BlankWindow/WinUI.Desktop.Cs.BlankWindow.vstemplate @@ -15,6 +15,7 @@ csharp windows desktop + winui BlankWindow.xaml diff --git a/dev/VSIX/ItemTemplates/Desktop/CppWinRT/BlankWindow/BlankWindow.cpp b/dev/VSIX/ItemTemplates/Desktop/CppWinRT/BlankWindow/BlankWindow.cpp index b9465ed819..71f96dbd85 100644 --- a/dev/VSIX/ItemTemplates/Desktop/CppWinRT/BlankWindow/BlankWindow.cpp +++ b/dev/VSIX/ItemTemplates/Desktop/CppWinRT/BlankWindow/BlankWindow.cpp @@ -1,6 +1,3 @@ -// Copyright (c) Microsoft Corporation and Contributors. -// Licensed under the MIT License. - #include "pch.h" #include "$safeitemname$.xaml.h" #if __has_include("$safeitemname$.g.cpp") @@ -15,11 +12,6 @@ using namespace Microsoft::UI::Xaml; namespace winrt::$rootnamespace$::implementation { - $safeitemname$::$safeitemname$() - { - InitializeComponent(); - } - int32_t $safeitemname$::MyProperty() { throw hresult_not_implemented(); diff --git a/dev/VSIX/ItemTemplates/Desktop/CppWinRT/BlankWindow/BlankWindow.h b/dev/VSIX/ItemTemplates/Desktop/CppWinRT/BlankWindow/BlankWindow.h index 298749282d..8eff169b57 100644 --- a/dev/VSIX/ItemTemplates/Desktop/CppWinRT/BlankWindow/BlankWindow.h +++ b/dev/VSIX/ItemTemplates/Desktop/CppWinRT/BlankWindow/BlankWindow.h @@ -1,6 +1,3 @@ -// Copyright (c) Microsoft Corporation and Contributors. -// Licensed under the MIT License. - #pragma once #include "$safeitemname$.g.h" @@ -9,12 +6,16 @@ namespace winrt::$rootnamespace$::implementation { struct $safeitemname$ : $safeitemname$T<$safeitemname$> { - $safeitemname$(); + $safeitemname$() + { + // Xaml objects should not call InitializeComponent during construction. + // See https://github.com/microsoft/cppwinrt/tree/master/nuget#initializecomponent + } int32_t MyProperty(); void MyProperty(int32_t value); - void myButton_Click(Windows::Foundation::IInspectable const& sender, Microsoft::UI::Xaml::RoutedEventArgs const& args); + void myButton_Click(IInspectable const& sender, Microsoft::UI::Xaml::RoutedEventArgs const& args); }; } diff --git a/dev/VSIX/ItemTemplates/Desktop/CppWinRT/BlankWindow/BlankWindow.idl b/dev/VSIX/ItemTemplates/Desktop/CppWinRT/BlankWindow/BlankWindow.idl index f830b44f06..948adbe989 100644 --- a/dev/VSIX/ItemTemplates/Desktop/CppWinRT/BlankWindow/BlankWindow.idl +++ b/dev/VSIX/ItemTemplates/Desktop/CppWinRT/BlankWindow/BlankWindow.idl @@ -1,6 +1,3 @@ -// Copyright (c) Microsoft Corporation and Contributors. -// Licensed under the MIT License. - namespace $rootnamespace$ { [default_interface] diff --git a/dev/VSIX/ItemTemplates/Desktop/CppWinRT/BlankWindow/WinUI.Desktop.CppWinRT.BlankWindow.vstemplate b/dev/VSIX/ItemTemplates/Desktop/CppWinRT/BlankWindow/WinUI.Desktop.CppWinRT.BlankWindow.vstemplate index c37a5908ad..62d2ec489e 100644 --- a/dev/VSIX/ItemTemplates/Desktop/CppWinRT/BlankWindow/WinUI.Desktop.CppWinRT.BlankWindow.vstemplate +++ b/dev/VSIX/ItemTemplates/Desktop/CppWinRT/BlankWindow/WinUI.Desktop.CppWinRT.BlankWindow.vstemplate @@ -15,6 +15,7 @@ cpp windows desktop + winui BlankWindow.xaml diff --git a/dev/VSIX/ItemTemplates/Neutral/CSharp/BlankPage/WinUI.Neutral.Cs.BlankPage.vstemplate b/dev/VSIX/ItemTemplates/Neutral/CSharp/BlankPage/WinUI.Neutral.Cs.BlankPage.vstemplate index ef1cde9152..b96bbce5ab 100644 --- a/dev/VSIX/ItemTemplates/Neutral/CSharp/BlankPage/WinUI.Neutral.Cs.BlankPage.vstemplate +++ b/dev/VSIX/ItemTemplates/Neutral/CSharp/BlankPage/WinUI.Neutral.Cs.BlankPage.vstemplate @@ -14,8 +14,8 @@ Windows csharp windows - uwp desktop + winui BlankPage.xaml diff --git a/dev/VSIX/ItemTemplates/Neutral/CSharp/ResourceDictionary/WinUI.Neutral.Cs.ResourceDictionary.vstemplate b/dev/VSIX/ItemTemplates/Neutral/CSharp/ResourceDictionary/WinUI.Neutral.Cs.ResourceDictionary.vstemplate index 7d1aa930c1..47352957f9 100644 --- a/dev/VSIX/ItemTemplates/Neutral/CSharp/ResourceDictionary/WinUI.Neutral.Cs.ResourceDictionary.vstemplate +++ b/dev/VSIX/ItemTemplates/Neutral/CSharp/ResourceDictionary/WinUI.Neutral.Cs.ResourceDictionary.vstemplate @@ -14,8 +14,8 @@ Windows csharp windows - uwp desktop + winui ResourceDictionary.xaml diff --git a/dev/VSIX/ItemTemplates/Neutral/CSharp/Resw/WinUI.Neutral.Cs.Resw.vstemplate b/dev/VSIX/ItemTemplates/Neutral/CSharp/Resw/WinUI.Neutral.Cs.Resw.vstemplate index d4f1586de1..8d82892557 100644 --- a/dev/VSIX/ItemTemplates/Neutral/CSharp/Resw/WinUI.Neutral.Cs.Resw.vstemplate +++ b/dev/VSIX/ItemTemplates/Neutral/CSharp/Resw/WinUI.Neutral.Cs.Resw.vstemplate @@ -14,8 +14,8 @@ Windows csharp windows - uwp desktop + winui Resources.resw diff --git a/dev/VSIX/ItemTemplates/Neutral/CSharp/TemplatedControl/WinUI.Neutral.Cs.TemplatedControl.vstemplate b/dev/VSIX/ItemTemplates/Neutral/CSharp/TemplatedControl/WinUI.Neutral.Cs.TemplatedControl.vstemplate index 434911da49..cec6d71915 100644 --- a/dev/VSIX/ItemTemplates/Neutral/CSharp/TemplatedControl/WinUI.Neutral.Cs.TemplatedControl.vstemplate +++ b/dev/VSIX/ItemTemplates/Neutral/CSharp/TemplatedControl/WinUI.Neutral.Cs.TemplatedControl.vstemplate @@ -14,8 +14,8 @@ Windows csharp windows - uwp desktop + winui CustomControl.cs diff --git a/dev/VSIX/ItemTemplates/Neutral/CSharp/UserControl/WinUI.Neutral.Cs.UserControl.vstemplate b/dev/VSIX/ItemTemplates/Neutral/CSharp/UserControl/WinUI.Neutral.Cs.UserControl.vstemplate index 3232e88cae..9b399e6767 100644 --- a/dev/VSIX/ItemTemplates/Neutral/CSharp/UserControl/WinUI.Neutral.Cs.UserControl.vstemplate +++ b/dev/VSIX/ItemTemplates/Neutral/CSharp/UserControl/WinUI.Neutral.Cs.UserControl.vstemplate @@ -14,8 +14,8 @@ Windows csharp windows - uwp desktop + winui UserControl.xaml diff --git a/dev/VSIX/ItemTemplates/Neutral/CppWinRT/BlankPage/BlankPage.cpp b/dev/VSIX/ItemTemplates/Neutral/CppWinRT/BlankPage/BlankPage.cpp index b9465ed819..71f96dbd85 100644 --- a/dev/VSIX/ItemTemplates/Neutral/CppWinRT/BlankPage/BlankPage.cpp +++ b/dev/VSIX/ItemTemplates/Neutral/CppWinRT/BlankPage/BlankPage.cpp @@ -1,6 +1,3 @@ -// Copyright (c) Microsoft Corporation and Contributors. -// Licensed under the MIT License. - #include "pch.h" #include "$safeitemname$.xaml.h" #if __has_include("$safeitemname$.g.cpp") @@ -15,11 +12,6 @@ using namespace Microsoft::UI::Xaml; namespace winrt::$rootnamespace$::implementation { - $safeitemname$::$safeitemname$() - { - InitializeComponent(); - } - int32_t $safeitemname$::MyProperty() { throw hresult_not_implemented(); diff --git a/dev/VSIX/ItemTemplates/Neutral/CppWinRT/BlankPage/BlankPage.h b/dev/VSIX/ItemTemplates/Neutral/CppWinRT/BlankPage/BlankPage.h index 298749282d..8eff169b57 100644 --- a/dev/VSIX/ItemTemplates/Neutral/CppWinRT/BlankPage/BlankPage.h +++ b/dev/VSIX/ItemTemplates/Neutral/CppWinRT/BlankPage/BlankPage.h @@ -1,6 +1,3 @@ -// Copyright (c) Microsoft Corporation and Contributors. -// Licensed under the MIT License. - #pragma once #include "$safeitemname$.g.h" @@ -9,12 +6,16 @@ namespace winrt::$rootnamespace$::implementation { struct $safeitemname$ : $safeitemname$T<$safeitemname$> { - $safeitemname$(); + $safeitemname$() + { + // Xaml objects should not call InitializeComponent during construction. + // See https://github.com/microsoft/cppwinrt/tree/master/nuget#initializecomponent + } int32_t MyProperty(); void MyProperty(int32_t value); - void myButton_Click(Windows::Foundation::IInspectable const& sender, Microsoft::UI::Xaml::RoutedEventArgs const& args); + void myButton_Click(IInspectable const& sender, Microsoft::UI::Xaml::RoutedEventArgs const& args); }; } diff --git a/dev/VSIX/ItemTemplates/Neutral/CppWinRT/BlankPage/BlankPage.idl b/dev/VSIX/ItemTemplates/Neutral/CppWinRT/BlankPage/BlankPage.idl index ee72b5f377..c91ead7c5e 100644 --- a/dev/VSIX/ItemTemplates/Neutral/CppWinRT/BlankPage/BlankPage.idl +++ b/dev/VSIX/ItemTemplates/Neutral/CppWinRT/BlankPage/BlankPage.idl @@ -1,6 +1,3 @@ -// Copyright (c) Microsoft Corporation and Contributors. -// Licensed under the MIT License. - namespace $rootnamespace$ { [default_interface] diff --git a/dev/VSIX/ItemTemplates/Neutral/CppWinRT/BlankPage/WinUI.Neutral.CppWinRT.BlankPage.vstemplate b/dev/VSIX/ItemTemplates/Neutral/CppWinRT/BlankPage/WinUI.Neutral.CppWinRT.BlankPage.vstemplate index d443e8b102..df9b8bfcef 100644 --- a/dev/VSIX/ItemTemplates/Neutral/CppWinRT/BlankPage/WinUI.Neutral.CppWinRT.BlankPage.vstemplate +++ b/dev/VSIX/ItemTemplates/Neutral/CppWinRT/BlankPage/WinUI.Neutral.CppWinRT.BlankPage.vstemplate @@ -14,8 +14,8 @@ Windows cpp windows - uwp desktop + winui BlankPage.xaml diff --git a/dev/VSIX/ItemTemplates/Neutral/CppWinRT/ResourceDictionary/WinUI.Neutral.CppWinRT.ResourceDictionary.vstemplate b/dev/VSIX/ItemTemplates/Neutral/CppWinRT/ResourceDictionary/WinUI.Neutral.CppWinRT.ResourceDictionary.vstemplate index ae167991ff..bbb7046144 100644 --- a/dev/VSIX/ItemTemplates/Neutral/CppWinRT/ResourceDictionary/WinUI.Neutral.CppWinRT.ResourceDictionary.vstemplate +++ b/dev/VSIX/ItemTemplates/Neutral/CppWinRT/ResourceDictionary/WinUI.Neutral.CppWinRT.ResourceDictionary.vstemplate @@ -14,8 +14,8 @@ Windows cpp windows - uwp desktop + winui ResourceDictionary.xaml diff --git a/dev/VSIX/ItemTemplates/Neutral/CppWinRT/Resw/WinUI.Neutral.CppWinRT.Resw.vstemplate b/dev/VSIX/ItemTemplates/Neutral/CppWinRT/Resw/WinUI.Neutral.CppWinRT.Resw.vstemplate index 1c1a590512..3512528fdc 100644 --- a/dev/VSIX/ItemTemplates/Neutral/CppWinRT/Resw/WinUI.Neutral.CppWinRT.Resw.vstemplate +++ b/dev/VSIX/ItemTemplates/Neutral/CppWinRT/Resw/WinUI.Neutral.CppWinRT.Resw.vstemplate @@ -14,8 +14,8 @@ Windows cpp windows - uwp desktop + winui Resources.resw diff --git a/dev/VSIX/ItemTemplates/Neutral/CppWinRT/TemplatedControl/TemplatedControl.cpp b/dev/VSIX/ItemTemplates/Neutral/CppWinRT/TemplatedControl/TemplatedControl.cpp index f885007964..d890d87161 100644 --- a/dev/VSIX/ItemTemplates/Neutral/CppWinRT/TemplatedControl/TemplatedControl.cpp +++ b/dev/VSIX/ItemTemplates/Neutral/CppWinRT/TemplatedControl/TemplatedControl.cpp @@ -1,6 +1,3 @@ -// Copyright (c) Microsoft Corporation and Contributors. -// Licensed under the MIT License. - #include "pch.h" #include "$safeitemname$.h" #if __has_include("$safeitemname$.g.cpp") diff --git a/dev/VSIX/ItemTemplates/Neutral/CppWinRT/TemplatedControl/TemplatedControl.h b/dev/VSIX/ItemTemplates/Neutral/CppWinRT/TemplatedControl/TemplatedControl.h index 5b2c7438a5..d7d67cec10 100644 --- a/dev/VSIX/ItemTemplates/Neutral/CppWinRT/TemplatedControl/TemplatedControl.h +++ b/dev/VSIX/ItemTemplates/Neutral/CppWinRT/TemplatedControl/TemplatedControl.h @@ -1,11 +1,5 @@ -// Copyright (c) Microsoft Corporation and Contributors. -// Licensed under the MIT License. - #pragma once -#include "winrt/Microsoft.UI.Xaml.h" -#include "winrt/Microsoft.UI.Xaml.Markup.h" -#include "winrt/Microsoft.UI.Xaml.Controls.Primitives.h" #include "$safeitemname$.g.h" namespace winrt::$rootnamespace$::implementation diff --git a/dev/VSIX/ItemTemplates/Neutral/CppWinRT/TemplatedControl/TemplatedControl.idl b/dev/VSIX/ItemTemplates/Neutral/CppWinRT/TemplatedControl/TemplatedControl.idl index 32b2c2cc02..3733d0c2b5 100644 --- a/dev/VSIX/ItemTemplates/Neutral/CppWinRT/TemplatedControl/TemplatedControl.idl +++ b/dev/VSIX/ItemTemplates/Neutral/CppWinRT/TemplatedControl/TemplatedControl.idl @@ -1,6 +1,3 @@ -// Copyright (c) Microsoft Corporation and Contributors. -// Licensed under the MIT License. - namespace $rootnamespace$ { [default_interface] diff --git a/dev/VSIX/ItemTemplates/Neutral/CppWinRT/TemplatedControl/WinUI.Neutral.CppWinRT.TemplatedControl.vstemplate b/dev/VSIX/ItemTemplates/Neutral/CppWinRT/TemplatedControl/WinUI.Neutral.CppWinRT.TemplatedControl.vstemplate index 73e42d8f90..46b8048bf0 100644 --- a/dev/VSIX/ItemTemplates/Neutral/CppWinRT/TemplatedControl/WinUI.Neutral.CppWinRT.TemplatedControl.vstemplate +++ b/dev/VSIX/ItemTemplates/Neutral/CppWinRT/TemplatedControl/WinUI.Neutral.CppWinRT.TemplatedControl.vstemplate @@ -14,8 +14,8 @@ Windows cpp windows - uwp desktop + winui TemplatedControl.cpp diff --git a/dev/VSIX/ItemTemplates/Neutral/CppWinRT/UserControl/UserControl.cpp b/dev/VSIX/ItemTemplates/Neutral/CppWinRT/UserControl/UserControl.cpp index b9465ed819..71f96dbd85 100644 --- a/dev/VSIX/ItemTemplates/Neutral/CppWinRT/UserControl/UserControl.cpp +++ b/dev/VSIX/ItemTemplates/Neutral/CppWinRT/UserControl/UserControl.cpp @@ -1,6 +1,3 @@ -// Copyright (c) Microsoft Corporation and Contributors. -// Licensed under the MIT License. - #include "pch.h" #include "$safeitemname$.xaml.h" #if __has_include("$safeitemname$.g.cpp") @@ -15,11 +12,6 @@ using namespace Microsoft::UI::Xaml; namespace winrt::$rootnamespace$::implementation { - $safeitemname$::$safeitemname$() - { - InitializeComponent(); - } - int32_t $safeitemname$::MyProperty() { throw hresult_not_implemented(); diff --git a/dev/VSIX/ItemTemplates/Neutral/CppWinRT/UserControl/UserControl.h b/dev/VSIX/ItemTemplates/Neutral/CppWinRT/UserControl/UserControl.h index 3ce4f4a724..8eff169b57 100644 --- a/dev/VSIX/ItemTemplates/Neutral/CppWinRT/UserControl/UserControl.h +++ b/dev/VSIX/ItemTemplates/Neutral/CppWinRT/UserControl/UserControl.h @@ -1,23 +1,21 @@ -// Copyright (c) Microsoft Corporation and Contributors. -// Licensed under the MIT License. - #pragma once -#include "winrt/Microsoft.UI.Xaml.h" -#include "winrt/Microsoft.UI.Xaml.Markup.h" -#include "winrt/Microsoft.UI.Xaml.Controls.Primitives.h" #include "$safeitemname$.g.h" namespace winrt::$rootnamespace$::implementation { struct $safeitemname$ : $safeitemname$T<$safeitemname$> { - $safeitemname$(); + $safeitemname$() + { + // Xaml objects should not call InitializeComponent during construction. + // See https://github.com/microsoft/cppwinrt/tree/master/nuget#initializecomponent + } int32_t MyProperty(); void MyProperty(int32_t value); - void myButton_Click(Windows::Foundation::IInspectable const& sender, Microsoft::UI::Xaml::RoutedEventArgs const& args); + void myButton_Click(IInspectable const& sender, Microsoft::UI::Xaml::RoutedEventArgs const& args); }; } diff --git a/dev/VSIX/ItemTemplates/Neutral/CppWinRT/UserControl/UserControl.idl b/dev/VSIX/ItemTemplates/Neutral/CppWinRT/UserControl/UserControl.idl index 1ce0f37546..e612c3ca7c 100644 --- a/dev/VSIX/ItemTemplates/Neutral/CppWinRT/UserControl/UserControl.idl +++ b/dev/VSIX/ItemTemplates/Neutral/CppWinRT/UserControl/UserControl.idl @@ -1,6 +1,3 @@ -// Copyright (c) Microsoft Corporation and Contributors. -// Licensed under the MIT License. - namespace $rootnamespace$ { [default_interface] diff --git a/dev/VSIX/ItemTemplates/Neutral/CppWinRT/UserControl/WinUI.Neutral.CppWinRT.UserControl.vstemplate b/dev/VSIX/ItemTemplates/Neutral/CppWinRT/UserControl/WinUI.Neutral.CppWinRT.UserControl.vstemplate index 4ad7a45b4a..6d1efeac1e 100644 --- a/dev/VSIX/ItemTemplates/Neutral/CppWinRT/UserControl/WinUI.Neutral.CppWinRT.UserControl.vstemplate +++ b/dev/VSIX/ItemTemplates/Neutral/CppWinRT/UserControl/WinUI.Neutral.CppWinRT.UserControl.vstemplate @@ -14,8 +14,8 @@ Windows cpp windows - uwp desktop + winui UserControl.xaml diff --git a/dev/VSIX/ProjectTemplates/Desktop/CSharp/ClassLibrary/WinUI.Desktop.Cs.ClassLibrary.vstemplate b/dev/VSIX/ProjectTemplates/Desktop/CSharp/ClassLibrary/WinUI.Desktop.Cs.ClassLibrary.vstemplate index 738db1ea85..c549f3a530 100644 --- a/dev/VSIX/ProjectTemplates/Desktop/CSharp/ClassLibrary/WinUI.Desktop.Cs.ClassLibrary.vstemplate +++ b/dev/VSIX/ProjectTemplates/Desktop/CSharp/ClassLibrary/WinUI.Desktop.Cs.ClassLibrary.vstemplate @@ -21,7 +21,7 @@ XAML windows desktop - WinUI + winui diff --git a/dev/VSIX/ProjectTemplates/Desktop/CSharp/PackagedApp/BlankApp/ProjectTemplate.csproj b/dev/VSIX/ProjectTemplates/Desktop/CSharp/PackagedApp/BlankApp/ProjectTemplate.csproj index a34ea33715..3790b6b3b3 100644 --- a/dev/VSIX/ProjectTemplates/Desktop/CSharp/PackagedApp/BlankApp/ProjectTemplate.csproj +++ b/dev/VSIX/ProjectTemplates/Desktop/CSharp/PackagedApp/BlankApp/ProjectTemplate.csproj @@ -11,7 +11,6 @@ - diff --git a/dev/VSIX/ProjectTemplates/Desktop/CSharp/PackagedApp/BlankApp/WinUI.Desktop.Cs.BlankApp.vstemplate b/dev/VSIX/ProjectTemplates/Desktop/CSharp/PackagedApp/BlankApp/WinUI.Desktop.Cs.BlankApp.vstemplate index b2eeb3afc8..e9b8927622 100644 --- a/dev/VSIX/ProjectTemplates/Desktop/CSharp/PackagedApp/BlankApp/WinUI.Desktop.Cs.BlankApp.vstemplate +++ b/dev/VSIX/ProjectTemplates/Desktop/CSharp/PackagedApp/BlankApp/WinUI.Desktop.Cs.BlankApp.vstemplate @@ -1,4 +1,4 @@ - + true @@ -22,7 +22,7 @@ XAML windows desktop - WinUI + winui @@ -36,4 +36,13 @@ MainWindow.xaml.cs - \ No newline at end of file + + WindowsAppSDK.Cs.Extension.Dev17, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + WindowsAppSDK.TemplateUtilities.NuGetPackageInstaller + + + + + + + diff --git a/dev/VSIX/ProjectTemplates/Desktop/CSharp/PackagedApp/WapProj/WapProjTemplate.wapproj b/dev/VSIX/ProjectTemplates/Desktop/CSharp/PackagedApp/WapProj/WapProjTemplate.wapproj index 0ba7d6ae6b..5adc78126d 100644 --- a/dev/VSIX/ProjectTemplates/Desktop/CSharp/PackagedApp/WapProj/WapProjTemplate.wapproj +++ b/dev/VSIX/ProjectTemplates/Desktop/CSharp/PackagedApp/WapProj/WapProjTemplate.wapproj @@ -77,15 +77,6 @@ - - - build - - - build - - - diff --git a/dev/VSIX/ProjectTemplates/Desktop/CSharp/PackagedApp/WapProj/WinUI.Desktop.Cs.WapProj.vstemplate b/dev/VSIX/ProjectTemplates/Desktop/CSharp/PackagedApp/WapProj/WinUI.Desktop.Cs.WapProj.vstemplate index 1f6e396a27..6e61c517f6 100644 --- a/dev/VSIX/ProjectTemplates/Desktop/CSharp/PackagedApp/WapProj/WinUI.Desktop.Cs.WapProj.vstemplate +++ b/dev/VSIX/ProjectTemplates/Desktop/CSharp/PackagedApp/WapProj/WinUI.Desktop.Cs.WapProj.vstemplate @@ -21,7 +21,7 @@ XAML windows desktop - WinUI + winui diff --git a/dev/VSIX/ProjectTemplates/Desktop/CSharp/PackagedApp/WinUI.Desktop.Cs.PackagedApp.vstemplate b/dev/VSIX/ProjectTemplates/Desktop/CSharp/PackagedApp/WinUI.Desktop.Cs.PackagedApp.vstemplate index 2e4e91fdba..1365432762 100644 --- a/dev/VSIX/ProjectTemplates/Desktop/CSharp/PackagedApp/WinUI.Desktop.Cs.PackagedApp.vstemplate +++ b/dev/VSIX/ProjectTemplates/Desktop/CSharp/PackagedApp/WinUI.Desktop.Cs.PackagedApp.vstemplate @@ -21,7 +21,7 @@ XAML windows desktop - WinUI + winui diff --git a/dev/VSIX/ProjectTemplates/Desktop/CSharp/SingleProjectPackagedApp/ProjectTemplate.csproj b/dev/VSIX/ProjectTemplates/Desktop/CSharp/SingleProjectPackagedApp/ProjectTemplate.csproj index 47d15b4f80..0794538bfb 100644 --- a/dev/VSIX/ProjectTemplates/Desktop/CSharp/SingleProjectPackagedApp/ProjectTemplate.csproj +++ b/dev/VSIX/ProjectTemplates/Desktop/CSharp/SingleProjectPackagedApp/ProjectTemplate.csproj @@ -23,7 +23,6 @@ - diff --git a/dev/VSIX/ProjectTemplates/Desktop/CSharp/SingleProjectPackagedApp/WinUI.Desktop.Cs.SingleProjectPackagedApp.vstemplate b/dev/VSIX/ProjectTemplates/Desktop/CSharp/SingleProjectPackagedApp/WinUI.Desktop.Cs.SingleProjectPackagedApp.vstemplate index fb34eff491..c5be3e488a 100644 --- a/dev/VSIX/ProjectTemplates/Desktop/CSharp/SingleProjectPackagedApp/WinUI.Desktop.Cs.SingleProjectPackagedApp.vstemplate +++ b/dev/VSIX/ProjectTemplates/Desktop/CSharp/SingleProjectPackagedApp/WinUI.Desktop.Cs.SingleProjectPackagedApp.vstemplate @@ -21,7 +21,7 @@ XAML windows desktop - WinUI + winui @@ -56,4 +56,13 @@ Microsoft.VisualStudio.WinRT.TemplateWizards, Version=16.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a Microsoft.VisualStudio.WinRT.TemplateWizards.UpdatePublisherInManifestWizard - \ No newline at end of file + + WindowsAppSDK.Cs.Extension.Dev17, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + WindowsAppSDK.TemplateUtilities.NuGetPackageInstaller + + + + + + + diff --git a/dev/VSIX/ProjectTemplates/Desktop/CppWinRT/PackagedApp/BlankApp/App.cpp b/dev/VSIX/ProjectTemplates/Desktop/CppWinRT/PackagedApp/BlankApp/App.cpp index cd08294f06..47f77e36cf 100644 --- a/dev/VSIX/ProjectTemplates/Desktop/CppWinRT/PackagedApp/BlankApp/App.cpp +++ b/dev/VSIX/ProjectTemplates/Desktop/CppWinRT/PackagedApp/BlankApp/App.cpp @@ -1,48 +1,43 @@ -// Copyright (c) Microsoft Corporation and Contributors. -// Licensed under the MIT License. - #include "pch.h" - #include "App.xaml.h" #include "MainWindow.xaml.h" using namespace winrt; -using namespace Windows::Foundation; using namespace Microsoft::UI::Xaml; -using namespace Microsoft::UI::Xaml::Controls; -using namespace Microsoft::UI::Xaml::Navigation; -using namespace $safeprojectname$; -using namespace $safeprojectname$::implementation; // To learn more about WinUI, the WinUI project structure, // and more about our project templates, see: http://aka.ms/winui-project-info. -/// -/// Initializes the singleton application object. This is the first line of authored code -/// executed, and as such is the logical equivalent of main() or WinMain(). -/// -App::App() +namespace winrt::$safeprojectname$::implementation { - InitializeComponent(); + /// + /// Initializes the singleton application object. This is the first line of authored code + /// executed, and as such is the logical equivalent of main() or WinMain(). + /// + App::App() + { + // Xaml objects should not call InitializeComponent during construction. + // See https://github.com/microsoft/cppwinrt/tree/master/nuget#initializecomponent #if defined _DEBUG && !defined DISABLE_XAML_GENERATED_BREAK_ON_UNHANDLED_EXCEPTION - UnhandledException([this](IInspectable const&, UnhandledExceptionEventArgs const& e) - { - if (IsDebuggerPresent()) + UnhandledException([](IInspectable const&, UnhandledExceptionEventArgs const& e) { - auto errorMessage = e.Message(); - __debugbreak(); - } - }); + if (IsDebuggerPresent()) + { + auto errorMessage = e.Message(); + __debugbreak(); + } + }); #endif -} + } -/// -/// Invoked when the application is launched. -/// -/// Details about the launch request and process. -void App::OnLaunched(LaunchActivatedEventArgs const&) -{ - window = make(); - window.Activate(); + /// + /// Invoked when the application is launched. + /// + /// Details about the launch request and process. + void App::OnLaunched([[maybe_unused]] LaunchActivatedEventArgs const& e) + { + window = make(); + window.Activate(); + } } diff --git a/dev/VSIX/ProjectTemplates/Desktop/CppWinRT/PackagedApp/BlankApp/App.h b/dev/VSIX/ProjectTemplates/Desktop/CppWinRT/PackagedApp/BlankApp/App.h index 5b835dda35..20431336d7 100644 --- a/dev/VSIX/ProjectTemplates/Desktop/CppWinRT/PackagedApp/BlankApp/App.h +++ b/dev/VSIX/ProjectTemplates/Desktop/CppWinRT/PackagedApp/BlankApp/App.h @@ -1,6 +1,3 @@ -// Copyright (c) Microsoft Corporation and Contributors. -// Licensed under the MIT License. - #pragma once #include "App.xaml.g.h" diff --git a/dev/VSIX/ProjectTemplates/Desktop/CppWinRT/PackagedApp/BlankApp/App.idl b/dev/VSIX/ProjectTemplates/Desktop/CppWinRT/PackagedApp/BlankApp/App.idl deleted file mode 100644 index 55ac0e3690..0000000000 --- a/dev/VSIX/ProjectTemplates/Desktop/CppWinRT/PackagedApp/BlankApp/App.idl +++ /dev/null @@ -1,6 +0,0 @@ -// Copyright (c) Microsoft Corporation and Contributors. -// Licensed under the MIT License. - -namespace $safeprojectname$ -{ -} diff --git a/dev/VSIX/ProjectTemplates/Desktop/CppWinRT/PackagedApp/BlankApp/MainWindow.cpp b/dev/VSIX/ProjectTemplates/Desktop/CppWinRT/PackagedApp/BlankApp/MainWindow.cpp index 746fe412aa..d6d47e7619 100644 --- a/dev/VSIX/ProjectTemplates/Desktop/CppWinRT/PackagedApp/BlankApp/MainWindow.cpp +++ b/dev/VSIX/ProjectTemplates/Desktop/CppWinRT/PackagedApp/BlankApp/MainWindow.cpp @@ -1,6 +1,3 @@ -// Copyright (c) Microsoft Corporation and Contributors. -// Licensed under the MIT License. - #include "pch.h" #include "MainWindow.xaml.h" #if __has_include("MainWindow.g.cpp") @@ -15,11 +12,6 @@ using namespace Microsoft::UI::Xaml; namespace winrt::$safeprojectname$::implementation { - MainWindow::MainWindow() - { - InitializeComponent(); - } - int32_t MainWindow::MyProperty() { throw hresult_not_implemented(); diff --git a/dev/VSIX/ProjectTemplates/Desktop/CppWinRT/PackagedApp/BlankApp/MainWindow.h b/dev/VSIX/ProjectTemplates/Desktop/CppWinRT/PackagedApp/BlankApp/MainWindow.h index f814ca11e7..1077d33b4f 100644 --- a/dev/VSIX/ProjectTemplates/Desktop/CppWinRT/PackagedApp/BlankApp/MainWindow.h +++ b/dev/VSIX/ProjectTemplates/Desktop/CppWinRT/PackagedApp/BlankApp/MainWindow.h @@ -1,19 +1,21 @@ -// Copyright (c) Microsoft Corporation and Contributors. -// Licensed under the MIT License. - #pragma once + #include "MainWindow.g.h" namespace winrt::$safeprojectname$::implementation { struct MainWindow : MainWindowT { - MainWindow(); + MainWindow() + { + // Xaml objects should not call InitializeComponent during construction. + // See https://github.com/microsoft/cppwinrt/tree/master/nuget#initializecomponent + } int32_t MyProperty(); void MyProperty(int32_t value); - void myButton_Click(Windows::Foundation::IInspectable const& sender, Microsoft::UI::Xaml::RoutedEventArgs const& args); + void myButton_Click(IInspectable const& sender, Microsoft::UI::Xaml::RoutedEventArgs const& args); }; } diff --git a/dev/VSIX/ProjectTemplates/Desktop/CppWinRT/PackagedApp/BlankApp/MainWindow.idl b/dev/VSIX/ProjectTemplates/Desktop/CppWinRT/PackagedApp/BlankApp/MainWindow.idl index 5d81f19d36..0e0ce71ae6 100644 --- a/dev/VSIX/ProjectTemplates/Desktop/CppWinRT/PackagedApp/BlankApp/MainWindow.idl +++ b/dev/VSIX/ProjectTemplates/Desktop/CppWinRT/PackagedApp/BlankApp/MainWindow.idl @@ -1,6 +1,3 @@ -// Copyright (c) Microsoft Corporation and Contributors. -// Licensed under the MIT License. - namespace $safeprojectname$ { [default_interface] diff --git a/dev/VSIX/ProjectTemplates/Desktop/CppWinRT/PackagedApp/BlankApp/ProjectTemplate.vcxproj b/dev/VSIX/ProjectTemplates/Desktop/CppWinRT/PackagedApp/BlankApp/ProjectTemplate.vcxproj index 125764fe81..e73a840592 100644 --- a/dev/VSIX/ProjectTemplates/Desktop/CppWinRT/PackagedApp/BlankApp/ProjectTemplate.vcxproj +++ b/dev/VSIX/ProjectTemplates/Desktop/CppWinRT/PackagedApp/BlankApp/ProjectTemplate.vcxproj @@ -123,10 +123,6 @@ - - Code - App.xaml - Code MainWindow.xaml diff --git a/dev/VSIX/ProjectTemplates/Desktop/CppWinRT/PackagedApp/BlankApp/ProjectTemplate.vcxproj.filters b/dev/VSIX/ProjectTemplates/Desktop/CppWinRT/PackagedApp/BlankApp/ProjectTemplate.vcxproj.filters index b34b6d068d..95cd21e016 100644 --- a/dev/VSIX/ProjectTemplates/Desktop/CppWinRT/PackagedApp/BlankApp/ProjectTemplate.vcxproj.filters +++ b/dev/VSIX/ProjectTemplates/Desktop/CppWinRT/PackagedApp/BlankApp/ProjectTemplate.vcxproj.filters @@ -7,7 +7,6 @@ - diff --git a/dev/VSIX/ProjectTemplates/Desktop/CppWinRT/PackagedApp/BlankApp/WinUI.Desktop.CppWinRT.BlankApp.vstemplate b/dev/VSIX/ProjectTemplates/Desktop/CppWinRT/PackagedApp/BlankApp/WinUI.Desktop.CppWinRT.BlankApp.vstemplate index a73f9039b9..a2ffc45741 100644 --- a/dev/VSIX/ProjectTemplates/Desktop/CppWinRT/PackagedApp/BlankApp/WinUI.Desktop.CppWinRT.BlankApp.vstemplate +++ b/dev/VSIX/ProjectTemplates/Desktop/CppWinRT/PackagedApp/BlankApp/WinUI.Desktop.CppWinRT.BlankApp.vstemplate @@ -21,7 +21,7 @@ XAML windows desktop - WinUI + winui @@ -30,7 +30,6 @@ pch.h app.manifest App.xaml - App.idl App.cpp App.h MainWindow.xaml diff --git a/dev/VSIX/ProjectTemplates/Desktop/CppWinRT/PackagedApp/BlankApp/pch.cpp b/dev/VSIX/ProjectTemplates/Desktop/CppWinRT/PackagedApp/BlankApp/pch.cpp index 0850baca11..1d9f38c57d 100644 --- a/dev/VSIX/ProjectTemplates/Desktop/CppWinRT/PackagedApp/BlankApp/pch.cpp +++ b/dev/VSIX/ProjectTemplates/Desktop/CppWinRT/PackagedApp/BlankApp/pch.cpp @@ -1,4 +1 @@ -// Copyright (c) Microsoft Corporation and Contributors. -// Licensed under the MIT License. - #include "pch.h" diff --git a/dev/VSIX/ProjectTemplates/Desktop/CppWinRT/PackagedApp/BlankApp/pch.h b/dev/VSIX/ProjectTemplates/Desktop/CppWinRT/PackagedApp/BlankApp/pch.h index 170dd76c69..6d06556701 100644 --- a/dev/VSIX/ProjectTemplates/Desktop/CppWinRT/PackagedApp/BlankApp/pch.h +++ b/dev/VSIX/ProjectTemplates/Desktop/CppWinRT/PackagedApp/BlankApp/pch.h @@ -1,6 +1,3 @@ -// Copyright (c) Microsoft Corporation and Contributors. -// Licensed under the MIT License. - #pragma once #include #include diff --git a/dev/VSIX/ProjectTemplates/Desktop/CppWinRT/PackagedApp/WapProj/WinUI.Desktop.CppWinRT.WapProj.vstemplate b/dev/VSIX/ProjectTemplates/Desktop/CppWinRT/PackagedApp/WapProj/WinUI.Desktop.CppWinRT.WapProj.vstemplate index 442142facb..2810c38a1e 100644 --- a/dev/VSIX/ProjectTemplates/Desktop/CppWinRT/PackagedApp/WapProj/WinUI.Desktop.CppWinRT.WapProj.vstemplate +++ b/dev/VSIX/ProjectTemplates/Desktop/CppWinRT/PackagedApp/WapProj/WinUI.Desktop.CppWinRT.WapProj.vstemplate @@ -21,7 +21,7 @@ XAML windows desktop - WinUI + winui diff --git a/dev/VSIX/ProjectTemplates/Desktop/CppWinRT/PackagedApp/WinUI.Desktop.CppWinRT.PackagedApp.vstemplate b/dev/VSIX/ProjectTemplates/Desktop/CppWinRT/PackagedApp/WinUI.Desktop.CppWinRT.PackagedApp.vstemplate index 36183ad922..e2a5c97540 100644 --- a/dev/VSIX/ProjectTemplates/Desktop/CppWinRT/PackagedApp/WinUI.Desktop.CppWinRT.PackagedApp.vstemplate +++ b/dev/VSIX/ProjectTemplates/Desktop/CppWinRT/PackagedApp/WinUI.Desktop.CppWinRT.PackagedApp.vstemplate @@ -20,7 +20,7 @@ XAML windows desktop - WinUI + winui diff --git a/dev/VSIX/ProjectTemplates/Desktop/CppWinRT/SingleProjectPackagedApp/App.cpp b/dev/VSIX/ProjectTemplates/Desktop/CppWinRT/SingleProjectPackagedApp/App.cpp index cd08294f06..47f77e36cf 100644 --- a/dev/VSIX/ProjectTemplates/Desktop/CppWinRT/SingleProjectPackagedApp/App.cpp +++ b/dev/VSIX/ProjectTemplates/Desktop/CppWinRT/SingleProjectPackagedApp/App.cpp @@ -1,48 +1,43 @@ -// Copyright (c) Microsoft Corporation and Contributors. -// Licensed under the MIT License. - #include "pch.h" - #include "App.xaml.h" #include "MainWindow.xaml.h" using namespace winrt; -using namespace Windows::Foundation; using namespace Microsoft::UI::Xaml; -using namespace Microsoft::UI::Xaml::Controls; -using namespace Microsoft::UI::Xaml::Navigation; -using namespace $safeprojectname$; -using namespace $safeprojectname$::implementation; // To learn more about WinUI, the WinUI project structure, // and more about our project templates, see: http://aka.ms/winui-project-info. -/// -/// Initializes the singleton application object. This is the first line of authored code -/// executed, and as such is the logical equivalent of main() or WinMain(). -/// -App::App() +namespace winrt::$safeprojectname$::implementation { - InitializeComponent(); + /// + /// Initializes the singleton application object. This is the first line of authored code + /// executed, and as such is the logical equivalent of main() or WinMain(). + /// + App::App() + { + // Xaml objects should not call InitializeComponent during construction. + // See https://github.com/microsoft/cppwinrt/tree/master/nuget#initializecomponent #if defined _DEBUG && !defined DISABLE_XAML_GENERATED_BREAK_ON_UNHANDLED_EXCEPTION - UnhandledException([this](IInspectable const&, UnhandledExceptionEventArgs const& e) - { - if (IsDebuggerPresent()) + UnhandledException([](IInspectable const&, UnhandledExceptionEventArgs const& e) { - auto errorMessage = e.Message(); - __debugbreak(); - } - }); + if (IsDebuggerPresent()) + { + auto errorMessage = e.Message(); + __debugbreak(); + } + }); #endif -} + } -/// -/// Invoked when the application is launched. -/// -/// Details about the launch request and process. -void App::OnLaunched(LaunchActivatedEventArgs const&) -{ - window = make(); - window.Activate(); + /// + /// Invoked when the application is launched. + /// + /// Details about the launch request and process. + void App::OnLaunched([[maybe_unused]] LaunchActivatedEventArgs const& e) + { + window = make(); + window.Activate(); + } } diff --git a/dev/VSIX/ProjectTemplates/Desktop/CppWinRT/SingleProjectPackagedApp/App.h b/dev/VSIX/ProjectTemplates/Desktop/CppWinRT/SingleProjectPackagedApp/App.h index 5b835dda35..20431336d7 100644 --- a/dev/VSIX/ProjectTemplates/Desktop/CppWinRT/SingleProjectPackagedApp/App.h +++ b/dev/VSIX/ProjectTemplates/Desktop/CppWinRT/SingleProjectPackagedApp/App.h @@ -1,6 +1,3 @@ -// Copyright (c) Microsoft Corporation and Contributors. -// Licensed under the MIT License. - #pragma once #include "App.xaml.g.h" diff --git a/dev/VSIX/ProjectTemplates/Desktop/CppWinRT/SingleProjectPackagedApp/App.idl b/dev/VSIX/ProjectTemplates/Desktop/CppWinRT/SingleProjectPackagedApp/App.idl deleted file mode 100644 index 55ac0e3690..0000000000 --- a/dev/VSIX/ProjectTemplates/Desktop/CppWinRT/SingleProjectPackagedApp/App.idl +++ /dev/null @@ -1,6 +0,0 @@ -// Copyright (c) Microsoft Corporation and Contributors. -// Licensed under the MIT License. - -namespace $safeprojectname$ -{ -} diff --git a/dev/VSIX/ProjectTemplates/Desktop/CppWinRT/SingleProjectPackagedApp/MainWindow.cpp b/dev/VSIX/ProjectTemplates/Desktop/CppWinRT/SingleProjectPackagedApp/MainWindow.cpp index 746fe412aa..d6d47e7619 100644 --- a/dev/VSIX/ProjectTemplates/Desktop/CppWinRT/SingleProjectPackagedApp/MainWindow.cpp +++ b/dev/VSIX/ProjectTemplates/Desktop/CppWinRT/SingleProjectPackagedApp/MainWindow.cpp @@ -1,6 +1,3 @@ -// Copyright (c) Microsoft Corporation and Contributors. -// Licensed under the MIT License. - #include "pch.h" #include "MainWindow.xaml.h" #if __has_include("MainWindow.g.cpp") @@ -15,11 +12,6 @@ using namespace Microsoft::UI::Xaml; namespace winrt::$safeprojectname$::implementation { - MainWindow::MainWindow() - { - InitializeComponent(); - } - int32_t MainWindow::MyProperty() { throw hresult_not_implemented(); diff --git a/dev/VSIX/ProjectTemplates/Desktop/CppWinRT/SingleProjectPackagedApp/MainWindow.h b/dev/VSIX/ProjectTemplates/Desktop/CppWinRT/SingleProjectPackagedApp/MainWindow.h index 6bc83fa80a..1077d33b4f 100644 --- a/dev/VSIX/ProjectTemplates/Desktop/CppWinRT/SingleProjectPackagedApp/MainWindow.h +++ b/dev/VSIX/ProjectTemplates/Desktop/CppWinRT/SingleProjectPackagedApp/MainWindow.h @@ -1,6 +1,3 @@ -// Copyright (c) Microsoft Corporation and Contributors. -// Licensed under the MIT License. - #pragma once #include "MainWindow.g.h" @@ -9,12 +6,16 @@ namespace winrt::$safeprojectname$::implementation { struct MainWindow : MainWindowT { - MainWindow(); + MainWindow() + { + // Xaml objects should not call InitializeComponent during construction. + // See https://github.com/microsoft/cppwinrt/tree/master/nuget#initializecomponent + } int32_t MyProperty(); void MyProperty(int32_t value); - void myButton_Click(Windows::Foundation::IInspectable const& sender, Microsoft::UI::Xaml::RoutedEventArgs const& args); + void myButton_Click(IInspectable const& sender, Microsoft::UI::Xaml::RoutedEventArgs const& args); }; } diff --git a/dev/VSIX/ProjectTemplates/Desktop/CppWinRT/SingleProjectPackagedApp/MainWindow.idl b/dev/VSIX/ProjectTemplates/Desktop/CppWinRT/SingleProjectPackagedApp/MainWindow.idl index 5d81f19d36..0e0ce71ae6 100644 --- a/dev/VSIX/ProjectTemplates/Desktop/CppWinRT/SingleProjectPackagedApp/MainWindow.idl +++ b/dev/VSIX/ProjectTemplates/Desktop/CppWinRT/SingleProjectPackagedApp/MainWindow.idl @@ -1,6 +1,3 @@ -// Copyright (c) Microsoft Corporation and Contributors. -// Licensed under the MIT License. - namespace $safeprojectname$ { [default_interface] diff --git a/dev/VSIX/ProjectTemplates/Desktop/CppWinRT/SingleProjectPackagedApp/ProjectTemplate.vcxproj b/dev/VSIX/ProjectTemplates/Desktop/CppWinRT/SingleProjectPackagedApp/ProjectTemplate.vcxproj index 8186b4bd45..18f24fc411 100644 --- a/dev/VSIX/ProjectTemplates/Desktop/CppWinRT/SingleProjectPackagedApp/ProjectTemplate.vcxproj +++ b/dev/VSIX/ProjectTemplates/Desktop/CppWinRT/SingleProjectPackagedApp/ProjectTemplate.vcxproj @@ -129,10 +129,6 @@ - - Code - App.xaml - Code MainWindow.xaml diff --git a/dev/VSIX/ProjectTemplates/Desktop/CppWinRT/SingleProjectPackagedApp/ProjectTemplate.vcxproj.filters b/dev/VSIX/ProjectTemplates/Desktop/CppWinRT/SingleProjectPackagedApp/ProjectTemplate.vcxproj.filters index 1af01fbcb6..474783025b 100644 --- a/dev/VSIX/ProjectTemplates/Desktop/CppWinRT/SingleProjectPackagedApp/ProjectTemplate.vcxproj.filters +++ b/dev/VSIX/ProjectTemplates/Desktop/CppWinRT/SingleProjectPackagedApp/ProjectTemplate.vcxproj.filters @@ -7,7 +7,6 @@ - diff --git a/dev/VSIX/ProjectTemplates/Desktop/CppWinRT/SingleProjectPackagedApp/WinUI.Desktop.CppWinRT.SingleProjectPackagedApp.csproj b/dev/VSIX/ProjectTemplates/Desktop/CppWinRT/SingleProjectPackagedApp/WinUI.Desktop.CppWinRT.SingleProjectPackagedApp.csproj index 9166a5b2f3..f591427e4d 100644 --- a/dev/VSIX/ProjectTemplates/Desktop/CppWinRT/SingleProjectPackagedApp/WinUI.Desktop.CppWinRT.SingleProjectPackagedApp.csproj +++ b/dev/VSIX/ProjectTemplates/Desktop/CppWinRT/SingleProjectPackagedApp/WinUI.Desktop.CppWinRT.SingleProjectPackagedApp.csproj @@ -56,7 +56,6 @@ - diff --git a/dev/VSIX/ProjectTemplates/Desktop/CppWinRT/SingleProjectPackagedApp/WinUI.Desktop.CppWinRT.SingleProjectPackagedApp.vstemplate b/dev/VSIX/ProjectTemplates/Desktop/CppWinRT/SingleProjectPackagedApp/WinUI.Desktop.CppWinRT.SingleProjectPackagedApp.vstemplate index b60e3cf737..530b82923f 100644 --- a/dev/VSIX/ProjectTemplates/Desktop/CppWinRT/SingleProjectPackagedApp/WinUI.Desktop.CppWinRT.SingleProjectPackagedApp.vstemplate +++ b/dev/VSIX/ProjectTemplates/Desktop/CppWinRT/SingleProjectPackagedApp/WinUI.Desktop.CppWinRT.SingleProjectPackagedApp.vstemplate @@ -20,7 +20,7 @@ XAML windows desktop - WinUI + winui @@ -29,7 +29,6 @@ pch.h app.manifest App.xaml - App.idl App.cpp App.h MainWindow.xaml diff --git a/dev/VSIX/ProjectTemplates/Desktop/CppWinRT/SingleProjectPackagedApp/pch.cpp b/dev/VSIX/ProjectTemplates/Desktop/CppWinRT/SingleProjectPackagedApp/pch.cpp index 0850baca11..1d9f38c57d 100644 --- a/dev/VSIX/ProjectTemplates/Desktop/CppWinRT/SingleProjectPackagedApp/pch.cpp +++ b/dev/VSIX/ProjectTemplates/Desktop/CppWinRT/SingleProjectPackagedApp/pch.cpp @@ -1,4 +1 @@ -// Copyright (c) Microsoft Corporation and Contributors. -// Licensed under the MIT License. - #include "pch.h" diff --git a/dev/VSIX/ProjectTemplates/Desktop/CppWinRT/SingleProjectPackagedApp/pch.h b/dev/VSIX/ProjectTemplates/Desktop/CppWinRT/SingleProjectPackagedApp/pch.h index 170dd76c69..6d06556701 100644 --- a/dev/VSIX/ProjectTemplates/Desktop/CppWinRT/SingleProjectPackagedApp/pch.h +++ b/dev/VSIX/ProjectTemplates/Desktop/CppWinRT/SingleProjectPackagedApp/pch.h @@ -1,6 +1,3 @@ -// Copyright (c) Microsoft Corporation and Contributors. -// Licensed under the MIT License. - #pragma once #include #include diff --git a/dev/VSIX/ProjectTemplates/Neutral/CppWinRT/RuntimeComponent/Class.cpp b/dev/VSIX/ProjectTemplates/Neutral/CppWinRT/RuntimeComponent/Class.cpp index 8b0049de60..a24a855b28 100644 --- a/dev/VSIX/ProjectTemplates/Neutral/CppWinRT/RuntimeComponent/Class.cpp +++ b/dev/VSIX/ProjectTemplates/Neutral/CppWinRT/RuntimeComponent/Class.cpp @@ -1,6 +1,3 @@ -// Copyright (c) Microsoft Corporation and Contributors. -// Licensed under the MIT License. - #include "pch.h" #include "Class.h" #if __has_include("Class.g.cpp") diff --git a/dev/VSIX/ProjectTemplates/Neutral/CppWinRT/RuntimeComponent/Class.h b/dev/VSIX/ProjectTemplates/Neutral/CppWinRT/RuntimeComponent/Class.h index b74291f717..67afcddeaf 100644 --- a/dev/VSIX/ProjectTemplates/Neutral/CppWinRT/RuntimeComponent/Class.h +++ b/dev/VSIX/ProjectTemplates/Neutral/CppWinRT/RuntimeComponent/Class.h @@ -1,6 +1,3 @@ -// Copyright (c) Microsoft Corporation and Contributors. -// Licensed under the MIT License. - #pragma once #include "Class.g.h" diff --git a/dev/VSIX/ProjectTemplates/Neutral/CppWinRT/RuntimeComponent/Class.idl b/dev/VSIX/ProjectTemplates/Neutral/CppWinRT/RuntimeComponent/Class.idl index 2d4c82c3a8..86166e9780 100644 --- a/dev/VSIX/ProjectTemplates/Neutral/CppWinRT/RuntimeComponent/Class.idl +++ b/dev/VSIX/ProjectTemplates/Neutral/CppWinRT/RuntimeComponent/Class.idl @@ -1,6 +1,3 @@ -// Copyright (c) Microsoft Corporation and Contributors. -// Licensed under the MIT License. - namespace $safeprojectname$ { [default_interface] diff --git a/dev/VSIX/ProjectTemplates/Neutral/CppWinRT/RuntimeComponent/ProjectTemplate.vcxproj b/dev/VSIX/ProjectTemplates/Neutral/CppWinRT/RuntimeComponent/ProjectTemplate.vcxproj index df8226c1fe..1c5ae504ca 100644 --- a/dev/VSIX/ProjectTemplates/Neutral/CppWinRT/RuntimeComponent/ProjectTemplate.vcxproj +++ b/dev/VSIX/ProjectTemplates/Neutral/CppWinRT/RuntimeComponent/ProjectTemplate.vcxproj @@ -9,7 +9,7 @@ $safeprojectname$ $currentuiculturename$ 16.0 - true + false Windows Store 10.0 $targetplatformversion$ diff --git a/dev/VSIX/ProjectTemplates/Neutral/CppWinRT/RuntimeComponent/WinUI.Neutral.CppWinRT.RuntimeComponent.vstemplate b/dev/VSIX/ProjectTemplates/Neutral/CppWinRT/RuntimeComponent/WinUI.Neutral.CppWinRT.RuntimeComponent.vstemplate index ce21009daa..99f5d734a2 100644 --- a/dev/VSIX/ProjectTemplates/Neutral/CppWinRT/RuntimeComponent/WinUI.Neutral.CppWinRT.RuntimeComponent.vstemplate +++ b/dev/VSIX/ProjectTemplates/Neutral/CppWinRT/RuntimeComponent/WinUI.Neutral.CppWinRT.RuntimeComponent.vstemplate @@ -20,8 +20,7 @@ XAML windows desktop - uwp - WinUI + winui diff --git a/dev/VSIX/ProjectTemplates/Neutral/CppWinRT/RuntimeComponent/pch.cpp b/dev/VSIX/ProjectTemplates/Neutral/CppWinRT/RuntimeComponent/pch.cpp index 0850baca11..1d9f38c57d 100644 --- a/dev/VSIX/ProjectTemplates/Neutral/CppWinRT/RuntimeComponent/pch.cpp +++ b/dev/VSIX/ProjectTemplates/Neutral/CppWinRT/RuntimeComponent/pch.cpp @@ -1,4 +1 @@ -// Copyright (c) Microsoft Corporation and Contributors. -// Licensed under the MIT License. - #include "pch.h" diff --git a/dev/VSIX/ProjectTemplates/Neutral/CppWinRT/RuntimeComponent/pch.h b/dev/VSIX/ProjectTemplates/Neutral/CppWinRT/RuntimeComponent/pch.h index 510ce87ab0..1533d96bb2 100644 --- a/dev/VSIX/ProjectTemplates/Neutral/CppWinRT/RuntimeComponent/pch.h +++ b/dev/VSIX/ProjectTemplates/Neutral/CppWinRT/RuntimeComponent/pch.h @@ -1,16 +1,26 @@ -// Copyright (c) Microsoft Corporation and Contributors. -// Licensed under the MIT License. - #pragma once +#include #include +#include +#include + +// Undefine GetCurrentTime macro to prevent +// conflict with Storyboard::GetCurrentTime +#undef GetCurrentTime + #include #include +#include +#include #include #include #include #include #include +#include #include +#include #include +#include #include #include diff --git a/dev/VSIX/WindowsAppSDK.Extension.sln b/dev/VSIX/WindowsAppSDK.Extension.sln index 902a2e6ccd..eacc540f42 100644 --- a/dev/VSIX/WindowsAppSDK.Extension.sln +++ b/dev/VSIX/WindowsAppSDK.Extension.sln @@ -76,12 +76,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WinUI.Desktop.Cs.SingleProj EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WinUI.Desktop.CppWinRT.SingleProjectPackagedApp", "ProjectTemplates\Desktop\CppWinRT\SingleProjectPackagedApp\WinUI.Desktop.CppWinRT.SingleProjectPackagedApp.csproj", "{E54D1AD4-E935-479D-8A69-FC073E4DB33D}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WindowsAppSDK.Cs.Extension.Dev16", "Extension\Cs\Dev16\WindowsAppSDK.Cs.Extension.Dev16.csproj", "{EBCE08A8-372E-47B8-88C4-24EEA650C44A}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WindowsAppSDK.Cs.Extension.Dev17", "Extension\Cs\Dev17\WindowsAppSDK.Cs.Extension.Dev17.csproj", "{E700DF09-42A9-4AC7-9855-400029FBFDBE}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WindowsAppSDK.Cpp.Extension.Dev16", "Extension\Cpp\Dev16\WindowsAppSDK.Cpp.Extension.Dev16.csproj", "{7C5EAFA9-BDB7-4A2E-A9CF-2AE62352B75A}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WindowsAppSDK.Cpp.Extension.Dev17", "Extension\Cpp\Dev17\WindowsAppSDK.Cpp.Extension.Dev17.csproj", "{85E88201-049C-4E42-AE85-DFEEFA7C533C}" EndProject Global @@ -236,14 +232,6 @@ Global {E54D1AD4-E935-479D-8A69-FC073E4DB33D}.Release|Any CPU.Build.0 = Release|Any CPU {E54D1AD4-E935-479D-8A69-FC073E4DB33D}.Release|x64.ActiveCfg = Release|Any CPU {E54D1AD4-E935-479D-8A69-FC073E4DB33D}.Release|x64.Build.0 = Release|Any CPU - {EBCE08A8-372E-47B8-88C4-24EEA650C44A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {EBCE08A8-372E-47B8-88C4-24EEA650C44A}.Debug|Any CPU.Build.0 = Debug|Any CPU - {EBCE08A8-372E-47B8-88C4-24EEA650C44A}.Debug|x64.ActiveCfg = Debug|Any CPU - {EBCE08A8-372E-47B8-88C4-24EEA650C44A}.Debug|x64.Build.0 = Debug|Any CPU - {EBCE08A8-372E-47B8-88C4-24EEA650C44A}.Release|Any CPU.ActiveCfg = Release|Any CPU - {EBCE08A8-372E-47B8-88C4-24EEA650C44A}.Release|Any CPU.Build.0 = Release|Any CPU - {EBCE08A8-372E-47B8-88C4-24EEA650C44A}.Release|x64.ActiveCfg = Release|Any CPU - {EBCE08A8-372E-47B8-88C4-24EEA650C44A}.Release|x64.Build.0 = Release|Any CPU {E700DF09-42A9-4AC7-9855-400029FBFDBE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {E700DF09-42A9-4AC7-9855-400029FBFDBE}.Debug|Any CPU.Build.0 = Debug|Any CPU {E700DF09-42A9-4AC7-9855-400029FBFDBE}.Debug|x64.ActiveCfg = Debug|Any CPU @@ -252,14 +240,6 @@ Global {E700DF09-42A9-4AC7-9855-400029FBFDBE}.Release|Any CPU.Build.0 = Release|Any CPU {E700DF09-42A9-4AC7-9855-400029FBFDBE}.Release|x64.ActiveCfg = Release|Any CPU {E700DF09-42A9-4AC7-9855-400029FBFDBE}.Release|x64.Build.0 = Release|Any CPU - {7C5EAFA9-BDB7-4A2E-A9CF-2AE62352B75A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {7C5EAFA9-BDB7-4A2E-A9CF-2AE62352B75A}.Debug|Any CPU.Build.0 = Debug|Any CPU - {7C5EAFA9-BDB7-4A2E-A9CF-2AE62352B75A}.Debug|x64.ActiveCfg = Debug|Any CPU - {7C5EAFA9-BDB7-4A2E-A9CF-2AE62352B75A}.Debug|x64.Build.0 = Debug|Any CPU - {7C5EAFA9-BDB7-4A2E-A9CF-2AE62352B75A}.Release|Any CPU.ActiveCfg = Release|Any CPU - {7C5EAFA9-BDB7-4A2E-A9CF-2AE62352B75A}.Release|Any CPU.Build.0 = Release|Any CPU - {7C5EAFA9-BDB7-4A2E-A9CF-2AE62352B75A}.Release|x64.ActiveCfg = Release|Any CPU - {7C5EAFA9-BDB7-4A2E-A9CF-2AE62352B75A}.Release|x64.Build.0 = Release|Any CPU {85E88201-049C-4E42-AE85-DFEEFA7C533C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {85E88201-049C-4E42-AE85-DFEEFA7C533C}.Debug|Any CPU.Build.0 = Debug|Any CPU {85E88201-049C-4E42-AE85-DFEEFA7C533C}.Debug|x64.ActiveCfg = Debug|Any CPU diff --git a/dev/WindowsAppRuntime_DLL/WindowsAppRuntime_DLL.vcxproj b/dev/WindowsAppRuntime_DLL/WindowsAppRuntime_DLL.vcxproj index df01b5362f..7c12d5d93e 100644 --- a/dev/WindowsAppRuntime_DLL/WindowsAppRuntime_DLL.vcxproj +++ b/dev/WindowsAppRuntime_DLL/WindowsAppRuntime_DLL.vcxproj @@ -97,6 +97,7 @@ + @@ -261,7 +262,7 @@ - + $(RepoRoot);%(AdditionalIncludeDirectories) diff --git a/dev/WindowsAppRuntime_DLL/dllmain.cpp b/dev/WindowsAppRuntime_DLL/dllmain.cpp index 9dff635ce0..cc0604d331 100644 --- a/dev/WindowsAppRuntime_DLL/dllmain.cpp +++ b/dev/WindowsAppRuntime_DLL/dllmain.cpp @@ -1,8 +1,9 @@ -// Copyright (c) Microsoft Corporation and Contributors. +// Copyright (c) Microsoft Corporation and Contributors. // Licensed under the MIT License. #include "pch.h" +#include #include #include @@ -30,6 +31,7 @@ static HRESULT DetoursInitialize() DetourRestoreAfterWith(); FAIL_FAST_IF_WIN32_ERROR(DetourTransactionBegin()); + FAIL_FAST_IF_FAILED(MddWin11Initialize()); FAIL_FAST_IF_FAILED(MddDetourPackageGraphInitialize()); FAIL_FAST_IF_FAILED(UrfwInitialize()); diff --git a/dev/WindowsAppRuntime_DLL/packages.config b/dev/WindowsAppRuntime_DLL/packages.config index 14efb7baf5..cd05427e9c 100644 --- a/dev/WindowsAppRuntime_DLL/packages.config +++ b/dev/WindowsAppRuntime_DLL/packages.config @@ -3,6 +3,6 @@ - + diff --git a/docs/roadmap.md b/docs/roadmap.md index b4533e4380..8615a8be2b 100644 --- a/docs/roadmap.md +++ b/docs/roadmap.md @@ -1,53 +1,43 @@ # Windows App SDK Roadmap - -This roadmap frames how the Windows Development Platform team will deliver the Windows App SDK (WinAppSDK) and various technologies contained within, focused on the year ahead. It is intended to be the best entry point to conceptualize what’s happening in the WinAppSDK, so you can form plans/strategies around this technology. - -Details of this roadmap may change, and when they do, we’ll strive to update the roadmap with the new information in a timely way. +This roadmap frames how the Windows Development Platform team will deliver the Windows App SDK (WinAppSDK) and various technologies contained within, focused on the year ahead. It is intended to be the best entry point to conceptualize what's happening in the WinAppSDK, so you can form plans/strategies around this technology. +Details of this roadmap may change, and when they do, we'll strive to update the roadmap with the new information in a timely way. We aim to update this roadmap after every major public release (such as 1.4.0) when the details for the next release are ready to share. ## Mission Empower developers to create the richest & most engaging native apps & surfaces for the Windows ecosystem. -## Looking back at 2021 - -Windows App SDK 1.0 [shipped](https://docs.microsoft.com/windows/apps/windows-app-sdk/stable-channel#version-10) on Nov 16, 2021 bringing the full power of the modern Windows dev platform to the Win32 app community. -This release was made possible by the excellent feedback & bug reports we received from you, the Windows development community! -WinAppSDK 1.0 includes rich features for production-level apps including WinUI 3, high-quality text rendering (DWriteCore), streamlined resource management (MRT Core), app lifecycle management, and framework agnostic windowing APIs. -There are also numerous ecosystem technologies that have begun building on top of Windows App SDK; see the [1.0 blog post](https://blogs.windows.com/windowsdeveloper/2022/02/11/window-app-sdk-ecosystem-update/) for a detailed look. - -## Primary areas of focus for 2022 - -In 2022, our overarching goal is to build upon the 1.0 release by raising overall reliability, and increasing usage across the industry. To do this, we’ll concentrate on three areas this year: - -- Ship WinAppSDK 1.1 and 1.2 with a range of new enhancements & features focused on enabling the first set of industry leading WinAppSDK-based apps to ship into market. -- Expand usage of WinUI 3 in Microsoft’s own products, including apps that are built-in & ship with Windows, and also the Windows OS shell itself. Having our own teams experience the platform firsthand will help us rapidly improve the product for everyone. -- Continue efforts to make WinAppSDK and WinUI 3 available to the .NET MAUI and React Native for Windows ecosystems. - -You will see improved reliability and new exciting features as we focus on these three areas. - -## Upcoming features & releases - -We aim to ship a high-quality release about every six months; as work begins on an upcoming release, we also kick off planning for the subsequent release in parallel. -Our next WinAppSDK release will be version 1.1, expected to arrive in the first half of 2022 (22H1). -Headline features for this release include: - -- Apps can create **multiple windows** with WinUI3 content on the same UI thread. -- **Mica** & **Background Acrylic** styles are available for WinUI 3 content. -- **Improved default and custom title bar** with new functionalities like z-order, sizing/resizing, tall title bar, and extended show. -- Apps using the Windows App SDK can **run with elevated permissions**. -- Apps can deploy **self-contained** with Windows App SDK as an included dependency. -- Apps can **push notifications** regardless of packaging type, and where the app is published. -- The **environment variables** PATH and PATHEXT can be managed and tracked at runtime using new convenient APIs. -- Apps can **restart** manually or register themselves to be restarted after a system update occurs. - -A list of 1.2 features, aimed to ship near the end of 2022, will be shared in a future roadmap update. +## Road to the next release + +Our next WinAppSDK release will be version 1.5, expected to arrive in the first half of 2024 (24H1). +In the last quarter of 2023 and going into the first half of 2024, the WinAppSDK's main goals are to become leaner and more efficient in our engineering processes and begin on an exciting new long-term journey towards supporting Cross-process Islands. + +### Upcoming features for the Windows App SDK 1.5 + +Headline areas of work and features for the 1.5 timeframe include: + +- **Windows App SDK** + - Upgrading our internal processes and infrastructure, allowing for more flexibility in shipping so we can speed up feature development and improve our undocked architecture + - Improving support for the next Visual Studio and .NET MAUI +- **WinUI 3** + - Getting started on a multi-release effort to support Cross-process Islands, including fundamental input and rendering support for Content Islands + - Continuing to support File Explorer enhancements that we started in the 1.4 release + - Adding controls to close the WinUI 2 to WinUI 3 gap for developers interested in porting their apps, including but not limited to the following: + - Segmented control + - Labels in the command bar flyout top bar items + - Maps control + - Investigations into the table view and ink controls + - Supporting highly functional tabbed windows that work with touch, snapping, and other OS features + - Drag and drop support in WebView2 + - Improved screen reader support, text scaling support, and other accessibility features + - Fixes, documentation, and recommendations on how to test WinUI apps + - Stability and performance improvements based on the prioritized GitHub bug backlog +- **Dynamic Lighting** + - Onboarding new and exciting APIs to the Windows App SDK ## Join in and stay connected! Technologies within the Windows App SDK have already benefitted greatly from the incredible feedback and insights the community has provided around features to build, and bugs to fix. -*Thank you* for your continued passion and drive to make Windows App SDK the best platform it can be; it has really made a difference! -We’re working on new strategies to try and tackle the volume of feedback in a timely manner. -As we concentrate on the areas of focus for 2022 mentioned above, we’ll prioritize responding to feedback in those areas first, and we’ll also publish clearer policies on handling stale issues that are unlikely to be addressed within the next couple releases. +*Thank you* for your continued passion and drive to make Windows App SDK the best platform it can be; it has really made a difference! -You can join in by contributing to existing issues, or filing a new issue on the [Windows App SDK](https://github.com/microsoft/WindowsAppSDK) or [WinUI](https://github.com/microsoft/microsoft-ui-xaml) GitHub repos. If you're interested in WinUI 3, come join us on our live monthly [WinUI Community Calls](https://www.youtube.com/playlist?list=PLI_J2v67C23ZqsolUDaHoFkF1GKvGrttB), which are hosted on the third Wednesday of every month at 9am PT. Finally, you can stay in touch with us on Twitter using [#WindowsAppSDK](https://twitter.com/search?q=%23WindowsAppSDK). \ No newline at end of file +You can join in by contributing to existing issues, or filing a new issue on the [Windows App SDK](https://github.com/microsoft/WindowsAppSDK) or [WinUI](https://github.com/microsoft/microsoft-ui-xaml) GitHub repos. If you're interested in WinUI 3, come join us on the live Windows Development [Community Calls](https://www.youtube.com/playlist?list=PLI_J2v67C23ZqsolUDaHoFkF1GKvGrttB), which are hosted quarterly. Finally, you can find and tag us on X (formerly Twitter) using [#WindowsAppSDK](https://twitter.com/search?q=%23WindowsAppSDK). \ No newline at end of file diff --git a/eng/Version.Dependencies.xml b/eng/Version.Dependencies.xml index 1918283612..fba4803c9f 100644 --- a/eng/Version.Dependencies.xml +++ b/eng/Version.Dependencies.xml @@ -29,9 +29,9 @@ - + - + diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 727f338056..12bf096b30 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -27,33 +27,33 @@ --> - + https://dev.azure.com/microsoft/LiftedIXP/_git/DCPP - 21e744a00a8be67e713d3ca24f1e91467b89cbe3 + aca3f84ba82804f6bbc99aedf97315da44cde57a - + https://dev.azure.com/microsoft/ProjectReunion/_git/WindowsAppSDKClosed - f8e1e474101834180971e60e68999becb053f367 + 7eacda339c05f68f2d64d3d0fd98ee70102012c2 - + https://dev.azure.com/microsoft/ProjectReunion/_git/WindowsAppSDKAggregator - 4af33042dd35c5b7c41ce901320657a64be2e7ab + cd02e3c39f21b488bbab4e3c494860015cdfb75e - + https://github.com/microsoft/CsWinRT fa7f5565cb53353dc15c28a09ebd500577dc0b72 - + https://github.com/microsoft/CsWinRT fa7f5565cb53353dc15c28a09ebd500577dc0b72 - + https://github.com/microsoft/CsWinRT fa7f5565cb53353dc15c28a09ebd500577dc0b72 - + https://github.com/microsoft/CsWinRT fa7f5565cb53353dc15c28a09ebd500577dc0b72 diff --git a/eng/common/AzurePipelinesTemplates/WindowsAppSDK-Build-Steps.yml b/eng/common/AzurePipelinesTemplates/WindowsAppSDK-Build-Steps.yml index c0f7680168..16def9ce27 100644 --- a/eng/common/AzurePipelinesTemplates/WindowsAppSDK-Build-Steps.yml +++ b/eng/common/AzurePipelinesTemplates/WindowsAppSDK-Build-Steps.yml @@ -46,7 +46,7 @@ parameters: steps: - ${{ if ne(parameters.TransportPackageArtifactName, '') }}: - - task: DownloadBuildArtifacts@0 + - task: DownloadPipelineArtifact@2 inputs: artifactName: ${{ parameters.TransportPackageArtifactName }} downloadPath: '$(Build.SourcesDirectory)\localpackages' diff --git a/eng/common/AzurePipelinesTemplates/WindowsAppSDK-BuildSetup-Steps.yml b/eng/common/AzurePipelinesTemplates/WindowsAppSDK-BuildSetup-Steps.yml index 3e3cb9264e..8aabb61c2e 100644 --- a/eng/common/AzurePipelinesTemplates/WindowsAppSDK-BuildSetup-Steps.yml +++ b/eng/common/AzurePipelinesTemplates/WindowsAppSDK-BuildSetup-Steps.yml @@ -22,7 +22,7 @@ parameters: default: 'ProjectReunionInternal' steps: - - checkout: git://ProjectReunion/WindowsAppSDKAggregator@release/1.4-stable + - checkout: git://ProjectReunion/WindowsAppSDKAggregator@release/1.5-stable - task: AzureKeyVault@1 inputs: diff --git a/eng/common/AzurePipelinesTemplates/WindowsAppSDK-IntegrationTest-Steps.yml b/eng/common/AzurePipelinesTemplates/WindowsAppSDK-IntegrationTest-Steps.yml index f89698f2f0..e3aa0db0cd 100644 --- a/eng/common/AzurePipelinesTemplates/WindowsAppSDK-IntegrationTest-Steps.yml +++ b/eng/common/AzurePipelinesTemplates/WindowsAppSDK-IntegrationTest-Steps.yml @@ -104,4 +104,4 @@ steps: displayName: MoveToOutputDirectory inputs: SourceFolder: '$(Build.SourcesDirectory)\PipelineTestOutput' - TargetFolder: '$(ob_outputDirectory)' \ No newline at end of file + TargetFolder: '$(ob_outputDirectory)' diff --git a/eng/common/DevCheck.ps1 b/eng/common/DevCheck.ps1 index b1cd46ab76..1289f0cf72 100644 --- a/eng/common/DevCheck.ps1 +++ b/eng/common/DevCheck.ps1 @@ -1,4 +1,5 @@ -# Make a valid AppxManifest.xml from a templated file and variable substititon +# Copyright (c) Microsoft Corporation and Contributors. +# Licensed under the MIT License. <# .SYNOPSIS @@ -6,9 +7,11 @@ .DESCRIPTION Review the current environment and fix or warn if anything is amiss. This includes... - * TAEF service is installed and running + * Developer mode is enabled * Test certificate to sign test MSIX packages is installed + * TAEF service is installed and running * Visual Studio 2022 is installed and properly configured + * Dependencies in use are in the approved list of packages and versions .PARAMETER CertPassword Password for new certificates @@ -19,6 +22,12 @@ .PARAMETER CheckAll Check all. If not specified this is set to true if all other -Check... options are false +.PARAMETER CheckDependencies + Verify dependencies in projects (*proj, packages.config, eng\Version.*.props) match defined dependencies (eng\Version.*.xml) + +.PARAMETER CheckDeveloperMode + Check developer mode + .PARAMETER CheckTAEFService Check the TAEF service @@ -37,6 +46,9 @@ .PARAMETER Offline Do not access the network +.PARAMETER OnlineVSWhere + Download and use the latest vswhere.exe on the network + .PARAMETER RemoveAll Remove all. @@ -46,6 +58,15 @@ .PARAMETER RemoveTestPfx Remove the MSIX Test signing certificate (i.e. undoc CheckTestPfx) +.PARAMETER StartTAEFService + Start the TAEF service + +.PARAMETER StopTAEFService + Stop the TAEF service + +.PARAMETER SyncDependencies + Update dependencies (*proj, packages.config, eng\Version.*.props) to match defined dependencies (eng\Version.*.xml) + .PARAMETER Verbose Display detailed information @@ -70,28 +91,50 @@ Param( [Switch]$CheckVisualStudio=$false, + [Switch]$CheckDependencies=$false, + + [Switch]$CheckDeveloperMode=$false, + [Switch]$Clean=$false, [Switch]$NoInteractive=$false, [Switch]$Offline=$false, + [Switch]$OnlineVSWhere=$false, + [Switch]$RemoveAll=$false, [Switch]$RemoveTestCert=$false, [Switch]$RemoveTestPfx=$false, + [Switch]$StartTAEFService=$false, + + [Switch]$StopTAEFService=$false, + + [Switch]$SyncDependencies=$false, + [Switch]$Verbose=$false ) +Set-StrictMode -Version 3.0 + +$ErrorActionPreference = "Stop" + $global:issues = 0 +$global:isadmin = $null + $remove_any = ($RemoveAll -eq $true) -or ($RemoveTestCert -eq $true) -or ($RemoveTestCert -eq $true) -if (($remove_any -eq $false) -And ($CheckTAEFService -eq $false) -And ($CheckTestCert -eq $false) -And ($CheckTestPfx -eq $false) -And ($CheckVisualStudio -eq $false)) +if (($remove_any -eq $false) -And ($CheckTAEFService -eq $false) -And ($StartTAEFService -eq $false) -And ($StopTAEFService -eq $false) -And ($CheckTestCert -eq $false) -And ($CheckTestPfx -eq $false) -And ($CheckVisualStudio -eq $false) -And ($CheckDependencies -eq $false) -And ($SyncDependencies -eq $false) -And ($CheckDeveloperMode -eq $false)) { $CheckAll = $true } +if ($SyncDependencies -eq $true) +{ + $CheckDependencies = $true +} function Write-Verbose { @@ -108,12 +151,16 @@ function Write-Verbose function Get-IsAdmin { - return [Security.Principal.WindowsIdentity]::GetCurrent().Groups -contains 'S-1-5-32-544' + if ($global:isadmin -eq $null) + { + $global:isadmin = [Security.Principal.WindowsIdentity]::GetCurrent().Groups -contains 'S-1-5-32-544' + } + return $global:isadmin } function Get-ProjectRoot { - return (get-item $PSScriptRoot ).parent.parent.FullName + return (Get-Item $PSScriptRoot ).parent.parent.FullName } function Get-TempPath @@ -161,6 +208,103 @@ function Get-CpuArchitecture } } +function Test-SemVer +{ + param( + [string]$left, + [string]$right + ) + + $lefty = $left.Split('.') + $righty = $right.Split('.') + + $cmp = [int]$lefty[0] - [int]$righty[0] + if ($cmp -ne 0) + { + return $cmp + } + + $cmp = [int]$lefty[1] - [int]$righty[1] + if ($cmp -ne 0) + { + return $cmp + } + + $null = $lefty[2] -Match "(\d+)(-[^+]+)?(\+.+)?$" + $lefty2 = $Matches[1] + $lefty2prerelease = $Matches[2] + $null = $righty[2] -Match "(\d+)(-[^+]+)?(\+.+)?$" + $righty2 = $Matches[1] + $righty2prerelease = $Matches[2] + $cmp = [int]$lefty2 - [int]$righty2 + if ($cmp -ne 0) + { + return $cmp + } + if ($lefty2prerelease -ilt $righty2prerelease) + { + return -1 + } + elseif ($lefty2prerelease -igt $righty2prerelease) + { + return 1 + } + else + { + return 0 + } +} + +function Get-TAEFPackageVersion +{ + $root = Get-ProjectRoot + $filename = Join-Path $root 'eng' + $filename = Join-Path $filename 'Version.Dependencies.xml' + $xml = [xml](Get-Content $filename -EA:Stop) + $taef = $xml.SelectSingleNode("/Dependencies/Dependency[@Name='Microsoft.Taef']") + return $taef.Version +} + +function Get-VSWhereOffline +{ + # Absolute Path = "%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere.exe" + + $programfilesx86 = [Environment]::GetFolderPath([Environment+SpecialFolder]::ProgramFilesX86) + $path = Join-Path $programfilesx86 "Microsoft Visual Studio\Installer\vswhere.exe" + if (-not(Test-Path -Path $path -PathType Leaf)) + { + return $null + } + return $path +} + +function Get-VSWhereOnline +{ + $path = Join-Path $env:TEMP 'vswhere.exe' + if ($Clean -eq $true -And (Test-Path -Path $path -PathType Leaf)) + { + Write-Verbose "Found $path. Deleting per -Clean..." + Remove-Item -Path $path -Force + } + if (-not(Test-Path -Path $path -PathType Leaf)) + { + if ($Offline -eq $true) + { + return $null + } + $vswhere_url = 'https://github.com/microsoft/vswhere/releases/download/3.1.1/vswhere.exe' + Write-Host "Downloading $vswhere from $vswhere_url..." + Write-Verbose "Executing: curl.exe --output $vswhere -L -# $vswhere_url" + $null = Start-Process curl.exe -ArgumentList "--output $vswhere -L -# $vswhere_url" -Wait -NoNewWindow -PassThru + + } + if (-not(Test-Path -Path $path -PathType Leaf)) + { + return $null + } + return $path +} + # Home of vswhere.exe: https://github.com/microsoft/vswhere $vswhere = '' $vswhere_url = '' @@ -169,32 +313,31 @@ function Get-VSWhere if ([string]::IsNullOrEmpty($global:vswhere)) { Write-Verbose "Detecting vswhere.exe..." - $vswhere = Join-Path $env:TEMP 'vswhere.exe' - if ($Clean -eq $true -And (Test-Path -Path $vswhere -PathType Leaf)) + if ($OnlineVSWhere -eq $false) { - Write-Verbose "Found $vswhere. Deleting per -Clean..." - Remove-Item -Path $vswhere -Force + $global:vswhere = Get-VSWhereOffline } - if (-not(Test-Path -Path $vswhere -PathType Leaf)) + if ([string]::IsNullOrEmpty($global:vswhere)) { - if ($Offline -eq $true) + if ($Offline -eq $false) { - Write-Host "vswhere.exe not detected" - $global:issues += 1 - return + $global:vswhere = Get-VSWhereOnline } - $vswhere_url = 'https://github.com/microsoft/vswhere/releases/download/2.8.4/vswhere.exe' - Write-Host "Downloading $vswhere from $vswhere_url..." - Write-Verbose "Executing: curl.exe --output $vswhere -L -# $vswhere_url" - $p = Start-Process curl.exe -ArgumentList "--output $vswhere -L -# $vswhere_url" -Wait -NoNewWindow -PassThru } + if ([string]::IsNullOrEmpty($global:vswhere)) + { + Write-Host "ERROR: vswhere.exe not found" -ForegroundColor Red -BackgroundColor Black + $global:issues += 1 + return $null + } + Write-Verbose "Using $vswhere" $global:vswhere = $vswhere } return $global:vswhere } -function Run-Process([string]$exe, [string]$arguments, [Ref][string]$stderr) +function Run-Process([string]$exe, [string]$arguments, [Ref][string]$stderr, [int]$throwIfExitCodeIsFailure=$false) { $pi = New-Object System.Diagnostics.ProcessStartInfo $pi.FileName = $exe @@ -212,6 +355,13 @@ function Run-Process([string]$exe, [string]$arguments, [Ref][string]$stderr) $p.WaitForExit() $stdout = $p.StandardOutput.ReadToEnd() $stderr = $p.StandardError.ReadToEnd() + if ($throwIfExitCodeIsFailure -eq $true) + { + if ($p.ExitCode -ne 0) + { + throw $p.ExitCode + } + } return $stdout } @@ -222,6 +372,10 @@ function Get-VisualStudio2022InstallPath { Write-Verbose "Detecting VisualStudio 2022..." $vswhere = Get-VSWhere + if ([string]::IsNullOrEmpty($global:vswhere)) + { + return $null + } $args = " -latest -products * -version [17.0,18.0) -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -property installationPath" Write-Verbose "Executing $vswhere $args" $path = Run-Process $vswhere $args @@ -232,14 +386,73 @@ function Get-VisualStudio2022InstallPath return $global:vspath } +function Test-VisualStudioComponent +{ + param( + [String]$component, + [String]$versionRange + ) + + $vswhere = Get-VSWhere + if ([string]::IsNullOrEmpty($global:vswhere)) + { + return 0 + } + $args = " -latest -products * -version $versionRange -requires $component -property productDisplayVersion" + Write-Verbose "Executing $vswhere $args" + try + { + $value = Run-Process $vswhere $args -throwIfExitCodeIsFailure $true + $path = $path -replace [environment]::NewLine, '' + Write-Verbose "Visual Studio component $($component) = $($value)" + return 0 + } + catch + { + $e = $_ + Write-Host "...ERROR $($e): $($component) not found or valid" -ForegroundColor Red -BackgroundColor Black + return 1 + } +} + +function Test-VisualStudioComponents +{ + Write-Verbose "Detecting VisualStudio components..." + $root = Get-ProjectRoot + $path = Join-Path $root 'docs\Coding-Guidelines' + $filename = Join-Path $path 'VisualStudio2022.vsconfig' + + $versionRange = "[17.0,18.0)" + + $json = Get-Content $filename -EA:Stop -Raw | ConvertFrom-Json + Write-Host "...Scanning $($json.components.Length) components in $($filename)" -NoNewline + $errors = 0 + $components = $json.components + ForEach ($component in $components) + { + Write-Host "." -NoNewline + $errors += (Test-VisualStudioComponent $component $versionRange) + } + if ($errors -gt 0) + { + Write-Host "" + return $false + } + Write-Host "OK" + return $true +} + function Test-VisualStudio2022Install { + $ok = $true $path = Get-VisualStudio2022InstallPath if ([string]::IsNullOrEmpty($path)) { $global:issues++ + $ok = $false } Write-Host "VisualStudio 2022...$path" + return $ok } function Test-DevTestPfx @@ -267,7 +480,7 @@ function Test-DevTestPfx return $false } - $cert = Get-ChildItem $cert_path + $cert = Get-ChildItem -Path $cert_path $expiration = $cert.NotAfter $now = Get-Date if ($expiration -lt $now) @@ -302,6 +515,7 @@ function Repair-DevTestPfx # -CertPassword is a required parameter for this work $password = '' + $password_plaintext = $null if (-not [string]::IsNullOrEmpty($CertPassword)) { $password_plaintext = $CertPassword @@ -320,7 +534,7 @@ function Repair-DevTestPfx { $password = Get-Content -Path $pwd_file -Encoding utf8 } - elseif ($NoInteractive -eq $false) + if ([string]::IsNullOrEmpty($password_plaintext) -And ($NoInteractive -eq $false)) { $password_plaintext = Read-Host -Prompt 'Creating test certificate. Please enter a password' } @@ -486,27 +700,96 @@ function Remove-DevTestCert return $true } +function Get-TAEFServiceImagePath +{ + $regkey = 'Registry::HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Te.Service' + if (-not(Test-Path -Path $regkey)) + { + return $null + } + + $path = Get-ItemProperty -Path $regkey | Select-Object 'ImagePath' + $path.ImagePath +} + +function Test-TAEFServiceVersion +{ + $path = Get-TAEFServiceImagePath + if ([string]::IsNullOrEmpty($path)) + { + return $null + } + if (-not($path -imatch '^.*Microsoft.Taef[\.](.+?)\\')) + { + return $null + } + $actual_taef_version = $Matches[1] + + $expected_taef_version = Get-TAEFPackageVersion + + $cmp = Test-SemVer $actual_taef_version $expected_taef_version + + if ($cmp -lt 0) + { + Write-Warning "WARNING: TAEF service older than the expected version (expected=$expected_taef_version, actual=$actual_taef_version)" + return 'OlderVersion' + } + elseif ($cmp -gt 0) + { + Write-Warning "WARNING: TAEF service newer than the expected version (expected=$expected_taef_version, actual=$actual_taef_version)" + return 'NewerVersion' + } + else + { + Write-Verbose "Expected TAEF service is registered ($actual_taef_version)" + return 'OK' + } +} + function Test-TAEFService { + $taef_version_status = Test-TAEFServiceVersion + if ([string]::IsNullOrEmpty($taef_version_status)) + { + Write-Host "TAEF service...Not Installed" + return 'NotFound' + } + + # Double-check the TAEF service is known as a service as far as Windows is concerned $service = Get-Service |Where-Object {$_.Name -eq "TE.Service"} if ([string]::IsNullOrEmpty($service)) { Write-Host "TAEF service...Not Installed" return 'NotFound' } - elseif ($service.Status -ne "Running") + + if ($service.Status -ne "Running") { Write-Host "TAEF service...Not running ($service.Status)" - return 'NotRunning' + if ($taef_version_status -eq 'OlderVersion') + { + return 'NotRunning-OlderVersion' + } + else + { + return 'NotRunning' + } } else { Write-Host "TAEF service...Running" - return 'Running' + if ($taef_version_status -eq 'OlderVersion') + { + return 'Running-OlderVersion' + } + else + { + return 'Running' + } } } -function Repair-TAEFService +function Install-TAEFService { $isadmin = Get-IsAdmin if ($isadmin -eq $false) @@ -518,7 +801,8 @@ function Repair-TAEFService $root = Get-ProjectRoot $cpu = Get-CpuArchitecture - $taef = 'Microsoft.Taef.10.75.221207001' + $taef_version = Get-TAEFPackageVersion + $taef = "Microsoft.Taef.$($taef_version)" $path = "$root\packages\$taef\build\Binaries\$cpu\Wex.Services.exe" if (-not(Test-Path -Path $path -PathType Leaf)) { @@ -543,6 +827,39 @@ function Repair-TAEFService } } +function Uninstall-TAEFService +{ + $isadmin = Get-IsAdmin + if ($isadmin -eq $false) + { + Write-Host "Uninstall TAEF service...Access Denied. Run from an admin prompt" + $global:issues += 1 + return + } + + $ok = Stop-TAEFService + if ($ok -ne $true) + { + return $ok + } + + $filename = Get-TAEFServiceImagePath + $args = '/remove:TE.Service' + $output = Run-Process $filename $args + $service = Get-Service |Where-Object {$_.Name -eq "TE.Service"} + if (-not([string]::IsNullOrEmpty($service))) + { + Write-Host "Uninstall TAEF service...Failed" + $global:issues += 1 + return 'UninstallError' + } + else + { + Write-Host "Uninstall TAEF service...OK" + return 'NotRunning' + } +} + function Start-TAEFService { $isadmin = Get-IsAdmin @@ -567,6 +884,402 @@ function Start-TAEFService } } +function Stop-TAEFService +{ + $isadmin = Get-IsAdmin + if ($isadmin -eq $false) + { + Write-Host "Stop TAEF service...Access Denied. Run from an admin prompt" + $global:issues += 1 + return $false + } + + $service = Get-Service |Where-Object {$_.Name -eq "TE.Service"} + if ($service -eq $null) + { + return 'NotFound' + } + elseif ($service.Status -ne "Stopped") + { + $ok = Stop-Service 'TE.Service' + } + $service = Get-Service |Where-Object {$_.Name -eq "TE.Service"} + if ($service -eq $null) + { + return 'NotFound' + } + elseif ($service.Status -ne "Stopped") + { + Write-Host "Stop TAEF service...Failed" + $global:issues += 1 + return $false + } + else + { + Write-Host "Stop TAEF service...OK" + return $true + } +} + +function Get-DependencyVersions +{ + # Dependencies are defined in Version.Details.xml + # - Automagically updated by Maestro + # Dependencies are defined in Version.Dependencies.xml + # - Manually updated by human beings + # Return the pair of lists + $dependencies = @{ Automagic=$null; Manual=$null } + + $root = Get-ProjectRoot + $path = Join-Path $root 'eng' + + # Parse the Version.Details.xml dependencies + $versionDetailsFileName = Join-Path $path 'Version.Details.xml' + Write-Host "Reading $($versionDetailsFileName)..." + $automagicXml = [xml](Get-Content $versionDetailsFileName -EA:Stop) + $automagicVersions = [ordered]@{} + ForEach ($dependency in $automagicXml.SelectNodes("/Dependencies/ProductDependencies/Dependency")) + { + $name = $dependency.Name + $version = $dependency.Version + $automagicVersions.Add($name, $version) + } + ForEach ($dependency in $automagicXml.SelectNodes("/Dependencies/ToolsetDependencies/Dependency")) + { + $name = $dependency.Name + $version = $dependency.Version + $automagicVersions.Add($name, $version) + } + $dependencies.Automagic = $automagicVersions + + # Parse The Version.Dependencies.xml dependencies + $versionDependenciesFileName = Join-Path $path 'Version.Dependencies.xml' + Write-Host "Reading $($versionDependenciesFileName)..." + $manualXml = [xml](Get-Content $versionDependenciesFileName -EA:Stop) + # Parse the Version.Dependencies.xml dependencies + $manualVersions = [ordered]@{} + ForEach ($dependency in $manualXml.SelectNodes("/Dependencies/Dependency")) + { + $name = $dependency.Name + $version = $dependency.Version + $manualVersions.Add($name, $version) + } + $dependencies.Manual = $manualVersions + + if ($Verbose -eq $true) + { + ForEach ($list in @($dependencies.AutoMagic, $dependencies.Manual)) + { + ForEach ($name in $list.Keys) + { + Write-Verbose "...$($name) = $($list[$name])" + } + } + } + + return $dependencies +} + +function Test-PackagesConfig +{ + param( + [string] $filename, + $versions + ) + + Write-Verbose "Scanning $filename" + $xml = [xml](Get-Content $filename -EA:Stop) + $changed = $false + ForEach ($package in $xml.packages.package) + { + $name = $package.id + $version = $package.version + + if (-not($versions.Contains($name))) + { + Write-Host "ERROR: Unknown package $name in $filename" -ForegroundColor Red -BackgroundColor Black + $global:issues++ + } + elseif ($version -ne $versions[$name]) + { + if ($SyncDependencies -eq $true) + { + Write-Host "Updating $name $($version) -> $($versions[$name]) in $filename" + $package.version = $versions[$name] + $changed = $true + } + else + { + Write-Host "ERROR: Unknown version $name=$version in $filename" -ForegroundColor Red -BackgroundColor Black + $global:issues++ + } + } + + if (-not($package.HasAttribute("targetFramework"))) + { + Write-Host "ERROR: targetFramework=""native"" missing in $filename" -ForegroundColor Red -BackgroundColor Black + $global:issues++ + } + else + { + $targetFramework = $package.targetFramework + if (($targetFramework -ne "native") -And ($targetFramework -ne "net45")) + { + Write-Host "ERROR: targetFramework != ""native"" in $filename" -ForegroundColor Red -BackgroundColor Black + $global:issues++ + } + } + + } + + if ($changed -eq $true) + { + $xml.Save($filename) + + # Save() doesn't add a newline at the end-of-file + # No newline at end-of-file makes git, GitHub diff and other tools cranky + # Make sure they're not cranky + $content = Get-Content $filename -EA:Stop -Encoding utf8 + Set-Content -Path $filename -Value $content -Force -Encoding utf8 + } +} + +function Test-VcxProj +{ + param( + [string] $filename, + $versions + ) + + Write-Verbose "Scanning $filename" + $xml = [xml](Get-Content $filename -EA:Stop) + $changed = $false + ForEach ($package in $xml.project.import.project) + { + Write-Verbose "TODO scan packages/dependencies in .vcxproj" + } +} + +function Build-Dependencies +{ + param( + [HashTable]$in + ) + + $automagic = $in["Automagic"] + $manual = $in["Manual"] + + $output = @" + + + + + `$(MSBuildThisFileDirectory)Version.Details.xml + `$([System.IO.File]::ReadAllText(`"`$(VersionDetailsXmlFilename)`")) + `$(MSBuildThisFileDirectory)Version.Dependencies.xml + `$([System.IO.File]::ReadAllText("`$(VersionDependenciesXmlFilename)")) + +"@ + + $output = $output + " `r`n" + $lines = @{} + ForEach ($name in $automagic.Keys) + { + # NOTE: Create macros per name.Replace(".","").Append("PackageVersion")=value + $macro = $name.Replace(".","") + "PackageVersion" + $value = $automagic[$name] + $lines.Add(" <$($macro)>`$([System.Text.RegularExpressions.Regex]::Match(`$(VersionDetailsXml), 'Name=`"$($name)`"\s+Version=`"(.*?)`"').Groups[1].Value)`r`n", $null) + + } + $sortedLines = $lines.Keys | Sort-Object + $output = $output + [String]::Join("", $sortedLines) + + $output = $output + "`r`n" + $output = $output + " `r`n" + $lines = @{} + ForEach ($name in $manual.Keys) + { + # NOTE: Create macros per name.Replace(".","").Append("Version")=value + $macro = $name.Replace(".","") + "Version" + $value = $manual[$name] + $lines.Add(" <$($macro)>`$([System.Text.RegularExpressions.Regex]::Match(`$(VersionDependenciesXml), 'Name=`"$($name)`"\s+Version=`"(.*?)`"').Groups[1].Value)`r`n", $null) + } + $sortedLines = $lines.Keys | Sort-Object + $output = $output + [String]::Join("", $sortedLines) + + $output = $output + @" + +"@ + + $output = $output + @" + + +"@ + + return $output +} + +function CheckAndSync-Dependencies +{ + param( + [HashTable]$in + ) + + $automagic = $in["Automagic"] + $manual = $in["Manual"] + + $expected = Build-Dependencies @{ Automagic=$automagic; Manual=$manual } + + $root = Get-ProjectRoot + $path = Join-Path $root 'eng' + $filename = Join-Path $path 'Version.Dependencies.props' + Write-Host "Reading $($filename)..." + if (-not(Test-Path -Path $filename -PathType Leaf)) + { + if ($SyncDependencies -eq $false) + { + Write-Host "ERROR: $filename not found. Create with 'DevCheck -SyncDependencies'" -ForegroundColor Red -BackgroundColor Black + $global:issues++ + return + } + } + else + { + $content = Get-Content $filename -EA:Stop -Raw + if ($content.TrimEnd() -eq $expected.TrimEnd()) # Ignore trailing whitespace + { + Write-Host "Verify $($filename)...OK" + return + } + elseif ($SyncDependencies -eq $false) + { + Write-Host "ERROR: $($filename) out of date. Update with 'DevCheck -SyncDependencies'" -ForegroundColor Red -BackgroundColor Black + $global:issues++ + } + } + + if ($SyncDependencies -eq $true) + { + Write-Host "Updating $($filename)..." + Set-Content -Path $filename -Value $expected -Force + } +} + +function Test-Dependencies +{ + # Get version information for dependencies + $fatal_errors = 0 + $dependencies = Get-DependencyVersions + if ([string]::IsNullOrEmpty($dependencies)) + { + $global:issues++ + $fatal_errors++ + } + $automagic = $dependencies.Automagic + $manual = $dependencies.Manual + if ([string]::IsNullOrEmpty($automagic)) + { + $global:issues++ + $fatal_errors++ + } + + # Merge the lists + $versions = [ordered]@{} + ForEach ($name in $automagic.Keys) + { + if ($versions.Contains($name)) + { + Write-Host "ERROR: Dependency defined multiple times ($name)" -ForegroundColor Red -BackgroundColor Black + $global:issues++ + $fatal_errors++ + } + else + { + $value = $automagic[$name] + $versions.Add($name, $value) + } + } + ForEach ($name in $manual.Keys) + { + if ($versions.Contains($name)) + { + Write-Host "ERROR: Dependency defined multiple times ($name)" -ForegroundColor Red -BackgroundColor Black + $global:issues++ + $fatal_errors++ + } + else + { + $value = $manual[$name] + $versions.Add($name, $value) + } + } + Write-Host "$($versions.Count) dependencies detected" + + # Fatal errors detected? + if ($fatal_errors++ -gt 0) + { + return + } + + # Check Version.Dependencies.props + $null = CheckAndSync-Dependencies @{ Automagic=$automagic; Manual=$manual } + + # Scan for references - packages.config + $root = Get-ProjectRoot + $files = 0 + ForEach ($subtree in 'dev', 'test', 'installer', 'tools') + { + $path = Join-Path $root $subtree + Write-Host "Scanning packages.config..." + ForEach ($file in (Get-ChildItem -Path $path -Recurse -File 'packages.config')) + { + $null = Test-PackagesConfig $file.FullName $versions + $files++ + } + } + Write-Host "Scanned $($files) packages.config" + + $files = 0 + ForEach ($subtree in 'dev', 'test', 'installer', 'tools') + { + $path = Join-Path $root $subtree + Write-Host "Scanning *.vcxproj..." + ForEach ($file in (Get-ChildItem -Path $path -Recurse -File '*.vcxproj')) + { + $null = Test-VcxProj $file.FullName $versions + $files++ + } + } + Write-Host "Scanned $($files) *.vcxproj" +} + +function Get-DeveloperMode +{ + $regkey = 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\AppModelUnlock' + if (Test-Path -Path $regkey -PathType Container) + { + $value = Get-ItemProperty -Path $regkey -Name AllowDevelopmentWithoutDevLicense + return $value.AllowDevelopmentWithoutDevLicense -eq 1 + } + + return $false +} + +function Test-DeveloperMode +{ + $developermode = Get-DeveloperMode + if ($developermode -eq $true) + { + Write-Host "Developer mode...Enabled" + } + else + { + Write-Host "ERROR: Developer mode is not enabled. Enable it via Settings" -ForegroundColor Red -BackgroundColor Black + $global:issues++ + $fatal_errors++ + } +} + Write-Output "Checking developer environment..." $cpu = Get-CpuArchitecture @@ -577,7 +1290,11 @@ Write-Output "Windows App SDK location...$project_root" if (($CheckAll -ne $false) -Or ($CheckVisualStudio -ne $false)) { - Test-VisualStudio2022Install + $ok = Test-VisualStudio2022Install + if ($ok -eq $true) + { + $null = Test-VisualStudioComponents + } } if (($CheckAll -ne $false) -Or ($CheckTestPfx -ne $false)) @@ -599,7 +1316,7 @@ if (($CheckAll -ne $false) -Or ($CheckTestCert -ne $false)) $test = Test-DevTestCert if ($test -ne $true) { - Repair-DevTestCert + $null = Repair-DevTestCert } } @@ -608,22 +1325,61 @@ if (($CheckAll -ne $false) -Or ($CheckTAEFService -ne $false)) $test = Test-TAEFService if ($test -eq 'NotFound') { - $test = Repair-TAEFService + $test = Install-TAEFService + } + elseif ($test -eq 'NotRunning-OlderVersion') + { + $test = Uninstall-TAEFService + $test = Install-TAEFService + $test = Start-TAEFService } - if ($test -eq 'NotRunning') + elseif ($test -eq 'NotRunning') { $test = Start-TAEFService } + elseif ($test -eq 'Running-OlderVersion') + { + $test = Stop-TAEFService + if ($test -ne $false) + { + if ($test -eq $true) + { + $test = Uninstall-TAEFService + } + $test = Install-TAEFService + $test = Start-TAEFService + } + } +} + +if (($CheckAll -ne $false) -Or ($CheckDependencies -ne $false)) +{ + $null = Test-Dependencies +} + +if (($CheckAll -ne $false) -Or ($CheckDeveloperMode -ne $false)) +{ + $null = Test-DeveloperMode +} + +if ($StartTAEFService -eq $true) +{ + $null = Start-TAEFService +} + +if ($StopTAEFService -eq $true) +{ + $null = Stop-TAEFService } if (($RemoveAll -ne $false) -Or ($RemoveTestCert -ne $false)) { - $test = Remove-DevTestCert + $null = Remove-DevTestCert } if (($RemoveAll -ne $false) -Or ($RemoveTestPfx -ne $false)) { - $test = Remove-DevTestPfx + $null = Remove-DevTestPfx } if ($global:issues -eq 0) diff --git a/eng/common/Scripts/MaestroHelpers.ps1 b/eng/common/Scripts/MaestroHelpers.ps1 index 71633d9ce9..630ba2a1f4 100644 --- a/eng/common/Scripts/MaestroHelpers.ps1 +++ b/eng/common/Scripts/MaestroHelpers.ps1 @@ -53,7 +53,7 @@ function ConvertToMaestroFriendlyAzureDevOpUri([string]$buildRepositoryUri) function IsGitHubRepo([string]$buildRepositoryUri) { - $githubUrls = @("https://github.com", "https://wwww.github.com") + $githubUrls = @("https://github.com", "https://www.github.com") for ($i = 0; $i -le ($githubUrls.length); $i += 1) { if ($buildRepositoryUri.length -ge $githubUrls[$i].length) diff --git a/eng/common/nuget.config b/eng/common/nuget.config index 6b5cfbb5cd..71c3921118 100644 --- a/eng/common/nuget.config +++ b/eng/common/nuget.config @@ -15,7 +15,4 @@ - - - diff --git a/global.json b/global.json index 6d4b68dc04..5f61a9c04d 100644 --- a/global.json +++ b/global.json @@ -1,8 +1,8 @@ { "tools": { - "dotnet": "6.0.104" + "dotnet": "6.0.414" }, "msbuild-sdks": { - "Microsoft.WinAppSDK.EngCommon": "1.3.230216" + "Microsoft.WinAppSDK.EngCommon": "1.5.230711" } } diff --git a/installer/dev/InstallActivityContext.cpp b/installer/dev/InstallActivityContext.cpp index 6d0c8bdcd9..567098b528 100644 --- a/installer/dev/InstallActivityContext.cpp +++ b/installer/dev/InstallActivityContext.cpp @@ -1,4 +1,4 @@ -// Copyright (c) Microsoft Corporation and Contributors. +// Copyright (c) Microsoft Corporation and Contributors. // Licensed under the MIT License. #include "pch.h" @@ -65,7 +65,7 @@ BOOL WindowsAppRuntimeInstaller::InstallActivity::Context::LogInstallerCommandLi WCHAR message[1024]{}; PCWSTR messageFormat{ L"Windows App Runtime Installer (ActivityId: %s) is called with Command Line Args: %s" }; auto installerActivityId{ winrt::to_hstring(*m_activity.Id()) }; - FAIL_FAST_IF_FAILED(StringCchPrintfW(message, ARRAYSIZE(message), messageFormat, installerActivityId, cmdlineArgs)); + FAIL_FAST_IF_FAILED(StringCchPrintfW(message, ARRAYSIZE(message), messageFormat, installerActivityId.data(), cmdlineArgs)); PCWSTR messageStrings[1]{ message }; return ReportEventW(m_hEventLog, EVENTLOG_INFORMATION_TYPE, 0, eventId, nullptr, ARRAYSIZE(messageStrings), 0, messageStrings, nullptr); } @@ -76,8 +76,6 @@ BOOL WindowsAppRuntimeInstaller::InstallActivity::Context::LogInstallerFailureEv { if (m_hEventLog) { - std::wstring customMessage{}; - switch (m_installStage) { case InstallStage::None: @@ -98,15 +96,15 @@ BOOL WindowsAppRuntimeInstaller::InstallActivity::Context::LogInstallerFailureEv case InstallStage::AddPackage: { WCHAR customMessage[1024]{}; - auto deploymentActivityId{ winrt::to_hstring(*m_activity.Id()) }; + auto deploymentErrorActivityId{ winrt::to_hstring(m_deploymentErrorActivityId) }; auto customMessageFormat{ L"Installing Package %s with DeploymentExtendedError: 0x%08X, DeploymentExtendedText:%s, DeploymentActivityId: %s" }; FAIL_FAST_IF_FAILED(StringCchPrintfW(customMessage, ARRAYSIZE(customMessage), customMessageFormat, - m_currentResourceId, + m_currentResourceId.c_str(), m_deploymentErrorExtendedHresult, - m_deploymentErrorText, - m_deploymentErrorActivityId)); + m_deploymentErrorText.c_str(), + deploymentErrorActivityId.data())); THROW_IF_WIN32_BOOL_FALSE(LogInstallerFailureEventWithResourceId(EVENTLOG_ERROR_TYPE, hresult, customMessage)); break; } @@ -125,22 +123,22 @@ BOOL WindowsAppRuntimeInstaller::InstallActivity::Context::LogInstallerFailureEv WCHAR customProvisionMessage[1024]{}; auto provisionActivityId{ winrt::to_hstring(*m_activity.Id()) }; auto customProvisionMessageFormat{ L"Provisioning Package %s (Activity Id:%s)" }; - FAIL_FAST_IF_FAILED(StringCchPrintfW(customProvisionMessage, ARRAYSIZE(customProvisionMessage), customProvisionMessageFormat, provisionActivityId)); + FAIL_FAST_IF_FAILED(StringCchPrintfW(customProvisionMessage, ARRAYSIZE(customProvisionMessage), customProvisionMessageFormat, m_currentResourceId.c_str(), provisionActivityId.data())); THROW_IF_WIN32_BOOL_FALSE(LogInstallerFailureEventWithResourceId(EVENTLOG_WARNING_TYPE, hresult, customProvisionMessage)); break; } case InstallStage::StagePackage: { WCHAR customMessage[1024]{}; - auto deploymentActivityId{ winrt::to_hstring(*m_activity.Id()) }; + auto deploymentErrorActivityId{ winrt::to_hstring(m_deploymentErrorActivityId) }; auto customMessageFormat{ L"Staging Package %s with DeploymentExtendedError: 0x%08X, DeploymentExtendedText:%s, DeploymentActivityId: %s" }; FAIL_FAST_IF_FAILED(StringCchPrintfW(customMessage, ARRAYSIZE(customMessage), customMessageFormat, - m_currentResourceId, + m_currentResourceId.c_str(), m_deploymentErrorExtendedHresult, - m_deploymentErrorText, - m_deploymentErrorActivityId)); + m_deploymentErrorText.c_str(), + deploymentErrorActivityId.data())); THROW_IF_WIN32_BOOL_FALSE(LogInstallerFailureEventWithResourceId(EVENTLOG_ERROR_TYPE, hresult, customMessage)); break; } @@ -166,7 +164,7 @@ BOOL WindowsAppRuntimeInstaller::InstallActivity::Context::LogInstallerFailureEv WCHAR message[1024]{}; PCWSTR messageFormat{ L"Error 0x%08X: Windows App Runtime Installer (Activity ID: %s) failed in %s" }; auto installerActivityId{ winrt::to_hstring(*m_activity.Id()) }; - FAIL_FAST_IF_FAILED(StringCchPrintfW(message, ARRAYSIZE(message), messageFormat, hresult, installerActivityId, (resourceId ? failedComponentMessage : failedComponentMessageFormat))); + FAIL_FAST_IF_FAILED(StringCchPrintfW(message, ARRAYSIZE(message), messageFormat, hresult, installerActivityId.data(), (resourceId ? failedComponentMessage : failedComponentMessageFormat))); PCWSTR messageStrings[1]{ message }; return ReportEventW(m_hEventLog, eventLogType, 0, eventId, nullptr, ARRAYSIZE(messageStrings), 0, messageStrings, nullptr); diff --git a/installer/dev/InstallActivityContext.h b/installer/dev/InstallActivityContext.h index f002a15563..0211670d99 100644 --- a/installer/dev/InstallActivityContext.h +++ b/installer/dev/InstallActivityContext.h @@ -1,4 +1,4 @@ -// Copyright (c) Microsoft Corporation and Contributors. +// Copyright (c) Microsoft Corporation and Contributors. // Licensed under the MIT License. #pragma once @@ -137,7 +137,7 @@ namespace WindowsAppRuntimeInstaller::InstallActivity return m_hEventLog; } - const BOOL& DeregisterInstallerEventSourceW() + const BOOL DeregisterInstallerEventSourceW() { return DeregisterEventSource(m_hEventLog); } diff --git a/installer/dev/WindowsAppRuntimeInstall.rc b/installer/dev/WindowsAppRuntimeInstall.rc index a36d068518..c4c2791cee 100644 --- a/installer/dev/WindowsAppRuntimeInstall.rc +++ b/installer/dev/WindowsAppRuntimeInstall.rc @@ -117,3 +117,8 @@ END ///////////////////////////////////////////////////////////////////////////// #endif // not APSTUDIO_INVOKED +#include + +#define VERSIONINFO_FILENAME "WindowsAppRuntimeInstall.exe" +#define VERSIONINFO_FILETYPE VFT_APP +#include "eng\common\VersionInfo\AssemblyInfo.ver" diff --git a/installer/dev/WindowsAppRuntimeInstall.vcxproj b/installer/dev/WindowsAppRuntimeInstall.vcxproj index 43b4a65db3..e45fcd3fe5 100644 --- a/installer/dev/WindowsAppRuntimeInstall.vcxproj +++ b/installer/dev/WindowsAppRuntimeInstall.vcxproj @@ -159,6 +159,7 @@ USE_DEFINITIONS_OVERRIDE_HEADER;%(PreprocessorDefinitions) + $(RepoRoot);%(AdditionalIncludeDirectories) diff --git a/installer/dev/WindowsAppSDK-VersionInfo.h b/installer/dev/WindowsAppSDK-VersionInfo.h new file mode 100644 index 0000000000..72f0772710 --- /dev/null +++ b/installer/dev/WindowsAppSDK-VersionInfo.h @@ -0,0 +1,7 @@ +// Copyright (c) Microsoft Corporation and Contributors. +// Licensed under the MIT License. +// +// This file is a PLACEHOLDER which will be replaced in the CreateInstaller +// build pipeline with a file which defines WINDOWSAPPSDK_RELEASE_MAJOR +// and WINDOWSAPPSDK_RELEASE_MINOR. For the dev inner loop, these will remain +// undefined and just version the installer as 0.0. diff --git a/installer/dev/install.cpp b/installer/dev/install.cpp index ef5dc4e42a..6f2ab7555c 100644 --- a/installer/dev/install.cpp +++ b/installer/dev/install.cpp @@ -1,4 +1,4 @@ -// Copyright (c) Microsoft Corporation and Contributors. +// Copyright (c) Microsoft Corporation and Contributors. // Licensed under the MIT License. #include "pch.h" @@ -35,6 +35,8 @@ namespace WindowsAppRuntimeInstaller RETURN_HR(static_cast(deploymentResult.ExtendedErrorCode() ? deploymentResult.ExtendedErrorCode() : deploymentOperation.ErrorCode())); } + + return S_OK; } HRESULT RegisterPackage( @@ -56,7 +58,7 @@ namespace WindowsAppRuntimeInstaller HRESULT AddPackage( WindowsAppRuntimeInstaller::InstallActivity::Context& installActivityContext, const Uri& packageUri, - const std::unique_ptr& packageProperties, + const std::unique_ptr&, bool forceDeployment) { const auto deploymentOptions{ forceDeployment ? diff --git a/installer/dev/packages.config b/installer/dev/packages.config index 2305cb7181..9ba3aa91dd 100644 --- a/installer/dev/packages.config +++ b/installer/dev/packages.config @@ -1,5 +1,5 @@  - + diff --git a/installer/test/InstallerFunctionalTests/packages.config b/installer/test/InstallerFunctionalTests/packages.config index 9b3e6252ff..1117ac430f 100644 --- a/installer/test/InstallerFunctionalTests/packages.config +++ b/installer/test/InstallerFunctionalTests/packages.config @@ -1,6 +1,6 @@  - - + + diff --git a/test/AccessControlTests/packages.config b/test/AccessControlTests/packages.config index c47d0469a5..3313efc9ef 100644 --- a/test/AccessControlTests/packages.config +++ b/test/AccessControlTests/packages.config @@ -1,5 +1,5 @@  - - + + diff --git a/test/AppLifecycle/packages.config b/test/AppLifecycle/packages.config index 9b3e6252ff..1117ac430f 100644 --- a/test/AppLifecycle/packages.config +++ b/test/AppLifecycle/packages.config @@ -1,6 +1,6 @@  - - + + diff --git a/test/AppNotificationBuilderTests/packages.config b/test/AppNotificationBuilderTests/packages.config index 9b3e6252ff..1117ac430f 100644 --- a/test/AppNotificationBuilderTests/packages.config +++ b/test/AppNotificationBuilderTests/packages.config @@ -1,6 +1,6 @@  - - + + diff --git a/test/AppNotificationTests/packages.config b/test/AppNotificationTests/packages.config index 9b3e6252ff..1117ac430f 100644 --- a/test/AppNotificationTests/packages.config +++ b/test/AppNotificationTests/packages.config @@ -1,6 +1,6 @@  - - + + diff --git a/test/Common/packages.config b/test/Common/packages.config index 9b3e6252ff..1117ac430f 100644 --- a/test/Common/packages.config +++ b/test/Common/packages.config @@ -1,6 +1,6 @@  - - + + diff --git a/test/Deployment/API/packages.config b/test/Deployment/API/packages.config index 9b3e6252ff..1117ac430f 100644 --- a/test/Deployment/API/packages.config +++ b/test/Deployment/API/packages.config @@ -1,6 +1,6 @@  - - + + diff --git a/test/Deployment/Test_DeploymentManagerAutoInitialize/CPP/Test_DeploymentManagerAutoInitialize_CPP_Default/packages.config b/test/Deployment/Test_DeploymentManagerAutoInitialize/CPP/Test_DeploymentManagerAutoInitialize_CPP_Default/packages.config index 2305cb7181..9ba3aa91dd 100644 --- a/test/Deployment/Test_DeploymentManagerAutoInitialize/CPP/Test_DeploymentManagerAutoInitialize_CPP_Default/packages.config +++ b/test/Deployment/Test_DeploymentManagerAutoInitialize/CPP/Test_DeploymentManagerAutoInitialize_CPP_Default/packages.config @@ -1,5 +1,5 @@  - + diff --git a/test/Deployment/Test_DeploymentManagerAutoInitialize/CPP/Test_DeploymentManagerAutoInitialize_CPP_Options_Default/packages.config b/test/Deployment/Test_DeploymentManagerAutoInitialize/CPP/Test_DeploymentManagerAutoInitialize_CPP_Options_Default/packages.config index 2305cb7181..9ba3aa91dd 100644 --- a/test/Deployment/Test_DeploymentManagerAutoInitialize/CPP/Test_DeploymentManagerAutoInitialize_CPP_Options_Default/packages.config +++ b/test/Deployment/Test_DeploymentManagerAutoInitialize/CPP/Test_DeploymentManagerAutoInitialize_CPP_Options_Default/packages.config @@ -1,5 +1,5 @@  - + diff --git a/test/Deployment/Test_DeploymentManagerAutoInitialize/CPP/Test_DeploymentManagerAutoInitialize_CPP_Options_Defined/packages.config b/test/Deployment/Test_DeploymentManagerAutoInitialize/CPP/Test_DeploymentManagerAutoInitialize_CPP_Options_Defined/packages.config index 2305cb7181..9ba3aa91dd 100644 --- a/test/Deployment/Test_DeploymentManagerAutoInitialize/CPP/Test_DeploymentManagerAutoInitialize_CPP_Options_Defined/packages.config +++ b/test/Deployment/Test_DeploymentManagerAutoInitialize/CPP/Test_DeploymentManagerAutoInitialize_CPP_Options_Defined/packages.config @@ -1,5 +1,5 @@  - + diff --git a/test/Deployment/Test_DeploymentManagerAutoInitialize/CPP/Test_DeploymentManagerAutoInitialize_CPP_Options_None/packages.config b/test/Deployment/Test_DeploymentManagerAutoInitialize/CPP/Test_DeploymentManagerAutoInitialize_CPP_Options_None/packages.config index 2305cb7181..9ba3aa91dd 100644 --- a/test/Deployment/Test_DeploymentManagerAutoInitialize/CPP/Test_DeploymentManagerAutoInitialize_CPP_Options_None/packages.config +++ b/test/Deployment/Test_DeploymentManagerAutoInitialize/CPP/Test_DeploymentManagerAutoInitialize_CPP_Options_None/packages.config @@ -1,5 +1,5 @@  - + diff --git a/test/DynamicDependency/Powershell/DynamicDependency_Powershell.testdef b/test/DynamicDependency/Powershell/DynamicDependency_Powershell.testdef new file mode 100644 index 0000000000..2ab636be0b --- /dev/null +++ b/test/DynamicDependency/Powershell/DynamicDependency_Powershell.testdef @@ -0,0 +1,20 @@ +{ + "Tests": [ + { + "Description": "Dynamic Dependencies Powershell API (x86 not currently enabled)", + "Type": "Powershell", + "Filename": "Test-MsixDynamicDependency.Tests.ps1", + "Parameters": "", + "Architectures": ["x64", "arm64"], + "Status": "Enabled" + }, + { + "Description": "Dynamic Dependencies Powershell cmdlets (x86 not currently enabled)", + "Type": "Powershell", + "Filename": "Test-PackageDependency.Tests.ps1", + "Parameters": "", + "Architectures": ["x64", "arm64"], + "Status": "Enabled" + } + ] +} diff --git a/test/DynamicDependency/Powershell/Test-MsixDynamicDependency.Tests.ps1 b/test/DynamicDependency/Powershell/Test-MsixDynamicDependency.Tests.ps1 new file mode 100644 index 0000000000..62b35b9b6d --- /dev/null +++ b/test/DynamicDependency/Powershell/Test-MsixDynamicDependency.Tests.ps1 @@ -0,0 +1,325 @@ +# Copyright (c) Microsoft Corporation and Contributors. +# Licensed under the MIT License. + +# Test Framework is Pester => https://pester.dev/docs/quick-start +# NOTE: Powershell 5.1.22621.1778 includes module Pester version 3.4.0 +# NOTE: Powershell 7.3.6 includes module Pester version version 3.4.0 + +Set-StrictMode -Version 3.0 + +$ErrorActionPreference = "Stop" + +# Errors +$E_INVALIDARG = 0x80070057 + +# Repository paths +$root = (Get-Item $PSScriptRoot).parent.parent.parent.FullName +$dev = Join-Path $root 'dev' +$test = Join-Path $root 'test' +$buildOutput = Join-Path $root 'BuildOutput\Debug\x64' + +# Test package(s) +$packageName = 'WindowsAppRuntime.Test.DynDep.Fwk.Widgets' +$packageFamilyName = 'WindowsAppRuntime.Test.DynDep.Fwk.Widgets_8wekyb3d8bbwe' +$packageFullName = 'WindowsAppRuntime.Test.DynDep.Fwk.Widgets_1.2.3.4_neutral__8wekyb3d8bbwe' +$packageMsixDir = 'Framework.Widgets' +$packageMsixFilename = 'Framework.Widgets.msix' +$packageMsixPath = Join-Path $buildOutput $packageMsixDir +$packageMsix = Join-Path $packageMsixPath $packageMsixFilename + +# Track resources to ensure we clean up +$packageDependencyIds = [ordered]@{} +$packageDependencyContexts = [ordered]@{} + +Function LogComment +{ + param([string]$message) + + " $message" | Write-Host +} + +Function Trace +{ + param([string]$message) + + Write-Host $message -ForegroundColor Magenta +} + +Function TraceEnter +{ + param([string]$message) + + Trace " Test: $message" +} + +Function RemoveTestPackages +{ + Write-Host "Removing $packageName..." -ForegroundColor Cyan + + # Remove our package(s) in case they were previously installed and incompletely removed + Get-AppxPackage $packageName | Remove-AppxPackage + $p = Get-AppxPackage $packageName + if ($p -ne $null) + { + Write-Error $p + Write-Error "Remove/Get-AppxPackage result not expected" + Exit 1 + } +} + +Function AddTestPackages +{ + Write-Host "Adding $packageMsix..." -ForegroundColor Cyan + + # Install our needed package(s) + if (-not(Test-Path -Path $packageMsix -PathType Leaf)) + { + Write-Error "$($packageMsix) not found" + Exit 1 + } + Add-AppxPackage $packageMsix + $p = Get-AppxPackage $packageName + if ($p -eq $null) + { + Write-Error $p + Write-Error "Get-AppxPackage result not expected" + Exit 1 + } + if ($p.PackageFullName -ne $packageFullName) + { + Write-Error "$p.PackageFullName not expected (expected=$packageFullName)" + Exit 1 + } +} + +Function CleanupPackageDependencies +{ + if ($packageDependencyContexts.Count -gt 0) + { + Write-Host "Cleanup: Releasing $packageDependencyContexts.Count PackageDependency Contexts" -ForegroundColor Cyan + ForEach ($pdc in $packageDependencyContexts.Keys) + { + if ([string]::IsNullOrEmpty($pdc)) + { + continue + } + $hr = [Microsoft.Windows.ApplicationModel.DynamicDependency.PackageDependency]::Remove($pdc) + LogComment "Delete($pdc): 0x$($hr.ToString("X"))" + } + } + + if ($packageDependencyIds.Count -gt 0) + { + Write-Host "Cleanup: Releasing $packageDependencyIds.Count PackageDependency Ids" -ForegroundColor Cyan + ForEach ($pdid in $packageDependencyIds.Keys) + { + if ([string]::IsNullOrEmpty($pdid)) + { + continue + } + $hr = [Microsoft.Windows.ApplicationModel.DynamicDependency.PackageDependency]::Delete($pdid) + LogComment "Delete($pdid): 0x$($hr.ToString("X"))" + } + } +} + +Describe "DynamicDependency API" { + + BeforeAll { + Trace "BeforeAll" + + # Import the MSIX Dynamic Dependency module + $module = Join-Path $dev 'DynamicDependency\Powershell\MsixDynamicDependency.psm1' + Import-Module -Name $module -Verbose:$true -ErrorAction Stop + + RemoveTestPackages + AddTestPackages + } + + AfterAll { + Trace "AfterAll" + + CleanupPackageDependencies + RemoveTestPackages + } + + It "Get RevisionId (expect 0)" { + TraceEnter "Get RevisionId (expect 0)" + + $rid = [Microsoft.Windows.ApplicationModel.DynamicDependency.PackageGraph]::RevisionId + $rid | Should Be 0 + } + + It "TryCreate + Delete" { + TraceEnter "TryCreate + Delete" + + $rid = [Microsoft.Windows.ApplicationModel.DynamicDependency.PackageGraph]::RevisionId + LogComment "RevisionId: $rid" + $rid | Should Be 0 + + $pdid = "before" + $hr = [Microsoft.Windows.ApplicationModel.DynamicDependency.PackageDependency]::TryCreate( + $packageFamilyName, + 0, + [Microsoft.Windows.ApplicationModel.DynamicDependency.PackageDependencyProcessorArchitectures]::None, + [Microsoft.Windows.ApplicationModel.DynamicDependency.PackageDependencyLifetimeKind]::Process, + "", + [Microsoft.Windows.ApplicationModel.DynamicDependency.CreatePackageDependencyOptions]::None, + [ref] $pdid) + LogComment "TryCreate: 0x$($hr.ToString("X"))" + LogComment " PackageDependencyId: $pdid" + $hr | Should Be 0 + $pdid | Should Not BeNullOrEmpty + $packageDependencyIds.Add($pdid, $null) + + $rid = [Microsoft.Windows.ApplicationModel.DynamicDependency.PackageGraph]::RevisionId + LogComment "RevisionId: $rid" + $rid | Should Be 0 + + $pfn = "before" + $hr = [Microsoft.Windows.ApplicationModel.DynamicDependency.PackageDependency]::GetResolvedPackageFullName($pdid, [ref] $pfn) + LogComment "GetResolvedPackageFullName: 0x$($hr.ToString("X"))" + LogComment " PackageFullName: $pfn" + $hr | Should Be 0 + $pfn | Should BeNullOrEmpty + + $hr = [Microsoft.Windows.ApplicationModel.DynamicDependency.PackageDependency]::Delete($pdid) + LogComment "Delete: 0x$($hr.ToString("X"))" + $hr | Should Be 0 + $packageDependencyIds.Remove($pdid) + + $rid = [Microsoft.Windows.ApplicationModel.DynamicDependency.PackageGraph]::RevisionId + LogComment "RevisionId: $rid" + $rid | Should Be 0 + } + + It "TryCreate + Add + Remove + Delete" { + TraceEnter "TryCreate + Add + Remove + Delete" + + $rid = [Microsoft.Windows.ApplicationModel.DynamicDependency.PackageGraph]::RevisionId + LogComment "RevisionId: $rid" + $rid | Should Be 0 + + $pdid = "before" + $hr = [Microsoft.Windows.ApplicationModel.DynamicDependency.PackageDependency]::TryCreate( + $packageFamilyName, + 0, + [Microsoft.Windows.ApplicationModel.DynamicDependency.PackageDependencyProcessorArchitectures]::None, + [Microsoft.Windows.ApplicationModel.DynamicDependency.PackageDependencyLifetimeKind]::Process, + "", + [Microsoft.Windows.ApplicationModel.DynamicDependency.CreatePackageDependencyOptions]::None, + [ref] $pdid) + LogComment "TryCreate: 0x$($hr.ToString("X"))" + LogComment " PackageDependencyId: $pdid" + $hr | Should Be 0 + $pdid | Should Not BeNullOrEmpty + $packageDependencyIds.Add($pdid, $null) + + $pfn = "before" + $hr = [Microsoft.Windows.ApplicationModel.DynamicDependency.PackageDependency]::GetResolvedPackageFullName($pdid, [ref] $pfn) + LogComment "GetResolvedPackageFullName: 0x$($hr.ToString("X"))" + LogComment " PackageFullName: $pfn" + $hr | Should Be 0 + $pfn | Should BeNullOrEmpty + + $pdc = 0 + $pfn = "before" + $hr = [Microsoft.Windows.ApplicationModel.DynamicDependency.PackageDependency]::Add( + $pdid, + [Microsoft.Windows.ApplicationModel.DynamicDependency.Rank]::Default, + [Microsoft.Windows.ApplicationModel.DynamicDependency.AddPackageDependencyOptions]::None, + [ref] $pdc, + [ref] $pfn) + LogComment "Add: 0x$($hr.ToString("X"))" + LogComment " PackageDependencyContext: $pdc" + LogComment " PackageFullName: $pfn" + $hr | Should Be 0 + $pdc | Should Not BeNullOrEmpty + $packageDependencyContexts.Add($pdc, $null) + $pfn | Should Not BeNullOrEmpty + $packageDependencyContexts[$pdc] = $pfn + + $rid = [Microsoft.Windows.ApplicationModel.DynamicDependency.PackageGraph]::RevisionId + LogComment "RevisionId: $rid" + $rid | Should Be 1 + + $id = "before" + $hr = [Microsoft.Windows.ApplicationModel.DynamicDependency.PackageDependency]::GetIdForContext($pdc, [ref] $id) + LogComment "GetIdForContext: 0x$($hr.ToString("X"))" + LogComment " PackageDependencyId: $id" + $hr | Should Be 0 + $id | Should Not BeNullOrEmpty + + $pfn = "before" + $hr = [Microsoft.Windows.ApplicationModel.DynamicDependency.PackageDependency]::GetResolvedPackageFullName($pdid, [ref] $pfn) + LogComment "GetResolvedPackageFullName: 0x$($hr.ToString("X"))" + LogComment " PackageFullName: $pfn" + $hr | Should Be 0 + $pfn | Should Not BeNullOrEmpty + + # New a WinRT type from the package dynamically added to our package graph" + $widget = [Microsoft.Test.DynamicDependency.Widgets.Widget1,Microsoft.Test.DynamicDependency.Widgets.Widget1,ContentType=WindowsRuntime]::GetStatic() + $widget | Format-Custom + $widget | Should Not Be $null + + $hr = [Microsoft.Windows.ApplicationModel.DynamicDependency.PackageDependency]::Remove($pdc) + LogComment "Remove: 0x$($hr.ToString("X"))" + $hr | Should Be 0 + $packageDependencyContexts.Remove($pdc) + + $rid = [Microsoft.Windows.ApplicationModel.DynamicDependency.PackageGraph]::RevisionId + LogComment "RevisionId: $rid" + $rid | Should Be 2 + + $pfn = "before" + $hr = [Microsoft.Windows.ApplicationModel.DynamicDependency.PackageDependency]::GetResolvedPackageFullName($pdid, [ref] $pfn) + LogComment "GetResolvedPackageFullName: 0x$($hr.ToString("X"))" + LogComment " PackageFullName: $pfn" + $hr | Should Be 0 + $pfn | Should BeNullOrEmpty + + $hr = [Microsoft.Windows.ApplicationModel.DynamicDependency.PackageDependency]::Delete($pdid) + LogComment "Delete: 0x$($hr.ToString("X"))" + $hr | Should Be 0 + $packageDependencyIds.Remove($pdid) + + $rid = [Microsoft.Windows.ApplicationModel.DynamicDependency.PackageGraph]::RevisionId + LogComment "RevisionId: $rid" + $rid | Should Be 2 + } + + It "Remove null" { + TraceEnter "Remove null" + + $hr = [Microsoft.Windows.ApplicationModel.DynamicDependency.PackageDependency]::Remove([IntPtr]0) + $hr | Should Be $E_INVALIDARG + } + + It "Get RevisionId" { + TraceEnter "Get RevisionId" + + $rid = [Microsoft.Windows.ApplicationModel.DynamicDependency.PackageGraph]::RevisionId + LogComment "RevisionId: $rid" + $rid | Should Not BeLessThan 0 + } + + It "GetResolvedPackageFullName null" { + TraceEnter "GetResolvedPackageFullName null" + + $pdid = $null + $pfn = "before" + $hr = [Microsoft.Windows.ApplicationModel.DynamicDependency.PackageDependency]::GetResolvedPackageFullName($pdid, [ref] $pfn) + LogComment "HRESULT: 0x$($hr.ToString("X"))" + LogComment "PackageFullName: $pfn" + $hr | Should Be 0 + $pfn | Should Be $null + } + + It "Delete null" { + TraceEnter "Delete null" + + $hr = [Microsoft.Windows.ApplicationModel.DynamicDependency.PackageDependency]::Delete([IntPtr]0) + LogComment "HRESULT: 0x$($hr.ToString("X"))" + $hr | Should Be 0 + } +} diff --git a/test/DynamicDependency/Powershell/Test-MsixDynamicDependency.cmd b/test/DynamicDependency/Powershell/Test-MsixDynamicDependency.cmd new file mode 100644 index 0000000000..ce5811b280 --- /dev/null +++ b/test/DynamicDependency/Powershell/Test-MsixDynamicDependency.cmd @@ -0,0 +1,5 @@ +@echo off + +powershell -ExecutionPolicy Unrestricted -NoLogo -NoProfile -File %~dp0\Test-MsixDynamicDependency.Tests.ps1 %* + +exit /b %ERRORLEVEL% diff --git a/test/DynamicDependency/Powershell/Test-PackageDependency.Tests.ps1 b/test/DynamicDependency/Powershell/Test-PackageDependency.Tests.ps1 new file mode 100644 index 0000000000..e5c7c5b451 --- /dev/null +++ b/test/DynamicDependency/Powershell/Test-PackageDependency.Tests.ps1 @@ -0,0 +1,285 @@ +# Copyright (c) Microsoft Corporation and Contributors. +# Licensed under the MIT License. + +Set-StrictMode -Version 3.0 + +$ErrorActionPreference = "Stop" + +# Repository paths +$root = (Get-Item $PSScriptRoot).parent.parent.parent.FullName +$dev = Join-Path $root 'dev' +$test = Join-Path $root 'test' +$buildOutput = Join-Path $root 'BuildOutput\Debug\x64' +$cmdlet = Join-Path $dev 'DynamicDependency\Powershell' + +# Test package(s) +$packageName = 'WindowsAppRuntime.Test.DynDep.Fwk.Widgets' +$packageFamilyName = 'WindowsAppRuntime.Test.DynDep.Fwk.Widgets_8wekyb3d8bbwe' +$packageFullName = 'WindowsAppRuntime.Test.DynDep.Fwk.Widgets_1.2.3.4_neutral__8wekyb3d8bbwe' +$packageMsixDir = 'Framework.Widgets' +$packageMsixFilename = 'Framework.Widgets.msix' +$packageMsixPath = Join-Path $buildOutput $packageMsixDir +$packageMsix = Join-Path $packageMsixPath $packageMsixFilename + +# Track resources to ensure we clean up +$packageDependencyIds = [ordered]@{} +$packageDependencyContexts = [ordered]@{} + +Function LogComment +{ + param([string]$message) + + " $message" | Write-Host +} + +Function Trace +{ + param([string]$message) + + Write-Host $message -ForegroundColor Magenta +} + +Function TraceEnter +{ + param([string]$message) + + Trace " Test: $message" +} + +Function RemoveTestPackages +{ + Write-Host "Removing $packageName..." -ForegroundColor Cyan + + # Remove our package(s) in case they were previously installed and incompletely removed + Get-AppxPackage $packageName | Remove-AppxPackage + $p = Get-AppxPackage $packageName + if ($p -ne $null) + { + Write-Error $p + Write-Error "Remove/Get-AppxPackage result not expected" + Exit 1 + } +} + +Function AddTestPackages +{ + Write-Host "Adding $packageMsix..." -ForegroundColor Cyan + + # Install our needed package(s) + if (-not(Test-Path -Path $packageMsix -PathType Leaf)) + { + Write-Error "$($packageMsix) not found" + Exit 1 + } + Add-AppxPackage $packageMsix + $p = Get-AppxPackage $packageName + if ($p -eq $null) + { + Write-Error $p + Write-Error "Get-AppxPackage result not expected" + Exit 1 + } + if ($p.PackageFullName -ne $packageFullName) + { + Write-Error "$p.PackageFullName not expected (expected=$packageFullName)" + Exit 1 + } +} + +Function CleanupPackageDependencies +{ + if ($packageDependencyContexts.Count -gt 0) + { + Write-Host "Cleanup: Releasing $packageDependencyContexts.Count PackageDependency Contexts" -ForegroundColor Cyan + ForEach ($pdc in $packageDependencyContexts.Keys) + { + if ([string]::IsNullOrEmpty($pdc)) + { + continue + } + $hr = [Microsoft.Windows.ApplicationModel.DynamicDependency.PackageDependency]::Remove($pdc) + LogComment "Delete($pdc): 0x$($hr.ToString("X"))" + } + } + + if ($packageDependencyIds.Count -gt 0) + { + Write-Host "Cleanup: Releasing $packageDependencyIds.Count PackageDependency Ids" -ForegroundColor Cyan + ForEach ($pdid in $packageDependencyIds.Keys) + { + if ([string]::IsNullOrEmpty($pdid)) + { + continue + } + $hr = [Microsoft.Windows.ApplicationModel.DynamicDependency.PackageDependency]::Delete($pdid) + LogComment "Delete($pdid): 0x$($hr.ToString("X"))" + } + } +} + +Describe "DynamicDependency cmdlets" { + + BeforeAll { + Trace "BeforeAll" + + RemoveTestPackages + AddTestPackages + } + + AfterAll { + Trace "AfterAll" + + CleanupPackageDependencies + RemoveTestPackages + } + + It "Get-PackageGraphRevisionId (expect 0)" { + TraceEnter "Get-PackageGraphRevisionId (expect 0)" + + $rid = & "$cmdlet\Get-PackageGraphRevisionId.ps1" + $rid | Should Be 0 + } + + It "TryCreate + Delete" { + TraceEnter "TryCreate + Delete" + + $rid = & "$cmdlet\Get-PackageGraphRevisionId.ps1" + LogComment "RevisionId: $rid" + $rid | Should Be 0 + + LogComment "TryCreate-PackageDependency" + $pdid = "before" + $pdid = & "$cmdlet\TryCreate-PackageDependency.ps1" -PackageFamilyName $packageFamilyName -MinVersion 0 -LifetimeKind Process + LogComment " PackageDependencyId: $pdid" + $pdid | Should Not BeNullOrEmpty + $packageDependencyIds.Add($pdid, $null) + + $rid = & "$cmdlet\Get-PackageGraphRevisionId.ps1" + LogComment "RevisionId: $rid" + $rid | Should Be 0 + + LogComment "Get-PackageDependencyResolved" + $pfn = "before" + $pfn = & "$cmdlet\Get-PackageDependencyResolved.ps1" -PackageDependencyId $pdid + LogComment " PackageFullName: $pfn" + $pfn | Should BeNullOrEmpty + + LogComment "Delete" + & "$cmdlet\Delete-PackageDependency.ps1" -PackageDependencyId $pdid + $packageDependencyIds.Remove($pdid) + + $rid = & "$cmdlet\Get-PackageGraphRevisionId.ps1" + LogComment "RevisionId: $rid" + $rid | Should Be 0 + } + + It "TryCreate + Add + Remove + Delete" { + TraceEnter "TryCreate + Delete" + + $rid = & "$cmdlet\Get-PackageGraphRevisionId.ps1" + LogComment "RevisionId: $rid" + $rid | Should Be 0 + + LogComment "TryCreate-PackageDependency" + $pdid = "before" + $pdid = & "$cmdlet\TryCreate-PackageDependency.ps1" -PackageFamilyName $packageFamilyName -MinVersion 0 -LifetimeKind Process + LogComment " PackageDependencyId: $pdid" + $pdid | Should Not BeNullOrEmpty + $packageDependencyIds.Add($pdid, $null) + + $rid = & "$cmdlet\Get-PackageGraphRevisionId.ps1" + LogComment "RevisionId: $rid" + $rid | Should Be 0 + + LogComment "Get-PackageDependencyResolved" + $pfn = "before" + $pfn = & "$cmdlet\Get-PackageDependencyResolved.ps1" -PackageDependencyId $pdid + LogComment " PackageFullName: $pfn" + $pfn | Should BeNullOrEmpty + + LogComment "Add-PackageDependency" + $pdc = 0 + $pfn = "before" + $h = & "$cmdlet\Add-PackageDependency.ps1" -PackageDependencyId $pdid + $pdc = $h.PackageDependencyContext + $pfn = $h.PackageFullName + LogComment " PackageDependencyContext: $pdc" + LogComment " PackageFullName: $pfn" + $pdc | Should Not BeNullOrEmpty + $packageDependencyContexts.Add($pdc, $null) + $pfn | Should Not BeNullOrEmpty + $packageDependencyContexts[$pdc] = $pfn + + $rid = & "$cmdlet\Get-PackageGraphRevisionId.ps1" + LogComment " RevisionId: $rid" + $rid | Should Be 1 + + LogComment "Get-PackageDependencyIdForContext" + $id = "before" + $id = & "$cmdlet\Get-PackageDependencyIdForContext.ps1" -PackageDependencyContext $pdc + LogComment " PackageDependencyId: $id" + $id | Should Not BeNullOrEmpty + + LogComment "Get-PackageDependencyResolved" + $pfn = "before" + $pfn = & "$cmdlet\Get-PackageDependencyResolved.ps1" -PackageDependencyId $pdid + LogComment " PackageFullName: $pfn" + + # New a WinRT type from the package dynamically added to our package graph" + $widget = [Microsoft.Test.DynamicDependency.Widgets.Widget1,Microsoft.Test.DynamicDependency.Widgets.Widget1,ContentType=WindowsRuntime]::GetStatic() + $widget | Format-Custom + $widget | Should Not Be $null + + LogComment "Remove" + & "$cmdlet\Remove-PackageDependency.ps1" -PackageDependencyContext $pdc + $packageDependencyContexts.Remove($pdc) + + $rid = & "$cmdlet\Get-PackageGraphRevisionId.ps1" + LogComment "RevisionId: $rid" + $rid | Should Be 2 + + LogComment "Get-PackageDependencyResolved" + $pfn = "before" + $pfn = & "$cmdlet\Get-PackageDependencyResolved.ps1" -PackageDependencyId $pdid + LogComment " PackageFullName: $pfn" + $pfn | Should BeNullOrEmpty + + LogComment "Delete" + & "$cmdlet\Delete-PackageDependency.ps1" -PackageDependencyId $pdid + $packageDependencyIds.Remove($pdid) + + $rid = & "$cmdlet\Get-PackageGraphRevisionId.ps1" + LogComment "RevisionId: $rid" + $rid | Should Be 2 + } + + It "Remove null" { + TraceEnter "Remove null" + + $scriptBlock = { & "$cmdlet\Delete-PackageDependency.ps1" -PackageDependencyId $null } + $scriptBlock | Should Throw "Cannot bind argument to parameter 'PackageDependencyId' because it is an empty string." + } + + It "Get RevisionId" { + TraceEnter "Get RevisionId" + + $rid = & "$cmdlet\Get-PackageGraphRevisionId.ps1" + LogComment "RevisionId: $rid" + $rid | Should Not BeLessThan 0 + } + + It "GetResolvedPackageFullName null" { + TraceEnter "GetResolvedPackageFullName null" + + LogComment "Get-PackageDependencyResolved" + $scriptBlock = { & "$cmdlet\Get-PackageDependencyResolved.ps1" -PackageDependencyId $null } + $scriptBlock | Should Throw "Cannot bind argument to parameter 'PackageDependencyId' because it is an empty string." + } + + It "Delete null" { + TraceEnter "Delete null" + + $scriptBlock = { & "$cmdlet\Delete-PackageDependency.ps1" -PackageDependencyId $null -ErrorAction Stop } + $scriptBlock | Should Throw "Cannot bind argument to parameter 'PackageDependencyId' because it is an empty string." + } +} diff --git a/test/DynamicDependency/Powershell/Test-PackageDependency.cmd b/test/DynamicDependency/Powershell/Test-PackageDependency.cmd new file mode 100644 index 0000000000..f234fe7326 --- /dev/null +++ b/test/DynamicDependency/Powershell/Test-PackageDependency.cmd @@ -0,0 +1,5 @@ +@echo off + +powershell -ExecutionPolicy Unrestricted -NoLogo -NoProfile -File %~dp0\Test-PackageDependency.Tests.ps1 %* + +exit /b %ERRORLEVEL% diff --git a/test/DynamicDependency/Test_Win32/packages.config b/test/DynamicDependency/Test_Win32/packages.config index f11cc64c3e..1861ca894b 100644 --- a/test/DynamicDependency/Test_Win32/packages.config +++ b/test/DynamicDependency/Test_Win32/packages.config @@ -1,4 +1,4 @@  - + diff --git a/test/DynamicDependency/Test_WinRT/packages.config b/test/DynamicDependency/Test_WinRT/packages.config index f11cc64c3e..1861ca894b 100644 --- a/test/DynamicDependency/Test_WinRT/packages.config +++ b/test/DynamicDependency/Test_WinRT/packages.config @@ -1,4 +1,4 @@  - + diff --git a/test/DynamicDependency/data/Framework.Widgets/Framework.Widgets.vcxproj b/test/DynamicDependency/data/Framework.Widgets/Framework.Widgets.vcxproj index 501eb8f82d..5518cdec22 100644 --- a/test/DynamicDependency/data/Framework.Widgets/Framework.Widgets.vcxproj +++ b/test/DynamicDependency/data/Framework.Widgets/Framework.Widgets.vcxproj @@ -271,6 +271,7 @@ + $(RepoTestCertificatePFX) diff --git a/test/DynamicDependency/data/Framework.Widgets/packages.config b/test/DynamicDependency/data/Framework.Widgets/packages.config index 2305cb7181..9ba3aa91dd 100644 --- a/test/DynamicDependency/data/Framework.Widgets/packages.config +++ b/test/DynamicDependency/data/Framework.Widgets/packages.config @@ -1,5 +1,5 @@  - + diff --git a/test/DynamicDependency/data/Microsoft.WindowsAppRuntime.Framework/appxmanifest.xml b/test/DynamicDependency/data/Microsoft.WindowsAppRuntime.Framework/appxmanifest.xml index 1d4eb4e23a..f0dd3f24ca 100644 --- a/test/DynamicDependency/data/Microsoft.WindowsAppRuntime.Framework/appxmanifest.xml +++ b/test/DynamicDependency/data/Microsoft.WindowsAppRuntime.Framework/appxmanifest.xml @@ -77,6 +77,30 @@ + + + Microsoft.WindowsAppRuntime.dll + + + + + + + + + + + + + + + + + + + + + Microsoft.WindowsAppRuntime.dll diff --git a/test/EnvironmentManagerTests/packages.config b/test/EnvironmentManagerTests/packages.config index 9b3e6252ff..1117ac430f 100644 --- a/test/EnvironmentManagerTests/packages.config +++ b/test/EnvironmentManagerTests/packages.config @@ -1,6 +1,6 @@  - - + + diff --git a/test/Kozani/KozaniAppGraphTests/packages.config b/test/Kozani/KozaniAppGraphTests/packages.config index 54378eec74..ecebfdd18e 100644 --- a/test/Kozani/KozaniAppGraphTests/packages.config +++ b/test/Kozani/KozaniAppGraphTests/packages.config @@ -3,7 +3,7 @@ - - + + diff --git a/test/Kozani/KozaniHostRuntimeTests/packages.config b/test/Kozani/KozaniHostRuntimeTests/packages.config index 54378eec74..ecebfdd18e 100644 --- a/test/Kozani/KozaniHostRuntimeTests/packages.config +++ b/test/Kozani/KozaniHostRuntimeTests/packages.config @@ -3,7 +3,7 @@ - - + + diff --git a/test/Kozani/KozaniManagerRuntimeTests/KozaniManagerRuntimeTests.cpp b/test/Kozani/KozaniManagerRuntimeTests/KozaniManagerRuntimeTests.cpp index 2202333e17..01d6d6f0c6 100644 --- a/test/Kozani/KozaniManagerRuntimeTests/KozaniManagerRuntimeTests.cpp +++ b/test/Kozani/KozaniManagerRuntimeTests/KozaniManagerRuntimeTests.cpp @@ -1,4 +1,4 @@ -// Copyright (c) Microsoft Corporation and Contributors. +// Copyright (c) Microsoft Corporation and Contributors. // Licensed under the MIT License. #include "pch.h" @@ -33,13 +33,13 @@ HRESULT RegisterDVCPluginIfNeeded() const HINSTANCE hInst{ ShellExecute(nullptr, nullptr, L"reg.exe", regCommand, nullptr, SW_SHOW) }; WEX::Logging::Log::Comment(WEX::Common::String().Format(L"ShellExecute reg add finished with code: %d", hInst)); - if ((int)hInst > 32) + if (reinterpret_cast(hInst) > 32) { WEX::Logging::Log::Comment(L"Successfully created DVC plugin key!"); } else { - const HRESULT hr{ HRESULT_FROM_WIN32(reinterpret_cast(hInst)) }; + const HRESULT hr{ HRESULT_FROM_WIN32(static_cast(reinterpret_cast(hInst))) }; WEX::Logging::Log::Comment(WEX::Common::String().Format(L"ShellExecute failed with: 0x%x", hr)); return hr; } @@ -139,10 +139,10 @@ namespace Test::KozaniManagerRuntimeTests try { runtimeManager.ActivateRemoteApplication(winrt::Windows::ApplicationModel::Activation::ActivationKind::Launch, - L"Microsoft.WindowsCalculator_8wekyb3d8bbwe!App", L"Non-existing.rdp", L"additionalSettings.txt", + L"Microsoft.WindowsCalculator_8wekyb3d8bbwe!App", L"Non-existing.rdp", 0, nullptr, // IActivatedEventArgs statusCallback.as(), - 0); + L"additionalSettings.txt"); } catch (winrt::hresult_error& e) { @@ -156,10 +156,10 @@ namespace Test::KozaniManagerRuntimeTests rdpFullPath.append(L"MissingConnectionId.rdp"); runtimeManager.ActivateRemoteApplication(winrt::Windows::ApplicationModel::Activation::ActivationKind::Launch, - L"Microsoft.WindowsCalculator_8wekyb3d8bbwe!App", rdpFullPath.c_str(), L"additionalSettings.txt", + L"Microsoft.WindowsCalculator_8wekyb3d8bbwe!App", rdpFullPath.c_str(), 0, nullptr, // IActivatedEventArgs statusCallback.as(), - 0); + L"additionalSettings.txt"); } catch (winrt::hresult_error& e) { @@ -178,12 +178,10 @@ namespace Test::KozaniManagerRuntimeTests rdpFullPath.append(L"connection.rdp"); runtimeManager.ActivateRemoteApplication(winrt::Windows::ApplicationModel::Activation::ActivationKind::Launch, - L"Microsoft.WindowsCalculator_8wekyb3d8bbwe!App", rdpFullPath.c_str(), winrt::param::hstring(), + L"Microsoft.WindowsCalculator_8wekyb3d8bbwe!App", rdpFullPath.c_str(), 0, nullptr, // IActivatedEventArgs statusCallback.as(), - 0); - - //VERIFY_IS_TRUE(statusCallback->IsActivated(), L"IKozaniStausCallback::OnActivated() should have been called."); + winrt::param::hstring()); } }; } diff --git a/test/Kozani/KozaniManagerRuntimeTests/ManualTests.cpp b/test/Kozani/KozaniManagerRuntimeTests/ManualTests.cpp index 38599004c0..a840ccf14b 100644 --- a/test/Kozani/KozaniManagerRuntimeTests/ManualTests.cpp +++ b/test/Kozani/KozaniManagerRuntimeTests/ManualTests.cpp @@ -275,10 +275,10 @@ namespace Test::KozaniManagerRuntime::ManualTests { runtimeManager.ActivateRemoteApplication( winrt::Windows::ApplicationModel::Activation::ActivationKind::Launch, - aumid.c_str(), rdpFullPath.c_str(), winrt::param::hstring(), + aumid.c_str(), rdpFullPath.c_str(), localProcessId, nullptr, // IActivatedEventArgs statusCallback.as(), - localProcessId); + winrt::param::hstring()); } catch (winrt::hresult_error& e) { diff --git a/test/Kozani/KozaniManagerRuntimeTests/packages.config b/test/Kozani/KozaniManagerRuntimeTests/packages.config index 54378eec74..ecebfdd18e 100644 --- a/test/Kozani/KozaniManagerRuntimeTests/packages.config +++ b/test/Kozani/KozaniManagerRuntimeTests/packages.config @@ -3,7 +3,7 @@ - - + + diff --git a/test/Kozani/KozaniManagerTests/packages.config b/test/Kozani/KozaniManagerTests/packages.config index 54378eec74..ecebfdd18e 100644 --- a/test/Kozani/KozaniManagerTests/packages.config +++ b/test/Kozani/KozaniManagerTests/packages.config @@ -3,7 +3,7 @@ - - + + diff --git a/test/Kozani/KozaniPackageTests/packages.config b/test/Kozani/KozaniPackageTests/packages.config index 54378eec74..ecebfdd18e 100644 --- a/test/Kozani/KozaniPackageTests/packages.config +++ b/test/Kozani/KozaniPackageTests/packages.config @@ -3,7 +3,7 @@ - - + + diff --git a/test/Kozani/KozaniRemoteManagerTests/packages.config b/test/Kozani/KozaniRemoteManagerTests/packages.config index 54378eec74..ecebfdd18e 100644 --- a/test/Kozani/KozaniRemoteManagerTests/packages.config +++ b/test/Kozani/KozaniRemoteManagerTests/packages.config @@ -3,7 +3,7 @@ - - + + diff --git a/test/Kozani/KozaniSendToLocalTests/packages.config b/test/Kozani/KozaniSendToLocalTests/packages.config index 54378eec74..ecebfdd18e 100644 --- a/test/Kozani/KozaniSendToLocalTests/packages.config +++ b/test/Kozani/KozaniSendToLocalTests/packages.config @@ -3,7 +3,7 @@ - - + + diff --git a/test/Kozani/KozaniSendToRemoteTests/packages.config b/test/Kozani/KozaniSendToRemoteTests/packages.config index 54378eec74..ecebfdd18e 100644 --- a/test/Kozani/KozaniSendToRemoteTests/packages.config +++ b/test/Kozani/KozaniSendToRemoteTests/packages.config @@ -3,7 +3,7 @@ - - + + diff --git a/test/Kozani/KozaniSettingsTests/packages.config b/test/Kozani/KozaniSettingsTests/packages.config index 54378eec74..ecebfdd18e 100644 --- a/test/Kozani/KozaniSettingsTests/packages.config +++ b/test/Kozani/KozaniSettingsTests/packages.config @@ -3,7 +3,7 @@ - - + + diff --git a/test/Kozani/MakeMSIXTests/packages.config b/test/Kozani/MakeMSIXTests/packages.config index 54378eec74..ecebfdd18e 100644 --- a/test/Kozani/MakeMSIXTests/packages.config +++ b/test/Kozani/MakeMSIXTests/packages.config @@ -3,7 +3,7 @@ - - + + diff --git a/test/Kozani/data/KozaniManager.Msix/KozaniManager.Msix.vcxproj b/test/Kozani/data/KozaniManager.Msix/KozaniManager.Msix.vcxproj index 4747cf2eb0..8f4adbe08c 100644 --- a/test/Kozani/data/KozaniManager.Msix/KozaniManager.Msix.vcxproj +++ b/test/Kozani/data/KozaniManager.Msix/KozaniManager.Msix.vcxproj @@ -83,6 +83,10 @@ + + + + $(RepoTestCertificatePFX) @@ -93,9 +97,15 @@ + + {84cc5d23-93d1-4319-bb94-fb7801e4f113} + {cfc67ac3-3dc3-4981-a9bb-bc5ed06542d4} + + {400ed5ec-4530-4adb-8dce-9d1e6708a1f5} + {829cdb09-eefe-4188-a045-3fc6be7bd96b} diff --git a/test/Kozani/data/KozaniManager.Msix/appxmanifest.xml b/test/Kozani/data/KozaniManager.Msix/appxmanifest.xml index 3b749f2a91..4f72fd1945 100644 --- a/test/Kozani/data/KozaniManager.Msix/appxmanifest.xml +++ b/test/Kozani/data/KozaniManager.Msix/appxmanifest.xml @@ -5,9 +5,11 @@ xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10" xmlns:uap3="http://schemas.microsoft.com/appx/manifest/uap/windows10/3" xmlns:uap5="http://schemas.microsoft.com/appx/manifest/uap/windows10/5" + xmlns:uap10="http://schemas.microsoft.com/appx/manifest/uap/windows10/10" xmlns:com="http://schemas.microsoft.com/appx/manifest/com/windows10" + xmlns:desktop4="http://schemas.microsoft.com/appx/manifest/desktop/windows10/4" xmlns:rescap="http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities" - IgnorableNamespaces="uap uap3 uap5 com rescap"> + IgnorableNamespaces="uap uap3 uap5 uap10 com desktop4 rescap"> - + @@ -29,6 +31,7 @@ + @@ -55,13 +58,36 @@ + + + + + + + + + + + + + + KozaniManagerRuntime.dll + + + + + + + + + diff --git a/test/Kozani/data/KozaniRemoteManager.Msix/appxmanifest.xml b/test/Kozani/data/KozaniRemoteManager.Msix/appxmanifest.xml index a58a1011e1..951f5cf26d 100644 --- a/test/Kozani/data/KozaniRemoteManager.Msix/appxmanifest.xml +++ b/test/Kozani/data/KozaniRemoteManager.Msix/appxmanifest.xml @@ -76,8 +76,9 @@ - - + + + diff --git a/test/LRPTests/packages.config b/test/LRPTests/packages.config index 9b3e6252ff..1117ac430f 100644 --- a/test/LRPTests/packages.config +++ b/test/LRPTests/packages.config @@ -1,6 +1,6 @@  - - + + diff --git a/test/PackageManager/API/PackageDeploymentManagerTests.cpp b/test/PackageManager/API/PackageDeploymentManagerTests.cpp new file mode 100644 index 0000000000..7b4c429665 --- /dev/null +++ b/test/PackageManager/API/PackageDeploymentManagerTests.cpp @@ -0,0 +1,1321 @@ +// Copyright (c) Microsoft Corporation and Contributors. +// Licensed under the MIT License. + +#include "pch.h" + +#include + +namespace TB = ::Test::Bootstrap; +namespace TP = ::Test::Packages; +namespace TPF = ::Test::Packages::Framework; +namespace TPMT = ::Test::PackageManager::Tests; + +namespace Test::PackageManager::Tests +{ + class PackageDeploymentManagerTests + { + public: + BEGIN_TEST_CLASS(PackageDeploymentManagerTests) + TEST_CLASS_PROPERTY(L"ThreadingModel", L"MTA") + END_TEST_CLASS() + + TEST_CLASS_SETUP(ClassSetup) + { + if (!::WindowsVersion::IsWindows10_20H1OrGreater()) + { + WEX::Logging::Log::Result(WEX::Logging::TestResults::Skipped, L"PackageDeploymentManager requires >= 20H1 (Vibranium). Skipping tests"); + return true; + } + RemovePackage_Blue(); + RemovePackage_Green(); + RemovePackage_Redder(); + RemovePackage_Red(); + ::TB::Setup(); + return true; + } + + TEST_CLASS_CLEANUP(ClassCleanup) + { + RemovePackage_Blue(); + RemovePackage_Green(); + RemovePackage_Redder(); + RemovePackage_Red(); + ::TB::Cleanup(); + return true; + } + + void SetPackageStatus(PCWSTR packageFamilyName, winrt::Windows::Management::Deployment::PackageStatus status) + { + TPMT::SetPackageStatus(m_packageManager, packageFamilyName, status); + } + + void ClearPackageStatus(PCWSTR packageFamilyName, winrt::Windows::Management::Deployment::PackageStatus status) + { + TPMT::ClearPackageStatus(m_packageManager, packageFamilyName, status); + } + + TEST_METHOD(IsPackageSetReady_InvalidParameter) + { + auto packageDeploymentManager{ winrt::Microsoft::Windows::Management::Deployment::PackageDeploymentManager::GetDefault() }; + + try + { + winrt::Microsoft::Windows::Management::Deployment::PackageSet packageSet; + packageDeploymentManager.IsPackageSetReady(packageSet); + VERIFY_FAIL(L"Success is not expected"); + } + catch (winrt::hresult_error& e) + { + VERIFY_ARE_EQUAL(E_INVALIDARG, e.code(), WEX::Common::String().Format(L"0x%X %s", e.code(), e.message().c_str())); + } + + try + { + winrt::Microsoft::Windows::Management::Deployment::PackageSet packageSet; + PCWSTR c_packageSetId{ L"Does.Not.Exist" }; + packageSet.Id(c_packageSetId); + + packageDeploymentManager.IsPackageSetReady(packageSet); + VERIFY_FAIL(L"Success is not expected"); + } + catch (winrt::hresult_error& e) + { + VERIFY_ARE_EQUAL(E_INVALIDARG, e.code(), WEX::Common::String().Format(L"0x%X %s", e.code(), e.message().c_str())); + } + + try + { + winrt::Microsoft::Windows::Management::Deployment::PackageSet packageSet; + PCWSTR c_packageSetId{ L"Does.Not.Exist" }; + packageSet.Id(c_packageSetId); + winrt::Microsoft::Windows::Management::Deployment::PackageSetItem packageSetItem; + packageSet.PackageSetItems().Append(packageSetItem); + + packageDeploymentManager.IsPackageSetReady(packageSet); + VERIFY_FAIL(L"Success is not expected"); + } + catch (winrt::hresult_error& e) + { + VERIFY_ARE_EQUAL(E_INVALIDARG, e.code(), WEX::Common::String().Format(L"0x%X %s", e.code(), e.message().c_str())); + } + + try + { + winrt::Microsoft::Windows::Management::Deployment::PackageSet packageSet; + PCWSTR c_packageSetId{ L"Does.Not.Exist" }; + packageSet.Id(c_packageSetId); + winrt::Microsoft::Windows::Management::Deployment::PackageSetItem packageSetItem; + PCWSTR c_packageFamilyName{ L"Not a valid Package Family Name" }; + packageSetItem.PackageFamilyName(c_packageFamilyName); + packageSet.PackageSetItems().Append(packageSetItem); + + packageDeploymentManager.IsPackageSetReady(packageSet); + VERIFY_FAIL(L"Success is not expected"); + } + catch (winrt::hresult_error& e) + { + VERIFY_ARE_EQUAL(E_INVALIDARG, e.code(), WEX::Common::String().Format(L"0x%X %s", e.code(), e.message().c_str())); + } + + try + { + winrt::Microsoft::Windows::Management::Deployment::PackageSet packageSet; + PCWSTR c_packageSetId{ L"Does.Not.Exist" }; + packageSet.Id(c_packageSetId); + winrt::Microsoft::Windows::Management::Deployment::PackageSetItem packageSetItem; + PCWSTR c_packageFamilyName{ L"Does.Not.Exist_1234567890abc" }; + packageSetItem.PackageFamilyName(c_packageFamilyName); + packageSet.PackageSetItems().Append(packageSetItem); + + packageDeploymentManager.IsPackageSetReady(packageSet); + VERIFY_FAIL(L"Success is not expected"); + } + catch (winrt::hresult_error& e) + { + VERIFY_ARE_EQUAL(E_INVALIDARG, e.code(), WEX::Common::String().Format(L"0x%X %s", e.code(), e.message().c_str())); + } + + try + { + winrt::Microsoft::Windows::Management::Deployment::PackageSet packageSet; + PCWSTR c_packageSetId{ L"Does.Not.Exist" }; + packageSet.Id(c_packageSetId); + winrt::Microsoft::Windows::Management::Deployment::PackageSetItem packageSetItem; + PCWSTR c_packageUriAsString{ L"https://doesnotexist.com/assemble.msix" }; + winrt::Windows::Foundation::Uri packageUri{ c_packageUriAsString }; + packageSetItem.PackageUri(packageUri); + packageSet.PackageSetItems().Append(packageSetItem); + + packageDeploymentManager.IsPackageSetReady(packageSet); + VERIFY_FAIL(L"Success is not expected"); + } + catch (winrt::hresult_error& e) + { + VERIFY_ARE_EQUAL(E_INVALIDARG, e.code(), WEX::Common::String().Format(L"0x%X %s", e.code(), e.message().c_str())); + } + } + + TEST_METHOD(IsPackageSetReady_1_NoSuchPackage_No) + { + auto packageDeploymentManager{ winrt::Microsoft::Windows::Management::Deployment::PackageDeploymentManager::GetDefault() }; + + winrt::Microsoft::Windows::Management::Deployment::PackageSet packageSet; + PCWSTR c_packageSetId{ L"Does.Not.Exist" }; + packageSet.Id(c_packageSetId); + winrt::Microsoft::Windows::Management::Deployment::PackageSetItem packageSetItem; + PCWSTR c_packageFamilyName{ L"Does.Not.Exist_1234567890abc" }; + packageSetItem.PackageFamilyName(c_packageFamilyName); + PCWSTR c_packageUriAsString{ L"file://c:/does/not/exist.msix" }; + winrt::Windows::Foundation::Uri packageUri{ c_packageUriAsString }; + packageSetItem.PackageUri(packageUri); + packageSet.PackageSetItems().Append(packageSetItem); + + VERIFY_IS_FALSE(packageDeploymentManager.IsPackageSetReady(packageSet)); + } + + TEST_METHOD(IsPackageSetReady_1_NotInstalled_No) + { + RemovePackage_Red(); + + auto packageDeploymentManager{ winrt::Microsoft::Windows::Management::Deployment::PackageDeploymentManager::GetDefault() }; + + winrt::Microsoft::Windows::Management::Deployment::PackageSet packageSet; + PCWSTR c_packageSetId{ L"RGB" }; + packageSet.Id(c_packageSetId); + winrt::Microsoft::Windows::Management::Deployment::PackageSetItem red{ Make_PackageSetItem(::TPF::Red::GetPackageFullName(), ::TPF::Red::c_packageDirName) }; + packageSet.PackageSetItems().Append(red); + + VERIFY_IS_FALSE(packageDeploymentManager.IsPackageSetReady(packageSet)); + } + + TEST_METHOD(IsPackageSetReady_1_Registered_Yes) + { + AddPackage_Red(); + + auto packageDeploymentManager{ winrt::Microsoft::Windows::Management::Deployment::PackageDeploymentManager::GetDefault() }; + + winrt::Microsoft::Windows::Management::Deployment::PackageSet packageSet; + PCWSTR c_packageSetId{ L"RGB" }; + packageSet.Id(c_packageSetId); + winrt::Microsoft::Windows::Management::Deployment::PackageSetItem red{ Make_PackageSetItem(::TPF::Red::GetPackageFullName(), ::TPF::Red::c_packageDirName) }; + packageSet.PackageSetItems().Append(red); + + VERIFY_IS_TRUE(packageDeploymentManager.IsPackageSetReady(packageSet)); + } + + TEST_METHOD(IsPackageSetReady_1_OlderRegistered_No) + { + AddPackage_Red(); + + auto packageDeploymentManager{ winrt::Microsoft::Windows::Management::Deployment::PackageDeploymentManager::GetDefault() }; + + winrt::Microsoft::Windows::Management::Deployment::PackageSet packageSet; + PCWSTR c_packageSetId{ L"RGB" }; + packageSet.Id(c_packageSetId); + winrt::Microsoft::Windows::Management::Deployment::PackageSetItem redder{ Make_PackageSetItem(::TPF::Redder::GetPackageFullName(), ::TPF::Redder::c_packageDirName) }; + packageSet.PackageSetItems().Append(redder); + + VERIFY_IS_FALSE(packageDeploymentManager.IsPackageSetReady(packageSet)); + } + + TEST_METHOD(IsPackageSetReady_1_NewerRegistered_Yes) + { + AddPackage_Redder(); + + auto packageDeploymentManager{ winrt::Microsoft::Windows::Management::Deployment::PackageDeploymentManager::GetDefault() }; + + winrt::Microsoft::Windows::Management::Deployment::PackageSet packageSet; + PCWSTR c_packageSetId{ L"RGB" }; + packageSet.Id(c_packageSetId); + winrt::Microsoft::Windows::Management::Deployment::PackageSetItem red{ Make_PackageSetItem(::TPF::Red::GetPackageFullName(), ::TPF::Red::c_packageDirName) }; + packageSet.PackageSetItems().Append(red); + + VERIFY_IS_TRUE(packageDeploymentManager.IsPackageSetReady(packageSet)); + + RemovePackage_Redder(); + } + + TEST_METHOD(IsPackageSetReady_1_RegisteredPackageStatusBad_No) + { + BEGIN_TEST_METHOD_PROPERTIES() + TEST_CLASS_PROPERTY(L"RunAs", L"ElevatedUser") + END_TEST_METHOD_PROPERTIES() + + AddPackage_Red(); + SetPackageStatus(::TPF::Red::c_packageFamilyName, winrt::Windows::Management::Deployment::PackageStatus::Modified); + + auto packageDeploymentManager{ winrt::Microsoft::Windows::Management::Deployment::PackageDeploymentManager::GetDefault() }; + + winrt::Microsoft::Windows::Management::Deployment::PackageSet packageSet; + PCWSTR c_packageSetId{ L"RGB" }; + packageSet.Id(c_packageSetId); + winrt::Microsoft::Windows::Management::Deployment::PackageSetItem red{ Make_PackageSetItem(::TPF::Red::GetPackageFullName(), ::TPF::Red::c_packageDirName) }; + packageSet.PackageSetItems().Append(red); + + VERIFY_IS_FALSE(packageDeploymentManager.IsPackageSetReady(packageSet)); + + ClearPackageStatus(::TPF::Red::c_packageFamilyName, winrt::Windows::Management::Deployment::PackageStatus::Modified); + } + + TEST_METHOD(IsPackageSetReady_N_NotInstalled_No) + { + RemovePackage_Red(); + RemovePackage_Green(); + RemovePackage_Blue(); + + auto packageDeploymentManager{ winrt::Microsoft::Windows::Management::Deployment::PackageDeploymentManager::GetDefault() }; + + winrt::Microsoft::Windows::Management::Deployment::PackageSet packageSet; + PCWSTR c_packageSetId{ L"RGB" }; + packageSet.Id(c_packageSetId); + winrt::Microsoft::Windows::Management::Deployment::PackageSetItem red{ Make_PackageSetItem(::TPF::Red::GetPackageFullName(), ::TPF::Red::c_packageDirName) }; + packageSet.PackageSetItems().Append(red); + winrt::Microsoft::Windows::Management::Deployment::PackageSetItem green{ Make_PackageSetItem(::TPF::Green::GetPackageFullName(), ::TPF::Green::c_packageDirName) }; + packageSet.PackageSetItems().Append(green); + winrt::Microsoft::Windows::Management::Deployment::PackageSetItem blue{ Make_PackageSetItem(::TPF::Blue::GetPackageFullName(), ::TPF::Blue::c_packageDirName) }; + packageSet.PackageSetItems().Append(blue); + + VERIFY_IS_FALSE(packageDeploymentManager.IsPackageSetReady(packageSet)); + } + + TEST_METHOD(IsPackageSetReady_N_Registered_Yes) + { + AddPackage_Red(); + AddPackage_Green(); + AddPackage_Blue(); + + auto packageDeploymentManager{ winrt::Microsoft::Windows::Management::Deployment::PackageDeploymentManager::GetDefault() }; + + winrt::Microsoft::Windows::Management::Deployment::PackageSet packageSet; + PCWSTR c_packageSetId{ L"RGB" }; + packageSet.Id(c_packageSetId); + winrt::Microsoft::Windows::Management::Deployment::PackageSetItem red{ Make_PackageSetItem(::TPF::Red::GetPackageFullName(), ::TPF::Red::c_packageDirName) }; + packageSet.PackageSetItems().Append(red); + winrt::Microsoft::Windows::Management::Deployment::PackageSetItem green{ Make_PackageSetItem(::TPF::Green::GetPackageFullName(), ::TPF::Green::c_packageDirName) }; + packageSet.PackageSetItems().Append(green); + winrt::Microsoft::Windows::Management::Deployment::PackageSetItem blue{ Make_PackageSetItem(::TPF::Blue::GetPackageFullName(), ::TPF::Blue::c_packageDirName) }; + packageSet.PackageSetItems().Append(blue); + + VERIFY_IS_TRUE(packageDeploymentManager.IsPackageSetReady(packageSet)); + } + + TEST_METHOD(IsPackageSetReady_N_OlderRegistered_No) + { + AddPackage_Red(); + AddPackage_Green(); + AddPackage_Blue(); + + auto packageDeploymentManager{ winrt::Microsoft::Windows::Management::Deployment::PackageDeploymentManager::GetDefault() }; + + winrt::Microsoft::Windows::Management::Deployment::PackageSet packageSet; + PCWSTR c_packageSetId{ L"RGB" }; + packageSet.Id(c_packageSetId); + winrt::Microsoft::Windows::Management::Deployment::PackageSetItem redder{ Make_PackageSetItem(::TPF::Redder::GetPackageFullName(), ::TPF::Redder::c_packageDirName) }; + packageSet.PackageSetItems().Append(redder); + winrt::Microsoft::Windows::Management::Deployment::PackageSetItem green{ Make_PackageSetItem(::TPF::Green::GetPackageFullName(), ::TPF::Green::c_packageDirName) }; + packageSet.PackageSetItems().Append(green); + winrt::Microsoft::Windows::Management::Deployment::PackageSetItem blue{ Make_PackageSetItem(::TPF::Blue::GetPackageFullName(), ::TPF::Blue::c_packageDirName) }; + packageSet.PackageSetItems().Append(blue); + + VERIFY_IS_FALSE(packageDeploymentManager.IsPackageSetReady(packageSet)); + } + + TEST_METHOD(IsPackageSetReady_N_NewerRegistered_Yes) + { + AddPackage_Redder(); + AddPackage_Green(); + AddPackage_Blue(); + + auto packageDeploymentManager{ winrt::Microsoft::Windows::Management::Deployment::PackageDeploymentManager::GetDefault() }; + + winrt::Microsoft::Windows::Management::Deployment::PackageSet packageSet; + PCWSTR c_packageSetId{ L"RGB" }; + packageSet.Id(c_packageSetId); + winrt::Microsoft::Windows::Management::Deployment::PackageSetItem red{ Make_PackageSetItem(::TPF::Red::GetPackageFullName(), ::TPF::Red::c_packageDirName) }; + packageSet.PackageSetItems().Append(red); + winrt::Microsoft::Windows::Management::Deployment::PackageSetItem green{ Make_PackageSetItem(::TPF::Green::GetPackageFullName(), ::TPF::Green::c_packageDirName) }; + packageSet.PackageSetItems().Append(green); + winrt::Microsoft::Windows::Management::Deployment::PackageSetItem blue{ Make_PackageSetItem(::TPF::Blue::GetPackageFullName(), ::TPF::Blue::c_packageDirName) }; + packageSet.PackageSetItems().Append(blue); + + VERIFY_IS_TRUE(packageDeploymentManager.IsPackageSetReady(packageSet)); + + RemovePackage_Redder(); + } + + TEST_METHOD(IsPackageSetReady_N_RegisteredAndNotInstalled_No) + { + AddPackage_Red(); + RemovePackage_Green(); + + auto packageDeploymentManager{ winrt::Microsoft::Windows::Management::Deployment::PackageDeploymentManager::GetDefault() }; + + winrt::Microsoft::Windows::Management::Deployment::PackageSet packageSet; + PCWSTR c_packageSetId{ L"RGB" }; + packageSet.Id(c_packageSetId); + winrt::Microsoft::Windows::Management::Deployment::PackageSetItem red{ Make_PackageSetItem(::TPF::Red::GetPackageFullName(), ::TPF::Red::c_packageDirName) }; + packageSet.PackageSetItems().Append(red); + winrt::Microsoft::Windows::Management::Deployment::PackageSetItem green{ Make_PackageSetItem(::TPF::Green::GetPackageFullName(), ::TPF::Green::c_packageDirName) }; + packageSet.PackageSetItems().Append(green); + + VERIFY_IS_FALSE(packageDeploymentManager.IsPackageSetReady(packageSet)); + } + + TEST_METHOD(IsPackageSetReady_N_No_NotAllPackageStatusOK) + { + BEGIN_TEST_METHOD_PROPERTIES() + TEST_CLASS_PROPERTY(L"RunAs", L"ElevatedUser") + END_TEST_METHOD_PROPERTIES() + + AddPackage_Red(); + AddPackage_Green(); + SetPackageStatus(::TPF::Green::c_packageFamilyName, winrt::Windows::Management::Deployment::PackageStatus::Modified); + + auto packageDeploymentManager{ winrt::Microsoft::Windows::Management::Deployment::PackageDeploymentManager::GetDefault() }; + + winrt::Microsoft::Windows::Management::Deployment::PackageSet packageSet; + PCWSTR c_packageSetId{ L"RGB" }; + packageSet.Id(c_packageSetId); + winrt::Microsoft::Windows::Management::Deployment::PackageSetItem red{ Make_PackageSetItem(::TPF::Red::GetPackageFullName(), ::TPF::Red::c_packageDirName) }; + packageSet.PackageSetItems().Append(red); + winrt::Microsoft::Windows::Management::Deployment::PackageSetItem green{ Make_PackageSetItem(::TPF::Green::GetPackageFullName(), ::TPF::Green::c_packageDirName) }; + packageSet.PackageSetItems().Append(green); + + VERIFY_IS_FALSE(packageDeploymentManager.IsPackageSetReady(packageSet)); + + ClearPackageStatus(::TPF::Green::c_packageFamilyName, winrt::Windows::Management::Deployment::PackageStatus::Modified); + } + + TEST_METHOD(EnsurePackageSetIsReadyAsync_InvalidParameter) + { + auto packageDeploymentManager{ winrt::Microsoft::Windows::Management::Deployment::PackageDeploymentManager::GetDefault() }; + + try + { + winrt::Microsoft::Windows::Management::Deployment::PackageSet packageSet; + winrt::Microsoft::Windows::Management::Deployment::EnsureIsReadyOptions options; + auto deploymentResult{ packageDeploymentManager.EnsurePackageSetIsReadyAsync(packageSet, options).get() }; + VERIFY_FAIL(L"Success is not expected"); + } + catch (winrt::hresult_error& e) + { + VERIFY_ARE_EQUAL(E_INVALIDARG, e.code(), WEX::Common::String().Format(L"0x%X %s", e.code(), e.message().c_str())); + } + + try + { + winrt::Microsoft::Windows::Management::Deployment::PackageSet packageSet; + PCWSTR c_packageSetId{ L"Does.Not.Exist" }; + packageSet.Id(c_packageSetId); + + winrt::Microsoft::Windows::Management::Deployment::EnsureIsReadyOptions options; + auto deploymentResult{ packageDeploymentManager.EnsurePackageSetIsReadyAsync(packageSet, options).get() }; + VERIFY_FAIL(L"Success is not expected"); + } + catch (winrt::hresult_error& e) + { + VERIFY_ARE_EQUAL(E_INVALIDARG, e.code(), WEX::Common::String().Format(L"0x%X %s", e.code(), e.message().c_str())); + } + + try + { + winrt::Microsoft::Windows::Management::Deployment::PackageSet packageSet; + PCWSTR c_packageSetId{ L"Does.Not.Exist" }; + packageSet.Id(c_packageSetId); + winrt::Microsoft::Windows::Management::Deployment::PackageSetItem packageSetItem; + packageSet.PackageSetItems().Append(packageSetItem); + + winrt::Microsoft::Windows::Management::Deployment::EnsureIsReadyOptions options; + auto deploymentResult{ packageDeploymentManager.EnsurePackageSetIsReadyAsync(packageSet, options).get() }; + VERIFY_FAIL(L"Success is not expected"); + } + catch (winrt::hresult_error& e) + { + VERIFY_ARE_EQUAL(E_INVALIDARG, e.code(), WEX::Common::String().Format(L"0x%X %s", e.code(), e.message().c_str())); + } + + try + { + winrt::Microsoft::Windows::Management::Deployment::PackageSet packageSet; + PCWSTR c_packageSetId{ L"Does.Not.Exist" }; + packageSet.Id(c_packageSetId); + winrt::Microsoft::Windows::Management::Deployment::PackageSetItem packageSetItem; + PCWSTR c_packageFamilyName{ L"Not a valid Package Family Name" }; + packageSetItem.PackageFamilyName(c_packageFamilyName); + packageSet.PackageSetItems().Append(packageSetItem); + + winrt::Microsoft::Windows::Management::Deployment::EnsureIsReadyOptions options; + auto deploymentResult{ packageDeploymentManager.EnsurePackageSetIsReadyAsync(packageSet, options).get() }; + VERIFY_FAIL(L"Success is not expected"); + } + catch (winrt::hresult_error& e) + { + VERIFY_ARE_EQUAL(E_INVALIDARG, e.code(), WEX::Common::String().Format(L"0x%X %s", e.code(), e.message().c_str())); + } + + try + { + winrt::Microsoft::Windows::Management::Deployment::PackageSet packageSet; + PCWSTR c_packageSetId{ L"Does.Not.Exist" }; + packageSet.Id(c_packageSetId); + winrt::Microsoft::Windows::Management::Deployment::PackageSetItem packageSetItem; + PCWSTR c_packageFamilyName{ L"Does.Not.Exist_1234567890abc" }; + packageSetItem.PackageFamilyName(c_packageFamilyName); + packageSet.PackageSetItems().Append(packageSetItem); + + winrt::Microsoft::Windows::Management::Deployment::EnsureIsReadyOptions options; + auto deploymentResult{ packageDeploymentManager.EnsurePackageSetIsReadyAsync(packageSet, options).get() }; + VERIFY_FAIL(L"Success is not expected"); + } + catch (winrt::hresult_error& e) + { + VERIFY_ARE_EQUAL(E_INVALIDARG, e.code(), WEX::Common::String().Format(L"0x%X %s", e.code(), e.message().c_str())); + } + + try + { + winrt::Microsoft::Windows::Management::Deployment::PackageSet packageSet; + PCWSTR c_packageSetId{ L"Does.Not.Exist" }; + packageSet.Id(c_packageSetId); + winrt::Microsoft::Windows::Management::Deployment::PackageSetItem packageSetItem; + PCWSTR c_packageUriAsString{ L"file://c:/assemble.msix" }; + winrt::Windows::Foundation::Uri packageUri{ c_packageUriAsString }; + packageSetItem.PackageUri(packageUri); + packageSet.PackageSetItems().Append(packageSetItem); + + winrt::Microsoft::Windows::Management::Deployment::EnsureIsReadyOptions options; + auto deploymentResult{ packageDeploymentManager.EnsurePackageSetIsReadyAsync(packageSet, options).get() }; + VERIFY_FAIL(L"Success is not expected"); + } + catch (winrt::hresult_error& e) + { + VERIFY_ARE_EQUAL(E_INVALIDARG, e.code(), WEX::Common::String().Format(L"0x%X %s", e.code(), e.message().c_str())); + } + } + + TEST_METHOD(EnsurePackageSetIsReadyAsync_1_NoSuchPackage_Fail) + { + auto packageDeploymentManager{ winrt::Microsoft::Windows::Management::Deployment::PackageDeploymentManager::GetDefault() }; + + winrt::Microsoft::Windows::Management::Deployment::PackageSet packageSet; + PCWSTR c_packageSetId{ L"Does.Not.Exist" }; + packageSet.Id(c_packageSetId); + winrt::Microsoft::Windows::Management::Deployment::PackageSetItem packageSetItem; + PCWSTR c_packageFamilyName{ L"Does.Not.Exist_1234567890abc" }; + packageSetItem.PackageFamilyName(c_packageFamilyName); + PCWSTR c_packageUriAsString{ L"file://c:/does/not/exist.msix" }; + winrt::Windows::Foundation::Uri packageUri{ c_packageUriAsString }; + packageSetItem.PackageUri(packageUri); + packageSet.PackageSetItems().Append(packageSetItem); + + winrt::Microsoft::Windows::Management::Deployment::EnsureIsReadyOptions options; + auto deploymentResult{ packageDeploymentManager.EnsurePackageSetIsReadyAsync(packageSet, options).get() }; + VERIFY_ARE_EQUAL(winrt::Microsoft::Windows::Management::Deployment::PackageDeploymentStatus::CompletedFailure, deploymentResult.Status()); + VERIFY_ARE_EQUAL(HRESULT_FROM_WIN32(ERROR_INSTALL_OPEN_PACKAGE_FAILED), deploymentResult.ExtendedError(), WEX::Common::String().Format(L"0x%X", deploymentResult.ExtendedError())); + + VERIFY_IS_FALSE(packageDeploymentManager.IsPackageSetReady(packageSet)); + } + + TEST_METHOD(EnsurePackageSetIsReadyAsync_1_NotInstalled_Success) + { + RemovePackage_Red(); + + auto packageDeploymentManager{ winrt::Microsoft::Windows::Management::Deployment::PackageDeploymentManager::GetDefault() }; + + winrt::Microsoft::Windows::Management::Deployment::PackageSet packageSet; + PCWSTR c_packageSetId{ L"RGB" }; + packageSet.Id(c_packageSetId); + winrt::Microsoft::Windows::Management::Deployment::PackageSetItem red{ Make_PackageSetItem(::TPF::Red::GetPackageFullName(), ::TPF::Red::c_packageDirName) }; + packageSet.PackageSetItems().Append(red); + + winrt::Microsoft::Windows::Management::Deployment::EnsureIsReadyOptions options; + auto deploymentResult{ packageDeploymentManager.EnsurePackageSetIsReadyAsync(packageSet, options).get() }; + VERIFY_ARE_EQUAL(winrt::Microsoft::Windows::Management::Deployment::PackageDeploymentStatus::CompletedSuccess, deploymentResult.Status()); + VERIFY_ARE_EQUAL(S_OK, deploymentResult.ExtendedError(), WEX::Common::String().Format(L"0x%X", deploymentResult.ExtendedError())); + + VERIFY_IS_TRUE(packageDeploymentManager.IsPackageSetReady(packageSet)); + } + + TEST_METHOD(EnsurePackageSetIsReadyAsync_1_Staged_Success) + { + BEGIN_TEST_METHOD_PROPERTIES() + TEST_CLASS_PROPERTY(L"RunAs", L"ElevatedUser") + END_TEST_METHOD_PROPERTIES() + + StagePackage_Red(); + + auto packageDeploymentManager{ winrt::Microsoft::Windows::Management::Deployment::PackageDeploymentManager::GetDefault() }; + + winrt::Microsoft::Windows::Management::Deployment::PackageSet packageSet; + PCWSTR c_packageSetId{ L"RGB" }; + packageSet.Id(c_packageSetId); + winrt::Microsoft::Windows::Management::Deployment::PackageSetItem red{ Make_PackageSetItem(::TPF::Red::GetPackageFullName(), ::TPF::Red::c_packageDirName) }; + packageSet.PackageSetItems().Append(red); + + winrt::Microsoft::Windows::Management::Deployment::EnsureIsReadyOptions options; + auto deploymentResult{ packageDeploymentManager.EnsurePackageSetIsReadyAsync(packageSet, options).get() }; + VERIFY_ARE_EQUAL(winrt::Microsoft::Windows::Management::Deployment::PackageDeploymentStatus::CompletedSuccess, deploymentResult.Status()); + VERIFY_ARE_EQUAL(S_OK, deploymentResult.ExtendedError(), WEX::Common::String().Format(L"0x%X", deploymentResult.ExtendedError())); + + VERIFY_IS_TRUE(packageDeploymentManager.IsPackageSetReady(packageSet)); + } + + TEST_METHOD(EnsurePackageSetIsReadyAsync_1_Registered_Success) + { + AddPackage_Red(); + + auto packageDeploymentManager{ winrt::Microsoft::Windows::Management::Deployment::PackageDeploymentManager::GetDefault() }; + + winrt::Microsoft::Windows::Management::Deployment::PackageSet packageSet; + PCWSTR c_packageSetId{ L"RGB" }; + packageSet.Id(c_packageSetId); + winrt::Microsoft::Windows::Management::Deployment::PackageSetItem red{ Make_PackageSetItem(::TPF::Red::GetPackageFullName(), ::TPF::Red::c_packageDirName) }; + packageSet.PackageSetItems().Append(red); + + winrt::Microsoft::Windows::Management::Deployment::EnsureIsReadyOptions options; + auto deploymentResult{ packageDeploymentManager.EnsurePackageSetIsReadyAsync(packageSet, options).get() }; + VERIFY_ARE_EQUAL(winrt::Microsoft::Windows::Management::Deployment::PackageDeploymentStatus::CompletedSuccess, deploymentResult.Status()); + VERIFY_ARE_EQUAL(S_OK, deploymentResult.ExtendedError(), WEX::Common::String().Format(L"0x%X", deploymentResult.ExtendedError())); + + VERIFY_IS_TRUE(packageDeploymentManager.IsPackageSetReady(packageSet)); + } + + TEST_METHOD(EnsurePackageSetIsReadyAsync_1_OlderRegistered_Success) + { + AddPackage_Red(); + + auto packageDeploymentManager{ winrt::Microsoft::Windows::Management::Deployment::PackageDeploymentManager::GetDefault() }; + + winrt::Microsoft::Windows::Management::Deployment::PackageSet packageSet; + PCWSTR c_packageSetId{ L"RGB" }; + packageSet.Id(c_packageSetId); + winrt::Microsoft::Windows::Management::Deployment::PackageSetItem redder{ Make_PackageSetItem(::TPF::Redder::GetPackageFullName(), ::TPF::Redder::c_packageDirName) }; + packageSet.PackageSetItems().Append(redder); + + winrt::Microsoft::Windows::Management::Deployment::EnsureIsReadyOptions options; + auto deploymentResult{ packageDeploymentManager.EnsurePackageSetIsReadyAsync(packageSet, options).get() }; + VERIFY_ARE_EQUAL(winrt::Microsoft::Windows::Management::Deployment::PackageDeploymentStatus::CompletedSuccess, deploymentResult.Status()); + VERIFY_ARE_EQUAL(S_OK, deploymentResult.ExtendedError(), WEX::Common::String().Format(L"0x%X", deploymentResult.ExtendedError())); + + VERIFY_IS_TRUE(packageDeploymentManager.IsPackageSetReady(packageSet)); + + RemovePackage_Redder(); + } + + TEST_METHOD(EnsurePackageSetIsReadyAsync_1_NewerRegistered_Success) + { + AddPackage_Redder(); + + auto packageDeploymentManager{ winrt::Microsoft::Windows::Management::Deployment::PackageDeploymentManager::GetDefault() }; + + winrt::Microsoft::Windows::Management::Deployment::PackageSet packageSet; + PCWSTR c_packageSetId{ L"RGB" }; + packageSet.Id(c_packageSetId); + winrt::Microsoft::Windows::Management::Deployment::PackageSetItem red{ Make_PackageSetItem(::TPF::Red::GetPackageFullName(), ::TPF::Red::c_packageDirName) }; + packageSet.PackageSetItems().Append(red); + + winrt::Microsoft::Windows::Management::Deployment::EnsureIsReadyOptions options; + auto deploymentResult{ packageDeploymentManager.EnsurePackageSetIsReadyAsync(packageSet, options).get() }; + VERIFY_ARE_EQUAL(winrt::Microsoft::Windows::Management::Deployment::PackageDeploymentStatus::CompletedSuccess, deploymentResult.Status()); + VERIFY_ARE_EQUAL(S_OK, deploymentResult.ExtendedError(), WEX::Common::String().Format(L"0x%X", deploymentResult.ExtendedError())); + + VERIFY_IS_TRUE(packageDeploymentManager.IsPackageSetReady(packageSet)); + + RemovePackage_Redder(); + } + + TEST_METHOD(EnsurePackageSetIsReadyAsync_1_RegisteredPackageStatusBad_Success) + { + BEGIN_TEST_METHOD_PROPERTIES() + TEST_CLASS_PROPERTY(L"RunAs", L"ElevatedUser") + END_TEST_METHOD_PROPERTIES() + + AddPackage_Red(); + SetPackageStatus(::TPF::Red::c_packageFamilyName, winrt::Windows::Management::Deployment::PackageStatus::Modified); + + auto packageDeploymentManager{ winrt::Microsoft::Windows::Management::Deployment::PackageDeploymentManager::GetDefault() }; + + winrt::Microsoft::Windows::Management::Deployment::PackageSet packageSet; + PCWSTR c_packageSetId{ L"RGB" }; + packageSet.Id(c_packageSetId); + winrt::Microsoft::Windows::Management::Deployment::PackageSetItem red{ Make_PackageSetItem(::TPF::Red::GetPackageFullName(), ::TPF::Red::c_packageDirName) }; + packageSet.PackageSetItems().Append(red); + + winrt::Microsoft::Windows::Management::Deployment::EnsureIsReadyOptions options; + auto deploymentResult{ packageDeploymentManager.EnsurePackageSetIsReadyAsync(packageSet, options).get() }; + VERIFY_ARE_EQUAL(winrt::Microsoft::Windows::Management::Deployment::PackageDeploymentStatus::CompletedSuccess, deploymentResult.Status()); + VERIFY_ARE_EQUAL(S_OK, deploymentResult.ExtendedError(), WEX::Common::String().Format(L"0x%X", deploymentResult.ExtendedError())); + + VERIFY_IS_TRUE(packageDeploymentManager.IsPackageSetReady(packageSet)); + + //TODO REMOVE ClearPackageStatus(::TPF::Red::c_packageFamilyName, winrt::Windows::Management::Deployment::PackageStatus::Modified); + } + + TEST_METHOD(EnsurePackageSetIsReadyAsync_N_NotInstalled_Success) + { + RemovePackage_Red(); + RemovePackage_Green(); + RemovePackage_Blue(); + + auto packageDeploymentManager{ winrt::Microsoft::Windows::Management::Deployment::PackageDeploymentManager::GetDefault() }; + + winrt::Microsoft::Windows::Management::Deployment::PackageSet packageSet; + PCWSTR c_packageSetId{ L"RGB" }; + packageSet.Id(c_packageSetId); + winrt::Microsoft::Windows::Management::Deployment::PackageSetItem red{ Make_PackageSetItem(::TPF::Red::GetPackageFullName(), ::TPF::Red::c_packageDirName) }; + packageSet.PackageSetItems().Append(red); + winrt::Microsoft::Windows::Management::Deployment::PackageSetItem green{ Make_PackageSetItem(::TPF::Green::GetPackageFullName(), ::TPF::Green::c_packageDirName) }; + packageSet.PackageSetItems().Append(green); + winrt::Microsoft::Windows::Management::Deployment::PackageSetItem blue{ Make_PackageSetItem(::TPF::Blue::GetPackageFullName(), ::TPF::Blue::c_packageDirName) }; + packageSet.PackageSetItems().Append(blue); + + winrt::Microsoft::Windows::Management::Deployment::EnsureIsReadyOptions options; + auto deploymentResult{ packageDeploymentManager.EnsurePackageSetIsReadyAsync(packageSet, options).get() }; + VERIFY_ARE_EQUAL(winrt::Microsoft::Windows::Management::Deployment::PackageDeploymentStatus::CompletedSuccess, deploymentResult.Status()); + VERIFY_ARE_EQUAL(S_OK, deploymentResult.ExtendedError(), WEX::Common::String().Format(L"0x%X", deploymentResult.ExtendedError())); + + VERIFY_IS_TRUE(packageDeploymentManager.IsPackageSetReady(packageSet)); + } + + TEST_METHOD(EnsurePackageSetIsReadyAsync_N_Registered_Success) + { + AddPackage_Red(); + AddPackage_Green(); + AddPackage_Blue(); + + auto packageDeploymentManager{ winrt::Microsoft::Windows::Management::Deployment::PackageDeploymentManager::GetDefault() }; + + winrt::Microsoft::Windows::Management::Deployment::PackageSet packageSet; + PCWSTR c_packageSetId{ L"RGB" }; + packageSet.Id(c_packageSetId); + winrt::Microsoft::Windows::Management::Deployment::PackageSetItem red{ Make_PackageSetItem(::TPF::Red::GetPackageFullName(), ::TPF::Red::c_packageDirName) }; + packageSet.PackageSetItems().Append(red); + winrt::Microsoft::Windows::Management::Deployment::PackageSetItem green{ Make_PackageSetItem(::TPF::Green::GetPackageFullName(), ::TPF::Green::c_packageDirName) }; + packageSet.PackageSetItems().Append(green); + winrt::Microsoft::Windows::Management::Deployment::PackageSetItem blue{ Make_PackageSetItem(::TPF::Blue::GetPackageFullName(), ::TPF::Blue::c_packageDirName) }; + packageSet.PackageSetItems().Append(blue); + + winrt::Microsoft::Windows::Management::Deployment::EnsureIsReadyOptions options; + auto deploymentResult{ packageDeploymentManager.EnsurePackageSetIsReadyAsync(packageSet, options).get() }; + VERIFY_ARE_EQUAL(winrt::Microsoft::Windows::Management::Deployment::PackageDeploymentStatus::CompletedSuccess, deploymentResult.Status()); + VERIFY_ARE_EQUAL(S_OK, deploymentResult.ExtendedError(), WEX::Common::String().Format(L"0x%X", deploymentResult.ExtendedError())); + + VERIFY_IS_TRUE(packageDeploymentManager.IsPackageSetReady(packageSet)); + } + + TEST_METHOD(EnsurePackageSetIsReadyAsync_N_NewerRegistered_Success) + { + AddPackage_Redder(); + AddPackage_Green(); + AddPackage_Blue(); + + auto packageDeploymentManager{ winrt::Microsoft::Windows::Management::Deployment::PackageDeploymentManager::GetDefault() }; + + winrt::Microsoft::Windows::Management::Deployment::PackageSet packageSet; + PCWSTR c_packageSetId{ L"RGB" }; + packageSet.Id(c_packageSetId); + winrt::Microsoft::Windows::Management::Deployment::PackageSetItem red{ Make_PackageSetItem(::TPF::Red::GetPackageFullName(), ::TPF::Red::c_packageDirName) }; + packageSet.PackageSetItems().Append(red); + winrt::Microsoft::Windows::Management::Deployment::PackageSetItem green{ Make_PackageSetItem(::TPF::Green::GetPackageFullName(), ::TPF::Green::c_packageDirName) }; + packageSet.PackageSetItems().Append(green); + winrt::Microsoft::Windows::Management::Deployment::PackageSetItem blue{ Make_PackageSetItem(::TPF::Blue::GetPackageFullName(), ::TPF::Blue::c_packageDirName) }; + packageSet.PackageSetItems().Append(blue); + + winrt::Microsoft::Windows::Management::Deployment::EnsureIsReadyOptions options; + auto deploymentResult{ packageDeploymentManager.EnsurePackageSetIsReadyAsync(packageSet, options).get() }; + VERIFY_ARE_EQUAL(winrt::Microsoft::Windows::Management::Deployment::PackageDeploymentStatus::CompletedSuccess, deploymentResult.Status()); + VERIFY_ARE_EQUAL(S_OK, deploymentResult.ExtendedError(), WEX::Common::String().Format(L"0x%X", deploymentResult.ExtendedError())); + + VERIFY_IS_TRUE(packageDeploymentManager.IsPackageSetReady(packageSet)); + + RemovePackage_Redder(); + } + + TEST_METHOD(EnsurePackageSetIsReadyAsync_N_OlderRegistered_Success) + { + AddPackage_Red(); + AddPackage_Green(); + AddPackage_Blue(); + + auto packageDeploymentManager{ winrt::Microsoft::Windows::Management::Deployment::PackageDeploymentManager::GetDefault() }; + + winrt::Microsoft::Windows::Management::Deployment::PackageSet packageSet; + PCWSTR c_packageSetId{ L"RGB" }; + packageSet.Id(c_packageSetId); + winrt::Microsoft::Windows::Management::Deployment::PackageSetItem redder{ Make_PackageSetItem(::TPF::Redder::GetPackageFullName(), ::TPF::Redder::c_packageDirName) }; + packageSet.PackageSetItems().Append(redder); + winrt::Microsoft::Windows::Management::Deployment::PackageSetItem green{ Make_PackageSetItem(::TPF::Green::GetPackageFullName(), ::TPF::Green::c_packageDirName) }; + packageSet.PackageSetItems().Append(green); + winrt::Microsoft::Windows::Management::Deployment::PackageSetItem blue{ Make_PackageSetItem(::TPF::Blue::GetPackageFullName(), ::TPF::Blue::c_packageDirName) }; + packageSet.PackageSetItems().Append(blue); + + winrt::Microsoft::Windows::Management::Deployment::EnsureIsReadyOptions options; + auto deploymentResult{ packageDeploymentManager.EnsurePackageSetIsReadyAsync(packageSet, options).get() }; + VERIFY_ARE_EQUAL(winrt::Microsoft::Windows::Management::Deployment::PackageDeploymentStatus::CompletedSuccess, deploymentResult.Status()); + VERIFY_ARE_EQUAL(S_OK, deploymentResult.ExtendedError(), WEX::Common::String().Format(L"0x%X", deploymentResult.ExtendedError())); + + VERIFY_IS_TRUE(packageDeploymentManager.IsPackageSetReady(packageSet)); + + RemovePackage_Redder(); + } + + TEST_METHOD(EnsurePackageSetIsReadyAsync_N_RegisteredAndNotInstalled_Success) + { + AddPackage_Red(); + RemovePackage_Green(); + + auto packageDeploymentManager{ winrt::Microsoft::Windows::Management::Deployment::PackageDeploymentManager::GetDefault() }; + + winrt::Microsoft::Windows::Management::Deployment::PackageSet packageSet; + PCWSTR c_packageSetId{ L"RGB" }; + packageSet.Id(c_packageSetId); + winrt::Microsoft::Windows::Management::Deployment::PackageSetItem red{ Make_PackageSetItem(::TPF::Red::GetPackageFullName(), ::TPF::Red::c_packageDirName) }; + packageSet.PackageSetItems().Append(red); + winrt::Microsoft::Windows::Management::Deployment::PackageSetItem green{ Make_PackageSetItem(::TPF::Green::GetPackageFullName(), ::TPF::Green::c_packageDirName) }; + packageSet.PackageSetItems().Append(green); + + winrt::Microsoft::Windows::Management::Deployment::EnsureIsReadyOptions options; + auto deploymentResult{ packageDeploymentManager.EnsurePackageSetIsReadyAsync(packageSet, options).get() }; + VERIFY_ARE_EQUAL(winrt::Microsoft::Windows::Management::Deployment::PackageDeploymentStatus::CompletedSuccess, deploymentResult.Status()); + VERIFY_ARE_EQUAL(S_OK, deploymentResult.ExtendedError(), WEX::Common::String().Format(L"0x%X", deploymentResult.ExtendedError())); + + VERIFY_IS_TRUE(packageDeploymentManager.IsPackageSetReady(packageSet)); + } + + TEST_METHOD(EnsurePackageSetIsReadyAsync_N_RegisteredAndNotInstalledAndStaged_Success) + { + BEGIN_TEST_METHOD_PROPERTIES() + TEST_CLASS_PROPERTY(L"RunAs", L"ElevatedUser") + END_TEST_METHOD_PROPERTIES() + + AddPackage_Red(); + RemovePackage_Green(); + StagePackage_Blue(); + + auto packageDeploymentManager{ winrt::Microsoft::Windows::Management::Deployment::PackageDeploymentManager::GetDefault() }; + + winrt::Microsoft::Windows::Management::Deployment::PackageSet packageSet; + PCWSTR c_packageSetId{ L"RGB" }; + packageSet.Id(c_packageSetId); + winrt::Microsoft::Windows::Management::Deployment::PackageSetItem red{ Make_PackageSetItem(::TPF::Red::GetPackageFullName(), ::TPF::Red::c_packageDirName) }; + packageSet.PackageSetItems().Append(red); + winrt::Microsoft::Windows::Management::Deployment::PackageSetItem green{ Make_PackageSetItem(::TPF::Green::GetPackageFullName(), ::TPF::Green::c_packageDirName) }; + packageSet.PackageSetItems().Append(green); + winrt::Microsoft::Windows::Management::Deployment::PackageSetItem blue{ Make_PackageSetItem(::TPF::Green::GetPackageFullName(), ::TPF::Green::c_packageDirName) }; + packageSet.PackageSetItems().Append(blue); + + winrt::Microsoft::Windows::Management::Deployment::EnsureIsReadyOptions options; + auto deploymentResult{ packageDeploymentManager.EnsurePackageSetIsReadyAsync(packageSet, options).get() }; + VERIFY_ARE_EQUAL(winrt::Microsoft::Windows::Management::Deployment::PackageDeploymentStatus::CompletedSuccess, deploymentResult.Status()); + VERIFY_ARE_EQUAL(S_OK, deploymentResult.ExtendedError(), WEX::Common::String().Format(L"0x%X", deploymentResult.ExtendedError())); + + VERIFY_IS_TRUE(packageDeploymentManager.IsPackageSetReady(packageSet)); + } + + TEST_METHOD(EnsurePackageSetIsReadyAsync_N_RegisteredPackageStatusOkAndBad_Success) + { + BEGIN_TEST_METHOD_PROPERTIES() + TEST_CLASS_PROPERTY(L"RunAs", L"ElevatedUser") + END_TEST_METHOD_PROPERTIES() + + AddPackage_Red(); + AddPackage_Green(); + SetPackageStatus(::TPF::Green::c_packageFamilyName, winrt::Windows::Management::Deployment::PackageStatus::Modified); + + auto packageDeploymentManager{ winrt::Microsoft::Windows::Management::Deployment::PackageDeploymentManager::GetDefault() }; + + winrt::Microsoft::Windows::Management::Deployment::PackageSet packageSet; + PCWSTR c_packageSetId{ L"RGB" }; + packageSet.Id(c_packageSetId); + winrt::Microsoft::Windows::Management::Deployment::PackageSetItem red{ Make_PackageSetItem(::TPF::Red::GetPackageFullName(), ::TPF::Red::c_packageDirName) }; + packageSet.PackageSetItems().Append(red); + winrt::Microsoft::Windows::Management::Deployment::PackageSetItem green{ Make_PackageSetItem(::TPF::Green::GetPackageFullName(), ::TPF::Green::c_packageDirName) }; + packageSet.PackageSetItems().Append(green); + + winrt::Microsoft::Windows::Management::Deployment::EnsureIsReadyOptions options; + auto deploymentResult{ packageDeploymentManager.EnsurePackageSetIsReadyAsync(packageSet, options).get() }; + VERIFY_ARE_EQUAL(winrt::Microsoft::Windows::Management::Deployment::PackageDeploymentStatus::CompletedSuccess, deploymentResult.Status()); + VERIFY_ARE_EQUAL(S_OK, deploymentResult.ExtendedError(), WEX::Common::String().Format(L"0x%X", deploymentResult.ExtendedError())); + + VERIFY_IS_TRUE(packageDeploymentManager.IsPackageSetReady(packageSet)); + + //TODO REMOVE ClearPackageStatus(::TPF::Green::c_packageFamilyName, winrt::Windows::Management::Deployment::PackageStatus::Modified); + } + + TEST_METHOD(AddPackageByUriAsync_NoSuchPackage_Fail) + { + auto packageDeploymentManager{ winrt::Microsoft::Windows::Management::Deployment::PackageDeploymentManager::GetDefault() }; + + PCWSTR c_packageUriAsString{ L"file://c:/does/not/exist.msix" }; + winrt::Windows::Foundation::Uri packageUri{ c_packageUriAsString }; + + winrt::Microsoft::Windows::Management::Deployment::AddPackageOptions options; + auto deploymentResult{ packageDeploymentManager.AddPackageByUriAsync(packageUri, options).get() }; + VERIFY_ARE_EQUAL(winrt::Microsoft::Windows::Management::Deployment::PackageDeploymentStatus::CompletedFailure, deploymentResult.Status()); + VERIFY_ARE_EQUAL(HRESULT_FROM_WIN32(ERROR_INSTALL_OPEN_PACKAGE_FAILED), deploymentResult.ExtendedError(), WEX::Common::String().Format(L"0x%X", deploymentResult.ExtendedError())); + } + + TEST_METHOD(AddPackageByUriAsync_NotInstalled_Success) + { + RemovePackage_Red(); + + auto packageDeploymentManager{ winrt::Microsoft::Windows::Management::Deployment::PackageDeploymentManager::GetDefault() }; + + winrt::Windows::Foundation::Uri packageUri{ TP::GetMsixPackageUri(::TPF::Red::c_packageDirName) }; + + winrt::Microsoft::Windows::Management::Deployment::AddPackageOptions options; + auto deploymentResult{ packageDeploymentManager.AddPackageByUriAsync(packageUri, options).get() }; + VERIFY_ARE_EQUAL(winrt::Microsoft::Windows::Management::Deployment::PackageDeploymentStatus::CompletedSuccess, deploymentResult.Status()); + VERIFY_ARE_EQUAL(S_OK, deploymentResult.ExtendedError(), WEX::Common::String().Format(L"0x%X", deploymentResult.ExtendedError())); + + VERIFY_IS_TRUE(IsPackageRegistered_Red()); + } + + TEST_METHOD(AddPackageByUriAsync_Staged_Success) + { + BEGIN_TEST_METHOD_PROPERTIES() + TEST_CLASS_PROPERTY(L"RunAs", L"ElevatedUser") + END_TEST_METHOD_PROPERTIES() + + StagePackage_Red(); + + auto packageDeploymentManager{ winrt::Microsoft::Windows::Management::Deployment::PackageDeploymentManager::GetDefault() }; + + winrt::Windows::Foundation::Uri packageUri{ TP::GetMsixPackageUri(::TPF::Red::c_packageDirName) }; + + winrt::Microsoft::Windows::Management::Deployment::AddPackageOptions options; + auto deploymentResult{ packageDeploymentManager.AddPackageByUriAsync(packageUri, options).get() }; + VERIFY_ARE_EQUAL(winrt::Microsoft::Windows::Management::Deployment::PackageDeploymentStatus::CompletedSuccess, deploymentResult.Status()); + VERIFY_ARE_EQUAL(S_OK, deploymentResult.ExtendedError(), WEX::Common::String().Format(L"0x%X", deploymentResult.ExtendedError())); + + VERIFY_IS_TRUE(IsPackageRegistered_Red()); + } + + TEST_METHOD(AddPackageByUriAsync_Registered_Success) + { + AddPackage_Red(); + + auto packageDeploymentManager{ winrt::Microsoft::Windows::Management::Deployment::PackageDeploymentManager::GetDefault() }; + + winrt::Windows::Foundation::Uri packageUri{ TP::GetMsixPackageUri(::TPF::Red::c_packageDirName) }; + + winrt::Microsoft::Windows::Management::Deployment::AddPackageOptions options; + auto deploymentResult{ packageDeploymentManager.AddPackageByUriAsync(packageUri, options).get() }; + VERIFY_ARE_EQUAL(winrt::Microsoft::Windows::Management::Deployment::PackageDeploymentStatus::CompletedSuccess, deploymentResult.Status()); + VERIFY_ARE_EQUAL(S_OK, deploymentResult.ExtendedError(), WEX::Common::String().Format(L"0x%X", deploymentResult.ExtendedError())); + + VERIFY_IS_TRUE(IsPackageRegistered_Red()); + } + + TEST_METHOD(AddPackageByUriAsync_OlderRegistered_Success) + { + AddPackage_Red(); + + auto packageDeploymentManager{ winrt::Microsoft::Windows::Management::Deployment::PackageDeploymentManager::GetDefault() }; + + winrt::Windows::Foundation::Uri packageUri{ TP::GetMsixPackageUri(::TPF::Red::c_packageDirName) }; + + winrt::Microsoft::Windows::Management::Deployment::AddPackageOptions options; + auto deploymentResult{ packageDeploymentManager.AddPackageByUriAsync(packageUri, options).get() }; + VERIFY_ARE_EQUAL(winrt::Microsoft::Windows::Management::Deployment::PackageDeploymentStatus::CompletedSuccess, deploymentResult.Status()); + VERIFY_ARE_EQUAL(S_OK, deploymentResult.ExtendedError(), WEX::Common::String().Format(L"0x%X", deploymentResult.ExtendedError())); + + VERIFY_IS_TRUE(IsPackageRegistered_Red()); + + RemovePackage_Redder(); + } + + TEST_METHOD(AddPackageByUriAsync_NewerRegistered_Success) + { + AddPackage_Redder(); + + auto packageDeploymentManager{ winrt::Microsoft::Windows::Management::Deployment::PackageDeploymentManager::GetDefault() }; + + winrt::Windows::Foundation::Uri packageUri{ TP::GetMsixPackageUri(::TPF::Red::c_packageDirName) }; + + winrt::Microsoft::Windows::Management::Deployment::AddPackageOptions options; + auto deploymentResult{ packageDeploymentManager.AddPackageByUriAsync(packageUri, options).get() }; + VERIFY_ARE_EQUAL(winrt::Microsoft::Windows::Management::Deployment::PackageDeploymentStatus::CompletedSuccess, deploymentResult.Status()); + VERIFY_ARE_EQUAL(S_OK, deploymentResult.ExtendedError(), WEX::Common::String().Format(L"0x%X", deploymentResult.ExtendedError())); + + VERIFY_IS_TRUE(IsPackageRegistered_Redder()); + + RemovePackage_Redder(); + } + + TEST_METHOD(AddPackageByUriAsync_RegisteredPackageStatusBad_Success) + { + BEGIN_TEST_METHOD_PROPERTIES() + TEST_CLASS_PROPERTY(L"RunAs", L"ElevatedUser") + END_TEST_METHOD_PROPERTIES() + + AddPackage_Red(); + SetPackageStatus(::TPF::Red::c_packageFamilyName, winrt::Windows::Management::Deployment::PackageStatus::Modified); + + auto packageDeploymentManager{ winrt::Microsoft::Windows::Management::Deployment::PackageDeploymentManager::GetDefault() }; + + winrt::Windows::Foundation::Uri packageUri{ TP::GetMsixPackageUri(::TPF::Red::c_packageDirName) }; + + winrt::Microsoft::Windows::Management::Deployment::AddPackageOptions options; + auto deploymentResult{ packageDeploymentManager.AddPackageByUriAsync(packageUri, options).get() }; + VERIFY_ARE_EQUAL(winrt::Microsoft::Windows::Management::Deployment::PackageDeploymentStatus::CompletedSuccess, deploymentResult.Status()); + VERIFY_ARE_EQUAL(S_OK, deploymentResult.ExtendedError(), WEX::Common::String().Format(L"0x%X", deploymentResult.ExtendedError())); + + VERIFY_IS_TRUE(IsPackageRegistered_Red()); + + //TODO REMOVE ClearPackageStatus(::TPF::Red::c_packageFamilyName, winrt::Windows::Management::Deployment::PackageStatus::Modified); + } + + TEST_METHOD(AddPackageSetAsync_1_NoSuchPackage_Fail) + { + auto packageDeploymentManager{ winrt::Microsoft::Windows::Management::Deployment::PackageDeploymentManager::GetDefault() }; + + winrt::Microsoft::Windows::Management::Deployment::PackageSet packageSet; + PCWSTR c_packageSetId{ L"Does.Not.Exist" }; + packageSet.Id(c_packageSetId); + winrt::Microsoft::Windows::Management::Deployment::PackageSetItem packageSetItem; + PCWSTR c_packageFamilyName{ L"Does.Not.Exist_1234567890abc" }; + packageSetItem.PackageFamilyName(c_packageFamilyName); + PCWSTR c_packageUriAsString{ L"file://c:/does/not/exist.msix" }; + winrt::Windows::Foundation::Uri packageUri{ c_packageUriAsString }; + packageSetItem.PackageUri(packageUri); + packageSet.PackageSetItems().Append(packageSetItem); + + winrt::Microsoft::Windows::Management::Deployment::AddPackageSetOptions options; + auto deploymentResult{ packageDeploymentManager.AddPackageSetAsync(packageSet, options).get() }; + VERIFY_ARE_EQUAL(winrt::Microsoft::Windows::Management::Deployment::PackageDeploymentStatus::CompletedFailure, deploymentResult.Status()); + VERIFY_ARE_EQUAL(HRESULT_FROM_WIN32(ERROR_INSTALL_OPEN_PACKAGE_FAILED), deploymentResult.ExtendedError(), WEX::Common::String().Format(L"0x%X", deploymentResult.ExtendedError())); + + VERIFY_IS_FALSE(packageDeploymentManager.IsPackageSetReady(packageSet)); + } + + TEST_METHOD(AddPackageSetAsync_1_NotInstalled_Success) + { + RemovePackage_Red(); + + auto packageDeploymentManager{ winrt::Microsoft::Windows::Management::Deployment::PackageDeploymentManager::GetDefault() }; + + winrt::Microsoft::Windows::Management::Deployment::PackageSet packageSet; + PCWSTR c_packageSetId{ L"RGB" }; + packageSet.Id(c_packageSetId); + winrt::Microsoft::Windows::Management::Deployment::PackageSetItem red{ Make_PackageSetItem(::TPF::Red::GetPackageFullName(), ::TPF::Red::c_packageDirName) }; + packageSet.PackageSetItems().Append(red); + + winrt::Microsoft::Windows::Management::Deployment::AddPackageSetOptions options; + auto deploymentResult{ packageDeploymentManager.AddPackageSetAsync(packageSet, options).get() }; + VERIFY_ARE_EQUAL(winrt::Microsoft::Windows::Management::Deployment::PackageDeploymentStatus::CompletedSuccess, deploymentResult.Status()); + VERIFY_ARE_EQUAL(S_OK, deploymentResult.ExtendedError(), WEX::Common::String().Format(L"0x%X", deploymentResult.ExtendedError())); + + VERIFY_IS_TRUE(packageDeploymentManager.IsPackageSetReady(packageSet)); + } + + TEST_METHOD(AddPackageSetAsync_1_Staged_Success) + { + BEGIN_TEST_METHOD_PROPERTIES() + TEST_CLASS_PROPERTY(L"RunAs", L"ElevatedUser") + END_TEST_METHOD_PROPERTIES() + + StagePackage_Red(); + + auto packageDeploymentManager{ winrt::Microsoft::Windows::Management::Deployment::PackageDeploymentManager::GetDefault() }; + + winrt::Microsoft::Windows::Management::Deployment::PackageSet packageSet; + PCWSTR c_packageSetId{ L"RGB" }; + packageSet.Id(c_packageSetId); + winrt::Microsoft::Windows::Management::Deployment::PackageSetItem red{ Make_PackageSetItem(::TPF::Red::GetPackageFullName(), ::TPF::Red::c_packageDirName) }; + packageSet.PackageSetItems().Append(red); + + winrt::Microsoft::Windows::Management::Deployment::AddPackageSetOptions options; + auto deploymentResult{ packageDeploymentManager.AddPackageSetAsync(packageSet, options).get() }; + VERIFY_ARE_EQUAL(winrt::Microsoft::Windows::Management::Deployment::PackageDeploymentStatus::CompletedSuccess, deploymentResult.Status()); + VERIFY_ARE_EQUAL(S_OK, deploymentResult.ExtendedError(), WEX::Common::String().Format(L"0x%X", deploymentResult.ExtendedError())); + + VERIFY_IS_TRUE(packageDeploymentManager.IsPackageSetReady(packageSet)); + } + + TEST_METHOD(AddPackageSetAsync_1_Registered_Success) + { + AddPackage_Red(); + + auto packageDeploymentManager{ winrt::Microsoft::Windows::Management::Deployment::PackageDeploymentManager::GetDefault() }; + + winrt::Microsoft::Windows::Management::Deployment::PackageSet packageSet; + PCWSTR c_packageSetId{ L"RGB" }; + packageSet.Id(c_packageSetId); + winrt::Microsoft::Windows::Management::Deployment::PackageSetItem red{ Make_PackageSetItem(::TPF::Red::GetPackageFullName(), ::TPF::Red::c_packageDirName) }; + packageSet.PackageSetItems().Append(red); + + winrt::Microsoft::Windows::Management::Deployment::AddPackageSetOptions options; + auto deploymentResult{ packageDeploymentManager.AddPackageSetAsync(packageSet, options).get() }; + VERIFY_ARE_EQUAL(winrt::Microsoft::Windows::Management::Deployment::PackageDeploymentStatus::CompletedSuccess, deploymentResult.Status()); + VERIFY_ARE_EQUAL(S_OK, deploymentResult.ExtendedError(), WEX::Common::String().Format(L"0x%X", deploymentResult.ExtendedError())); + + VERIFY_IS_TRUE(packageDeploymentManager.IsPackageSetReady(packageSet)); + } + + TEST_METHOD(AddPackageSetAsync_1_OlderRegistered_Success) + { + AddPackage_Red(); + + auto packageDeploymentManager{ winrt::Microsoft::Windows::Management::Deployment::PackageDeploymentManager::GetDefault() }; + + winrt::Microsoft::Windows::Management::Deployment::PackageSet packageSet; + PCWSTR c_packageSetId{ L"RGB" }; + packageSet.Id(c_packageSetId); + winrt::Microsoft::Windows::Management::Deployment::PackageSetItem redder{ Make_PackageSetItem(::TPF::Redder::GetPackageFullName(), ::TPF::Redder::c_packageDirName) }; + packageSet.PackageSetItems().Append(redder); + + winrt::Microsoft::Windows::Management::Deployment::AddPackageSetOptions options; + auto deploymentResult{ packageDeploymentManager.AddPackageSetAsync(packageSet, options).get() }; + VERIFY_ARE_EQUAL(winrt::Microsoft::Windows::Management::Deployment::PackageDeploymentStatus::CompletedSuccess, deploymentResult.Status()); + VERIFY_ARE_EQUAL(S_OK, deploymentResult.ExtendedError(), WEX::Common::String().Format(L"0x%X", deploymentResult.ExtendedError())); + + VERIFY_IS_TRUE(packageDeploymentManager.IsPackageSetReady(packageSet)); + + RemovePackage_Redder(); + } + + TEST_METHOD(AddPackageSetAsync_1_NewerRegistered_Success) + { + AddPackage_Redder(); + + auto packageDeploymentManager{ winrt::Microsoft::Windows::Management::Deployment::PackageDeploymentManager::GetDefault() }; + + winrt::Microsoft::Windows::Management::Deployment::PackageSet packageSet; + PCWSTR c_packageSetId{ L"RGB" }; + packageSet.Id(c_packageSetId); + winrt::Microsoft::Windows::Management::Deployment::PackageSetItem red{ Make_PackageSetItem(::TPF::Red::GetPackageFullName(), ::TPF::Red::c_packageDirName) }; + packageSet.PackageSetItems().Append(red); + + winrt::Microsoft::Windows::Management::Deployment::AddPackageSetOptions options; + auto deploymentResult{ packageDeploymentManager.AddPackageSetAsync(packageSet, options).get() }; + VERIFY_ARE_EQUAL(winrt::Microsoft::Windows::Management::Deployment::PackageDeploymentStatus::CompletedSuccess, deploymentResult.Status()); + VERIFY_ARE_EQUAL(S_OK, deploymentResult.ExtendedError(), WEX::Common::String().Format(L"0x%X", deploymentResult.ExtendedError())); + + VERIFY_IS_TRUE(packageDeploymentManager.IsPackageSetReady(packageSet)); + + RemovePackage_Redder(); + } + + TEST_METHOD(AddPackageSetAsync_1_RegisteredPackageStatusBad_Success) + { + BEGIN_TEST_METHOD_PROPERTIES() + TEST_CLASS_PROPERTY(L"RunAs", L"ElevatedUser") + END_TEST_METHOD_PROPERTIES() + + AddPackage_Red(); + SetPackageStatus(::TPF::Red::c_packageFamilyName, winrt::Windows::Management::Deployment::PackageStatus::Modified); + + auto packageDeploymentManager{ winrt::Microsoft::Windows::Management::Deployment::PackageDeploymentManager::GetDefault() }; + + winrt::Microsoft::Windows::Management::Deployment::PackageSet packageSet; + PCWSTR c_packageSetId{ L"RGB" }; + packageSet.Id(c_packageSetId); + winrt::Microsoft::Windows::Management::Deployment::PackageSetItem red{ Make_PackageSetItem(::TPF::Red::GetPackageFullName(), ::TPF::Red::c_packageDirName) }; + packageSet.PackageSetItems().Append(red); + + winrt::Microsoft::Windows::Management::Deployment::AddPackageSetOptions options; + auto deploymentResult{ packageDeploymentManager.AddPackageSetAsync(packageSet, options).get() }; + VERIFY_ARE_EQUAL(winrt::Microsoft::Windows::Management::Deployment::PackageDeploymentStatus::CompletedSuccess, deploymentResult.Status()); + VERIFY_ARE_EQUAL(S_OK, deploymentResult.ExtendedError(), WEX::Common::String().Format(L"0x%X", deploymentResult.ExtendedError())); + + VERIFY_IS_TRUE(packageDeploymentManager.IsPackageSetReady(packageSet)); + + //TODO REMOVE ClearPackageStatus(::TPF::Red::c_packageFamilyName, winrt::Windows::Management::Deployment::PackageStatus::Modified); + } + + TEST_METHOD(AddPackageSetAsync_N_NotInstalled_Success) + { + RemovePackage_Red(); + RemovePackage_Green(); + RemovePackage_Blue(); + + auto packageDeploymentManager{ winrt::Microsoft::Windows::Management::Deployment::PackageDeploymentManager::GetDefault() }; + + winrt::Microsoft::Windows::Management::Deployment::PackageSet packageSet; + PCWSTR c_packageSetId{ L"RGB" }; + packageSet.Id(c_packageSetId); + winrt::Microsoft::Windows::Management::Deployment::PackageSetItem red{ Make_PackageSetItem(::TPF::Red::GetPackageFullName(), ::TPF::Red::c_packageDirName) }; + packageSet.PackageSetItems().Append(red); + winrt::Microsoft::Windows::Management::Deployment::PackageSetItem green{ Make_PackageSetItem(::TPF::Green::GetPackageFullName(), ::TPF::Green::c_packageDirName) }; + packageSet.PackageSetItems().Append(green); + winrt::Microsoft::Windows::Management::Deployment::PackageSetItem blue{ Make_PackageSetItem(::TPF::Blue::GetPackageFullName(), ::TPF::Blue::c_packageDirName) }; + packageSet.PackageSetItems().Append(blue); + + winrt::Microsoft::Windows::Management::Deployment::AddPackageSetOptions options; + auto deploymentResult{ packageDeploymentManager.AddPackageSetAsync(packageSet, options).get() }; + VERIFY_ARE_EQUAL(winrt::Microsoft::Windows::Management::Deployment::PackageDeploymentStatus::CompletedSuccess, deploymentResult.Status()); + VERIFY_ARE_EQUAL(S_OK, deploymentResult.ExtendedError(), WEX::Common::String().Format(L"0x%X", deploymentResult.ExtendedError())); + + VERIFY_IS_TRUE(packageDeploymentManager.IsPackageSetReady(packageSet)); + } + + TEST_METHOD(AddPackageSetAsync_N_Registered_Success) + { + AddPackage_Red(); + AddPackage_Green(); + AddPackage_Blue(); + + auto packageDeploymentManager{ winrt::Microsoft::Windows::Management::Deployment::PackageDeploymentManager::GetDefault() }; + + winrt::Microsoft::Windows::Management::Deployment::PackageSet packageSet; + PCWSTR c_packageSetId{ L"RGB" }; + packageSet.Id(c_packageSetId); + winrt::Microsoft::Windows::Management::Deployment::PackageSetItem red{ Make_PackageSetItem(::TPF::Red::GetPackageFullName(), ::TPF::Red::c_packageDirName) }; + packageSet.PackageSetItems().Append(red); + winrt::Microsoft::Windows::Management::Deployment::PackageSetItem green{ Make_PackageSetItem(::TPF::Green::GetPackageFullName(), ::TPF::Green::c_packageDirName) }; + packageSet.PackageSetItems().Append(green); + winrt::Microsoft::Windows::Management::Deployment::PackageSetItem blue{ Make_PackageSetItem(::TPF::Blue::GetPackageFullName(), ::TPF::Blue::c_packageDirName) }; + packageSet.PackageSetItems().Append(blue); + + winrt::Microsoft::Windows::Management::Deployment::AddPackageSetOptions options; + auto deploymentResult{ packageDeploymentManager.AddPackageSetAsync(packageSet, options).get() }; + VERIFY_ARE_EQUAL(winrt::Microsoft::Windows::Management::Deployment::PackageDeploymentStatus::CompletedSuccess, deploymentResult.Status()); + VERIFY_ARE_EQUAL(S_OK, deploymentResult.ExtendedError(), WEX::Common::String().Format(L"0x%X", deploymentResult.ExtendedError())); + + VERIFY_IS_TRUE(packageDeploymentManager.IsPackageSetReady(packageSet)); + } + + TEST_METHOD(AddPackageSetAsync_N_NewerRegistered_Success) + { + AddPackage_Redder(); + AddPackage_Green(); + AddPackage_Blue(); + + auto packageDeploymentManager{ winrt::Microsoft::Windows::Management::Deployment::PackageDeploymentManager::GetDefault() }; + + winrt::Microsoft::Windows::Management::Deployment::PackageSet packageSet; + PCWSTR c_packageSetId{ L"RGB" }; + packageSet.Id(c_packageSetId); + winrt::Microsoft::Windows::Management::Deployment::PackageSetItem red{ Make_PackageSetItem(::TPF::Red::GetPackageFullName(), ::TPF::Red::c_packageDirName) }; + packageSet.PackageSetItems().Append(red); + winrt::Microsoft::Windows::Management::Deployment::PackageSetItem green{ Make_PackageSetItem(::TPF::Green::GetPackageFullName(), ::TPF::Green::c_packageDirName) }; + packageSet.PackageSetItems().Append(green); + winrt::Microsoft::Windows::Management::Deployment::PackageSetItem blue{ Make_PackageSetItem(::TPF::Blue::GetPackageFullName(), ::TPF::Blue::c_packageDirName) }; + packageSet.PackageSetItems().Append(blue); + + winrt::Microsoft::Windows::Management::Deployment::AddPackageSetOptions options; + auto deploymentResult{ packageDeploymentManager.AddPackageSetAsync(packageSet, options).get() }; + VERIFY_ARE_EQUAL(winrt::Microsoft::Windows::Management::Deployment::PackageDeploymentStatus::CompletedSuccess, deploymentResult.Status()); + VERIFY_ARE_EQUAL(S_OK, deploymentResult.ExtendedError(), WEX::Common::String().Format(L"0x%X", deploymentResult.ExtendedError())); + + VERIFY_IS_TRUE(packageDeploymentManager.IsPackageSetReady(packageSet)); + + RemovePackage_Redder(); + } + + TEST_METHOD(AddPackageSetAsync_N_OlderRegistered_Success) + { + AddPackage_Red(); + AddPackage_Green(); + AddPackage_Blue(); + + auto packageDeploymentManager{ winrt::Microsoft::Windows::Management::Deployment::PackageDeploymentManager::GetDefault() }; + + winrt::Microsoft::Windows::Management::Deployment::PackageSet packageSet; + PCWSTR c_packageSetId{ L"RGB" }; + packageSet.Id(c_packageSetId); + winrt::Microsoft::Windows::Management::Deployment::PackageSetItem redder{ Make_PackageSetItem(::TPF::Redder::GetPackageFullName(), ::TPF::Redder::c_packageDirName) }; + packageSet.PackageSetItems().Append(redder); + winrt::Microsoft::Windows::Management::Deployment::PackageSetItem green{ Make_PackageSetItem(::TPF::Green::GetPackageFullName(), ::TPF::Green::c_packageDirName) }; + packageSet.PackageSetItems().Append(green); + winrt::Microsoft::Windows::Management::Deployment::PackageSetItem blue{ Make_PackageSetItem(::TPF::Blue::GetPackageFullName(), ::TPF::Blue::c_packageDirName) }; + packageSet.PackageSetItems().Append(blue); + + winrt::Microsoft::Windows::Management::Deployment::AddPackageSetOptions options; + auto deploymentResult{ packageDeploymentManager.AddPackageSetAsync(packageSet, options).get() }; + VERIFY_ARE_EQUAL(winrt::Microsoft::Windows::Management::Deployment::PackageDeploymentStatus::CompletedSuccess, deploymentResult.Status()); + VERIFY_ARE_EQUAL(S_OK, deploymentResult.ExtendedError(), WEX::Common::String().Format(L"0x%X", deploymentResult.ExtendedError())); + + VERIFY_IS_TRUE(packageDeploymentManager.IsPackageSetReady(packageSet)); + + RemovePackage_Redder(); + } + + TEST_METHOD(AddPackageSetAsync_N_RegisteredAndNotInstalled_Success) + { + AddPackage_Red(); + RemovePackage_Green(); + + auto packageDeploymentManager{ winrt::Microsoft::Windows::Management::Deployment::PackageDeploymentManager::GetDefault() }; + + winrt::Microsoft::Windows::Management::Deployment::PackageSet packageSet; + PCWSTR c_packageSetId{ L"RGB" }; + packageSet.Id(c_packageSetId); + winrt::Microsoft::Windows::Management::Deployment::PackageSetItem red{ Make_PackageSetItem(::TPF::Red::GetPackageFullName(), ::TPF::Red::c_packageDirName) }; + packageSet.PackageSetItems().Append(red); + winrt::Microsoft::Windows::Management::Deployment::PackageSetItem green{ Make_PackageSetItem(::TPF::Green::GetPackageFullName(), ::TPF::Green::c_packageDirName) }; + packageSet.PackageSetItems().Append(green); + + winrt::Microsoft::Windows::Management::Deployment::AddPackageSetOptions options; + auto deploymentResult{ packageDeploymentManager.AddPackageSetAsync(packageSet, options).get() }; + VERIFY_ARE_EQUAL(winrt::Microsoft::Windows::Management::Deployment::PackageDeploymentStatus::CompletedSuccess, deploymentResult.Status()); + VERIFY_ARE_EQUAL(S_OK, deploymentResult.ExtendedError(), WEX::Common::String().Format(L"0x%X", deploymentResult.ExtendedError())); + + VERIFY_IS_TRUE(packageDeploymentManager.IsPackageSetReady(packageSet)); + } + + TEST_METHOD(AddPackageSetAsync_N_RegisteredAndNotInstalledAndStaged_Success) + { + BEGIN_TEST_METHOD_PROPERTIES() + TEST_CLASS_PROPERTY(L"RunAs", L"ElevatedUser") + END_TEST_METHOD_PROPERTIES() + + AddPackage_Red(); + RemovePackage_Green(); + StagePackage_Blue(); + + auto packageDeploymentManager{ winrt::Microsoft::Windows::Management::Deployment::PackageDeploymentManager::GetDefault() }; + + winrt::Microsoft::Windows::Management::Deployment::PackageSet packageSet; + PCWSTR c_packageSetId{ L"RGB" }; + packageSet.Id(c_packageSetId); + winrt::Microsoft::Windows::Management::Deployment::PackageSetItem red{ Make_PackageSetItem(::TPF::Red::GetPackageFullName(), ::TPF::Red::c_packageDirName) }; + packageSet.PackageSetItems().Append(red); + winrt::Microsoft::Windows::Management::Deployment::PackageSetItem green{ Make_PackageSetItem(::TPF::Green::GetPackageFullName(), ::TPF::Green::c_packageDirName) }; + packageSet.PackageSetItems().Append(green); + winrt::Microsoft::Windows::Management::Deployment::PackageSetItem blue{ Make_PackageSetItem(::TPF::Green::GetPackageFullName(), ::TPF::Green::c_packageDirName) }; + packageSet.PackageSetItems().Append(blue); + + winrt::Microsoft::Windows::Management::Deployment::AddPackageSetOptions options; + auto deploymentResult{ packageDeploymentManager.AddPackageSetAsync(packageSet, options).get() }; + VERIFY_ARE_EQUAL(winrt::Microsoft::Windows::Management::Deployment::PackageDeploymentStatus::CompletedSuccess, deploymentResult.Status()); + VERIFY_ARE_EQUAL(S_OK, deploymentResult.ExtendedError(), WEX::Common::String().Format(L"0x%X", deploymentResult.ExtendedError())); + + VERIFY_IS_TRUE(packageDeploymentManager.IsPackageSetReady(packageSet)); + } + + TEST_METHOD(AddPackageSetAsync_N_RegisteredPackageStatusOkAndBad_Success) + { + BEGIN_TEST_METHOD_PROPERTIES() + TEST_CLASS_PROPERTY(L"RunAs", L"ElevatedUser") + END_TEST_METHOD_PROPERTIES() + + AddPackage_Red(); + AddPackage_Green(); + SetPackageStatus(::TPF::Green::c_packageFamilyName, winrt::Windows::Management::Deployment::PackageStatus::Modified); + + auto packageDeploymentManager{ winrt::Microsoft::Windows::Management::Deployment::PackageDeploymentManager::GetDefault() }; + + winrt::Microsoft::Windows::Management::Deployment::PackageSet packageSet; + PCWSTR c_packageSetId{ L"RGB" }; + packageSet.Id(c_packageSetId); + winrt::Microsoft::Windows::Management::Deployment::PackageSetItem red{ Make_PackageSetItem(::TPF::Red::GetPackageFullName(), ::TPF::Red::c_packageDirName) }; + packageSet.PackageSetItems().Append(red); + winrt::Microsoft::Windows::Management::Deployment::PackageSetItem green{ Make_PackageSetItem(::TPF::Green::GetPackageFullName(), ::TPF::Green::c_packageDirName) }; + packageSet.PackageSetItems().Append(green); + + winrt::Microsoft::Windows::Management::Deployment::AddPackageSetOptions options; + auto deploymentResult{ packageDeploymentManager.AddPackageSetAsync(packageSet, options).get() }; + VERIFY_ARE_EQUAL(winrt::Microsoft::Windows::Management::Deployment::PackageDeploymentStatus::CompletedSuccess, deploymentResult.Status()); + VERIFY_ARE_EQUAL(S_OK, deploymentResult.ExtendedError(), WEX::Common::String().Format(L"0x%X", deploymentResult.ExtendedError())); + + VERIFY_IS_TRUE(packageDeploymentManager.IsPackageSetReady(packageSet)); + + //TODO REMOVE ClearPackageStatus(::TPF::Green::c_packageFamilyName, winrt::Windows::Management::Deployment::PackageStatus::Modified); + } + + private: + winrt::Windows::Management::Deployment::PackageManager m_packageManager; + }; +} diff --git a/test/PackageManager/API/PackageManagerTests.Packages.h b/test/PackageManager/API/PackageManagerTests.Packages.h new file mode 100644 index 0000000000..2a8901c297 --- /dev/null +++ b/test/PackageManager/API/PackageManagerTests.Packages.h @@ -0,0 +1,231 @@ +// Copyright (c) Microsoft Corporation and Contributors. +// Licensed under the MIT License. + +#ifndef __PACKAGEMANAGERTESTS_PACKAGES_H +#define __PACKAGEMANAGERTESTS_PACKAGES_H + +namespace Test::Packages::Framework +{ +namespace Red +{ + constexpr PCWSTR c_packageDirName = L"PackageManager.Test.F.Red"; + constexpr PCWSTR c_packageFamilyName = L"Test.PackageManager.F.Red_8wekyb3d8bbwe"; + constexpr PCWSTR c_packageFullName_x86 = L"Test.PackageManager.F.Red_1.2.3.4_x86__8wekyb3d8bbwe"; + constexpr PCWSTR c_packageFullName_x64 = L"Test.PackageManager.F.Red_1.2.3.4_x64__8wekyb3d8bbwe"; + constexpr PCWSTR c_packageFullName_arm64 = L"Test.PackageManager.F.Red_1.2.3.4_arm64__8wekyb3d8bbwe"; + constexpr inline PCWSTR GetPackageFullName() + { +#if defined(_M_ARM64) + return c_packageFullName_arm64; +#elif defined(_M_IX86) + return c_packageFullName_x86; +#elif defined(_M_X64) + return c_packageFullName_x64; +#else +# error "Unknown processor architecture" +#endif + } +} +namespace Redder +{ + constexpr PCWSTR c_packageDirName = L"PackageManager.Test.F.Redder"; + constexpr PCWSTR c_packageFamilyName = L"Test.PackageManager.F.Red_8wekyb3d8bbwe"; + constexpr PCWSTR c_packageFullName_x86 = L"Test.PackageManager.F.Red_2.4.6.8_x86__8wekyb3d8bbwe"; + constexpr PCWSTR c_packageFullName_x64 = L"Test.PackageManager.F.Red_2.4.6.8_x64__8wekyb3d8bbwe"; + constexpr PCWSTR c_packageFullName_arm64 = L"Test.PackageManager.F.Red_2.4.6.8_arm64__8wekyb3d8bbwe"; + constexpr inline PCWSTR GetPackageFullName() + { +#if defined(_M_ARM64) + return c_packageFullName_arm64; +#elif defined(_M_IX86) + return c_packageFullName_x86; +#elif defined(_M_X64) + return c_packageFullName_x64; +#else +# error "Unknown processor architecture" +#endif + } +} +namespace Green +{ + constexpr PCWSTR c_packageDirName = L"PackageManager.Test.F.Green"; + constexpr PCWSTR c_packageFamilyName = L"Test.PackageManager.F.Green_8wekyb3d8bbwe"; + constexpr PCWSTR c_packageFullName_x86 = L"Test.PackageManager.F.Green_1.2.3.4_x86__8wekyb3d8bbwe"; + constexpr PCWSTR c_packageFullName_x64 = L"Test.PackageManager.F.Green_1.2.3.4_x64__8wekyb3d8bbwe"; + constexpr PCWSTR c_packageFullName_arm64 = L"Test.PackageManager.F.Green_1.2.3.4_arm64__8wekyb3d8bbwe"; + constexpr inline PCWSTR GetPackageFullName() + { +#if defined(_M_ARM64) + return c_packageFullName_arm64; +#elif defined(_M_IX86) + return c_packageFullName_x86; +#elif defined(_M_X64) + return c_packageFullName_x64; +#else +# error "Unknown processor architecture" +#endif + } +} +namespace Blue +{ + constexpr PCWSTR c_packageDirName = L"PackageManager.Test.F.Blue"; + constexpr PCWSTR c_packageFamilyName = L"Test.PackageManager.F.Blue_8wekyb3d8bbwe"; + constexpr PCWSTR c_packageFullName_x86 = L"Test.PackageManager.F.Blue_1.2.3.4_x86__8wekyb3d8bbwe"; + constexpr PCWSTR c_packageFullName_x64 = L"Test.PackageManager.F.Blue_1.2.3.4_x64__8wekyb3d8bbwe"; + constexpr PCWSTR c_packageFullName_arm64 = L"Test.PackageManager.F.Blue_1.2.3.4_arm64__8wekyb3d8bbwe"; + constexpr inline PCWSTR GetPackageFullName() + { +#if defined(_M_ARM64) + return c_packageFullName_arm64; +#elif defined(_M_IX86) + return c_packageFullName_x86; +#elif defined(_M_X64) + return c_packageFullName_x64; +#else +# error "Unknown processor architecture" +#endif + } +} +} + +namespace Test::PackageManager::Tests +{ + namespace TP = ::Test::Packages; + namespace TPF = ::Test::Packages::Framework; + + inline winrt::Microsoft::Windows::Management::Deployment::PackageSetItem Make_PackageSetItem( + PCWSTR packageFullName, + PCWSTR packageDirName) + { + + WEX::Logging::Log::Comment(WEX::Common::String().Format(L"PackageSetItem: PackageFullName:%s Path:%s", packageFullName, packageDirName)); + const auto [packageName, packageVersion, packageArchitecture, packageResourceId, packagePublisherId, packageFamilyName]{ ::AppModel::Package::ParsePackageFullName(packageFullName) }; + + winrt::Microsoft::Windows::Management::Deployment::PackageSetItem psi; + psi.PackageFamilyName(packageFamilyName); + psi.PackageUri(TP::GetMsixPackageUri(packageDirName)); + const ::AppModel::Identity::PackageVersion version{ packageVersion }; + psi.MinVersion(version.ToWinrtPackageVersion()); + return psi; + } + + inline void AddPackage_Red() + { + TP::AddPackageIfNecessary(Test::Packages::Framework::Red::c_packageDirName, TPF::Red::GetPackageFullName()); + } + inline void StagePackage_Red() + { + TP::StagePackageIfNecessary(Test::Packages::Framework::Red::c_packageDirName, TPF::Red::GetPackageFullName()); + } + inline void RemovePackage_Red() + { + // Best-effort removal. PackageManager.RemovePackage errors if the package + // is not registered, but if it's not registered we're good. "'Tis the destination + // that matters, not the journey" so regardless how much or little work + // we need do, we're happy as long as the package isn't registered when we're done + // + // Thus, do a *IfNecessary removal + TP::RemovePackageIfNecessary(TPF::Red::GetPackageFullName()); + } + inline bool IsPackageRegistered_Red() + { + return TP::IsPackageRegistered(TPF::Red::GetPackageFullName()); + } + + inline void AddPackage_Redder() + { + TP::AddPackageIfNecessary(Test::Packages::Framework::Redder::c_packageDirName, TPF::Redder::GetPackageFullName()); + } + inline void StagePackage_Redder() + { + TP::StagePackageIfNecessary(Test::Packages::Framework::Redder::c_packageDirName, TPF::Redder::GetPackageFullName()); + } + inline void RemovePackage_Redder() + { + // Best-effort removal. PackageManager.RemovePackage errors if the package + // is not registered, but if it's not registered we're good. "'Tis the destination + // that matters, not the journey" so regardless how much or little work + // we need do, we're happy as long as the package isn't registered when we're done + // + // Thus, do a *IfNecessary removal + TP::RemovePackageIfNecessary(TPF::Redder::GetPackageFullName()); + } + inline bool IsPackageRegistered_Redder() + { + return TP::IsPackageRegistered(TPF::Redder::GetPackageFullName()); + } + + inline void AddPackage_Green() + { + TP::AddPackageIfNecessary(Test::Packages::Framework::Green::c_packageDirName, TPF::Green::GetPackageFullName()); + } + inline void StagePackage_Green() + { + TP::StagePackageIfNecessary(Test::Packages::Framework::Green::c_packageDirName, TPF::Green::GetPackageFullName()); + } + inline void RemovePackage_Green() + { + // Best-effort removal. PackageManager.RemovePackage errors if the package + // is not registered, but if it's not registered we're good. "'Tis the destination + // that matters, not the journey" so regardless how much or little work + // we need do, we're happy as long as the package isn't registered when we're done + // + // Thus, do a *IfNecessary removal + TP::RemovePackageIfNecessary(TPF::Green::GetPackageFullName()); + } + inline bool IsPackageRegistered_Green() + { + return TP::IsPackageRegistered(TPF::Green::GetPackageFullName()); + } + + inline void AddPackage_Blue() + { + TP::AddPackageIfNecessary(Test::Packages::Framework::Blue::c_packageDirName, TPF::Blue::GetPackageFullName()); + } + inline void StagePackage_Blue() + { + TP::StagePackageIfNecessary(Test::Packages::Framework::Blue::c_packageDirName, TPF::Blue::GetPackageFullName()); + } + inline void RemovePackage_Blue() + { + // Best-effort removal. PackageManager.RemovePackage errors if the package + // is not registered, but if it's not registered we're good. "'Tis the destination + // that matters, not the journey" so regardless how much or little work + // we need do, we're happy as long as the package isn't registered when we're done + // + // Thus, do a *IfNecessary removal + TP::RemovePackageIfNecessary(TPF::Blue::GetPackageFullName()); + } + inline bool IsPackageRegistered_Blue() + { + return TP::IsPackageRegistered(TPF::Blue::GetPackageFullName()); + } + + inline winrt::Windows::ApplicationModel::PackageStatus GetPackageStatus(winrt::Windows::Management::Deployment::PackageManager packageManager, PCWSTR packageFullName) + { + auto package{ packageManager.FindPackageForUser(winrt::hstring(), packageFullName) }; + return package.Status(); + } + + inline void SetPackageStatus(winrt::Windows::Management::Deployment::PackageManager packageManager, PCWSTR packageFamilyName, winrt::Windows::Management::Deployment::PackageStatus status) + { + const auto packageTypes{ winrt::Windows::Management::Deployment::PackageTypes::Framework }; + auto packages{ packageManager.FindPackagesForUserWithPackageTypes(winrt::hstring(), packageFamilyName, packageTypes) }; + for (const winrt::Windows::ApplicationModel::Package& package : packages) + { + packageManager.SetPackageStatus(package.Id().FullName(), status); + } + } + + inline void ClearPackageStatus(winrt::Windows::Management::Deployment::PackageManager packageManager, PCWSTR packageFamilyName, winrt::Windows::Management::Deployment::PackageStatus status) + { + const auto packageTypes{ winrt::Windows::Management::Deployment::PackageTypes::Framework }; + auto packages{ packageManager.FindPackagesForUserWithPackageTypes(winrt::hstring(), packageFamilyName, packageTypes) }; + for (const winrt::Windows::ApplicationModel::Package& package : packages) + { + packageManager.ClearPackageStatus(package.Id().FullName(), status); + } + } +} + +#endif // __PACKAGEMANAGERTESTS_PACKAGES_H diff --git a/test/PackageManager/API/PackageManagerTests.vcxproj b/test/PackageManager/API/PackageManagerTests.vcxproj new file mode 100644 index 0000000000..a874267c5e --- /dev/null +++ b/test/PackageManager/API/PackageManagerTests.vcxproj @@ -0,0 +1,172 @@ + + + + + + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + Debug + ARM64 + + + Release + ARM64 + + + + 16.0 + {4a38cb80-3580-4960-9b31-3301058b7afe} + Win32Proj + PackageManagerTests + 10.0 + NativeUnitTestProject + PackageManagerTests + + + DynamicLibrary + false + v143 + Unicode + + + true + + + false + + + + + + + + + + + + + + + + + + + + + + + + + + + Use + true + pch.h + $(RepoRoot)\test\inc;$(RepoRoot)\dev\common;$(VCInstallDir)UnitTest\include;$(OutDir)\..\WindowsAppRuntime_DLL;$(OutDir)\..\WindowsAppRuntime_BootstrapDLL;%(AdditionalIncludeDirectories) + $(RepoRoot);%(AdditionalIncludeDirectories) + + + Windows + onecore.lib;onecoreuap.lib;Microsoft.WindowsAppRuntime.lib;wex.common.lib;wex.logger.lib;te.common.lib;%(AdditionalDependencies) + $(VCInstallDir)UnitTest\lib;%(AdditionalLibraryDirectories);$(OutDir)\..\WindowsAppRuntime_DLL + Microsoft.WindowsAppRuntime.Bootstrap.dll;%(DelayLoadDLLs) + + + + + _DEBUG;%(PreprocessorDefinitions) + + + + + NDEBUG;%(PreprocessorDefinitions) + + + + + WIN32;%(PreprocessorDefinitions) + + + + + Create + + + + + + + + + + + + + + $(OutDir)\..\WindowsAppRuntime_DLL\Microsoft.Windows.Management.Deployment.winmd + true + + + + + $(OutDir)\..\WindowsAppRuntime_DLL\Microsoft.Windows.ApplicationModel.DynamicDependency.winmd + true + + + + + $(OutDir)\..\WindowsAppRuntime_DLL\Microsoft.Windows.ApplicationModel.WindowsAppRuntime.winmd + true + + + + + + + + {f76b776e-86f5-48c5-8fc7-d2795ecc9746} + + + + + + + + + + + + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + + + + + + + + + + diff --git a/test/PackageManager/API/PackageManagerTests.vcxproj.filters b/test/PackageManager/API/PackageManagerTests.vcxproj.filters new file mode 100644 index 0000000000..50298e2af0 --- /dev/null +++ b/test/PackageManager/API/PackageManagerTests.vcxproj.filters @@ -0,0 +1,39 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Source Files + + + Source Files + + + Source Files + + + + + Header Files + + + Header Files + + + + + + diff --git a/test/PackageManager/API/PackageRuntimeManagerTests.cpp b/test/PackageManager/API/PackageRuntimeManagerTests.cpp new file mode 100644 index 0000000000..9156b375ac --- /dev/null +++ b/test/PackageManager/API/PackageRuntimeManagerTests.cpp @@ -0,0 +1,582 @@ +// Copyright (c) Microsoft Corporation and Contributors. +// Licensed under the MIT License. + +#include "pch.h" + +#include + +namespace TB = ::Test::Bootstrap; +namespace TP = ::Test::Packages; +namespace TPF = ::Test::Packages::Framework; +namespace TPMT = ::Test::PackageManager::Tests; + +namespace Test::PackageManager::Tests +{ + class PackageRuntimeManagerTests + { + public: + BEGIN_TEST_CLASS(PackageRuntimeManagerTests) + TEST_CLASS_PROPERTY(L"ThreadingModel", L"MTA") + END_TEST_CLASS() + + TEST_CLASS_SETUP(ClassSetup) + { + if (!::WindowsVersion::IsWindows11_22H2OrGreater()) + { + WEX::Logging::Log::Result(WEX::Logging::TestResults::Skipped, L"PackageRuntimeManager requires >= 22H2 (Sun Valley 2). Skipping tests"); + return true; + } + RemovePackage_Blue(); + RemovePackage_Green(); + RemovePackage_Redder(); + RemovePackage_Red(); + ::TB::Setup(); + AddPackage_Red(); + AddPackage_Green(); + AddPackage_Blue(); + return true; + } + + TEST_CLASS_CLEANUP(ClassCleanup) + { + RemovePackage_Blue(); + RemovePackage_Green(); + RemovePackage_Redder(); + RemovePackage_Red(); + ::TB::Cleanup(); + return true; + } + + void SetPackageStatus(PCWSTR packageFamilyName, winrt::Windows::Management::Deployment::PackageStatus status) + { + TPMT::SetPackageStatus(m_packageManager, packageFamilyName, status); + } + + void ClearPackageStatus(PCWSTR packageFamilyName, winrt::Windows::Management::Deployment::PackageStatus status) + { + TPMT::ClearPackageStatus(m_packageManager, packageFamilyName, status); + } + + TEST_METHOD(AddPackageSet_InvalidParameter) + { + auto packageRuntimeManager{ winrt::Microsoft::Windows::Management::Deployment::PackageRuntimeManager::GetDefault() }; + + try + { + winrt::Microsoft::Windows::Management::Deployment::PackageSet packageSet; + winrt::Microsoft::Windows::ApplicationModel::DynamicDependency::CreatePackageDependencyOptions createOptions; + winrt::Microsoft::Windows::ApplicationModel::DynamicDependency::AddPackageDependencyOptions addOptions; + packageRuntimeManager.AddPackageSet(packageSet, createOptions, addOptions); + VERIFY_FAIL(L"Success is not expected"); + } + catch (winrt::hresult_error& e) + { + VERIFY_ARE_EQUAL(E_INVALIDARG, e.code(), WEX::Common::String().Format(L"0x%X %s", e.code(), e.message().c_str())); + } + + try + { + winrt::Microsoft::Windows::Management::Deployment::PackageSet packageSet; + PCWSTR c_packageSetId{ L"Does.Not.Exist" }; + packageSet.Id(c_packageSetId); + + winrt::Microsoft::Windows::ApplicationModel::DynamicDependency::CreatePackageDependencyOptions createOptions; + winrt::Microsoft::Windows::ApplicationModel::DynamicDependency::AddPackageDependencyOptions addOptions; + packageRuntimeManager.AddPackageSet(packageSet, createOptions, addOptions); + VERIFY_FAIL(L"Success is not expected"); + } + catch (winrt::hresult_error& e) + { + VERIFY_ARE_EQUAL(E_INVALIDARG, e.code(), WEX::Common::String().Format(L"0x%X %s", e.code(), e.message().c_str())); + } + + try + { + winrt::Microsoft::Windows::Management::Deployment::PackageSet packageSet; + PCWSTR c_packageSetId{ L"Does.Not.Exist" }; + packageSet.Id(c_packageSetId); + winrt::Microsoft::Windows::Management::Deployment::PackageSetItem packageSetItem; + packageSet.PackageSetItems().Append(packageSetItem); + + winrt::Microsoft::Windows::ApplicationModel::DynamicDependency::CreatePackageDependencyOptions createOptions; + winrt::Microsoft::Windows::ApplicationModel::DynamicDependency::AddPackageDependencyOptions addOptions; + packageRuntimeManager.AddPackageSet(packageSet, createOptions, addOptions); + VERIFY_FAIL(L"Success is not expected"); + } + catch (winrt::hresult_error& e) + { + VERIFY_ARE_EQUAL(E_INVALIDARG, e.code(), WEX::Common::String().Format(L"0x%X %s", e.code(), e.message().c_str())); + } + + try + { + winrt::Microsoft::Windows::Management::Deployment::PackageSet packageSet; + PCWSTR c_packageSetId{ L"Does.Not.Exist" }; + packageSet.Id(c_packageSetId); + winrt::Microsoft::Windows::Management::Deployment::PackageSetItem packageSetItem; + PCWSTR c_packageFamilyName{ L"Not a valid Package Family Name" }; + packageSetItem.PackageFamilyName(c_packageFamilyName); + packageSet.PackageSetItems().Append(packageSetItem); + + winrt::Microsoft::Windows::ApplicationModel::DynamicDependency::CreatePackageDependencyOptions createOptions; + winrt::Microsoft::Windows::ApplicationModel::DynamicDependency::AddPackageDependencyOptions addOptions; + packageRuntimeManager.AddPackageSet(packageSet, createOptions, addOptions); + VERIFY_FAIL(L"Success is not expected"); + } + catch (winrt::hresult_error& e) + { + VERIFY_ARE_EQUAL(E_INVALIDARG, e.code(), WEX::Common::String().Format(L"0x%X %s", e.code(), e.message().c_str())); + } + + try + { + winrt::Microsoft::Windows::Management::Deployment::PackageSet packageSet; + PCWSTR c_packageSetId{ L"Does.Not.Exist" }; + packageSet.Id(c_packageSetId); + winrt::Microsoft::Windows::Management::Deployment::PackageSetItem packageSetItem; + PCWSTR c_packageFamilyName{ L"Does.Not.Exist_1234567890abc" }; + packageSetItem.PackageFamilyName(c_packageFamilyName); + packageSet.PackageSetItems().Append(packageSetItem); + + winrt::Microsoft::Windows::ApplicationModel::DynamicDependency::CreatePackageDependencyOptions createOptions; + winrt::Microsoft::Windows::ApplicationModel::DynamicDependency::AddPackageDependencyOptions addOptions; + packageRuntimeManager.AddPackageSet(packageSet, createOptions, addOptions); + VERIFY_FAIL(L"Success is not expected"); + } + catch (winrt::hresult_error& e) + { + VERIFY_ARE_EQUAL(E_INVALIDARG, e.code(), WEX::Common::String().Format(L"0x%X %s", e.code(), e.message().c_str())); + } + + try + { + winrt::Microsoft::Windows::Management::Deployment::PackageSet packageSet; + PCWSTR c_packageSetId{ L"Does.Not.Exist" }; + packageSet.Id(c_packageSetId); + winrt::Microsoft::Windows::Management::Deployment::PackageSetItem packageSetItem; + PCWSTR c_packageUriAsString{ L"file://c:/assemble.msix" }; + winrt::Windows::Foundation::Uri c_packageUri{ c_packageUriAsString }; + packageSetItem.PackageUri(c_packageUri); + packageSet.PackageSetItems().Append(packageSetItem); + + winrt::Microsoft::Windows::ApplicationModel::DynamicDependency::CreatePackageDependencyOptions createOptions; + winrt::Microsoft::Windows::ApplicationModel::DynamicDependency::AddPackageDependencyOptions addOptions; + packageRuntimeManager.AddPackageSet(packageSet, createOptions, addOptions); + VERIFY_FAIL(L"Success is not expected"); + } + catch (winrt::hresult_error& e) + { + VERIFY_ARE_EQUAL(E_INVALIDARG, e.code(), WEX::Common::String().Format(L"0x%X %s", e.code(), e.message().c_str())); + } + } + + TEST_METHOD(AddPackageSet_1_NoSuchPackage_Fail) + { + winrt::Microsoft::Windows::Management::Deployment::PackageSet packageSet; + PCWSTR c_packageSetId{ L"Does.Not.Exist" }; + packageSet.Id(c_packageSetId); + winrt::Microsoft::Windows::Management::Deployment::PackageSetItem packageSetItem; + PCWSTR c_packageFamilyName{ L"Does.Not.Exist_1234567890abc" }; + packageSetItem.PackageFamilyName(c_packageFamilyName); + PCWSTR c_packageUriAsString{ L"file://c:/does/not/exist.msix" }; + winrt::Windows::Foundation::Uri c_packageUri{ c_packageUriAsString }; + packageSetItem.PackageUri(c_packageUri); + packageSet.PackageSetItems().Append(packageSetItem); + auto packageDeploymentManager{ winrt::Microsoft::Windows::Management::Deployment::PackageDeploymentManager::GetDefault() }; + VERIFY_IS_FALSE(packageDeploymentManager.IsPackageSetReady(packageSet)); + + try + { + winrt::Microsoft::Windows::ApplicationModel::DynamicDependency::CreatePackageDependencyOptions createOptions; + winrt::Microsoft::Windows::ApplicationModel::DynamicDependency::AddPackageDependencyOptions addOptions; + auto packageRuntimeManager{ winrt::Microsoft::Windows::Management::Deployment::PackageRuntimeManager::GetDefault() }; + packageRuntimeManager.AddPackageSet(packageSet, createOptions, addOptions); + VERIFY_FAIL(L"Success is not expected"); + } + catch (winrt::hresult_error& e) + { + VERIFY_ARE_EQUAL(STATEREPOSITORY_E_DEPENDENCY_NOT_RESOLVED, e.code(), WEX::Common::String().Format(L"0x%X %s", e.code(), e.message().c_str())); + } + } + + TEST_METHOD(AddPackageSet_1_NotInstalled_Fail) + { + RemovePackage_Red(); + + winrt::Microsoft::Windows::Management::Deployment::PackageSet packageSet; + PCWSTR c_packageSetId{ L"RGB" }; + packageSet.Id(c_packageSetId); + winrt::Microsoft::Windows::Management::Deployment::PackageSetItem red{ Make_PackageSetItem(::TPF::Red::GetPackageFullName(), ::TPF::Red::c_packageDirName) }; + packageSet.PackageSetItems().Append(red); + + auto packageDeploymentManager{ winrt::Microsoft::Windows::Management::Deployment::PackageDeploymentManager::GetDefault() }; + VERIFY_IS_FALSE(packageDeploymentManager.IsPackageSetReady(packageSet)); + + try + { + winrt::Microsoft::Windows::ApplicationModel::DynamicDependency::CreatePackageDependencyOptions createOptions; + winrt::Microsoft::Windows::ApplicationModel::DynamicDependency::AddPackageDependencyOptions addOptions; + auto packageRuntimeManager{ winrt::Microsoft::Windows::Management::Deployment::PackageRuntimeManager::GetDefault() }; + packageRuntimeManager.AddPackageSet(packageSet, createOptions, addOptions); + VERIFY_FAIL(L"Success is not expected"); + } + catch (winrt::hresult_error& e) + { + VERIFY_ARE_EQUAL(STATEREPOSITORY_E_DEPENDENCY_NOT_RESOLVED, e.code(), WEX::Common::String().Format(L"0x%X %s", e.code(), e.message().c_str())); + } + } + + TEST_METHOD(AddPackageSet_1_Staged_Fail) + { + BEGIN_TEST_METHOD_PROPERTIES() + TEST_CLASS_PROPERTY(L"RunAs", L"ElevatedUser") + END_TEST_METHOD_PROPERTIES() + + RemovePackage_Red(); + StagePackage_Red(); + + winrt::Microsoft::Windows::Management::Deployment::PackageSet packageSet; + PCWSTR c_packageSetId{ L"RGB" }; + packageSet.Id(c_packageSetId); + winrt::Microsoft::Windows::Management::Deployment::PackageSetItem red{ Make_PackageSetItem(::TPF::Red::GetPackageFullName(), ::TPF::Red::c_packageDirName) }; + packageSet.PackageSetItems().Append(red); + auto packageDeploymentManager{ winrt::Microsoft::Windows::Management::Deployment::PackageDeploymentManager::GetDefault() }; + VERIFY_IS_FALSE(packageDeploymentManager.IsPackageSetReady(packageSet)); + + try + { + winrt::Microsoft::Windows::ApplicationModel::DynamicDependency::CreatePackageDependencyOptions createOptions; + winrt::Microsoft::Windows::ApplicationModel::DynamicDependency::AddPackageDependencyOptions addOptions; + auto packageRuntimeManager{ winrt::Microsoft::Windows::Management::Deployment::PackageRuntimeManager::GetDefault() }; + packageRuntimeManager.AddPackageSet(packageSet, createOptions, addOptions); + VERIFY_FAIL(L"Success is not expected"); + } + catch (winrt::hresult_error& e) + { + VERIFY_ARE_EQUAL(STATEREPOSITORY_E_DEPENDENCY_NOT_RESOLVED, e.code(), WEX::Common::String().Format(L"0x%X %s", e.code(), e.message().c_str())); + } + } + + TEST_METHOD(AddPackageSet_1_Registered_Success) + { + AddPackage_Red(); + + winrt::Microsoft::Windows::Management::Deployment::PackageSet packageSet; + PCWSTR c_packageSetId{ L"RGB" }; + packageSet.Id(c_packageSetId); + winrt::Microsoft::Windows::Management::Deployment::PackageSetItem red{ Make_PackageSetItem(::TPF::Red::GetPackageFullName(), ::TPF::Red::c_packageDirName) }; + packageSet.PackageSetItems().Append(red); + auto packageDeploymentManager{ winrt::Microsoft::Windows::Management::Deployment::PackageDeploymentManager::GetDefault() }; + VERIFY_IS_TRUE(packageDeploymentManager.IsPackageSetReady(packageSet)); + + winrt::Microsoft::Windows::ApplicationModel::DynamicDependency::CreatePackageDependencyOptions createOptions; + winrt::Microsoft::Windows::ApplicationModel::DynamicDependency::AddPackageDependencyOptions addOptions; + auto packageRuntimeManager{ winrt::Microsoft::Windows::Management::Deployment::PackageRuntimeManager::GetDefault() }; + const auto packageSetRuntimeDisposition{ packageRuntimeManager.AddPackageSet(packageSet, createOptions, addOptions) }; + + packageRuntimeManager.RemovePackageSet(packageSetRuntimeDisposition); + } + + TEST_METHOD(AddPackageSet_1_OlderRegistered_Fail) + { + RemovePackage_Redder(); + AddPackage_Red(); + + winrt::Microsoft::Windows::Management::Deployment::PackageSet packageSet; + PCWSTR c_packageSetId{ L"RGB" }; + packageSet.Id(c_packageSetId); + winrt::Microsoft::Windows::Management::Deployment::PackageSetItem redder{ Make_PackageSetItem(::TPF::Redder::GetPackageFullName(), ::TPF::Redder::c_packageDirName) }; + packageSet.PackageSetItems().Append(redder); + auto packageDeploymentManager{ winrt::Microsoft::Windows::Management::Deployment::PackageDeploymentManager::GetDefault() }; + VERIFY_IS_FALSE(packageDeploymentManager.IsPackageSetReady(packageSet)); + + try + { + winrt::Microsoft::Windows::ApplicationModel::DynamicDependency::CreatePackageDependencyOptions createOptions; + winrt::Microsoft::Windows::ApplicationModel::DynamicDependency::AddPackageDependencyOptions addOptions; + auto packageRuntimeManager{ winrt::Microsoft::Windows::Management::Deployment::PackageRuntimeManager::GetDefault() }; + packageRuntimeManager.AddPackageSet(packageSet, createOptions, addOptions); + VERIFY_FAIL(L"Success is not expected"); + } + catch (winrt::hresult_error& e) + { + VERIFY_ARE_EQUAL(STATEREPOSITORY_E_DEPENDENCY_NOT_RESOLVED, e.code(), WEX::Common::String().Format(L"0x%X %s", e.code(), e.message().c_str())); + } + } + + TEST_METHOD(AddPackageSet_1_NewerRegistered_Success) + { + AddPackage_Redder(); + + winrt::Microsoft::Windows::Management::Deployment::PackageSet packageSet; + PCWSTR c_packageSetId{ L"RGB" }; + packageSet.Id(c_packageSetId); + winrt::Microsoft::Windows::Management::Deployment::PackageSetItem red{ Make_PackageSetItem(::TPF::Red::GetPackageFullName(), ::TPF::Red::c_packageDirName) }; + packageSet.PackageSetItems().Append(red); + auto packageDeploymentManager{ winrt::Microsoft::Windows::Management::Deployment::PackageDeploymentManager::GetDefault() }; + VERIFY_IS_TRUE(packageDeploymentManager.IsPackageSetReady(packageSet)); + + winrt::Microsoft::Windows::ApplicationModel::DynamicDependency::CreatePackageDependencyOptions createOptions; + winrt::Microsoft::Windows::ApplicationModel::DynamicDependency::AddPackageDependencyOptions addOptions; + auto packageRuntimeManager{ winrt::Microsoft::Windows::Management::Deployment::PackageRuntimeManager::GetDefault() }; + const auto packageSetRuntimeDisposition{ packageRuntimeManager.AddPackageSet(packageSet, createOptions, addOptions) }; + + packageRuntimeManager.RemovePackageSet(packageSetRuntimeDisposition); + RemovePackage_Redder(); + } + + TEST_METHOD(AddPackageSet_1_RegisteredPackageStatusBad_Fail) + { + BEGIN_TEST_METHOD_PROPERTIES() + TEST_CLASS_PROPERTY(L"RunAs", L"ElevatedUser") + END_TEST_METHOD_PROPERTIES() + + AddPackage_Red(); + SetPackageStatus(::TPF::Red::c_packageFamilyName, winrt::Windows::Management::Deployment::PackageStatus::Modified); + + winrt::Microsoft::Windows::Management::Deployment::PackageSet packageSet; + PCWSTR c_packageSetId{ L"RGB" }; + packageSet.Id(c_packageSetId); + winrt::Microsoft::Windows::Management::Deployment::PackageSetItem red{ Make_PackageSetItem(::TPF::Red::GetPackageFullName(), ::TPF::Red::c_packageDirName) }; + packageSet.PackageSetItems().Append(red); + auto packageDeploymentManager{ winrt::Microsoft::Windows::Management::Deployment::PackageDeploymentManager::GetDefault() }; + VERIFY_IS_FALSE(packageDeploymentManager.IsPackageSetReady(packageSet)); + + try + { + winrt::Microsoft::Windows::ApplicationModel::DynamicDependency::CreatePackageDependencyOptions createOptions; + winrt::Microsoft::Windows::ApplicationModel::DynamicDependency::AddPackageDependencyOptions addOptions; + auto packageRuntimeManager{ winrt::Microsoft::Windows::Management::Deployment::PackageRuntimeManager::GetDefault() }; + packageRuntimeManager.AddPackageSet(packageSet, createOptions, addOptions); + VERIFY_FAIL(L"Success is not expected"); + } + catch (winrt::hresult_error& e) + { + VERIFY_ARE_EQUAL(STATEREPOSITORY_E_DEPENDENCY_NOT_RESOLVED, e.code(), WEX::Common::String().Format(L"0x%X %s", e.code(), e.message().c_str())); + } + + ClearPackageStatus(::TPF::Red::c_packageFamilyName, winrt::Windows::Management::Deployment::PackageStatus::Modified); + } + + TEST_METHOD(AddPackageSet_N_NotInstalled_Fail) + { + RemovePackage_Red(); + RemovePackage_Green(); + RemovePackage_Blue(); + + winrt::Microsoft::Windows::Management::Deployment::PackageSet packageSet; + PCWSTR c_packageSetId{ L"RGB" }; + packageSet.Id(c_packageSetId); + winrt::Microsoft::Windows::Management::Deployment::PackageSetItem red{ Make_PackageSetItem(::TPF::Red::GetPackageFullName(), ::TPF::Red::c_packageDirName) }; + packageSet.PackageSetItems().Append(red); + winrt::Microsoft::Windows::Management::Deployment::PackageSetItem green{ Make_PackageSetItem(::TPF::Green::GetPackageFullName(), ::TPF::Green::c_packageDirName) }; + packageSet.PackageSetItems().Append(green); + winrt::Microsoft::Windows::Management::Deployment::PackageSetItem blue{ Make_PackageSetItem(::TPF::Blue::GetPackageFullName(), ::TPF::Blue::c_packageDirName) }; + packageSet.PackageSetItems().Append(blue); + auto packageDeploymentManager{ winrt::Microsoft::Windows::Management::Deployment::PackageDeploymentManager::GetDefault() }; + VERIFY_IS_FALSE(packageDeploymentManager.IsPackageSetReady(packageSet)); + + try + { + winrt::Microsoft::Windows::ApplicationModel::DynamicDependency::CreatePackageDependencyOptions createOptions; + winrt::Microsoft::Windows::ApplicationModel::DynamicDependency::AddPackageDependencyOptions addOptions; + auto packageRuntimeManager{ winrt::Microsoft::Windows::Management::Deployment::PackageRuntimeManager::GetDefault() }; + packageRuntimeManager.AddPackageSet(packageSet, createOptions, addOptions); + VERIFY_FAIL(L"Success is not expected"); + } + catch (winrt::hresult_error& e) + { + VERIFY_ARE_EQUAL(STATEREPOSITORY_E_DEPENDENCY_NOT_RESOLVED, e.code(), WEX::Common::String().Format(L"0x%X %s", e.code(), e.message().c_str())); + } + } + + TEST_METHOD(AddPackageSet_N_Registered_Success) + { + AddPackage_Red(); + AddPackage_Green(); + AddPackage_Blue(); + + winrt::Microsoft::Windows::Management::Deployment::PackageSet packageSet; + PCWSTR c_packageSetId{ L"RGB" }; + packageSet.Id(c_packageSetId); + winrt::Microsoft::Windows::Management::Deployment::PackageSetItem red{ Make_PackageSetItem(::TPF::Red::GetPackageFullName(), ::TPF::Red::c_packageDirName) }; + packageSet.PackageSetItems().Append(red); + winrt::Microsoft::Windows::Management::Deployment::PackageSetItem green{ Make_PackageSetItem(::TPF::Green::GetPackageFullName(), ::TPF::Green::c_packageDirName) }; + packageSet.PackageSetItems().Append(green); + winrt::Microsoft::Windows::Management::Deployment::PackageSetItem blue{ Make_PackageSetItem(::TPF::Blue::GetPackageFullName(), ::TPF::Blue::c_packageDirName) }; + packageSet.PackageSetItems().Append(blue); + auto packageDeploymentManager{ winrt::Microsoft::Windows::Management::Deployment::PackageDeploymentManager::GetDefault() }; + VERIFY_IS_TRUE(packageDeploymentManager.IsPackageSetReady(packageSet)); + + winrt::Microsoft::Windows::ApplicationModel::DynamicDependency::CreatePackageDependencyOptions createOptions; + winrt::Microsoft::Windows::ApplicationModel::DynamicDependency::AddPackageDependencyOptions addOptions; + auto packageRuntimeManager{ winrt::Microsoft::Windows::Management::Deployment::PackageRuntimeManager::GetDefault() }; + const auto packageSetRuntimeDisposition{ packageRuntimeManager.AddPackageSet(packageSet, createOptions, addOptions) }; + + packageRuntimeManager.RemovePackageSet(packageSetRuntimeDisposition); + } + + TEST_METHOD(AddPackageSet_N_NewerRegistered_Success) + { + AddPackage_Redder(); + AddPackage_Green(); + AddPackage_Blue(); + + winrt::Microsoft::Windows::Management::Deployment::PackageSet packageSet; + PCWSTR c_packageSetId{ L"RGB" }; + packageSet.Id(c_packageSetId); + winrt::Microsoft::Windows::Management::Deployment::PackageSetItem red{ Make_PackageSetItem(::TPF::Red::GetPackageFullName(), ::TPF::Red::c_packageDirName) }; + packageSet.PackageSetItems().Append(red); + winrt::Microsoft::Windows::Management::Deployment::PackageSetItem green{ Make_PackageSetItem(::TPF::Green::GetPackageFullName(), ::TPF::Green::c_packageDirName) }; + packageSet.PackageSetItems().Append(green); + winrt::Microsoft::Windows::Management::Deployment::PackageSetItem blue{ Make_PackageSetItem(::TPF::Blue::GetPackageFullName(), ::TPF::Blue::c_packageDirName) }; + packageSet.PackageSetItems().Append(blue); + auto packageDeploymentManager{ winrt::Microsoft::Windows::Management::Deployment::PackageDeploymentManager::GetDefault() }; + VERIFY_IS_TRUE(packageDeploymentManager.IsPackageSetReady(packageSet)); + + winrt::Microsoft::Windows::ApplicationModel::DynamicDependency::CreatePackageDependencyOptions createOptions; + winrt::Microsoft::Windows::ApplicationModel::DynamicDependency::AddPackageDependencyOptions addOptions; + auto packageRuntimeManager{ winrt::Microsoft::Windows::Management::Deployment::PackageRuntimeManager::GetDefault() }; + const auto packageSetRuntimeDisposition{ packageRuntimeManager.AddPackageSet(packageSet, createOptions, addOptions) }; + + packageRuntimeManager.RemovePackageSet(packageSetRuntimeDisposition); + RemovePackage_Redder(); + } + + TEST_METHOD(AddPackageSet_N_OlderRegistered_Fail) + { + AddPackage_Red(); + AddPackage_Green(); + AddPackage_Blue(); + + winrt::Microsoft::Windows::Management::Deployment::PackageSet packageSet; + PCWSTR c_packageSetId{ L"RGB" }; + packageSet.Id(c_packageSetId); + winrt::Microsoft::Windows::Management::Deployment::PackageSetItem redder{ Make_PackageSetItem(::TPF::Redder::GetPackageFullName(), ::TPF::Redder::c_packageDirName) }; + packageSet.PackageSetItems().Append(redder); + winrt::Microsoft::Windows::Management::Deployment::PackageSetItem green{ Make_PackageSetItem(::TPF::Green::GetPackageFullName(), ::TPF::Green::c_packageDirName) }; + packageSet.PackageSetItems().Append(green); + winrt::Microsoft::Windows::Management::Deployment::PackageSetItem blue{ Make_PackageSetItem(::TPF::Blue::GetPackageFullName(), ::TPF::Blue::c_packageDirName) }; + packageSet.PackageSetItems().Append(blue); + auto packageDeploymentManager{ winrt::Microsoft::Windows::Management::Deployment::PackageDeploymentManager::GetDefault() }; + VERIFY_IS_FALSE(packageDeploymentManager.IsPackageSetReady(packageSet)); + + try + { + winrt::Microsoft::Windows::ApplicationModel::DynamicDependency::CreatePackageDependencyOptions createOptions; + winrt::Microsoft::Windows::ApplicationModel::DynamicDependency::AddPackageDependencyOptions addOptions; + auto packageRuntimeManager{ winrt::Microsoft::Windows::Management::Deployment::PackageRuntimeManager::GetDefault() }; + packageRuntimeManager.AddPackageSet(packageSet, createOptions, addOptions); + VERIFY_FAIL(L"Success is not expected"); + } + catch (winrt::hresult_error& e) + { + VERIFY_ARE_EQUAL(STATEREPOSITORY_E_DEPENDENCY_NOT_RESOLVED, e.code(), WEX::Common::String().Format(L"0x%X %s", e.code(), e.message().c_str())); + } + } + + TEST_METHOD(AddPackageSet_N_RegisteredAndNotInstalled_Fail) + { + AddPackage_Red(); + RemovePackage_Green(); + + winrt::Microsoft::Windows::Management::Deployment::PackageSet packageSet; + PCWSTR c_packageSetId{ L"RGB" }; + packageSet.Id(c_packageSetId); + winrt::Microsoft::Windows::Management::Deployment::PackageSetItem red{ Make_PackageSetItem(::TPF::Red::GetPackageFullName(), ::TPF::Red::c_packageDirName) }; + packageSet.PackageSetItems().Append(red); + winrt::Microsoft::Windows::Management::Deployment::PackageSetItem green{ Make_PackageSetItem(::TPF::Green::GetPackageFullName(), ::TPF::Green::c_packageDirName) }; + packageSet.PackageSetItems().Append(green); + auto packageDeploymentManager{ winrt::Microsoft::Windows::Management::Deployment::PackageDeploymentManager::GetDefault() }; + VERIFY_IS_FALSE(packageDeploymentManager.IsPackageSetReady(packageSet)); + + try + { + winrt::Microsoft::Windows::ApplicationModel::DynamicDependency::CreatePackageDependencyOptions createOptions; + winrt::Microsoft::Windows::ApplicationModel::DynamicDependency::AddPackageDependencyOptions addOptions; + auto packageRuntimeManager{ winrt::Microsoft::Windows::Management::Deployment::PackageRuntimeManager::GetDefault() }; + packageRuntimeManager.AddPackageSet(packageSet, createOptions, addOptions); + VERIFY_FAIL(L"Success is not expected"); + } + catch (winrt::hresult_error& e) + { + VERIFY_ARE_EQUAL(STATEREPOSITORY_E_DEPENDENCY_NOT_RESOLVED, e.code(), WEX::Common::String().Format(L"0x%X %s", e.code(), e.message().c_str())); + } + } + + TEST_METHOD(AddPackageSet_N_RegisteredAndNotInstalledAndStaged_Fail) + { + BEGIN_TEST_METHOD_PROPERTIES() + TEST_CLASS_PROPERTY(L"RunAs", L"ElevatedUser") + END_TEST_METHOD_PROPERTIES() + + AddPackage_Red(); + RemovePackage_Green(); + StagePackage_Blue(); + + winrt::Microsoft::Windows::Management::Deployment::PackageSet packageSet; + PCWSTR c_packageSetId{ L"RGB" }; + packageSet.Id(c_packageSetId); + winrt::Microsoft::Windows::Management::Deployment::PackageSetItem red{ Make_PackageSetItem(::TPF::Red::GetPackageFullName(), ::TPF::Red::c_packageDirName) }; + packageSet.PackageSetItems().Append(red); + winrt::Microsoft::Windows::Management::Deployment::PackageSetItem green{ Make_PackageSetItem(::TPF::Green::GetPackageFullName(), ::TPF::Green::c_packageDirName) }; + packageSet.PackageSetItems().Append(green); + winrt::Microsoft::Windows::Management::Deployment::PackageSetItem blue{ Make_PackageSetItem(::TPF::Green::GetPackageFullName(), ::TPF::Green::c_packageDirName) }; + packageSet.PackageSetItems().Append(blue); + auto packageDeploymentManager{ winrt::Microsoft::Windows::Management::Deployment::PackageDeploymentManager::GetDefault() }; + VERIFY_IS_FALSE(packageDeploymentManager.IsPackageSetReady(packageSet)); + + try + { + winrt::Microsoft::Windows::ApplicationModel::DynamicDependency::CreatePackageDependencyOptions createOptions; + winrt::Microsoft::Windows::ApplicationModel::DynamicDependency::AddPackageDependencyOptions addOptions; + auto packageRuntimeManager{ winrt::Microsoft::Windows::Management::Deployment::PackageRuntimeManager::GetDefault() }; + packageRuntimeManager.AddPackageSet(packageSet, createOptions, addOptions); + VERIFY_FAIL(L"Success is not expected"); + } + catch (winrt::hresult_error& e) + { + VERIFY_ARE_EQUAL(STATEREPOSITORY_E_DEPENDENCY_NOT_RESOLVED, e.code(), WEX::Common::String().Format(L"0x%X %s", e.code(), e.message().c_str())); + } + } + + TEST_METHOD(AddPackageSet_N_RegisteredPackageStatusOkAndBad_Fail) + { + BEGIN_TEST_METHOD_PROPERTIES() + TEST_CLASS_PROPERTY(L"RunAs", L"ElevatedUser") + END_TEST_METHOD_PROPERTIES() + + AddPackage_Red(); + AddPackage_Green(); + SetPackageStatus(::TPF::Green::c_packageFamilyName, winrt::Windows::Management::Deployment::PackageStatus::Modified); + + winrt::Microsoft::Windows::Management::Deployment::PackageSet packageSet; + PCWSTR c_packageSetId{ L"RGB" }; + packageSet.Id(c_packageSetId); + winrt::Microsoft::Windows::Management::Deployment::PackageSetItem red{ Make_PackageSetItem(::TPF::Red::GetPackageFullName(), ::TPF::Red::c_packageDirName) }; + packageSet.PackageSetItems().Append(red); + winrt::Microsoft::Windows::Management::Deployment::PackageSetItem green{ Make_PackageSetItem(::TPF::Green::GetPackageFullName(), ::TPF::Green::c_packageDirName) }; + packageSet.PackageSetItems().Append(green); + auto packageDeploymentManager{ winrt::Microsoft::Windows::Management::Deployment::PackageDeploymentManager::GetDefault() }; + VERIFY_IS_FALSE(packageDeploymentManager.IsPackageSetReady(packageSet)); + + try + { + winrt::Microsoft::Windows::ApplicationModel::DynamicDependency::CreatePackageDependencyOptions createOptions; + winrt::Microsoft::Windows::ApplicationModel::DynamicDependency::AddPackageDependencyOptions addOptions; + auto packageRuntimeManager{ winrt::Microsoft::Windows::Management::Deployment::PackageRuntimeManager::GetDefault() }; + packageRuntimeManager.AddPackageSet(packageSet, createOptions, addOptions); + VERIFY_FAIL(L"Success is not expected"); + } + catch (winrt::hresult_error& e) + { + VERIFY_ARE_EQUAL(STATEREPOSITORY_E_DEPENDENCY_NOT_RESOLVED, e.code(), WEX::Common::String().Format(L"0x%X %s", e.code(), e.message().c_str())); + } + + ClearPackageStatus(::TPF::Green::c_packageFamilyName, winrt::Windows::Management::Deployment::PackageStatus::Modified); + } + + private: + winrt::Windows::Management::Deployment::PackageManager m_packageManager; + }; +} diff --git a/test/PackageManager/API/Test.testdef b/test/PackageManager/API/Test.testdef new file mode 100644 index 0000000000..4f9f4e6de3 --- /dev/null +++ b/test/PackageManager/API/Test.testdef @@ -0,0 +1,11 @@ +{ + "Tests": [ + { + "Description": "PackageManagerTests tests for feature PackageManager (arm64 not currently enabled)", + "Filename": "PackageManagerTests.dll", + "Parameters": "", + "Architectures": ["x86", "x64"], + "Status": "Enabled" + } + ] +} diff --git a/test/PackageManager/API/packages.config b/test/PackageManager/API/packages.config new file mode 100644 index 0000000000..ecebfdd18e --- /dev/null +++ b/test/PackageManager/API/packages.config @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/test/PackageManager/API/pch.cpp b/test/PackageManager/API/pch.cpp new file mode 100644 index 0000000000..f59e66e263 --- /dev/null +++ b/test/PackageManager/API/pch.cpp @@ -0,0 +1,6 @@ +// Copyright (c) Microsoft Corporation and Contributors. +// Licensed under the MIT License. + +// pch.cpp: source file corresponding to the pre-compiled header + +#include "pch.h" diff --git a/test/PackageManager/API/pch.h b/test/PackageManager/API/pch.h new file mode 100644 index 0000000000..6a5c7c20a6 --- /dev/null +++ b/test/PackageManager/API/pch.h @@ -0,0 +1,30 @@ +// Copyright (c) Microsoft Corporation and Contributors. +// Licensed under the MIT License. + +#ifndef PCH_H +#define PCH_H + +#include + +#include + +#include +#include + +#include +#include + +#include +#include + +#include + +#include + +#include +#include +#include + +#include "PackageManagerTests.Packages.h" + +#endif //PCH_H diff --git a/test/PackageManager/data/PackageManager.Test.F.Blue.msix/PackageManager.Test.F.Blue.msix.vcxproj b/test/PackageManager/data/PackageManager.Test.F.Blue.msix/PackageManager.Test.F.Blue.msix.vcxproj new file mode 100644 index 0000000000..36f92c6d49 --- /dev/null +++ b/test/PackageManager/data/PackageManager.Test.F.Blue.msix/PackageManager.Test.F.Blue.msix.vcxproj @@ -0,0 +1,130 @@ + + + + + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + Debug + ARM64 + + + Release + ARM64 + + + + {FBAE1876-C50A-4EFC-A686-3008B6438731} + VCProjectVersion + PackageManager.Test.F.Blue.Msix + en-US + 16.0 + 10.0.22621.0 + 10.0.17763.0 + 10.0 + + + Utility + v143 + + + true + + + false + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + $(TargetName) + + + + appxmanifest.xml + + + appxmanifest.xml + + + appxmanifest.xml + + + + + $(RepoTestCertificatePFX) + $(RepoTestCertificatePassword) + + + + + + + + + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + + + + + + diff --git a/test/PackageManager/data/PackageManager.Test.F.Blue.msix/PackageManager.Test.F.Blue.msix.vcxproj.filters b/test/PackageManager/data/PackageManager.Test.F.Blue.msix/PackageManager.Test.F.Blue.msix.vcxproj.filters new file mode 100644 index 0000000000..3987f7c194 --- /dev/null +++ b/test/PackageManager/data/PackageManager.Test.F.Blue.msix/PackageManager.Test.F.Blue.msix.vcxproj.filters @@ -0,0 +1,14 @@ + + + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tga;tiff;tif;png;wav;mfcribbon-ms + + + + + + + + \ No newline at end of file diff --git a/test/PackageManager/data/PackageManager.Test.F.Blue.msix/PackageManager.Test.F.Blue.vcxproj.filters b/test/PackageManager/data/PackageManager.Test.F.Blue.msix/PackageManager.Test.F.Blue.vcxproj.filters new file mode 100644 index 0000000000..2df21c891a --- /dev/null +++ b/test/PackageManager/data/PackageManager.Test.F.Blue.msix/PackageManager.Test.F.Blue.vcxproj.filters @@ -0,0 +1,17 @@ + + + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tga;tiff;tif;png;wav;mfcribbon-ms + + + + + + + + + + + diff --git a/test/PackageManager/data/PackageManager.Test.F.Blue.msix/appxmanifest-arm64.xml b/test/PackageManager/data/PackageManager.Test.F.Blue.msix/appxmanifest-arm64.xml new file mode 100644 index 0000000000..07adf08379 --- /dev/null +++ b/test/PackageManager/data/PackageManager.Test.F.Blue.msix/appxmanifest-arm64.xml @@ -0,0 +1,28 @@ + + + + + + + + true + Test.PackageManager.F.Blue + Microsoft Corporation + logo.png + + + + + + + + + + diff --git a/test/PackageManager/data/PackageManager.Test.F.Blue.msix/appxmanifest-x64.xml b/test/PackageManager/data/PackageManager.Test.F.Blue.msix/appxmanifest-x64.xml new file mode 100644 index 0000000000..26fb38fd09 --- /dev/null +++ b/test/PackageManager/data/PackageManager.Test.F.Blue.msix/appxmanifest-x64.xml @@ -0,0 +1,28 @@ + + + + + + + + true + Test.PackageManager.F.Blue + Microsoft Corporation + logo.png + + + + + + + + + + diff --git a/test/PackageManager/data/PackageManager.Test.F.Blue.msix/appxmanifest-x86.xml b/test/PackageManager/data/PackageManager.Test.F.Blue.msix/appxmanifest-x86.xml new file mode 100644 index 0000000000..aa38863c63 --- /dev/null +++ b/test/PackageManager/data/PackageManager.Test.F.Blue.msix/appxmanifest-x86.xml @@ -0,0 +1,28 @@ + + + + + + + + true + Test.PackageManager.F.Blue + Microsoft Corporation + logo.png + + + + + + + + + + diff --git a/test/PackageManager/data/PackageManager.Test.F.Blue.msix/logo.png b/test/PackageManager/data/PackageManager.Test.F.Blue.msix/logo.png new file mode 100644 index 0000000000..5bd7c0ce4d Binary files /dev/null and b/test/PackageManager/data/PackageManager.Test.F.Blue.msix/logo.png differ diff --git a/test/PackageManager/data/PackageManager.Test.F.Blue.msix/packages.config b/test/PackageManager/data/PackageManager.Test.F.Blue.msix/packages.config new file mode 100644 index 0000000000..d9db55a1b3 --- /dev/null +++ b/test/PackageManager/data/PackageManager.Test.F.Blue.msix/packages.config @@ -0,0 +1,6 @@ + + + + + + diff --git a/test/PackageManager/data/PackageManager.Test.F.Green.msix/PackageManager.Test.F.Green.msix.vcxproj b/test/PackageManager/data/PackageManager.Test.F.Green.msix/PackageManager.Test.F.Green.msix.vcxproj new file mode 100644 index 0000000000..ec537a9085 --- /dev/null +++ b/test/PackageManager/data/PackageManager.Test.F.Green.msix/PackageManager.Test.F.Green.msix.vcxproj @@ -0,0 +1,130 @@ + + + + + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + Debug + ARM64 + + + Release + ARM64 + + + + {4626E11F-A7A4-41A2-B22D-5A108BC369AC} + VCProjectVersion + PackageManager.Test.F.Green.Msix + en-US + 16.0 + 10.0.22621.0 + 10.0.17763.0 + 10.0 + + + Utility + v143 + + + true + + + false + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + $(TargetName) + + + + appxmanifest.xml + + + appxmanifest.xml + + + appxmanifest.xml + + + + + $(RepoTestCertificatePFX) + $(RepoTestCertificatePassword) + + + + + + + + + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + + + + + + diff --git a/test/PackageManager/data/PackageManager.Test.F.Green.msix/PackageManager.Test.F.Green.msix.vcxproj.filters b/test/PackageManager/data/PackageManager.Test.F.Green.msix/PackageManager.Test.F.Green.msix.vcxproj.filters new file mode 100644 index 0000000000..3987f7c194 --- /dev/null +++ b/test/PackageManager/data/PackageManager.Test.F.Green.msix/PackageManager.Test.F.Green.msix.vcxproj.filters @@ -0,0 +1,14 @@ + + + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tga;tiff;tif;png;wav;mfcribbon-ms + + + + + + + + \ No newline at end of file diff --git a/test/PackageManager/data/PackageManager.Test.F.Green.msix/PackageManager.Test.F.Green.vcxproj.filters b/test/PackageManager/data/PackageManager.Test.F.Green.msix/PackageManager.Test.F.Green.vcxproj.filters new file mode 100644 index 0000000000..2df21c891a --- /dev/null +++ b/test/PackageManager/data/PackageManager.Test.F.Green.msix/PackageManager.Test.F.Green.vcxproj.filters @@ -0,0 +1,17 @@ + + + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tga;tiff;tif;png;wav;mfcribbon-ms + + + + + + + + + + + diff --git a/test/PackageManager/data/PackageManager.Test.F.Green.msix/appxmanifest-arm64.xml b/test/PackageManager/data/PackageManager.Test.F.Green.msix/appxmanifest-arm64.xml new file mode 100644 index 0000000000..dd67e588f8 --- /dev/null +++ b/test/PackageManager/data/PackageManager.Test.F.Green.msix/appxmanifest-arm64.xml @@ -0,0 +1,28 @@ + + + + + + + + true + Test.PackageManager.F.Green + Microsoft Corporation + logo.png + + + + + + + + + + diff --git a/test/PackageManager/data/PackageManager.Test.F.Green.msix/appxmanifest-x64.xml b/test/PackageManager/data/PackageManager.Test.F.Green.msix/appxmanifest-x64.xml new file mode 100644 index 0000000000..bcc4e0a65f --- /dev/null +++ b/test/PackageManager/data/PackageManager.Test.F.Green.msix/appxmanifest-x64.xml @@ -0,0 +1,28 @@ + + + + + + + + true + Test.PackageManager.F.Green + Microsoft Corporation + logo.png + + + + + + + + + + diff --git a/test/PackageManager/data/PackageManager.Test.F.Green.msix/appxmanifest-x86.xml b/test/PackageManager/data/PackageManager.Test.F.Green.msix/appxmanifest-x86.xml new file mode 100644 index 0000000000..b9621318dd --- /dev/null +++ b/test/PackageManager/data/PackageManager.Test.F.Green.msix/appxmanifest-x86.xml @@ -0,0 +1,28 @@ + + + + + + + + true + Test.PackageManager.F.Green + Microsoft Corporation + logo.png + + + + + + + + + + diff --git a/test/PackageManager/data/PackageManager.Test.F.Green.msix/logo.png b/test/PackageManager/data/PackageManager.Test.F.Green.msix/logo.png new file mode 100644 index 0000000000..5bd7c0ce4d Binary files /dev/null and b/test/PackageManager/data/PackageManager.Test.F.Green.msix/logo.png differ diff --git a/test/PackageManager/data/PackageManager.Test.F.Green.msix/packages.config b/test/PackageManager/data/PackageManager.Test.F.Green.msix/packages.config new file mode 100644 index 0000000000..d9db55a1b3 --- /dev/null +++ b/test/PackageManager/data/PackageManager.Test.F.Green.msix/packages.config @@ -0,0 +1,6 @@ + + + + + + diff --git a/test/PackageManager/data/PackageManager.Test.F.Red.msix/PackageManager.Test.F.Red.msix.vcxproj b/test/PackageManager/data/PackageManager.Test.F.Red.msix/PackageManager.Test.F.Red.msix.vcxproj new file mode 100644 index 0000000000..5399098729 --- /dev/null +++ b/test/PackageManager/data/PackageManager.Test.F.Red.msix/PackageManager.Test.F.Red.msix.vcxproj @@ -0,0 +1,130 @@ + + + + + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + Debug + ARM64 + + + Release + ARM64 + + + + {f2946790-daf7-4dff-a754-ba471a12e494} + VCProjectVersion + PackageManager.Test.F.Red.Msix + en-US + 16.0 + 10.0.22621.0 + 10.0.17763.0 + 10.0 + + + Utility + v143 + + + true + + + false + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + $(TargetName) + + + + appxmanifest.xml + + + appxmanifest.xml + + + appxmanifest.xml + + + + + $(RepoTestCertificatePFX) + $(RepoTestCertificatePassword) + + + + + + + + + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + + + + + + diff --git a/test/PackageManager/data/PackageManager.Test.F.Red.msix/PackageManager.Test.F.Red.msix.vcxproj.filters b/test/PackageManager/data/PackageManager.Test.F.Red.msix/PackageManager.Test.F.Red.msix.vcxproj.filters new file mode 100644 index 0000000000..2df21c891a --- /dev/null +++ b/test/PackageManager/data/PackageManager.Test.F.Red.msix/PackageManager.Test.F.Red.msix.vcxproj.filters @@ -0,0 +1,17 @@ + + + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tga;tiff;tif;png;wav;mfcribbon-ms + + + + + + + + + + + diff --git a/test/PackageManager/data/PackageManager.Test.F.Red.msix/PackageManager.Test.F.Red.vcxproj.filters b/test/PackageManager/data/PackageManager.Test.F.Red.msix/PackageManager.Test.F.Red.vcxproj.filters new file mode 100644 index 0000000000..2df21c891a --- /dev/null +++ b/test/PackageManager/data/PackageManager.Test.F.Red.msix/PackageManager.Test.F.Red.vcxproj.filters @@ -0,0 +1,17 @@ + + + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tga;tiff;tif;png;wav;mfcribbon-ms + + + + + + + + + + + diff --git a/test/PackageManager/data/PackageManager.Test.F.Red.msix/appxmanifest-arm64.xml b/test/PackageManager/data/PackageManager.Test.F.Red.msix/appxmanifest-arm64.xml new file mode 100644 index 0000000000..508357f066 --- /dev/null +++ b/test/PackageManager/data/PackageManager.Test.F.Red.msix/appxmanifest-arm64.xml @@ -0,0 +1,28 @@ + + + + + + + + true + Test.PackageManager.F.Red + Microsoft Corporation + logo.png + + + + + + + + + + diff --git a/test/PackageManager/data/PackageManager.Test.F.Red.msix/appxmanifest-x64.xml b/test/PackageManager/data/PackageManager.Test.F.Red.msix/appxmanifest-x64.xml new file mode 100644 index 0000000000..fd238b8fd4 --- /dev/null +++ b/test/PackageManager/data/PackageManager.Test.F.Red.msix/appxmanifest-x64.xml @@ -0,0 +1,28 @@ + + + + + + + + true + Test.PackageManager.F.Red + Microsoft Corporation + logo.png + + + + + + + + + + diff --git a/test/PackageManager/data/PackageManager.Test.F.Red.msix/appxmanifest-x86.xml b/test/PackageManager/data/PackageManager.Test.F.Red.msix/appxmanifest-x86.xml new file mode 100644 index 0000000000..1f3b97b2e0 --- /dev/null +++ b/test/PackageManager/data/PackageManager.Test.F.Red.msix/appxmanifest-x86.xml @@ -0,0 +1,28 @@ + + + + + + + + true + Test.PackageManager.F.Red + Microsoft Corporation + logo.png + + + + + + + + + + diff --git a/test/PackageManager/data/PackageManager.Test.F.Red.msix/logo.png b/test/PackageManager/data/PackageManager.Test.F.Red.msix/logo.png new file mode 100644 index 0000000000..5bd7c0ce4d Binary files /dev/null and b/test/PackageManager/data/PackageManager.Test.F.Red.msix/logo.png differ diff --git a/test/PackageManager/data/PackageManager.Test.F.Red.msix/packages.config b/test/PackageManager/data/PackageManager.Test.F.Red.msix/packages.config new file mode 100644 index 0000000000..d9db55a1b3 --- /dev/null +++ b/test/PackageManager/data/PackageManager.Test.F.Red.msix/packages.config @@ -0,0 +1,6 @@ + + + + + + diff --git a/test/PackageManager/data/PackageManager.Test.F.Redder.msix/PackageManager.Test.F.Redder.msix.vcxproj b/test/PackageManager/data/PackageManager.Test.F.Redder.msix/PackageManager.Test.F.Redder.msix.vcxproj new file mode 100644 index 0000000000..c4ce1e0606 --- /dev/null +++ b/test/PackageManager/data/PackageManager.Test.F.Redder.msix/PackageManager.Test.F.Redder.msix.vcxproj @@ -0,0 +1,130 @@ + + + + + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + Debug + ARM64 + + + Release + ARM64 + + + + {d0a1dfb8-8cee-4cfc-b57b-b7c574b411c2} + VCProjectVersion + PackageManager.Test.F.Redder.Msix + en-US + 16.0 + 10.0.22621.0 + 10.0.17763.0 + 10.0 + + + Utility + v143 + + + true + + + false + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + $(TargetName) + + + + appxmanifest.xml + + + appxmanifest.xml + + + appxmanifest.xml + + + + + $(RepoTestCertificatePFX) + $(RepoTestCertificatePassword) + + + + + + + + + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + + + + + + diff --git a/test/PackageManager/data/PackageManager.Test.F.Redder.msix/PackageManager.Test.F.Redder.msix.vcxproj.filters b/test/PackageManager/data/PackageManager.Test.F.Redder.msix/PackageManager.Test.F.Redder.msix.vcxproj.filters new file mode 100644 index 0000000000..2df21c891a --- /dev/null +++ b/test/PackageManager/data/PackageManager.Test.F.Redder.msix/PackageManager.Test.F.Redder.msix.vcxproj.filters @@ -0,0 +1,17 @@ + + + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tga;tiff;tif;png;wav;mfcribbon-ms + + + + + + + + + + + diff --git a/test/PackageManager/data/PackageManager.Test.F.Redder.msix/PackageManager.Test.F.Redder.vcxproj.filters b/test/PackageManager/data/PackageManager.Test.F.Redder.msix/PackageManager.Test.F.Redder.vcxproj.filters new file mode 100644 index 0000000000..2df21c891a --- /dev/null +++ b/test/PackageManager/data/PackageManager.Test.F.Redder.msix/PackageManager.Test.F.Redder.vcxproj.filters @@ -0,0 +1,17 @@ + + + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tga;tiff;tif;png;wav;mfcribbon-ms + + + + + + + + + + + diff --git a/test/PackageManager/data/PackageManager.Test.F.Redder.msix/appxmanifest-arm64.xml b/test/PackageManager/data/PackageManager.Test.F.Redder.msix/appxmanifest-arm64.xml new file mode 100644 index 0000000000..1ff95c6355 --- /dev/null +++ b/test/PackageManager/data/PackageManager.Test.F.Redder.msix/appxmanifest-arm64.xml @@ -0,0 +1,28 @@ + + + + + + + + true + Test.PackageManager.F.Redder + Microsoft Corporation + logo.png + + + + + + + + + + diff --git a/test/PackageManager/data/PackageManager.Test.F.Redder.msix/appxmanifest-x64.xml b/test/PackageManager/data/PackageManager.Test.F.Redder.msix/appxmanifest-x64.xml new file mode 100644 index 0000000000..1d7385d32d --- /dev/null +++ b/test/PackageManager/data/PackageManager.Test.F.Redder.msix/appxmanifest-x64.xml @@ -0,0 +1,28 @@ + + + + + + + + true + Test.PackageManager.F.Redder + Microsoft Corporation + logo.png + + + + + + + + + + diff --git a/test/PackageManager/data/PackageManager.Test.F.Redder.msix/appxmanifest-x86.xml b/test/PackageManager/data/PackageManager.Test.F.Redder.msix/appxmanifest-x86.xml new file mode 100644 index 0000000000..5618a73163 --- /dev/null +++ b/test/PackageManager/data/PackageManager.Test.F.Redder.msix/appxmanifest-x86.xml @@ -0,0 +1,28 @@ + + + + + + + + true + Test.PackageManager.F.Redder + Microsoft Corporation + logo.png + + + + + + + + + + diff --git a/test/PackageManager/data/PackageManager.Test.F.Redder.msix/logo.png b/test/PackageManager/data/PackageManager.Test.F.Redder.msix/logo.png new file mode 100644 index 0000000000..5bd7c0ce4d Binary files /dev/null and b/test/PackageManager/data/PackageManager.Test.F.Redder.msix/logo.png differ diff --git a/test/PackageManager/data/PackageManager.Test.F.Redder.msix/packages.config b/test/PackageManager/data/PackageManager.Test.F.Redder.msix/packages.config new file mode 100644 index 0000000000..d9db55a1b3 --- /dev/null +++ b/test/PackageManager/data/PackageManager.Test.F.Redder.msix/packages.config @@ -0,0 +1,6 @@ + + + + + + diff --git a/test/PowerNotifications/packages.config b/test/PowerNotifications/packages.config index 9b3e6252ff..1117ac430f 100644 --- a/test/PowerNotifications/packages.config +++ b/test/PowerNotifications/packages.config @@ -1,6 +1,6 @@  - - + + diff --git a/test/PushNotificationTests/packages.config b/test/PushNotificationTests/packages.config index 9b3e6252ff..1117ac430f 100644 --- a/test/PushNotificationTests/packages.config +++ b/test/PushNotificationTests/packages.config @@ -1,6 +1,6 @@  - - + + diff --git a/test/TestApps/AccessControlTestApp/packages.config b/test/TestApps/AccessControlTestApp/packages.config index 9b3e6252ff..1117ac430f 100644 --- a/test/TestApps/AccessControlTestApp/packages.config +++ b/test/TestApps/AccessControlTestApp/packages.config @@ -1,6 +1,6 @@  - - + + diff --git a/test/TestApps/AppLifecycleTestApp/packages.config b/test/TestApps/AppLifecycleTestApp/packages.config index 9b3e6252ff..1117ac430f 100644 --- a/test/TestApps/AppLifecycleTestApp/packages.config +++ b/test/TestApps/AppLifecycleTestApp/packages.config @@ -1,6 +1,6 @@  - - + + diff --git a/test/TestApps/ManualTestApp/packages.config b/test/TestApps/ManualTestApp/packages.config index 9b3e6252ff..1117ac430f 100644 --- a/test/TestApps/ManualTestApp/packages.config +++ b/test/TestApps/ManualTestApp/packages.config @@ -1,6 +1,6 @@  - - + + diff --git a/test/TestApps/PushNotificationsDemoApp/packages.config b/test/TestApps/PushNotificationsDemoApp/packages.config index 9b3e6252ff..1117ac430f 100644 --- a/test/TestApps/PushNotificationsDemoApp/packages.config +++ b/test/TestApps/PushNotificationsDemoApp/packages.config @@ -1,6 +1,6 @@  - - + + diff --git a/test/TestApps/PushNotificationsTestApp/packages.config b/test/TestApps/PushNotificationsTestApp/packages.config index 9b3e6252ff..1117ac430f 100644 --- a/test/TestApps/PushNotificationsTestApp/packages.config +++ b/test/TestApps/PushNotificationsTestApp/packages.config @@ -1,6 +1,6 @@  - - + + diff --git a/test/TestApps/ToastNotificationsDemoApp/packages.config b/test/TestApps/ToastNotificationsDemoApp/packages.config index 9b3e6252ff..1117ac430f 100644 --- a/test/TestApps/ToastNotificationsDemoApp/packages.config +++ b/test/TestApps/ToastNotificationsDemoApp/packages.config @@ -1,6 +1,6 @@  - - + + diff --git a/test/TestApps/ToastNotificationsTestApp/packages.config b/test/TestApps/ToastNotificationsTestApp/packages.config index 9b3e6252ff..1117ac430f 100644 --- a/test/TestApps/ToastNotificationsTestApp/packages.config +++ b/test/TestApps/ToastNotificationsTestApp/packages.config @@ -1,6 +1,6 @@  - - + + diff --git a/test/VersionInfo/packages.config b/test/VersionInfo/packages.config index 9b3e6252ff..1117ac430f 100644 --- a/test/VersionInfo/packages.config +++ b/test/VersionInfo/packages.config @@ -1,6 +1,6 @@  - - + + diff --git a/test/inc/WindowsAppRuntime.Test.Metadata.h b/test/inc/WindowsAppRuntime.Test.Metadata.h index 34b60ad924..952857eba1 100644 --- a/test/inc/WindowsAppRuntime.Test.Metadata.h +++ b/test/inc/WindowsAppRuntime.Test.Metadata.h @@ -19,7 +19,8 @@ #define WINDOWSAPPRUNTIME_TEST_MSIX_SINGLETON_PACKAGE_NAME L"Microsoft.WindowsAppRuntime.Singleton" #define WINDOWSAPPRUNTIME_TEST_PACKAGE_DDLM_NAMEPREFIX L"WindowsAppRuntime.Test.DDLM" -#define WINDOWSAPPRUNTIME_TEST_PACKAGE_DDLM_VERSION WINDOWSAPPRUNTIME_TEST_MSIX_MAIN_PACKAGE_NAME +#define WINDOWSAPPRUNTIME_TEST_PACKAGE_DDLM_VERSION WINDOWSAPPRUNTIME_TEST_METADATA_VERSION +#define WINDOWSAPPRUNTIME_TEST_PACKAGE_DDLM_VERSION_STRING WINDOWSAPPRUNTIME_TEST_METADATA_VERSION_STRING #define MSIX_PACKAGE_ARCHITECTURE_ARM L"arm" @@ -39,9 +40,9 @@ #else # error "Unknown processor architecture" #endif -#define WINDOWSAPPRUNTIME_TEST_PACKAGE_DDLM_NAME WINDOWSAPPRUNTIME_TEST_PACKAGE_DDLM_NAMEPREFIX L"-" WINDOWSAPPRUNTIME_TEST_METADATA_VERSION_STRING L"-" WINDOWSAPPRUNTIME_TEST_PACKAGE_DDLM_ARCHITECTURE +#define WINDOWSAPPRUNTIME_TEST_PACKAGE_DDLM_NAME WINDOWSAPPRUNTIME_TEST_PACKAGE_DDLM_NAMEPREFIX L"-" WINDOWSAPPRUNTIME_TEST_PACKAGE_DDLM_VERSION_STRING L"-" WINDOWSAPPRUNTIME_TEST_PACKAGE_DDLM_ARCHITECTURE #define WINDOWSAPPRUNTIME_TEST_PACKAGE_DDLM_PUBLISHERID WINDOWSAPPRUNTIME_TEST_MSIX_PUBLISHERID #define WINDOWSAPPRUNTIME_TEST_PACKAGE_DDLM_FAMILYNAME WINDOWSAPPRUNTIME_TEST_PACKAGE_DDLM_NAME L"_" WINDOWSAPPRUNTIME_TEST_PACKAGE_DDLM_PUBLISHERID -#define WINDOWSAPPRUNTIME_TEST_PACKAGE_DDLM_FULLNAME WINDOWSAPPRUNTIME_TEST_PACKAGE_DDLM_NAME L"_" WINDOWSAPPRUNTIME_TEST_PACKAGE_DDLM_VERSION L"_" WINDOWSAPPRUNTIME_TEST_PACKAGE_DDLM_ARCHITECTURE L"__" WINDOWSAPPRUNTIME_TEST_PACKAGE_DDLM_PUBLISHERID +#define WINDOWSAPPRUNTIME_TEST_PACKAGE_DDLM_FULLNAME WINDOWSAPPRUNTIME_TEST_PACKAGE_DDLM_NAME L"_" WINDOWSAPPRUNTIME_TEST_PACKAGE_DDLM_VERSION_STRING L"_" WINDOWSAPPRUNTIME_TEST_PACKAGE_DDLM_ARCHITECTURE L"__" WINDOWSAPPRUNTIME_TEST_PACKAGE_DDLM_PUBLISHERID #endif //__WINDOWSAPPRUNTIME_TEST_METADATA_H diff --git a/test/inc/WindowsAppRuntime.Test.Package.h b/test/inc/WindowsAppRuntime.Test.Package.h index 3d619a0450..a7f670cdea 100644 --- a/test/inc/WindowsAppRuntime.Test.Package.h +++ b/test/inc/WindowsAppRuntime.Test.Package.h @@ -1,4 +1,4 @@ -// Copyright (c) Microsoft Corporation and Contributors. +// Copyright (c) Microsoft Corporation and Contributors. // Licensed under the MIT License. #ifndef __WINDOWSAPPRUNTIME_TEST_PACKAGE_H @@ -30,22 +30,28 @@ #define WINDOWSAPPRUNTIME_TEST_MSIX_DEPLOYMENT_SINGLETON_PACKAGE_NAME L"Microsoft.WindowsAppRuntime.Singleton-Test" #define WINDOWSAPPRUNTIME_TEST_PACKAGE_DDLM_NAMEPREFIX L"WindowsAppRuntime.Test.DDLM" -#define WINDOWSAPPRUNTIME_TEST_PACKAGE_DDLM_VERSION WINDOWSAPPRUNTIME_TEST_METADATA_VERSION_STRING +#define WINDOWSAPPRUNTIME_TEST_PACKAGE_DDLM_VERSION WINDOWSAPPRUNTIME_TEST_METADATA_VERSION +#define WINDOWSAPPRUNTIME_TEST_PACKAGE_DDLM_VERSION_STRING WINDOWSAPPRUNTIME_TEST_METADATA_VERSION_STRING +#define MSIX_PACKAGE_ARCHITECTURE_ARM L"arm" +#define MSIX_PACKAGE_ARCHITECTURE_ARM64 L"arm64" +#define MSIX_PACKAGE_ARCHITECTURE_NEUTRAL L"neutral" +#define MSIX_PACKAGE_ARCHITECTURE_X64 L"x64" +#define MSIX_PACKAGE_ARCHITECTURE_X86 L"x86" #if defined(_M_X64) -#define WINDOWSAPPRUNTIME_TEST_PACKAGE_DDLM_ARCHITECTURE L"x64" +#define WINDOWSAPPRUNTIME_TEST_PACKAGE_DDLM_ARCHITECTURE MSIX_PACKAGE_ARCHITECTURE_X64 #elif defined(_M_IX86) -#define WINDOWSAPPRUNTIME_TEST_PACKAGE_DDLM_ARCHITECTURE L"x86" +#define WINDOWSAPPRUNTIME_TEST_PACKAGE_DDLM_ARCHITECTURE MSIX_PACKAGE_ARCHITECTURE_X86 #elif defined(_M_ARM64) -#define WINDOWSAPPRUNTIME_TEST_PACKAGE_DDLM_ARCHITECTURE L"arm64" +#define WINDOWSAPPRUNTIME_TEST_PACKAGE_DDLM_ARCHITECTURE MSIX_PACKAGE_ARCHITECTURE_ARM64 #elif defined(_M_ARM) -#define WINDOWSAPPRUNTIME_TEST_PACKAGE_DDLM_ARCHITECTURE L"arm" +#define WINDOWSAPPRUNTIME_TEST_PACKAGE_DDLM_ARCHITECTURE MSIX_PACKAGE_ARCHITECTURE_ARM #else # error "Unknown processor architecture" #endif -#define WINDOWSAPPRUNTIME_TEST_PACKAGE_DDLM_NAME WINDOWSAPPRUNTIME_TEST_PACKAGE_DDLM_NAMEPREFIX L"-" WINDOWSAPPRUNTIME_TEST_PACKAGE_DDLM_VERSION L"-" WINDOWSAPPRUNTIME_TEST_PACKAGE_DDLM_ARCHITECTURE +#define WINDOWSAPPRUNTIME_TEST_PACKAGE_DDLM_NAME WINDOWSAPPRUNTIME_TEST_PACKAGE_DDLM_NAMEPREFIX L"-" WINDOWSAPPRUNTIME_TEST_PACKAGE_DDLM_VERSION_STRING L"-" WINDOWSAPPRUNTIME_TEST_PACKAGE_DDLM_ARCHITECTURE #define WINDOWSAPPRUNTIME_TEST_PACKAGE_DDLM_PUBLISHERID WINDOWSAPPRUNTIME_TEST_MSIX_PUBLISHERID #define WINDOWSAPPRUNTIME_TEST_PACKAGE_DDLM_FAMILYNAME WINDOWSAPPRUNTIME_TEST_PACKAGE_DDLM_NAME L"_" WINDOWSAPPRUNTIME_TEST_PACKAGE_DDLM_PUBLISHERID -#define WINDOWSAPPRUNTIME_TEST_PACKAGE_DDLM_FULLNAME WINDOWSAPPRUNTIME_TEST_PACKAGE_DDLM_NAME L"_" WINDOWSAPPRUNTIME_TEST_PACKAGE_DDLM_VERSION L"_" WINDOWSAPPRUNTIME_TEST_PACKAGE_DDLM_ARCHITECTURE L"__" WINDOWSAPPRUNTIME_TEST_PACKAGE_DDLM_PUBLISHERID +#define WINDOWSAPPRUNTIME_TEST_PACKAGE_DDLM_FULLNAME WINDOWSAPPRUNTIME_TEST_PACKAGE_DDLM_NAME L"_" WINDOWSAPPRUNTIME_TEST_PACKAGE_DDLM_VERSION_STRING L"_" WINDOWSAPPRUNTIME_TEST_PACKAGE_DDLM_ARCHITECTURE L"__" WINDOWSAPPRUNTIME_TEST_PACKAGE_DDLM_PUBLISHERID namespace Test::Packages { @@ -88,7 +94,7 @@ namespace DynamicDependencyDataStore constexpr PCWSTR c_PackageDirName = L"DynamicDependency.DataStore"; constexpr PCWSTR c_PackageNamePrefix = L"WindowsAppRuntime.Test.DynDep.DataStore"; constexpr PCWSTR c_PackageFamilyName = L"WindowsAppRuntime.Test.DynDep.DataStore-" WINDOWSAPPRUNTIME_TEST_METADATA_RELEASE_STRING "_" WINDOWSAPPRUNTIME_TEST_MSIX_PUBLISHERID; - constexpr PCWSTR c_PackageFullName = L"WindowsAppRuntime.Test.DynDep.DataStore-" WINDOWSAPPRUNTIME_TEST_METADATA_RELEASE_STRING "_" WINDOWSAPPRUNTIME_TEST_PACKAGE_DDLM_VERSION L"_neutral__" WINDOWSAPPRUNTIME_TEST_MSIX_PUBLISHERID; + constexpr PCWSTR c_PackageFullName = L"WindowsAppRuntime.Test.DynDep.DataStore-" WINDOWSAPPRUNTIME_TEST_METADATA_RELEASE_STRING "_" WINDOWSAPPRUNTIME_TEST_PACKAGE_DDLM_VERSION_STRING L"_neutral__" WINDOWSAPPRUNTIME_TEST_MSIX_PUBLISHERID; } namespace WindowsAppRuntimeMain = DynamicDependencyDataStore; @@ -96,7 +102,7 @@ namespace WindowsAppRuntimeSingleton { constexpr PCWSTR c_PackageDirName = L"WindowsAppRuntime.Test.Singleton"; constexpr PCWSTR c_PackageFamilyName = L"WindowsAppRuntime.Test.Singleton_" WINDOWSAPPRUNTIME_TEST_MSIX_PUBLISHERID; - constexpr PCWSTR c_PackageFullName = L"WindowsAppRuntime.Test.Singleton_" WINDOWSAPPRUNTIME_TEST_PACKAGE_DDLM_VERSION L"_neutral__" WINDOWSAPPRUNTIME_TEST_MSIX_PUBLISHERID; + constexpr PCWSTR c_PackageFullName = L"WindowsAppRuntime.Test.Singleton_" WINDOWSAPPRUNTIME_TEST_PACKAGE_DDLM_VERSION_STRING L"_neutral__" WINDOWSAPPRUNTIME_TEST_MSIX_PUBLISHERID; } namespace DeploymentWindowsAppRuntimeFramework @@ -149,7 +155,30 @@ inline bool IsPackageRegistered(PCWSTR packageFullName) return !path.empty(); } -inline void AddPackage(PCWSTR packageDirName, PCWSTR packageFullName) +inline bool IsPackageAvailable(PCWSTR packageFullName) +{ + // Check if the package is available for use + // This means registered to the current user OR staged + // NOTE: To check if a package is staged and not registered to the current user: + // bool isStaged = IsPackageAvailable(p) && !IsPackageRegistered(p) + if (IsPackageRegistered(packageFullName)) + { + return true; + } + PackageOrigin packageOrigin{}; + const auto rc{ GetStagedPackageOrigin(packageFullName, &packageOrigin) }; + if (rc == ERROR_SUCCESS) + { + return true; + } + else if (rc == ERROR_APP_DATA_NOT_FOUND) + { + return false; + } + THROW_WIN32(rc); +} + +inline std::filesystem::path GetMsixPackagePath(PCWSTR packageDirName) { // Build the target package's .msix filename. It's under the Solution's $(OutDir) // NOTE: It could live in ...\Something.msix\... or ...\Something\... @@ -179,7 +208,18 @@ inline void AddPackage(PCWSTR packageDirName, PCWSTR packageFullName) //VERIFY_IS_TRUE(std::filesystem::is_regular_file(msix)); } - auto msixUri = winrt::Windows::Foundation::Uri(msix.c_str()); + return msix.c_str(); +} + +inline winrt::Windows::Foundation::Uri GetMsixPackageUri(PCWSTR packageDirName) +{ + auto path{ GetMsixPackagePath(packageDirName) }; + return winrt::Windows::Foundation::Uri{ path.c_str() }; +} + +inline void AddPackage(PCWSTR packageDirName, PCWSTR packageFullName) +{ + auto msixUri{ GetMsixPackageUri(packageDirName) }; // Install the package winrt::Windows::Management::Deployment::PackageManager packageManager; @@ -190,12 +230,41 @@ inline void AddPackage(PCWSTR packageDirName, PCWSTR packageFullName) inline void AddPackageIfNecessary(PCWSTR packageDirName, PCWSTR packageFullName) { - if (!IsPackageRegistered(packageFullName)) + if (IsPackageRegistered(packageFullName)) + { + WEX::Logging::Log::Comment(WEX::Common::String().Format(L"AddPackageIfNecessary: %s already registered", packageFullName)); + } + else { + WEX::Logging::Log::Comment(WEX::Common::String().Format(L"AddPackageIfNecessary: %s not registered, adding...", packageFullName)); AddPackage(packageDirName, packageFullName); } } +inline void StagePackage(PCWSTR packageDirName, PCWSTR packageFullName) +{ + auto msixUri{ GetMsixPackageUri(packageDirName) }; + + // Install the package + winrt::Windows::Management::Deployment::PackageManager packageManager; + auto options{ winrt::Windows::Management::Deployment::DeploymentOptions::None }; + auto deploymentResult{ packageManager.StagePackageAsync(msixUri, nullptr, options).get() }; + VERIFY_SUCCEEDED(deploymentResult.ExtendedErrorCode(), WEX::Common::String().Format(L"StagePackageAsync('%s') = 0x%0X %s", packageFullName, deploymentResult.ExtendedErrorCode(), deploymentResult.ErrorText().c_str())); +} + +inline void StagePackageIfNecessary(PCWSTR packageDirName, PCWSTR packageFullName) +{ + if (IsPackageAvailable(packageFullName)) + { + WEX::Logging::Log::Comment(WEX::Common::String().Format(L"StagePackageIfNecessary: %s already staged", packageFullName)); + } + else + { + WEX::Logging::Log::Comment(WEX::Common::String().Format(L"StagePackageIfNecessary: %s not staged, staging...", packageFullName)); + StagePackage(packageDirName, packageFullName); + } +} + inline void RemovePackage(PCWSTR packageFullName) { winrt::Windows::Management::Deployment::PackageManager packageManager; diff --git a/tools/ProjectTemplates/dev.cpp.dll.winrt-client-server/packages.config b/tools/ProjectTemplates/dev.cpp.dll.winrt-client-server/packages.config index 14efb7baf5..cd05427e9c 100644 --- a/tools/ProjectTemplates/dev.cpp.dll.winrt-client-server/packages.config +++ b/tools/ProjectTemplates/dev.cpp.dll.winrt-client-server/packages.config @@ -3,6 +3,6 @@ - + diff --git a/tools/ProjectTemplates/dev.cpp.dll.winrt-client/packages.config b/tools/ProjectTemplates/dev.cpp.dll.winrt-client/packages.config index 14efb7baf5..cd05427e9c 100644 --- a/tools/ProjectTemplates/dev.cpp.dll.winrt-client/packages.config +++ b/tools/ProjectTemplates/dev.cpp.dll.winrt-client/packages.config @@ -3,6 +3,6 @@ - + diff --git a/tools/ProjectTemplates/dev.cpp.exe+dll.com-oopserver/PurojekutoTenpuret/packages.config b/tools/ProjectTemplates/dev.cpp.exe+dll.com-oopserver/PurojekutoTenpuret/packages.config index 14efb7baf5..cd05427e9c 100644 --- a/tools/ProjectTemplates/dev.cpp.exe+dll.com-oopserver/PurojekutoTenpuret/packages.config +++ b/tools/ProjectTemplates/dev.cpp.exe+dll.com-oopserver/PurojekutoTenpuret/packages.config @@ -3,6 +3,6 @@ - + diff --git a/tools/ProjectTemplates/dev.cpp.exe.com-oopserver-main/packages.config b/tools/ProjectTemplates/dev.cpp.exe.com-oopserver-main/packages.config index 14efb7baf5..cd05427e9c 100644 --- a/tools/ProjectTemplates/dev.cpp.exe.com-oopserver-main/packages.config +++ b/tools/ProjectTemplates/dev.cpp.exe.com-oopserver-main/packages.config @@ -3,6 +3,6 @@ - + diff --git a/tools/ProjectTemplates/dev.cpp.exe.console-winrt-client/packages.config b/tools/ProjectTemplates/dev.cpp.exe.console-winrt-client/packages.config index 14efb7baf5..cd05427e9c 100644 --- a/tools/ProjectTemplates/dev.cpp.exe.console-winrt-client/packages.config +++ b/tools/ProjectTemplates/dev.cpp.exe.console-winrt-client/packages.config @@ -3,6 +3,6 @@ - + diff --git a/tools/ProjectTemplates/dev.cpp.exe.winmain-winrt-client/packages.config b/tools/ProjectTemplates/dev.cpp.exe.winmain-winrt-client/packages.config index 14efb7baf5..cd05427e9c 100644 --- a/tools/ProjectTemplates/dev.cpp.exe.winmain-winrt-client/packages.config +++ b/tools/ProjectTemplates/dev.cpp.exe.winmain-winrt-client/packages.config @@ -3,6 +3,6 @@ - + diff --git a/tools/ProjectTemplates/test.cpp.dll.taef/packages.config b/tools/ProjectTemplates/test.cpp.dll.taef/packages.config index 54378eec74..ecebfdd18e 100644 --- a/tools/ProjectTemplates/test.cpp.dll.taef/packages.config +++ b/tools/ProjectTemplates/test.cpp.dll.taef/packages.config @@ -3,7 +3,7 @@ - - + + diff --git a/tools/nuget/microsoft.taef.10.75.221207001.nupkg b/tools/nuget/microsoft.taef.10.75.221207001.nupkg new file mode 100644 index 0000000000..468fa0f535 Binary files /dev/null and b/tools/nuget/microsoft.taef.10.75.221207001.nupkg differ