microsoft / WindowsAppSDK

The Windows App SDK empowers all Windows desktop apps with modern Windows UI, APIs, and platform features, including back-compat support, shipped via NuGet.
https://docs.microsoft.com/windows/apps/windows-app-sdk/
MIT License
3.78k stars 319 forks source link

Cannot load Microsoft.WindowsAppRuntime.dll #1883

Open DeepthiCG opened 2 years ago

DeepthiCG commented 2 years ago

Describe the bug

Cannot use dynamic dependent API like MddTryCreatePackageDependency, MddAddPackageDependency etc in a C++ application, showing errors related to Microsoft.WindowsAppRuntime.dll not found. Seems MddBootstrapInitialize cannot load this dll.

Steps to reproduce the bug

  1. Created a sample application(C++ Console App) using the steps mentioned in https://docs.microsoft.com/en-us/windows/apps/windows-app-sdk/tutorial-unpackaged-deployment?tabs=cpp It could successfully run.

  2. Now tried to use dynamic dependent API like MddTryCreatePackageDependency, MddAddPackageDependency etc in that, for referring framework packages like WinUI2 or anyother. These APIs are called after calling "MddBootstrapInitialize".

But errors showing that "Microsoft.WindowsAppRuntime.dll was not found"

  1. Tried to add "WindowsPackageType>None</WindowsPackageType in project settings. In this case project could not be build, showing errors like, Error MSB3843 Project "DynamicDependenciesTest" targets platform "Windows", but references SDK "Visual C++ 2015-2019 UWP Desktop Runtime for native apps v14.0" which targets platform "UAP".

Please suggest a solution for this.

Expected behavior

No response

Screenshots

No response

NuGet package version

No response

Packaging type

No response

Windows version

No response

IDE

No response

Additional context

No response

riverar commented 2 years ago

Hi @DeepthiCG, can you please edit this issue and complete it properly?

Can you also expand on what you're trying to do? You don't need to use those Mdd Add/Create APIs if you're just consuming WinAppSDK. What are you adding references to?

DeepthiCG commented 2 years ago

Hi,

Actually I want to use a framework package(WinUI2 stable) in an unpackaged application using XAML Island. I could use WinUI2 prerelease versions, but framework packages are not supported earlier.

In the latest Windows app SDK, it is noted like unpackaged apps can use framework package like winui2 stable version. That i tried using above steps.

I am facing issue with using "MddTryCreatePackageDependency" in win32 app. Please help.

huichen123 commented 2 years ago

have you installed the WindowsAppSDK runtime (step 7 in https://docs.microsoft.com/en-us/windows/apps/winui/winui3/create-your-first-winui3-app?pivots=winui3-unpackaged-cpp)?

as of the build error in your step 3, you may add this in your project file:

<WinUISDKReferences>false</WinUISDKReferences>
DeepthiCG commented 2 years ago

have you installed the WindowsAppSDK runtime (step 7 in https://docs.microsoft.com/en-us/windows/apps/winui/winui3/create-your-first-winui3-app?pivots=winui3-unpackaged-cpp)?

Yes, Runtime installed(Microsoft.WindowsAppRuntime.Redist.1.0.0.zip) , and the installation was success.

as of the build error in your step 3, you may add this in your project file:

false

Thank you. Build Error mentioned step 3 solved by this. Now runtime error related to Microsoft.WindowsAppRuntime.dll not found coming.

DrusTheAxe commented 2 years ago

I am facing issue with using "MddTryCreatePackageDependency" in win32 app. Please help.

You have a C++ executable that calls MddBootstrapInitialize() to get access to WinAppSDK's framework package and then call MddTryCreatePackageDependency() etc to access WinUI2's framework package? Do you link with /DELAYLOAD:Microsoft.WindowsAppRuntime.dll ?

If not then correct, your app won't load.

My apologies if some of this is old news to you. It's been a recurring question so it's worth elaborating, for the wider audience and future reference.

When you compile and link exported functions (like MddTryCreatePackageDependency) your PE file's ImportAddressTable (IAT) notes the import reference, and when you run Windows loads your file into memory and (among other things) has to resolve your IAT entries to point to the actual address in memory where those functions/dlls actually live at the moment. Windows looks for DLLs to satisfy these imports per the DLL Search Order which includes your process' package graph.

But unpackaged apps1 are born with an empty package graph. Windows loading your exe doesn't know to look in the WinAppSDK framework package to satisfy your imports.

This is no different for the Bootstrap APIs, except the Bootstrap DLL is redistributed by/with your app. Long as you put it somewhere Windows' Loader can find it when loading your PE file (e.g. in the same directory as your exe) your IAT entries for Microsoft.WindowsAppRuntime.Bootstrap.dll resolve just fine.

Unpackaged apps have a few options to use WinAppSDK exported APIs:

  1. Compile calls to exported APIs and link with /DELAYLOAD:Microsoft.WindowsAppRuntime.dll
  2. Use LoadLibrary and GetProcAddress to dynamically access exported APIs at runtime
  3. Make a DLL containing your calls to WinAppSDK's Flat-C APIs. Use /DELAYLOAD or LoadLibrary/GetProcAddress for your exe to access your DLL
  4. Make a WinRT object containing your calls to WinAppSDK's Flat-C APIs. Use ActivateInstance/GetActivationFactory for your exe to access your WinRT object
  5. ...other equivalent dynamic games (e.g. COM object and CoCreateInstance instead of WinRT...)

1 is used by the Bootstrapper's implementation. The Bootstrapper API is a wrapper over the Dynamic Dependencies API, specialized for WinAppSDK, to solve the chicken-egg problem of "I want to use DynDep APIs to access WinAppSDK framework package but don't have access to the WinAppSDK framework package until I call DynDep..." This is literally a 'bootstrapping' problem, but it's one unique to WinAppSDK. Thus the bootstrap DLL delay-loads its imports to Microsoft.WindowsAppRuntime.dll and doesn't touch the DynDep APIs until after the process' environmental soup is updated for Windows to be able to resolve those imports.

2 also works, but using the classic 'dynamically load and call DLL exports' game. You don't link with Microsoft.WindowsAppRuntime.lib so you have no IAT references Windows can't resolve when you load. Syntactically your code differs slightly for the same end result.

Visual C++ /DELAYLOAD adds a small bit of helper code to your PE file so you can write foo();. When you're loaded your IAT entry is NOT resolved. When foo() is called that helper code knows if the IAT entry hasn't been resolved yet and if not, calls LoadLibrary, GetProcAddress, updates the IAT entry with the actual address and then your call goes through to the exported function. Upside is same result but you don't have to write the explicit LL/GPA code.

See WindowsAppRuntime_BootstrapDLL.vcxproj line 188 for a living example how to do this.

3 is a variation on #1 just with an added layer of indirection. It's a useful technique in some scenarios but frankly they're rather uncommon, so I only note if here for completeness. I wouldn't recommend it, unless you have other reasons for such a split of your code and find this helpful (at which point it's probably obvious to you anyway :-))

4+5 are more variations of #1+2. WinRT inproc servers are hosted by DLLs but only loaded dynamically at runtime when used. Ditto COM inproc servers. A form of 'just-in-time load'. Again, noted for completeness, not recommended in its own right, but if you're already doing these sorts of games maybe useful (and again, probably already obvious to you).

1 Packaged apps are born with any manifested <PackageDependency...> references in their package graph and thus Windows can find DLLs for your imports when your process is created, before any of your code runs.

DrusTheAxe commented 2 years ago

Actually I want to use a framework package(WinUI2 stable) in an unpackaged application using XAML Island.

How are you ensuring lifetime management?

Do you control WinUI2 servicing on these machines, ensuring it's never serviced while in use?

Did you create something equivalent to the DDLM for WinUI2?

riverar commented 2 years ago

@DeepthiCG We need a sample project--or minimally a snippet of how you call MddTryCreatePackageDependency/etc. We also need you to complete the issue correctly (e.g. provide windows version, nuget version, etc.). If you can't help us, why would we help you?

Does WinUI 2 even ship a framework package?

DrusTheAxe commented 2 years ago

Does WinUI 2 even ship a framework package?

Yes. WinUI 2 releases are framework packages.

WinUI 2 shipped/ships prerelease builds as individual files for 'SelfContained' redistribution, but final (i.e. what WinAppSDK Calls 'stable') releases are only framework packages.

DeepthiCG commented 2 years ago

Do you link with /DELAYLOAD:Microsoft.WindowsAppRuntime.dll ?

Thank you. Runtime error related to Microsoft.WindowsAppRuntime.dll not found, solved by this.

DeepthiCG commented 2 years ago

How are you ensuring lifetime management?

Thank you for notifying this. I have read the Dynamic dependency API limitations at https://docs.microsoft.com/en-us/windows/apps/desktop/modernize/framework-packages/use-the-dynamic-dependency-api

Do you control WinUI2 servicing on these machines, ensuring it's never serviced while in use?

Can you explain, how this can be done? Whether there any other solutions without creating something equivalent to DDLM?

Also , I would like to clarify some issues observed when using dependency API for using WinUI2 framework package in an MFC app using XAML island. I have an MFC app and a UWP dll for XAML design. I have called dynamic dependent API at MFC side. If the UWP DLL not using WinUI2 framework, code running without issues. But When installed WinUI2 framework in UWP DLL, some runtime exceptions are coming

Trying to use Dynamic dependent API for using winui2 framework package for XAML Island hosting

There is an MFC app and UWP DLL project. UWP DLL using winui2 framework package for UI design. Dynamic dependent API is used in MFC App for updating package graph for using WinUI2 framework. But runtime exceptions coming. Please see below log

'MFCApplication.exe' (Win32): Loaded 'D:\UnpackagedApp\bin\x64\Release\MFCApplication.exe'. Symbols loaded. 'MFCApplication.exe' (Win32): Loaded 'C:\Windows\System32\ntdll.dll'. 'MFCApplication.exe' (Win32): Loaded 'C:\Windows\System32\kernel32.dll'. 'MFCApplication.exe' (Win32): Loaded 'C:\Windows\System32\KernelBase.dll'. 'MFCApplication.exe' (Win32): Loaded 'C:\Windows\System32\user32.dll'. 'MFCApplication.exe' (Win32): Loaded 'D:\UnpackagedApp\bin\x64\Release\Microsoft.WindowsAppRuntime.Bootstrap.dll'. 'MFCApplication.exe' (Win32): Loaded 'C:\Windows\System32\win32u.dll'. 'MFCApplication.exe' (Win32): Loaded 'C:\Windows\System32\advapi32.dll'. 'MFCApplication.exe' (Win32): Loaded 'C:\Windows\System32\msvcrt.dll'. 'MFCApplication.exe' (Win32): Loaded 'C:\Windows\System32\gdi32.dll'. 'MFCApplication.exe' (Win32): Loaded 'C:\Windows\System32\gdi32full.dll'. 'MFCApplication.exe' (Win32): Loaded 'C:\Windows\System32\sechost.dll'. 'MFCApplication.exe' (Win32): Loaded 'C:\Windows\System32\msvcp_win.dll'. 'MFCApplication.exe' (Win32): Loaded 'C:\Windows\System32\ucrtbase.dll'. 'MFCApplication.exe' (Win32): Loaded 'C:\Windows\System32\rpcrt4.dll'. 'MFCApplication.exe' (Win32): Loaded 'C:\Windows\System32\ole32.dll'. 'MFCApplication.exe' (Win32): Loaded 'C:\Windows\System32\combase.dll'. 'MFCApplication.exe' (Win32): Loaded 'C:\Windows\System32\oleaut32.dll'. 'MFCApplication.exe' (Win32): Loaded 'C:\Windows\WinSxS\amd64_microsoft.windows.common-controls_6595b64144ccf1df_6.0.19041.1110_none_60b5254171f9507e\comctl32.dll'. 'MFCApplication.exe' (Win32): Loaded 'C:\Windows\System32\vcruntime140_1.dll'. 'MFCApplication.exe' (Win32): Loaded 'C:\Windows\System32\msvcp140.dll'. 'MFCApplication.exe' (Win32): Loaded 'C:\Windows\System32\vcruntime140.dll'. 'MFCApplication.exe' (Win32): Loaded 'C:\Windows\System32\mfc140u.dll'. 'MFCApplication.exe' (Win32): Loaded 'C:\Windows\System32\shlwapi.dll'. 'MFCApplication.exe' (Win32): Loaded 'C:\Windows\System32\imm32.dll'. 'MFCApplication.exe' (Win32): Loaded 'C:\Windows\System32\uxtheme.dll'. 'MFCApplication.exe' (Win32): Loaded 'C:\Windows\System32\umppc14505.dll'. 'MFCApplication.exe' (Win32): Unloaded 'C:\Windows\System32\umppc14505.dll' 'MFCApplication.exe' (Win32): Loaded 'C:\Windows\System32\umppc14505.dll'. 'MFCApplication.exe' (Win32): Loaded 'C:\Windows\System32\QIPCAP64.dll'. 'MFCApplication.exe' (Win32): Loaded 'C:\Windows\System32\shell32.dll'. 'MFCApplication.exe' (Win32): Loaded 'C:\Windows\System32\dnsapi.dll'. 'MFCApplication.exe' (Win32): Loaded 'C:\Windows\System32\IPHLPAPI.DLL'. 'MFCApplication.exe' (Win32): Loaded 'C:\Windows\System32\nsi.dll'. 'MFCApplication.exe' (Win32): Loaded 'C:\Windows\System32\bcryptprimitives.dll'. 'MFCApplication.exe' (Win32): Loaded 'C:\Windows\System32\kernel.appcore.dll'. 'MFCApplication.exe' (Win32): Loaded 'C:\Windows\System32\clbcatq.dll'. 'MFCApplication.exe' (Win32): Loaded 'C:\Windows\System32\AppExtension.dll'. 'MFCApplication.exe' (Win32): Loaded 'C:\Windows\System32\SHCore.dll'. 'MFCApplication.exe' (Win32): Loaded 'C:\Windows\System32\propsys.dll'. 'MFCApplication.exe' (Win32): Loaded 'C:\Windows\System32\twinapi.appcore.dll'. 'MFCApplication.exe' (Win32): Loaded 'C:\Windows\System32\AppXDeploymentClient.dll'. 'MFCApplication.exe' (Win32): Loaded 'C:\Windows\System32\Windows.StateRepositoryPS.dll'. 'MFCApplication.exe' (Win32): Loaded 'C:\Windows\System32\WinTypes.dll'. 'MFCApplication.exe' (Win32): Loaded 'C:\Windows\System32\Windows.StateRepositoryCore.dll'. 'MFCApplication.exe' (Win32): Loaded 'C:\ProgramData\Microsoft\Windows\AppRepository\Packages\Microsoft.WinAppRuntime.DDLM.0.319.455.0-x6_0.319.455.0_x648wekyb3d8bbwe\PackagedCom\DynamicDependencyLifetimeManager.ProxyStub.dll'. 'MFCApplication.exe' (Win32): Loaded 'C:\Program Files\WindowsApps\Microsoft.WindowsAppRuntime.1.0_0.319.455.0_x648wekyb3d8bbwe\Microsoft.WindowsAppRuntime.dll'. 'MFCApplication.exe' (Win32): Loaded 'C:\Windows\System32\xmllite.dll'. 'MFCApplication.exe' (Win32): Loaded 'C:\Windows\System32\powrprof.dll'. 'MFCApplication.exe' (Win32): Loaded 'C:\Windows\System32\rometadata.dll'. 'MFCApplication.exe' (Win32): Loaded 'C:\Windows\System32\umpdc.dll'. 'MFCApplication.exe' (Win32): Loaded 'C:\Windows\System32\Windows.ApplicationModel.dll'. 'MFCApplication.exe' (Win32): Loaded 'C:\Windows\System32\Windows.StateRepositoryClient.dll'. 'MFCApplication.exe' (Win32): Loaded 'C:\Windows\System32\msctf.dll'. 'MFCApplication.exe' (Win32): Loaded 'D:\UnpackagedApp\bin\x64\Release\WinUI2x_DLL.dll'. Symbols loaded. 'MFCApplication.exe' (Win32): Loaded 'D:\UnpackagedApp\bin\x64\Release\msvcp140_app.dll'. 'MFCApplication.exe' (Win32): Loaded 'D:\UnpackagedApp\bin\x64\Release\vcruntime140_1_app.dll'. 'MFCApplication.exe' (Win32): Loaded 'D:\UnpackagedApp\bin\x64\Release\vcruntime140_app.dll'. 'MFCApplication.exe' (Win32): Loaded 'D:\UnpackagedApp\bin\x64\Release\Microsoft.Toolkit.Win32.UI.XamlHost.dll'. 'MFCApplication.exe' (Win32): Loaded 'C:\Windows\System32\threadpoolwinrt.dll'. 'MFCApplication.exe' (Win32): Loaded 'C:\Windows\System32\Windows.UI.Xaml.dll'. 'MFCApplication.exe' (Win32): Loaded 'C:\Windows\System32\CoreMessaging.dll'. 'MFCApplication.exe' (Win32): Loaded 'C:\Windows\System32\ws2_32.dll'. 'MFCApplication.exe' (Win32): Loaded 'C:\Windows\System32\BCP47Langs.dll'. 'MFCApplication.exe' (Win32): Loaded 'C:\Windows\System32\iertutil.dll'. 'MFCApplication.exe' (Win32): Loaded 'C:\Windows\System32\dcomp.dll'. 'MFCApplication.exe' (Win32): Loaded 'C:\Windows\System32\OneCoreUAPCommonProxyStub.dll'. 'MFCApplication.exe' (Win32): Loaded 'C:\Windows\System32\Windows.UI.dll'. 'MFCApplication.exe' (Win32): Loaded 'C:\Windows\System32\WindowManagementAPI.dll'. 'MFCApplication.exe' (Win32): Loaded 'C:\Windows\System32\TextInputFramework.dll'. 'MFCApplication.exe' (Win32): Loaded 'C:\Windows\System32\InputHost.dll'. 'MFCApplication.exe' (Win32): Loaded 'C:\Windows\System32\CoreUIComponents.dll'. 'MFCApplication.exe' (Win32): Loaded 'C:\Windows\System32\ntmarta.dll'. Exception thrown at 0x00007FF99E2B4F69 (KernelBase.dll) in MFCApplication.exe: 0x40080202: WinRT transform error (parameters: 0x000000008000000B, 0x0000000080070490, 0x0000000000000014, 0x00000084BEF4DC30). 'MFCApplication.exe' (Win32): Loaded 'C:\Windows\System32\UiaManager.dll'. 'MFCApplication.exe' (Win32): Loaded 'C:\Windows\System32\urlmon.dll'. 'MFCApplication.exe' (Win32): Loaded 'C:\Windows\System32\srvcli.dll'. 'MFCApplication.exe' (Win32): Loaded 'C:\Windows\System32\netutils.dll'. 'MFCApplication.exe' (Win32): Loaded 'C:\Windows\System32\dxgi.dll'. 'MFCApplication.exe' (Win32): Loaded 'C:\Windows\System32\ResourcePolicyClient.dll'. 'MFCApplication.exe' (Win32): Loaded 'C:\Windows\System32\MrmCoreR.dll'. 'MFCApplication.exe' (Win32): Unloaded 'C:\Windows\System32\ResourcePolicyClient.dll' 'MFCApplication.exe' (Win32): Loaded 'C:\Windows\System32\BCP47mrm.dll'. 'MFCApplication.exe' (Win32): Loaded 'C:\Windows\System32\windows.storage.dll'. 'MFCApplication.exe' (Win32): Loaded 'C:\Windows\System32\wldp.dll'. onecore\base\appmodel\statemanager\apiset\lib\statespace.cpp(108)\kernelbase.dll!00007FF99E2DF2C6: (caller: 00007FF99E2DF16B) ReturnHr(1) tid(a900) 80073D54 The process has no package identity. Msg:[GetCurrentPackageFamilyName 0] onecore\base\appmodel\statemanager\apiset\lib\statemanager.cpp(53)\kernelbase.dll!00007FF99E2DF1B8: (caller: 00007FF988DACAEE) ReturnHr(2) tid(a900) 80073D54 The process has no package identity. Msg:[Create] 'MFCApplication.exe' (Win32): Loaded 'C:\Program Files\WindowsApps\Microsoft.WindowsAppRuntime.1.0_0.319.455.0_x648wekyb3d8bbwe\Microsoft.UI.Xaml.Controls.dll'. 'MFCApplication.exe' (Win32): Loaded 'C:\Windows\System32\d2d1.dll'. 'MFCApplication.exe' (Win32): Loaded 'C:\Windows\System32\DriverStore\FileRepository\u0358337.inf_amd64_4c4ee6c1ac83c0d2\B358199\amdhdl64.dll'. 'MFCApplication.exe' (Win32): Loaded 'C:\Program Files\WindowsApps\Microsoft.WindowsAppRuntime.1.0_0.319.455.0_x648wekyb3d8bbwe\Microsoft.ui.xaml.dll'. 'MFCApplication.exe' (Win32): Loaded 'C:\Program Files\WindowsApps\Microsoft.WindowsAppRuntime.1.0_0.319.455.0_x648wekyb3d8bbwe\Microsoft.Internal.FrameworkUdk.dll'. 'MFCApplication.exe' (Win32): Loaded 'C:\Program Files\WindowsApps\Microsoft.WindowsAppRuntime.1.0_0.319.455.0_x648wekyb3d8bbwe\Microsoft.UI.Xaml.Internal.dll'. 'MFCApplication.exe' (Win32): Loaded 'C:\Windows\System32\DWrite.dll'. 'MFCApplication.exe' (Win32): Loaded 'C:\Windows\System32\dwmapi.dll'. 'MFCApplication.exe' (Win32): Loaded 'C:\Windows\System32\profapi.dll'. 'MFCApplication.exe' (Win32): Unloaded 'C:\Windows\System32\DriverStore\FileRepository\u0358337.inf_amd64_4c4ee6c1ac83c0d2\B358199\amdhdl64.dll' 'MFCApplication.exe' (Win32): Loaded 'C:\Windows\System32\d3d11.dll'. Exception thrown at 0x00007FF99E2B4F69 (KernelBase.dll) in MFCApplication.exe: WinRT originate error - 0x8001010E : 'The application called an interface that was marshalled for a different thread.'. 'MFCApplication.exe' (Win32): Loaded 'C:\Windows\System32\bcrypt.dll'. Exception thrown at 0x00007FF99E2B4F69 in MFCApplication.exe: Microsoft C++ exception: winrt::hresult_wrong_thread at memory location 0x00000084BEF4D450. Exception thrown at 0x00007FF99E2B4F69 in MFCApplication.exe: Microsoft C++ exception: [rethrow] at memory location 0x0000000000000000. Exception thrown at 0x00007FF99E2B4F69 in MFCApplication.exe: Microsoft C++ exception: winrt::hresult_wrong_thread at memory location 0x00000084BEF4D510. 'MFCApplication.exe' (Win32): Loaded 'C:\Windows\System32\DriverStore\FileRepository\oem78.inf_amd64_dc945736c722f2b5\igd10iumd64.dll'. 'MFCApplication.exe' (Win32): Loaded 'C:\Windows\System32\ncrypt.dll'. Exception thrown at 0x00007FF99E2B4F69 in MFCApplication.exe: Microsoft C++ exception: [rethrow] at memory location 0x0000000000000000. 'MFCApplication.exe' (Win32): Loaded 'C:\Windows\System32\ntasn1.dll'. Exception thrown at 0x00007FF99E2B4F69 (KernelBase.dll) in MFCApplication.exe: WinRT originate error - 0x802B000A : 'Cannot create instance of type 'Microsoft.UI.Xaml.Controls.XamlControlsResources' [Line: 0 Position: 0]'. 'MFCApplication.exe' (Win32): Loaded 'C:\Windows\System32\DriverStore\FileRepository\oem78.inf_amd64_dc945736c722f2b5\igdgmm64.dll'. 'MFCApplication.exe' (Win32): Loaded 'C:\Windows\System32\DriverStore\FileRepository\oem78.inf_amd64_dc945736c722f2b5\igc64.dll'. 'MFCApplication.exe' (Win32): Loaded 'C:\Windows\System32\DXCore.dll'. 'MFCApplication.exe' (Win32): Loaded 'C:\Windows\System32\cfgmgr32.dll'. Unhandled exception at 0x00007FF99E38B302 (KernelBase.dll) in MFCApplication.exe: 0xC000027B: An application-internal exception has occurred (parameters: 0x00000197C7867080, 0x0000000000000002).

DrusTheAxe commented 2 years ago

Can you explain, how this can be done? Whether there any other solutions without creating something equivalent to DDLM?

Only one: use Windows 11 and the OS' Dynamic Dependency APIs (eg. TryCreatePackageDependency instead of MddTryCreatePackageDependency). Deployment was updated in Win11 to know about dynamic depenencies.

If you need a downlevel solution options are limited. Deployment only knows a framework package is in use if (1) there's a running process (2) with package identity (3) whose manifest declares a ` on the framework and (4) that dependency resolved to the specific framework package.

NOTE: <PackageDependency> is a criteria. That's resolved to a specific package for use at runtime. Hence the reason manifested <PackageDependency> has a MinVersion attribute. You can see what what packages those resolved to for a particular user e.g.

[C:] powershell -c Get-AppxPackage *zunev*
...
Dependencies      : {Microsoft.VCLibs.140.00_14.0.30704.0_x64__8wekyb3d8bbwe,
                    Microsoft.UI.Xaml.2.7_7.2109.13004.0_x64__8wekyb3d8bbwe,

Here you can see ZuneVideo's manifest declared a dependency on VCLibs and WinUI framework packages, which has been resolved to specific instances of those framework packages.

Now replace 'ZuneVideo' with 'unpackage app'. There's a running process but it has no package identity, nor any manifest to declare <PackageDependency>. That's why the DDLM exists - because unpackaged apps have no way to tell Deployment "I'm using that framework package". At least, no direct way. So we cheat ;-) The DDLM is a helper package, whose ultimate purpose is to allow us to get a process running with a package identity with a manifested dependency on WinAppSDK's framework package. MddBootstrapInitialize creates that process and it stays running until MddBootstrapShutdown (or process death).

If you're a packaged app you just add <PackageDependency Name="Microsoft.WindowsAppRuntime.1.0"...> in your appxmanifest.xml and you're covered. If you're an unpackaged app, that's not an option. That leaves (a) use the DynDep API in the OS or (b) do something like the DDLM. I'm not aware of a 3rd option (and we wracked our brains pretty hard before before eventually landing on the DDLM).

You don't need the DDLM per se. Just a process with package identity for a package with a the appropos <PackageIdentity>. But whether you call it 'DDLM' it's equivalent.

Does Win11-required work for you?

DrusTheAxe commented 2 years ago

Trying to use Dynamic dependent API for using winui2 framework package for XAML Island hosting

You call MddAddPackageDependency(...winui2...) after calling MddBootstrapInitialize? Can you share the snippet?

If so your process' package graph is [WinAppSDK, WinUI2]. When you ActivateInstance(Microsoft.UI.Xaml.Button) it'll walk the package graph looking for a match...and if WinUI 2 + 3 objects have identical ACIDs this would resolve to a WinUI3 object. Getting a WinUI3 widget at runtime when you're compiled expecting a WinUI2 would easily lead to crashes if their VTBLs aren't identical.

I believe WinUI 3 is not ABI compatible with WinUI 2.

If this is your problem you may be able to workaround it by tweaking your MddAddPackageDependency(...winui2...) call to add WinUI2 to the package graph BEFORE WinAppSDK e.g. specify rank as <0 (MddBootstrapInitialize adds WinAppSDK with rank=default (0)).

@MikeHillberg @jevansaks for visibility

DeepthiCG commented 2 years ago

You call MddAddPackageDependency(...winui2...) after calling MddBootstrapInitialize? Can you share the snippet?

Yes, MddAddPackageDependency called after MddBootstrapInitialize in "CMFCApplicationApp::InitInstance()" function.

 const UINT32 majorMinorVersion{ 0x00010000 };
PCWSTR versionTag{ L"" };
const PACKAGE_VERSION minVersionboot{};

const HRESULT hr{ MddBootstrapInitialize(majorMinorVersion, versionTag, minVersionboot) };

// Check the return code for errors. If there is an error, display the result.
if (FAILED(hr))
{
    wprintf(L"Error 0x%X in MddBootstrapInitialize(0x%08X, %s, %hu.%hu.%hu.%hu)\n",
        hr, majorMinorVersion, versionTag, minVersionboot.Major, minVersionboot.Minor, minVersionboot.Build, minVersionboot.Revision);
    return hr;
}

PCWSTR packageFamilyName = L"Microsoft.UI.Xaml.2.5_8wekyb3d8bbwe";
PACKAGE_VERSION minVersion{};
minVersion.Major = 2;
minVersion.Minor = 52012;
minVersion.Build = 2002;
minVersion.Revision = 0;
const auto architectureFilter = MddPackageDependencyProcessorArchitectures::None;
const auto lifetimeKind = MddPackageDependencyLifetimeKind::Process;
const auto createOptions = MddCreatePackageDependencyOptions::None;

MddTryCreatePackageDependency(0,
    packageFamilyName, minVersion, architectureFilter, lifetimeKind, nullptr, createOptions, &packageDependencyId);
// lifetimeArtifact=null gives the PackageDepedency a lifetime of the current process
// The PackageDependency is not persisted. It will be implicitly deleted when the process terminates.

const INT32 rank = MDD_PACKAGE_DEPENDENCY_RANK_DEFAULT;
const auto addOptions = MddAddPackageDependencyOptions::None;
MDD_PACKAGEDEPENDENCY_CONTEXT packageDependencyContext = nullptr;
wil::unique_process_heap_string packageFullName;
RETURN_IF_FAILED(MddAddPackageDependency(
    packageDependencyId.get(), rank, addOptions, &packageDependencyContext, &packageFullName));
DeepthiCG commented 2 years ago

Getting a WinUI3 widget at runtime when you're compiled expecting a WinUI2 would easily lead to crashes if their VTBLs aren't identical.

From the exception log, it seems WinUI3 dlls are loaded.

If this is your problem you may be able to workaround it by tweaking your MddAddPackageDependency(...winui2...) call to add WinUI2 to the package graph BEFORE WinAppSDK e.g. specify rank as <0 (MddBootstrapInitialize adds WinAppSDK with rank=default (0)).

Modified rank as -1 as below. Still same exception coming. const INT32 rank = -1; const auto addOptions = MddAddPackageDependencyOptions::PrependIfRankCollision; MDD_PACKAGEDEPENDENCY_CONTEXT packageDependencyContext = nullptr; wil::unique_process_heap_string packageFullName; RETURN_IF_FAILED(MddAddPackageDependency( packageDependencyId.get(), rank, addOptions, &packageDependencyContext, &packageFullName));

DeepthiCG commented 2 years ago

Sample code for demonstrating above issue added at https://github.com/DeepthiCG/DynamicdependentAPI_XamlIsland

DrusTheAxe commented 2 years ago

Sample code for demonstrating above issue added at https://github.com/DeepthiCG/DynamicdependentAPI_XamlIsland

404 page not found :-(

DeepthiCG commented 2 years ago

Could you please check , whether it is accessible now?

riverar commented 2 years ago

@DeepthiCG It is not. If you'd like, you can send me a zip and I can rehost it. Or you can drag the zip into the thread here.

DeepthiCG commented 2 years ago

DynamicdependentAPI_XamlIsland-main.zip