Skip to content

Commit

Permalink
Use embedded CsWinRT (#5178)
Browse files Browse the repository at this point in the history
## Issue
Updating the version of CsWinRT that we use lead to a problem with
conflicting WinRT.Runtime assemblies (microsoft/winget-dsc#140). While
that issue was mitigated by delisting the offending version, in order to
ship any release with the newer version of CsWinRT, we need to embed the
WinRT.Runtime in our assemblies.

## Change
Move to use embedded CsWinRT, specifically in
`Microsoft.WinGet.Client.Engine` and
`Microsoft.Management.Configuration.Processor`. The dependent projects
are updated to no longer reference CsWinRT, but requires some special
handling to prevent errors.

Since the configuration code was leveraging a projection assembly, it is
being replaced by the processor. The projected types are shared out to
those dependent binaries via `InternalsVisibleTo`.

Also fixes an annoying behavior where an exception escaping from a
command execution would prevent the `--logs` option from opening the log
location (error cases being more likely to be the time one would want
the logs of course).
  • Loading branch information
JohnMcPMS committed Feb 5, 2025
1 parent 2b8ca4d commit 53c9dbe
Show file tree
Hide file tree
Showing 36 changed files with 344 additions and 188 deletions.
2 changes: 2 additions & 0 deletions .github/actions/spelling/excludes.txt
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,9 @@
^src/catch2/
^src/cpprestsdk/
^src/JsonCppLib/
^src/Microsoft.Management.Configuration.Processor/Microsoft.Management.Configuration.Processor.csproj$
^src/PowerShell/Help/markdownlint\.yaml$
^src/PowerShell/Microsoft.WinGet.Client.Engine/Microsoft.WinGet.Client.Engine.csproj$
^src/PureLib/
^src/SfsClient/
^src/UndockedRegFreeWinRT/
Expand Down
7 changes: 7 additions & 0 deletions src/AppInstallerCLI.sln
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,12 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Microsoft.Management.Deploy
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Management.Deployment.CsWinRTProjection", "Microsoft.Management.Deployment.CsWinRTProjection\Microsoft.Management.Deployment.CsWinRTProjection.csproj", "{9406322E-6272-487E-902A-9953889719EA}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "targets", "targets", "{A0B4F808-B190-41C4-97CB-C8EA1932F84F}"
ProjectSection(SolutionItems) = preProject
targets\EmbeddedCsWinRT.targets = targets\EmbeddedCsWinRT.targets
targets\ReferenceEmbeddedCsWinRTProject.targets = targets\ReferenceEmbeddedCsWinRTProject.targets
EndProjectSection
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|ARM64 = Debug|ARM64
Expand Down Expand Up @@ -1301,6 +1307,7 @@ Global
{5A52D9FC-0059-4A4A-8196-427A7AA0D1C5} = {7C218A3E-9BC8-48FF-B91B-BCACD828C0C9}
{1B9077B3-8923-4ECD-8FC9-B3190FCBE4D4} = {60618CAC-2995-4DF9-9914-45C6FC02C995}
{76B26B2C-602A-4AD0-9736-4162D3FCA92A} = {1A5D7A7D-5CB2-47D5-B40D-4E61CAEDC798}
{A0B4F808-B190-41C4-97CB-C8EA1932F84F} = {8D53D749-D51C-46F8-A162-9371AAA6C2E7}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {B6FDB70C-A751-422C-ACD1-E35419495857}
Expand Down
16 changes: 0 additions & 16 deletions src/AppInstallerCLICore/AppInstallerCLICore.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -530,9 +530,6 @@
<ProjectReference Include="..\YamlCppLib\YamlCppLib.vcxproj">
<Project>{8bb94bb8-374f-4294-bca1-c7811514a6b7}</Project>
</ProjectReference>
<ProjectReference Include="..\Microsoft.Management.Configuration.Processor\Microsoft.Management.Configuration.Processor.csproj">
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
</ProjectReference>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
Expand All @@ -546,18 +543,5 @@
<Error Condition="!Exists('$(SolutionDir)\packages\Microsoft.Windows.ImplementationLibrary.1.0.231028.1\build\native\Microsoft.Windows.ImplementationLibrary.targets')" Text="$([System.String]::Format('$(ErrorTextNuget)', '$(SolutionDir)\packages\Microsoft.Windows.ImplementationLibrary.1.0.231028.1\build\native\Microsoft.Windows.ImplementationLibrary.targets'))" />
<Error Condition="!Exists('$(SolutionDir)\packages\Microsoft.Windows.CppWinRT.2.0.230706.1\build\native\Microsoft.Windows.CppWinRT.props')" Text="$([System.String]::Format('$(ErrorTextNuget)', '$(SolutionDir)\packages\Microsoft.Windows.CppWinRT.2.0.230706.1\build\native\Microsoft.Windows.CppWinRT.props'))" />
<Error Condition="!Exists('$(SolutionDir)\packages\Microsoft.Windows.CppWinRT.2.0.230706.1\build\native\Microsoft.Windows.CppWinRT.targets')" Text="$([System.String]::Format('$(ErrorTextNuget)', '$(SolutionDir)\packages\Microsoft.Windows.CppWinRT.2.0.230706.1\build\native\Microsoft.Windows.CppWinRT.targets'))" />
<PropertyGroup>
<!-- The output path for this project is different on some builds where the RIDs are not used in the output. -->
<MicrosoftManagementConfigurationProcessorPath>$(SolutionDir)\AnyCPU\$(Configuration)\Microsoft.Management.Configuration.Processor\Microsoft.Management.Configuration.Processor.winmd</MicrosoftManagementConfigurationProcessorPath>
<MicrosoftManagementConfigurationProcessorPath Condition="!Exists('$(MicrosoftManagementConfigurationProcessorPath)')">$(SolutionDir)\AnyCPU\$(Configuration)\Microsoft.Management.Configuration.Processor\net8.0-windows10.0.22000.0\win\Microsoft.Management.Configuration.Processor.winmd</MicrosoftManagementConfigurationProcessorPath>
</PropertyGroup>
<Message Importance="high" Text="Microsoft.Management.Configuration.Processor.winmd -&gt; $(MicrosoftManagementConfigurationProcessorPath)" />
<Error Condition="!Exists('$(MicrosoftManagementConfigurationProcessorPath)')" Text="Microsoft.Management.Configuration.Processor.winmd was not found in $(MicrosoftManagementConfigurationProcessorPath)" />
<ItemGroup Condition="Exists('$(MicrosoftManagementConfigurationProcessorPath)')">
<Reference Include="Microsoft.Management.Configuration.Processor">
<HintPath>$(MicrosoftManagementConfigurationProcessorPath)</HintPath>
<IsWinMDFile>true</IsWinMDFile>
</Reference>
</ItemGroup>
</Target>
</Project>
28 changes: 21 additions & 7 deletions src/AppInstallerCLICore/Command.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,24 @@ using namespace AppInstaller::Settings;

namespace AppInstaller::CLI
{
constexpr Utility::LocIndView s_Command_ArgName_SilentAndInteractive = "silent|interactive"_liv;
namespace
{
constexpr Utility::LocIndView s_Command_ArgName_SilentAndInteractive = "silent|interactive"_liv;

void LaunchLogsIfRequested(Execution::Context& context)
{
try
{
if (context.Args.Contains(Execution::Args::Type::OpenLogs))
{
// TODO: Consider possibly adding functionality that if the context contains 'Execution::Args::Type::Log' to open the path provided for the log
// The above was omitted initially as a security precaution to ensure that user input to '--log' wouldn't be passed directly to ShellExecute
ShellExecute(NULL, NULL, Runtime::GetPathTo(Runtime::PathName::DefaultLogLocation).wstring().c_str(), NULL, NULL, SW_SHOWNORMAL);
}
}
CATCH_LOG();
}
}

Command::Command(
std::string_view name,
Expand Down Expand Up @@ -952,12 +969,7 @@ namespace AppInstaller::CLI
}
else
{
if (context.Args.Contains(Execution::Args::Type::OpenLogs))
{
// TODO: Consider possibly adding functionality that if the context contains 'Execution::Args::Type::Log' to open the path provided for the log
// The above was omitted initially as a security precaution to ensure that user input to '--log' wouldn't be passed directly to ShellExecute
ShellExecute(NULL, NULL, Runtime::GetPathTo(Runtime::PathName::DefaultLogLocation).wstring().c_str(), NULL, NULL, SW_SHOWNORMAL);
}
LaunchLogsIfRequested(context);

if (context.Args.Contains(Execution::Args::Type::Wait))
{
Expand Down Expand Up @@ -1046,6 +1058,8 @@ namespace AppInstaller::CLI
catch (...)
{
context.SetTerminationHR(Workflow::HandleException(context, std::current_exception()));

LaunchLogsIfRequested(context);
}
}

Expand Down
2 changes: 2 additions & 0 deletions src/AppInstallerCLICore/Commands/DebugCommand.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#if _DEBUG
#include "DebugCommand.h"
#include <winrt/Microsoft.Management.Configuration.h>
#include <winrt/Microsoft.Management.Configuration.SetProcessorFactory.h>
#include "AppInstallerDownloader.h"
#include "Sixel.h"

Expand Down Expand Up @@ -106,6 +107,7 @@ namespace AppInstaller::CLI
OutputProxyStubInterfaceRegistration<winrt::Microsoft::Management::Configuration::IConfigurationUnitProcessorDetails2>(context);
OutputProxyStubInterfaceRegistration<winrt::Microsoft::Management::Configuration::IGetAllSettingsConfigurationUnitProcessor>(context);
OutputProxyStubInterfaceRegistration<winrt::Microsoft::Management::Configuration::IConfigurationStatics2>(context);
OutputProxyStubInterfaceRegistration<winrt::Microsoft::Management::Configuration::SetProcessorFactory::IPwshConfigurationSetProcessorFactoryProperties>(context);

// TODO: Fix the layering inversion created by the COM deployment API (probably in order to operate winget.exe against the COM server).
// Then this code can just have a CppWinRT reference to the deployment API and spit out the interface registrations just like for configuration.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
#include <AppInstallerRuntime.h>
#include <AppInstallerStrings.h>
#include <winget/ILifetimeWatcher.h>
#include <winrt/Microsoft.Management.Configuration.Processor.h>
#include <winrt/Microsoft.Management.Configuration.SetProcessorFactory.h>

using namespace winrt::Windows::Foundation;
Expand Down Expand Up @@ -250,40 +249,40 @@ namespace AppInstaller::CLI::ConfigurationRemoting
// Create a copy for remote and set remote module paths
std::vector<winrt::hstring> newRemotePaths{ newModulePaths };
m_remoteAdditionalModulePaths = winrt::single_threaded_vector<winrt::hstring>(std::move(newRemotePaths));
m_remoteFactory.as<Processor::IPowerShellConfigurationProcessorFactoryProperties>().AdditionalModulePaths(m_remoteAdditionalModulePaths.GetView());
m_remoteFactory.as<SetProcessorFactory::IPwshConfigurationSetProcessorFactoryProperties>().AdditionalModulePaths(m_remoteAdditionalModulePaths.GetView());

// Store the updated module paths that we were given
m_additionalModulePaths = winrt::single_threaded_vector<winrt::hstring>(std::move(newModulePaths));
}

SetProcessorFactory::PwshConfigurationProcessorPolicy Policy() const
{
return Convert(m_remoteFactory.as<Processor::IPowerShellConfigurationProcessorFactoryProperties>().Policy());
return m_remoteFactory.as<SetProcessorFactory::IPwshConfigurationSetProcessorFactoryProperties>().Policy();
}

void Policy(SetProcessorFactory::PwshConfigurationProcessorPolicy value)
{
m_remoteFactory.as<Processor::IPowerShellConfigurationProcessorFactoryProperties>().Policy(Convert(value));
m_remoteFactory.as<SetProcessorFactory::IPwshConfigurationSetProcessorFactoryProperties>().Policy(value);
}

SetProcessorFactory::PwshConfigurationProcessorLocation Location() const
{
return Convert(m_remoteFactory.as<Processor::IPowerShellConfigurationProcessorFactoryProperties>().Location());
return m_remoteFactory.as<SetProcessorFactory::IPwshConfigurationSetProcessorFactoryProperties>().Location();
}

void Location(SetProcessorFactory::PwshConfigurationProcessorLocation value)
{
m_remoteFactory.as<Processor::IPowerShellConfigurationProcessorFactoryProperties>().Location(Convert(value));
m_remoteFactory.as<SetProcessorFactory::IPwshConfigurationSetProcessorFactoryProperties>().Location(value);
}

winrt::hstring CustomLocation() const
{
return m_remoteFactory.as<Processor::IPowerShellConfigurationProcessorFactoryProperties>().CustomLocation();
return m_remoteFactory.as<SetProcessorFactory::IPwshConfigurationSetProcessorFactoryProperties>().CustomLocation();
}

void CustomLocation(winrt::hstring value)
{
m_remoteFactory.as<Processor::IPowerShellConfigurationProcessorFactoryProperties>().CustomLocation(value);
m_remoteFactory.as<SetProcessorFactory::IPwshConfigurationSetProcessorFactoryProperties>().CustomLocation(value);
}

HRESULT STDMETHODCALLTYPE SetLifetimeWatcher(IUnknown* watcher)
Expand All @@ -292,30 +291,6 @@ namespace AppInstaller::CLI::ConfigurationRemoting
}

private:
static SetProcessorFactory::PwshConfigurationProcessorPolicy Convert(Processor::PowerShellConfigurationProcessorPolicy policy)
{
// We have used the same values intentionally; if that changes, update this.
return ToEnum<SetProcessorFactory::PwshConfigurationProcessorPolicy>(ToIntegral(policy));
}

static Processor::PowerShellConfigurationProcessorPolicy Convert(SetProcessorFactory::PwshConfigurationProcessorPolicy policy)
{
// We have used the same values intentionally; if that changes, update this.
return ToEnum<Processor::PowerShellConfigurationProcessorPolicy>(ToIntegral(policy));
}

static SetProcessorFactory::PwshConfigurationProcessorLocation Convert(Processor::PowerShellConfigurationProcessorLocation location)
{
// We have used the same values intentionally; if that changes, update this.
return ToEnum<SetProcessorFactory::PwshConfigurationProcessorLocation>(ToIntegral(location));
}

static Processor::PowerShellConfigurationProcessorLocation Convert(SetProcessorFactory::PwshConfigurationProcessorLocation location)
{
// We have used the same values intentionally; if that changes, update this.
return ToEnum<Processor::PowerShellConfigurationProcessorLocation>(ToIntegral(location));
}

IConfigurationSetProcessorFactory m_remoteFactory;
wil::unique_event m_completionEvent;
Collections::IVector<winrt::hstring> m_additionalModulePaths{ winrt::single_threaded_vector<winrt::hstring>() };
Expand Down
6 changes: 0 additions & 6 deletions src/AppInstallerCLIPackage/AppInstallerCLIPackage.wapproj
Original file line number Diff line number Diff line change
Expand Up @@ -244,12 +244,6 @@
<WinGetAdditionalPackageFile Include="$(WinGetAdditionalPackageFileRoot)\$(PlatformTarget)\$(Configuration)\Microsoft.Management.Configuration\Microsoft.Management.Configuration.winmd">
<PackagePath>Microsoft.Management.Configuration.winmd</PackagePath>
</WinGetAdditionalPackageFile>
<WinGetAdditionalPackageFile Include="$(WinGetAdditionalPackageFileRoot)\AnyCPU\$(Configuration)\Microsoft.Management.Configuration.Processor\**\Microsoft.Management.Configuration.Processor.winmd">
<PackagePath>Microsoft.Management.Configuration.Processor.winmd</PackagePath>
</WinGetAdditionalPackageFile>
<WinGetAdditionalPackageFile Include="$(WinGetAdditionalPackageFileRoot)\AnyCPU\$(Configuration)\Microsoft.Management.Configuration.Projection\**\Microsoft.Management.Configuration.Projection.dll">
<PackagePath>ConfigurationRemotingServer\Microsoft.Management.Configuration.Projection.dll</PackagePath>
</WinGetAdditionalPackageFile>
<WinGetAdditionalPackageFile Include="$(WinGetAdditionalPackageFileRoot)\$(PlatformTarget)\$(Configuration)\ConfigurationRemotingServer\net8.0-windows10.0.22000.0\$(ConfigServerRid)\**\*">
<PackagePath>ConfigurationRemotingServer</PackagePath>
<Recurse>true</Recurse>
Expand Down
1 change: 1 addition & 0 deletions src/AppInstallerCLIPackage/Package.appxmanifest
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@
<Interface Name="Microsoft.Management.Configuration.IConfigurationUnitProcessorDetails2" InterfaceId="E89623ED-76E2-5145-B920-D09659554E35" />
<Interface Name="Microsoft.Management.Configuration.IGetAllSettingsConfigurationUnitProcessor" InterfaceId="72EB8304-D8D3-57D4-9940-7C1C4AD8C40C" />
<Interface Name="Microsoft.Management.Configuration.IConfigurationStatics2" InterfaceId="540BE073-F2EF-5375-83AA-8E23086B0669" />
<Interface Name="Microsoft.Management.Configuration.SetProcessorFactory.IPwshConfigurationSetProcessorFactoryProperties" InterfaceId="2C298A30-BD3B-5D00-BCD1-2EB633AB7E3B" />
</ProxyStub>
</Extension>
<!-- This entry forces the package registration to process the windows.activatableClass.proxyStub extension above. -->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,6 @@
<OutputPath>$(SolutionDir)$(Platform)\$(Configuration)\$(MSBuildProjectName)\</OutputPath>
<SelfContained>true</SelfContained>
<RuntimeIdentifiers>win-x64;win-x86;win-arm64</RuntimeIdentifiers>
<!--
!!! Remove or update this on the next Microsoft.Windows.CsWinRT package version update. !!!
-->
<WindowsSdkPackageVersion>10.0.22000.53</WindowsSdkPackageVersion>
</PropertyGroup>

<PropertyGroup Condition=" '$(Platform)' == 'x64' ">
Expand All @@ -28,9 +24,7 @@
<RuntimeIdentifier>win-arm64</RuntimeIdentifier>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.Windows.CsWinRT" Version="2.1.6" />
</ItemGroup>
<Import Project="..\targets\ReferenceEmbeddedCsWinRTProject.targets" />

<ItemGroup>
<ProjectReference Include="..\Microsoft.Management.Configuration.Processor\Microsoft.Management.Configuration.Processor.csproj" />
Expand Down
Loading

0 comments on commit 53c9dbe

Please sign in to comment.