microsoft / winget-cli

WinGet is the Windows Package Manager. This project includes a CLI (Command Line Interface), PowerShell modules, and a COM (Component Object Model) API (Application Programming Interface).
https://learn.microsoft.com/windows/package-manager/
MIT License
23.38k stars 1.46k forks source link

WinRT.Runtime conflict in PowerShell 7.3.8 #3819

Open jdhitsolutions opened 1 year ago

jdhitsolutions commented 1 year ago

Brief description of your issue

I am running version 0.2.2 of the Microsoft.Winget.Client module, although I had this problem in the earlier version. In a PowerShell 7 session running with no profile, I can import and use the module with no problem. In my normal session, with a profile, I can import the module with no errors. But when I run any command, I get the error The type initializer for '<Module>' threw an exception.

I've narrowed down at least part of the problem to the fact that not all DLLs are getting loaded. I think the WinRT.Runtime is the culprit. I tried manually adding it in my PowerShell session and it fails.

PSMessageDetails      :
Exception             : System.IO.FileLoadException: Could not load file or assembly 'WinRT.Runtime, Version=2.0.0.0,
                        Culture=neutral, PublicKeyToken=99ea127f02d97709'.
                           at System.Runtime.Loader.AssemblyLoadContext.<LoadFromPath>g____PInvoke|5_0(IntPtr
                        ptrNativeAssemblyBinder, UInt16* ilPath, UInt16* niPath, ObjectHandleOnStack retAssembly)
                           at System.Runtime.Loader.AssemblyLoadContext.LoadFromAssemblyPath(String assemblyPath)
                           at System.Reflection.Assembly.LoadFrom(String assemblyFile)
                           at Microsoft.PowerShell.Commands.AddTypeCommand.LoadAssemblies(IEnumerable`1 assemblies)
                           at System.Management.Automation.CommandProcessorBase.Complete()
TargetObject          :
CategoryInfo          : NotSpecified: (:) [Add-Type], FileLoadException
FullyQualifiedErrorId : System.IO.FileLoadException,Microsoft.PowerShell.Commands.AddTypeCommand
ErrorDetails          :
InvocationInfo        : System.Management.Automation.InvocationInfo
ScriptStackTrace      : at <ScriptBlock>, <No file>: line 1
PipelineIterationInfo : {}
```a 

### Steps to reproduce

I can't give you steps to reproduce.  I'm hoping for guidance on how to figure out what might be conflicting with the WinRT.Runtime assembly.

### Expected behavior

Commands should work as expected.

### Actual behavior

```powershell
PS C:\> get-wingetsettings -Verbose
Get-WinGetSettings: The type initializer for '<Module>' threw an exception.

Environment

Windows Package Manager v1.6.2771
Copyright (c) Microsoft Corporation. All rights reserved.

Windows: Windows.Desktop v10.0.22624.1391
System Architecture: X64
Package: Microsoft.DesktopAppInstaller v1.21.2771.0

Winget Directories                 
-----------------------------------------------------------------------------------------------------------------------
Logs                               %LOCALAPPDATA%\Packages\Microsoft.DesktopAppInstaller_8wekyb3d8bbwe\LocalState\Diag…
User Settings                      %LOCALAPPDATA%\Packages\Microsoft.DesktopAppInstaller_8wekyb3d8bbwe\LocalState\sett…
Portable Links Directory (User)    %LOCALAPPDATA%\Microsoft\WinGet\Links
Portable Links Directory (Machine) C:\Program Files\WinGet\Links
Portable Package Root (User)       %LOCALAPPDATA%\Microsoft\WinGet\Packages
Portable Package Root              C:\Program Files\WinGet\Packages
Portable Package Root (x86)        C:\Program Files (x86)\WinGet\Packages
Installer Downloads                %USERPROFILE%\Downloads

Links               
---------------------------------------------------------------------------
Privacy Statement   https://aka.ms/winget-privacy
License Agreement   https://aka.ms/winget-license
Third Party Notices https://aka.ms/winget-3rdPartyNotice
Homepage            https://aka.ms/winget
Windows Store Terms https://www.microsoft.com/en-us/storedocs/terms-of-sale

Admin Setting                             State
--------------------------------------------------
LocalManifestFiles                        Disabled
BypassCertificatePinningForMicrosoftStore Disabled
InstallerHashOverride                     Disabled
LocalArchiveMalwareScanOverride           Disabled

Name                           Value
----                           -----
PSVersion                      7.3.8
PSEdition                      Core
GitCommitId                    7.3.8
OS                             Microsoft Windows 10.0.22624
Platform                       Win32NT
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0…}
PSRemotingProtocolVersion      2.3
SerializationVersion           1.1.0.1
WSManStackVersion              3.0
jdhitsolutions commented 1 year ago

As I was writing this issue, I came up with a culprit. The BurnToast module uses the same assembly.

If I load this module after the Winget module, I get an error:

Write-Error: Failed to load library C:\Program Files\WindowsPowerShell\Modules\burnttoast\0.8.5\lib\Microsoft.Windows.SDK.NET\WinRT.Runtime.dll: Assembly with same name is already loaded

If I load the BurnToast module first, I can load the Winget module without error. I only get the error when I try to run a command. The import process should throw the same type of exception that the BurntToast module does.

jdhitsolutions commented 1 year ago

It looks like the BurnToast module and Winget module use the same version of WinRT.Runtime.

denelon commented 1 year ago

Is this happening in Windows PowerShell or in PowerShell 7?

We have some missing assemblies to hunt down to get everything working correctly in Windows PowerShell.

jdhitsolutions commented 1 year ago

I'm using PowerShell 7 for this.

msftrubengu commented 1 year ago

Which version of BurnToast are you using? This won't work with the latest non prerelease version (0.8.5), but will do for 1.0.0

Pre release version

PS C:\Dev> import-module BurntToast
PS C:\Dev> get-module BurntToast | select-object -Property Version

Version
-------
1.0.0

PS C:\Dev> import-module microsoft.winget.client
PS C:\Dev> Get-WinGetUserSettings

Name                           Value
----                           -----
visual                         {[progressBar, rainbow]}
installBehavior                {[disableInstallNotes, True]}
experimentalFeatures           {[configuration, True]}
$schema                        https://aka.ms/winget-settings.schema.json
source                         {[autoUpdateIntervalInMinutes, 1]}

PS C:\Dev> get-module microsoft.winget.client | select-object -Property Version

Version
-------
0.2.2
PS C:\Dev> [Reflection.AssemblyName]::GetAssemblyName("C:\Users\rubengu\Documents\PowerShell\Modules\BurntToast\1.0.0\lib\Microsoft.Windows.SDK.NET\WinRT.Runtime.dll")

Version        Name
-------        ----
2.0.0.0        WinRT.Runtime

Release version

PS C:\Dev> import-module burntToast -RequiredVersion 0.8.5
PS C:\Dev> import-module microsoft.winget.client
PS C:\Dev> Get-WinGetUserSettings
Get-WinGetUserSettings: The type initializer for '<Module>' threw an exception.
PS C:\Dev> [Reflection.AssemblyName]::GetAssemblyName("C:\Users\rubengu\Documents\PowerShell\Modules\BurntToast\0.8.5\lib\Microsoft.Windows.SDK.NET\WinRT.Runtime.dll")

Version        Name
-------        ----
1.1.0.0        WinRT.Runtime

For more context, the winget modules uses their own custom AssemblyLoadContext to load binaries there with the goal to avoid these kinds of conflicts, but sadly WinRT.Runtime.dll can't be loaded in a custom ALC. See more info in #3253. Because of that we explicitly load it in the default context.

jdhitsolutions commented 1 year ago

I'm still using 0.8.5. I'm not ready to jump to the pre-release version. It looks like options are extremely limited, so I'll stick to using the winget PowerShell module in a separate session.

msftrubengu commented 1 year ago

I created an issue in CsWinRT https://github.com/microsoft/CsWinRT/issues/1371