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.85k stars 322 forks source link

Immediate crash when trying to run as a different user #2555

Open conioh opened 2 years ago

conioh commented 2 years ago

Describe the bug

App crashes during load when run as a different user than the one to whom the Terminal Services session belongs.

Steps to reproduce the bug

  1. Install Visual Studio 2022 version 17.2.3.
  2. Restart the computer.
  3. On the Windows sign-in screen sign-in to User A.
  4. Install Windows App SDK C++ VS2022 Templates extension version 1.1.0.76285337.
  5. Install the Windows App SDK Runtime version 1.1.0 x64 (WindowsAppRuntimeInstall-1.1.0-x64.exe).
  6. Start Visual Studio.
  7. Create a new project using the instructions at the following page: https://docs.microsoft.com/en-us/windows/apps/winui/winui3/create-your-first-winui3-app#non-msix-packaged-create-a-new-project-for-a-non-msix-packaged-c-or-c-winui-3-desktop-app
    1. Use the Blank App, Packaged (WinUI 3 in Desktop) template.
    2. Add <WindowsPackageType>None</WindowsPackageType> to the .vcxproj.
    3. Modify <AppxPackage>true</AppxPackage> to <AppxPackage>false</AppxPackage>
    4. Run using the Unpackaged launch profile and make sure everything works.
  8. Locate the EXE and launch it in a variety of other ways - double click in Windows Explorer, launch using full path in PowerShell, execute (F6) in WinDbg, etc. - and see that they all work.
  9. Sign out of the TS session or lock it (🪟+L).
  10. Back in the Windows sign-in screen sign-in to User B.
  11. Install the same WindowsAppRuntimeInstall-1.1.0-x64.exe from above.
  12. Launch the EXE in all the ways mentioned in section 8 and verify that they all work.
  13. Sign out of the TS session or lock it.
  14. Back again in the Windows sign-in screen sign-in to User A again.
  15. From the TS session of User A run the EXE as User B in any of the following ways and note that it crashes in them all:
    1. From Windows Explorer, hold shift and right click on the EXE, select Run as a different user,
    2. If User A is not an administrator and User B is, right click and select Run as administrator.
    3. Launch PowerShell/cmd as a User B and launch the EXE from there.
    4. Run WinDbg as User B, and launch the EXE from there.

Microsoft (R) Windows Debugger Version 10.0.22621.1 AMD64
Copyright (c) Microsoft Corporation. All rights reserved.

CommandLine: D:\repos\App5\App5\x64\Debug\App5\App5.exe

************* Path validation summary **************
Response                         Time (ms)     Location
Deferred                                       SRV*D:\Symbols\Microsoft*http://msdl.microsoft.com/download/symbols
REDACTED

************* Path validation summary **************
Response                         Time (ms)     Location
REDACTED
Symbol search path is: REDACTED
Executable search path is: 
ModLoad: 00007ff7`87b50000 00007ff7`87cce000   App5.exe
ModLoad: 00007ffa`e0300000 00007ffa`e0509000   ntdll.dll
ModLoad: 00007ffa`dfd20000 00007ffa`dfddd000   C:\WINDOWS\System32\KERNEL32.DLL
ModLoad: 00007ffa`dd7f0000 00007ffa`ddb69000   C:\WINDOWS\System32\KERNELBASE.dll
ModLoad: 00007ffa`dfe20000 00007ffa`e0198000   C:\WINDOWS\System32\combase.dll
ModLoad: 00007ffa`ddec0000 00007ffa`ddfd1000   C:\WINDOWS\System32\ucrtbase.dll
ModLoad: 00007ffa`9cc90000 00007ffa`9ccbb000   C:\WINDOWS\SYSTEM32\VCRUNTIME140D.dll
ModLoad: 00007ffa`df590000 00007ffa`df6b0000   C:\WINDOWS\System32\RPCRT4.dll
ModLoad: 00007ffa`6daa0000 00007ffa`6db83000   C:\WINDOWS\SYSTEM32\MSVCP140D.dll
ModLoad: 00007ffa`ded20000 00007ffa`dedf6000   C:\WINDOWS\System32\OLEAUT32.dll
ModLoad: 00007ffa`c0f30000 00007ffa`c0f3f000   C:\WINDOWS\SYSTEM32\VCRUNTIME140_1D.dll
ModLoad: 00007ffa`ddfe0000 00007ffa`de07d000   C:\WINDOWS\System32\msvcp_win.dll
ModLoad: 00007ffa`6d050000 00007ffa`6d271000   C:\WINDOWS\SYSTEM32\ucrtbased.dll
ModLoad: 00007ffa`9cb10000 00007ffa`9cb44000   D:\repos\App5\App5\x64\Debug\App5\Microsoft.WindowsAppRuntime.Bootstrap.dll
ModLoad: 00007ffa`dfb80000 00007ffa`dfd1a000   C:\WINDOWS\System32\ole32.dll
ModLoad: 00007ffa`dea80000 00007ffa`deaa9000   C:\WINDOWS\System32\GDI32.dll
ModLoad: 00007ffa`ddc30000 00007ffa`ddc56000   C:\WINDOWS\System32\win32u.dll
ModLoad: 00007ffa`de080000 00007ffa`de192000   C:\WINDOWS\System32\gdi32full.dll
ModLoad: 00007ffa`def70000 00007ffa`df11c000   C:\WINDOWS\System32\USER32.dll
ModLoad: 00007ffa`de950000 00007ffa`de9fe000   C:\WINDOWS\System32\ADVAPI32.dll
ModLoad: 00007ffa`deec0000 00007ffa`def63000   C:\WINDOWS\System32\msvcrt.dll
ModLoad: 00007ffa`e0200000 00007ffa`e029e000   C:\WINDOWS\System32\sechost.dll
ModLoad: 00007ffa`de1a0000 00007ffa`de94f000   C:\WINDOWS\System32\SHELL32.dll
(8cb0.740c): Break instruction exception - code 80000003 (first chance)
ntdll!LdrpDoDebuggerBreak+0x30:
00007ffa`e03dd114 cc              int     3
0:000> g
ModLoad: 00007ffa`dfde0000 00007ffa`dfe11000   C:\WINDOWS\System32\IMM32.DLL
ModLoad: 00007ffa`dde40000 00007ffa`ddebf000   C:\WINDOWS\System32\bcryptPrimitives.dll
D:\a\_work\1\s\BuildOutput\Release\x64\WindowsAppRuntime_DLL\WindowsAppRuntimeInsights.h(53)\Microsoft.WindowsAppRuntime.Bootstrap.dll!00007FFA9CB224DB: (caller: 00007FFA9CB1E1C6) LogHr(1) tid(740c) 8007007E The specified module could not be found.
    Msg:[Unable to load resource dll. Microsoft.WindowsAppRuntime.Insights.Resource.dll] 
ModLoad: 00007ffa`dc9a0000 00007ffa`dc9b8000   C:\WINDOWS\SYSTEM32\kernel.appcore.dll
ModLoad: 00007ffa`dee00000 00007ffa`deeaf000   C:\WINDOWS\System32\clbcatq.dll
ModLoad: 00007ffa`d3250000 00007ffa`d3384000   C:\Windows\System32\AppXDeploymentClient.dll
ModLoad: 00007ffa`d3d60000 00007ffa`d3f4f000   C:\WINDOWS\SYSTEM32\urlmon.dll
ModLoad: 00007ffa`d3d30000 00007ffa`d3d58000   C:\Windows\System32\srvcli.dll
ModLoad: 00007ffa`dc440000 00007ffa`dc44c000   C:\Windows\System32\netutils.dll
ModLoad: 00007ffa`d3a70000 00007ffa`d3d23000   C:\Windows\System32\iertutil.dll
ModLoad: 00007ffa`be890000 00007ffa`be980000   C:\Windows\System32\Windows.ApplicationModel.dll
ModLoad: 00007ffa`db7b0000 00007ffa`db916000   C:\WINDOWS\SYSTEM32\wintypes.dll
D:\a\_work\1\s\dev\WindowsAppRuntime_BootstrapDLL\MddBootstrap.cpp(776)\Microsoft.WindowsAppRuntime.Bootstrap.dll!00007FFA9CB1B0D9: (caller: 00007FFA9CB19C2F) LogHr(2) tid(740c) 80040010 Object is not in any of the inplace active states
    Msg:[Bootstrap.Intitialize: Scanning packages for Major.Minor=1.1, Tag=, MinVersion=1000.516.2156.0] CallContext:[\Initialize] 
ModLoad: 00007ffa`d3420000 00007ffa`d343b000   C:\WINDOWS\SYSTEM32\windows.staterepositorycore.dll
D:\a\_work\1\s\dev\WindowsAppRuntime_BootstrapDLL\MddBootstrap.cpp(865)\Microsoft.WindowsAppRuntime.Bootstrap.dll!00007FFA9CB1B85C: (caller: 00007FFA9CB19C2F) LogHr(3) tid(740c) 80040011 Not able to convert object
    Msg:[Bootstrap.Intitialize: Microsoft.WinAppRuntime.DDLM.1000.485.2229.0-x6-p3_1000.485.2229.0_x64__8wekyb3d8bbwe not applicable. Version doesn't match MinVersion criteria (Major.Minor=1.1, Tag=, MinVersion=1000.516.2156.0)] CallContext:[\Initialize] 
D:\a\_work\1\s\dev\WindowsAppRuntime_BootstrapDLL\MddBootstrap.cpp(865)\Microsoft.WindowsAppRuntime.Bootstrap.dll!00007FFA9CB1B85C: (caller: 00007FFA9CB19C2F) LogHr(4) tid(740c) 80040011 Not able to convert object
    Msg:[Bootstrap.Intitialize: Microsoft.WinAppRuntime.DDLM.1000.485.2229.0-x8-p3_1000.485.2229.0_x86__8wekyb3d8bbwe not applicable. Version doesn't match MinVersion criteria (Major.Minor=1.1, Tag=, MinVersion=1000.516.2156.0)] CallContext:[\Initialize] 
D:\a\_work\1\s\dev\WindowsAppRuntime_BootstrapDLL\MddBootstrap.cpp(885)\Microsoft.WindowsAppRuntime.Bootstrap.dll!00007FFA9CB1BB5E: (caller: 00007FFA9CB19C2F) LogHr(5) tid(740c) 80040012 Not able to perform the operation because object is not given storage yet
    Msg:[Bootstrap.Intitialize: Microsoft.WinAppRuntime.DDLM.1000.516.2156.0-x6_1000.516.2156.0_x64__8wekyb3d8bbwe is applicable (Major.Minor=1.1, Tag=, MinVersion=1000.516.2156.0)] CallContext:[\Initialize] 
D:\a\_work\1\s\dev\WindowsAppRuntime_BootstrapDLL\MddBootstrap.cpp(876)\Microsoft.WindowsAppRuntime.Bootstrap.dll!00007FFA9CB1B9F8: (caller: 00007FFA9CB19C2F) LogHr(6) tid(740c) 80040011 Not able to convert object
    Msg:[Bootstrap.Intitialize: Microsoft.WinAppRuntime.DDLM.1000.516.2156.0-x8_1000.516.2156.0_x86__8wekyb3d8bbwe not applicable. Architecture doesn't match current architecture x64 (Major.Minor=1.1, Tag=, MinVersion=1000.516.2156.0)] CallContext:[\Initialize] 
D:\a\_work\1\s\dev\WindowsAppRuntime_BootstrapDLL\MddBootstrap.cpp(908)\Microsoft.WindowsAppRuntime.Bootstrap.dll!00007FFA9CB1C486: (caller: 00007FFA9CB19C2F) LogHr(7) tid(740c) 80040013     Msg:[Bootstrap.Intitialize: Microsoft.WinAppRuntime.DDLM.1000.516.2156.0-x6_1000.516.2156.0_x64__8wekyb3d8bbwe best matches the criteria (Major.Minor=1.1, Tag=, MinVersion=1000.516.2156.0) of 118 packages scanned] CallContext:[\Initialize] 
ModLoad: 00007ffa`ac030000 00007ffa`ac0fa000   C:\WINDOWS\System32\twinui.appcore.dll
ModLoad: 00007ffa`db920000 00007ffa`dc188000   C:\WINDOWS\System32\Windows.Storage.dll
ModLoad: 00007ffa`cceb0000 00007ffa`cd6c6000   C:\Windows\System32\OneCoreUAPCommonProxyStub.dll
ModLoad: 00007ffa`dec30000 00007ffa`ded1a000   C:\WINDOWS\System32\shcore.dll
ModLoad: 00007ffa`acca0000 00007ffa`acda4000   C:\WINDOWS\SYSTEM32\daxexec.dll
ModLoad: 00007ffa`dce60000 00007ffa`dce89000   C:\WINDOWS\System32\USERENV.dll
ModLoad: 00007ffa`c1ff0000 00007ffa`c2033000   C:\WINDOWS\System32\container.dll
ModLoad: 00007ffa`d84a0000 00007ffa`d84b7000   C:\WINDOWS\SYSTEM32\usermgrcli.dll
onecore\base\appmodel\execmodel\desktopappx\lib\aamextensions.cpp(332)\daxexec.dll!00007FFAACD41F38: (caller: 00007FFAACD4154D) Exception(1) tid(740c) 80070520 A specified logon session does not exist. It may already have been terminated.
    CallContext:[\TryActivateDesktopAppXApplication] 
(8cb0.740c): C++ EH exception - code e06d7363 (first chance)
(8cb0.740c): C++ EH exception - code e06d7363 (first chance)
onecore\base\appmodel\execmodel\desktopappx\lib\aamextensions.cpp(113)\daxexec.dll!00007FFAACD570E1: (caller: 00007FFAACD1D3FF) ReturnHr(1) tid(740c) 80070520 A specified logon session does not exist. It may already have been terminated.
    Msg:[onecore\base\appmodel\execmodel\desktopappx\lib\aamextensions.cpp(332)\daxexec.dll!00007FFAACD41F38: (caller: 00007FFAACD4154D) Exception(1) tid(740c) 80070520 A specified logon session does not exist. It may already have been terminated.
    CallContext:[\TryActivateDesktopAppXApplication] 
] CallContext:[\TryActivateDesktopAppXApplication] 
onecore\base\appmodel\execmodel\desktopappx\desktoplib\desktopaamextensions.cpp(170)\daxexec.dll!00007FFAACD1D428: (caller: 00007FFAAC05C412) LogHr(1) tid(740c) 80070520 A specified logon session does not exist. It may already have been terminated.
    CallContext:[\TryActivateDesktopAppXApplication] 
onecore\base\appmodel\execmodel\desktopappx\desktoplib\desktopaamextensions.cpp(203)\daxexec.dll!00007FFAACD1D5CD: (caller: 00007FFAAC05C412) ReturnHr(2) tid(740c) 80070520 A specified logon session does not exist. It may already have been terminated.
    CallContext:[\TryActivateDesktopAppXApplication] 
onecoreuap\shell\twinui\activation\lib\applicationactivationmanagerproxy.cpp(90)\twinui.appcore.dll!00007FFAAC05C435: (caller: 00007FFA9CB19E34) ReturnHr(1) tid(740c) 80070520 A specified logon session does not exist. It may already have been terminated.
(8cb0.740c): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
Microsoft_WindowsAppRuntime_Bootstrap!MddBootstrap_StopActivity+0x93:
00007ffa`9cb24403 88050d230100    mov     byte ptr [Microsoft_WindowsAppRuntime_Bootstrap!_tlgEvent+0xf (00007ffa`9cb36716)],al ds:00007ffa`9cb36716=00
0:000> k
 # Child-SP          RetAddr               Call Site
00 0000004f`a496d940 00007ffa`9cb248ff     Microsoft_WindowsAppRuntime_Bootstrap!MddBootstrap_StopActivity+0x93 [D:\a\_work\1\s\dev\WindowsAppRuntime_BootstrapDLL\MddBootstrapTracelogging.cpp @ 15] 
01 0000004f`a496da10 00007ffa`9cb1d2d1     Microsoft_WindowsAppRuntime_Bootstrap!wilResultLoggingThreadCallback+0x20f [D:\a\_work\1\s\dev\WindowsAppRuntime_BootstrapDLL\MddBootstrapTracelogging.cpp @ 143] 
02 0000004f`a496dad0 00007ffa`9cb26313     Microsoft_WindowsAppRuntime_Bootstrap!wil::details::ThreadFailureCallbackFn<bool (__cdecl&)(wil::FailureInfo const &) noexcept>::NotifyFailure+0x11 [D:\a\_work\1\s\packages\Microsoft.Windows.ImplementationLibrary.1.0.210930.1\include\wil\result.h @ 1085] 
03 (Inline Function) --------`--------     Microsoft_WindowsAppRuntime_Bootstrap!wil::details::ThreadFailureCallbackHolder::GetContextAndNotifyFailure+0xa0 [D:\a\_work\1\s\packages\Microsoft.Windows.ImplementationLibrary.1.0.210930.1\include\wil\result.h @ 1040] 
04 0000004f`a496db00 00007ffa`9cb1428e     Microsoft_WindowsAppRuntime_Bootstrap!wil::details::GetContextAndNotifyFailure+0xc3 [D:\a\_work\1\s\packages\Microsoft.Windows.ImplementationLibrary.1.0.210930.1\include\wil\result.h @ 1100] 
05 (Inline Function) --------`--------     Microsoft_WindowsAppRuntime_Bootstrap!wil::details::LogFailure+0xed [D:\a\_work\1\s\packages\Microsoft.Windows.ImplementationLibrary.1.0.210930.1\include\wil\result_macros.h @ 3522] 
06 0000004f`a496db30 00007ffa`9cb14410     Microsoft_WindowsAppRuntime_Bootstrap!wil::details::ReportFailure_NoReturn<0>+0x12e [D:\a\_work\1\s\packages\Microsoft.Windows.ImplementationLibrary.1.0.210930.1\include\wil\result_macros.h @ 3669] 
07 0000004f`a496f030 00007ffa`9cb1447f     Microsoft_WindowsAppRuntime_Bootstrap!wil::details::ReportFailure_Base<0,0>+0x30 [D:\a\_work\1\s\packages\Microsoft.Windows.ImplementationLibrary.1.0.210930.1\include\wil\result_macros.h @ 3705] 
08 0000004f`a496f090 00007ffa`9cb14498     Microsoft_WindowsAppRuntime_Bootstrap!wil::details::ReportFailure_Hr<0>+0x5f [D:\a\_work\1\s\packages\Microsoft.Windows.ImplementationLibrary.1.0.210930.1\include\wil\result_macros.h @ 3866] 
09 0000004f`a496f110 00007ffa`9cb1a092     Microsoft_WindowsAppRuntime_Bootstrap!wil::details::in1diag3::_Throw_Hr+0x18 [D:\a\_work\1\s\packages\Microsoft.Windows.ImplementationLibrary.1.0.210930.1\include\wil\result_macros.h @ 5630] 
0a (Inline Function) --------`--------     Microsoft_WindowsAppRuntime_Bootstrap!wil::details::in1diag3::Throw_IfFailed+0x257 [D:\a\_work\1\s\packages\Microsoft.Windows.ImplementationLibrary.1.0.210930.1\include\wil\result_macros.h @ 5662] 
0b 0000004f`a496f160 00007ffa`9cb18ede     Microsoft_WindowsAppRuntime_Bootstrap!CreateLifetimeManagerViaEnumeration+0x4e2 [D:\a\_work\1\s\dev\WindowsAppRuntime_BootstrapDLL\MddBootstrap.cpp @ 616] 
0c (Inline Function) --------`--------     Microsoft_WindowsAppRuntime_Bootstrap!CreateLifetimeManager+0x13b [D:\a\_work\1\s\dev\WindowsAppRuntime_BootstrapDLL\MddBootstrap.cpp @ 555] 
0d 0000004f`a496f430 00007ffa`9cb18453     Microsoft_WindowsAppRuntime_Bootstrap!FirstTimeInitialization+0x1fe [D:\a\_work\1\s\dev\WindowsAppRuntime_BootstrapDLL\MddBootstrap.cpp @ 343] 
0e 0000004f`a496f5e0 00007ffa`9cb18128     Microsoft_WindowsAppRuntime_Bootstrap!_MddBootstrapInitialize+0x53 [D:\a\_work\1\s\dev\WindowsAppRuntime_BootstrapDLL\MddBootstrap.cpp @ 204] 
*** WARNING: Unable to verify checksum for App5.exe
0f 0000004f`a496f620 00007ff7`87c28e6c     Microsoft_WindowsAppRuntime_Bootstrap!MddBootstrapInitialize2+0x2e8 [D:\a\_work\1\s\dev\WindowsAppRuntime_BootstrapDLL\MddBootstrap.cpp @ 129] 
10 0000004f`a496f860 00007ff7`87c28d94     App5!Microsoft::Windows::ApplicationModel::DynamicDependency::Bootstrap::AutoInitialize::Initialize+0x6c [D:\repos\App5\App5\packages\Microsoft.WindowsAppSDK.1.1.0\include\MddBootstrapAutoInitializer.cpp @ 75] 
11 0000004f`a496fa00 00007ff7`87babc07     App5!Microsoft::Windows::ApplicationModel::DynamicDependency::Bootstrap::AutoInitialize::AutoInitialize+0x24 [D:\repos\App5\App5\packages\Microsoft.WindowsAppSDK.1.1.0\include\MddBootstrapAutoInitializer.cpp @ 32] 
12 0000004f`a496fb00 00007ffa`6d1022a3     App5!Microsoft::Windows::ApplicationModel::DynamicDependency::Bootstrap::`dynamic initializer for 'g_autoInitialize''+0x27 [D:\repos\App5\App5\packages\Microsoft.WindowsAppSDK.1.1.0\include\MddBootstrapAutoInitializer.cpp @ 82] 
13 0000004f`a496fc00 00007ff7`87c44819     ucrtbased!_initterm+0x63 [minkernel\crts\ucrt\src\appcrt\startup\initterm.cpp @ 22] 
14 0000004f`a496fc40 00007ff7`87c4477e     App5!__scrt_common_main_seh+0x89 [D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl @ 258] 
15 0000004f`a496fcb0 00007ff7`87c44aae     App5!__scrt_common_main+0xe [D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl @ 331] 
16 0000004f`a496fce0 00007ffa`dfd354e0     App5!wWinMainCRTStartup+0xe [D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_wwinmain.cpp @ 17] 
17 0000004f`a496fd10 00007ffa`e030485b     KERNEL32!BaseThreadInitThunk+0x10
18 0000004f`a496fd40 00000000`00000000     ntdll!RtlUserThreadStart+0x2b

Expected behavior

Program running.

Screenshots

image

NuGet package version

1.1.0

Packaging type

Unpackaged

Windows version

Windows 11 version 21H2 (22000)

IDE

Visual Studio 2022

riverar commented 2 years ago

@DrusTheAxe Are runas scenarios supported? I can repro this and a similar issue (inability to find machine-wide runtime).

conioh commented 2 years ago

@DrusTheAxe Are runas scenarios supported? I can repro this and a similar issue (inability to find machine-wide runtime).

Note that I have installed the runtime for the other user too.

DrusTheAxe commented 2 years ago

Hmmm. I haven't seen the Run as another user feature before. Let me do some investigation to determine what it's actually doing.

As a general rule, you can run an app using WinAppSDK as long as the runtime is installed for that user e.g. the Microsoft.WindowsAppRuntime.1.1 MSIX package is registered for that user.

Alternatively, if the package is provisioned then it's made available to all users. At login a list of packages you should have but don't (and have but shouldn't) is built and processed, before you get to the desktop.

I doubt Run as another user is performing a full login. If it's just CreateProcessAsUser then results would depend on state of the machine and that user's profile. Will do some digging.

conioh commented 2 years ago

Hmmm. I haven't seen the Run as another user feature before. Let me do some investigation to determine what it's actually doing.

That's odd. It's been there at least since Windows XP, where it was called Run as..., and probably even before that, but my memory doesn't go that far.

As a general rule, you can run an app using WinAppSDK as long as the runtime is installed for that user e.g. the Microsoft.WindowsAppRuntime.1.1 MSIX package is registered for that user.

Right. Except it doesn't. Hence this issue.

Alternatively, if the package is provisioned then it's made available to all users. At login a list of packages you should have but don't (and have but shouldn't) is built and processed, before you get to the desktop.

That's interesting but not the situation here, since I've run the runtime installer from the second user, and when the TS session belongs to the second user the test program runs.

I doubt Run as another user is performing a full login. If it's just CreateProcessAsUser then results would depend on state of the machine and that user's profile. Will do some digging.

I don't know what that means. A call to CreateProcessAsUser requires a previous call to LogonUser or equivalent, and the flags passed to it are certainly not LOGON32_LOGON_BATCH or LOGON32_LOGON_SERVICE so that pretty much leaves only LOGON32_LOGON_INTERACTIVE. What's a "full login"?

Anyway, again, this doesn't really matter here since, again, I have installed the runtime for the second user, being logged on to the console as the second user, so there was no dependency on the provisioned package being auto-installed for the user.

conioh commented 2 years ago

I have updated the steps to reproduce above in hopes of making the situation more clear.

Balkoth commented 2 years ago

Is it relevant that this happens on a terminal session? I can see it crash when trying to run an unpackaged app from a normal desktop session as different user. It also crashes when trying to run as admin which is supposed to work with 1.1 onwards. So what is going on here?

conioh commented 2 years ago

Is it relevant that this happens on a terminal session? I can see it crash when trying to run an unpackaged app from a normal desktop session as different user. It also crashes when trying to run as admin which is supposed to work with 1.1 onwards. So what is going on here?

That's just the term. I never said it was a remote session.

In the context of users and programs run by those users there are two things called "a session".

One of them is logon sessions, which represent a login for the purposes of permissions (including by a service account, or a login for SMB), are the basis for tokens, are represented by the SEP_LOGON_SESSION_REFERENCES struct and can be enumerated with LsaEnumerateLogonSessions.

The other one is Terminal Services sessions which represent a physical connection a console†, local or remote, used by Remote Desktop Services and Fast User Switching. They can be enumerated by the WTSEnumerateSessions function, where WTS stands for Windows Terminal Services. Certain information about them is published via the WM_WTSSESSION_CHANGE windows message, where again WTS stands for the same thing.

Each token is linked to a specific Terminal Services session, and while the member of the TOKEN struct that identifies the session is called simply SessionId rather than the lengthy MicrosoftWindowsTerminalServicesSessionId (as is the member of the MM_SESSION_SPACE struct etc.), WinDbg's !token command does use the term "TS session". Once more "TS" stands for Terminal Services.

0: kd> !token ffffd50c6602a060
_TOKEN 0xffffd50c6602a060
TS Session ID: 0
User: S-1-5-18
User Groups:
 00 S-1-16-16384
    Attributes - GroupIntegrity GroupIntegrityEnabled
...

0: kd> dt nt!_TOKEN ffffd50c6602a060
   +0x000 TokenSource      : _TOKEN_SOURCE
   +0x010 TokenId          : _LUID
   +0x018 AuthenticationId : _LUID
   +0x020 ParentTokenId    : _LUID
   +0x028 ExpirationTime   : _LARGE_INTEGER 0x06207526`b64ceb90
   +0x030 TokenLock        : 0xffff8887`f1245210 _ERESOURCE
   +0x038 ModifiedId       : _LUID
   +0x040 Privileges       : _SEP_TOKEN_PRIVILEGES
   +0x058 AuditPolicy      : _SEP_AUDIT_POLICY
   +0x078 SessionId        : 0
...

0: kd> !token ffffd50c75adb7f0
_TOKEN 0xffffd50c75adb7f0
TS Session ID: 0x1
User: S-1-5-21-3728847233-3017425221-756437700-1001
User Groups:
 00 S-1-16-0
    Attributes - GroupIntegrity GroupIntegrityEnabled
...

0: kd> dt nt!_TOKEN ffffd50c75adb7f0
   +0x000 TokenSource      : _TOKEN_SOURCE
   +0x010 TokenId          : _LUID
   +0x018 AuthenticationId : _LUID
   +0x020 ParentTokenId    : _LUID
   +0x028 ExpirationTime   : _LARGE_INTEGER 0x7fffff36`d5969fff
   +0x030 TokenLock        : 0xffff8887`f817be90 _ERESOURCE
   +0x038 ModifiedId       : _LUID
   +0x040 Privileges       : _SEP_TOKEN_PRIVILEGES
   +0x058 AuditPolicy      : _SEP_AUDIT_POLICY
   +0x078 SessionId        : 1
...

This term is used throughout Windows.

Here, since the processes run under different users, using different logon sessions, but in the same TS session, it was appropriate to qualify the term so as to reduce confusion. "Two processes in different logon session running in the same session" is undoubtedly worse than "two processes in different logon sessions running in the same Terminal Services session."

"Normal desktop session" isn't a thing. It's unclear and suggests the question are there abnormal desktop sessions. There's an existing term and I simply used it.

It also crashes when trying to run as admin which is supposed to work with 1.1 onwards. So what is going on here?

Programming is hard and not everyone is equally qualified or able to do it adequately.

† Except in the special case of session 0 since Windows Vista. Vista leverages the security boundary formed by TS session (in the Object Manager etc.) to separate certain system processes from user processes and protect them. That Windows XP gave the first user that logs on to the machine access to the "global namespace" it just odd and that was fixed in Vista.

Balkoth commented 2 years ago

In my case on a normal dekstop session, with no terminal services involved, event viewer logs the following error:

<EventData>
  <Data>Windows App Runtime</Data>
  <Data>ERROR 0x80070520: Bootstrapper initialization failed while looking for version 1.1 (MSIX package version >= 1002.543.1943.0)</Data>
</EventData>
Balkoth commented 2 years ago

Further investigation shows that adding <WindowsAppSDKSelfContained>true</WindowsAppSDKSelfContained> to the project or publishing file lets the application run successfully with a different than the logged on user.

DrusTheAxe commented 2 years ago

Install the Windows App SDK Runtime version 1.1.0 x64

Does this repro with a recent servicing update (1.1.2+)? There were some fixes in 1.1.2 that may be significant here.

Is 1.1.2+ registered for the other user? Easiest way to tell is via an admin cmd prompt

powershell -c get-appxpackage -AllUsers micro*win*apprun*

and the PackageUserInformation property shows which users have the package registered e.g.

...
PackageUserInformation : {S-1-5-21-4071067175-473297690-1648030122-1003 [bob]: Installed}
...
conioh commented 2 years ago

Does this repro with a recent servicing update (1.1.2+)? There were some fixes in 1.1.2 that may be significant here.

As expected, the same crash still happens with:

CreateLifetimeManagerViaEnumeration make the following call:

https://github.com/microsoft/WindowsAppSDK/blob/097d2209d7bd417a3936978fa6c1f4984901f42a/dev/WindowsAppRuntime_BootstrapDLL/MddBootstrap.cpp#L654

with the following values:

      lifetimeManagerApplicationUserModelId = wchar_t [130] "Microsoft.WinAppRuntime.DDLM.1003.565.600.0-x6_8wekyb3d8bbwe!DDLM"
                          packageFamilyName = "Microsoft.WinAppRuntime.DDLM.1003.565.600.0-x6_8wekyb3d8bbwe"
                            packageFullName = "Microsoft.WinAppRuntime.DDLM.1003.565.600.0-x6_1003.565.600.0_x64__8wekyb3d8bbwe"

The package indeed exists:

PS C:\> Get-AppxPackage | Where-Object -Property "PackageFullName" -EQ "Microsoft.WinAppRuntime.DDLM.1003.565.600.0-x6_1003.565.600.0_x64__8wekyb3d8bbwe" | Select-Object Name, PackageFamilyName, PackageFullName | fl

Name              : Microsoft.WinAppRuntime.DDLM.1003.565.600.0-x6
PackageFamilyName : Microsoft.WinAppRuntime.DDLM.1003.565.600.0-x6_8wekyb3d8bbwe
PackageFullName   : Microsoft.WinAppRuntime.DDLM.1003.565.600.0-x6_1003.565.600.0_x64__8wekyb3d8bbwe

And has the requested AUMID. (I'll skip dumping the manifest here.)

From there the call flow is the following:

Microsoft_WindowsAppRuntime_Bootstrap!CreateLifetimeManagerViaEnumeration;
|-- twinui_appcore!ApplicationActivationManagerProxy::ActivateApplication;
    |-- daxexec!TryActivateDesktopAppXApplication;
        |-- daxexec!EvaluateApplicationLaunch;
            |-- daxexec!GetActivationProperties;
                |-- daxexec!GetTargetUserTokenAndUserContext;
                    |-- daxexec!wil::open_current_access_token;
                    |-- usermgrcli!UMgrQueryUserContext;

daxexec!wil::open_current_access_token simply returns the process token and then usermgrcli!UMgrQueryUserContext does an RPC call that fails with error 0x80070520.

I don't see anything that was done in relation to this, which is why it makes sense that except for the version (the AUMID passed to aam->ActivateApplication) this is exactly the same flow and error as with the previous versions.

Regarding your previous comment:

I doubt Run as another user is performing a full login. If it's just CreateProcessAsUser then results would depend on state of the machine and that user's profile. Will do some digging.

runas.exe uses CreateProcessWithLogonW which does login as full as any other and is enough to run any other program I can think of and have tried.

I don't know if the fault is with Windows or the Windows App SDK, and without source code access I can't debug it any more than point the stack trace mentioned above, but even if the problem is with Windows such that everything in Windows works under such a login except for IApplicationActivationManager::ActivateApplication, maybe the newest application framework shouldn't depend on it?

DrusTheAxe commented 2 years ago

I don't know if the fault is with Windows or the Windows App SDK

That'll be Windows. From your info it's pretty clear CreateProcessWithLogonW and app activation aren't intersecting in expected/desired ways, and that's Windows and its support for MSIX.

WinAppSDK provides added functionality, in some cases working around Windows to achieve equivalent ends, but only so much you can work around.

Hunting up the activation experts...

+@jsidewhite @brialmsft @dhoehna

DrusTheAxe commented 2 years ago

daxexec!wil::open_current_access_token simply returns the process token and then usermgrcli!UMgrQueryUserContext does an RPC call that fails with error 0x80070520.

BTW 0x80070520 == ERROR_NO_SUCH_LOGON_SESSION. "A specified logon session does not exist. It may already have been terminated."

Comparing notes with the activation experts

conioh commented 2 years ago

That'll be Windows. From your info it's pretty clear CreateProcessWithLogonW and app activation aren't intersecting in expected/desired ways, and that's Windows and its support for MSIX.

Indeed seems so. The following code fails with the same error when run as a different user (and succeeds as the same user):

...
IApplicationActivationManagerPtr aam{ CLSID_ApplicationActivationManager };
DWORD pid{};
HRESULT hr = aam->ActivateApplication(L"Microsoft.WinDbg_8wekyb3d8bbwe!Microsoft.WinDbg", L"", AO_NOERRORUI | AO_NOSPLASHSCREEN, &pid);

(Same happens with AO_NONE, I used the same flags as you just to make sure.)

But:

WinAppSDK provides added functionality, in some cases working around Windows to achieve equivalent ends, but only so much you can work around.

Why is it so important to lookup and load the framework using the whole AppX/AAM thing? What's so wrong with distributing the Windows App SDK runtime as a bunch of DLLs, installed in something like %LOCALAPPDATA%\Microsoft\WindowsAppSDKRuntime\_version_\? Even if there's some reason to distribute as a "package" for packaged apps, why not also additionally distribute as just-a-bunch-of-files? Is there functionality that is available to unpackaged apps that can't be implemented in a unpackaged adaptation of the framework?

Edit: Given that the Windows App SDK officially supports "self-contained apps", and it actually works - both in general and in the runas scenario - I tend to think there is no such functionality. In that case I can hardly see a reason for not providing "framework-dependent apps" (i.e. apps that don't have to carry extra 60MB and use the newest framework available on the host machine) a version of the framework that doesn't rely on the AAM and all the related machinery.

DrusTheAxe commented 2 years ago

Why is it so important to lookup and load the framework using the whole AppX/AAM thing?

The core problem is the Deployment stack in Windows doesn't know about unpackaged apps (not until Win11 and the new inbox Dynamic Dependencies API). Thus if you install an unpackaged app and use the bootstrapper to give a process access to the framework's content, and Deployment happens to run and decide "hey, this framework is unused because I only know about static dependencies declared in packaged apps' appxmanifest.xml and I see none needing this framework package so let's remove it". Even though your unpackaged process is running using it. Aaaand BadMojo™.

To enable unpackaged apps to use packaged goods we need to make it clear to the Deployment stack for both install-time and run-time.

For install-time we need a main package with a declared dependency on the framework package. As long as that main package is installed the framework won't get removed. WinAppSDK's Main + DDLM packages satisfy that.

For run-time we need a running process with package identity and its appxmanifest.xml to declare a <PackageDependency> on the framework package. WinAppSDK's DDLM package solves that by declaring (a) a <PackageDependency> on the framework package and (b) an application. When MddBootstrapInitialize finds a applicable framework package, it activates the app to create a process meeting a+b (pkgidentity + static dependency on the framework) to hang around until MddBootstrapShutdown (or process death). This expresses to the Deployment stack (in ways it understands!) regarding our need for the framework package not to be serviced at this time.

Lacking this 'helper' DDLM process we'd don't get unpackaged apps reliably using framework packages.

What's so wrong with distributing the Windows App SDK runtime as a bunch of DLLs

The tradeoffs of MSIX vs redistributables (i.e. SelfContained) are documented but sorry, link eludes my memory at the moment. Servicing, perf and disk footprint are some of the differences.

SelfContained has its merits but it's not without its downsides. Neither option (MSIX vs SelfContained) fully supplants the other which is why we support both :-)

conioh commented 2 years ago

The core problem is the Deployment stack in Windows doesn't know about unpackaged apps (not until Win11 and the new inbox Dynamic Dependencies API). Thus if you install an unpackaged app and use the bootstrapper to give a process access to the framework's content, and Deployment happens to run and decide "hey, this framework is unused because I only know about static dependencies declared in packaged apps' appxmanifest.xml and I see none needing this framework package so let's remove it". Even though your unpackaged process is running using it. Aaaand BadMojo™.

I don't see how that's relevant to unpackaged EXEs loading unpackaged DLLs. Since the packaging infrastructure isn't aware of unpackaged apps, for an unpackaged app to take a reference of a package it needs to do something special, explicit, like calling TryCreatePackageDependency and AddPackageDependency. That's great. But why isn't that enough? Why do you call IAAM->ActivateApplication instead of just LoadLibrary?

To enable unpackaged apps to use packaged goods we need to make it clear to the Deployment stack for both install-time and run-time.

For install-time we need a main package with a declared dependency on the framework package. As long as that main package is installed the framework won't get removed. WinAppSDK's Main + DDLM packages satisfy that.

For run-time we need a running process with package identity and its appxmanifest.xml to declare a <PackageDependency> on the framework package. WinAppSDK's DDLM package solves that by declaring (a) a <PackageDependency> on the framework package and (b) an application. When MddBootstrapInitialize finds a applicable framework package, it activates the app to create a process meeting a+b (pkgidentity + static dependency on the framework) to hang around until MddBootstrapShutdown (or process death). This expresses to the Deployment stack (in ways it understands!) regarding our need for the framework package not to be serviced at this time.

Lacking this 'helper' DDLM process we'd don't get unpackaged apps reliably using framework packages.

Again, this doesn't answer the question and talks about something comepletely different. To enable unpackaged apps to use packaged goods you need to But I want unpackaged apps to use unpackaged goods.

The tradeoffs of MSIX vs redistributables (i.e. SelfContained) are documented but sorry, link eludes my memory at the moment. Servicing, perf and disk footprint are some of the differences.

SelfContained has its merits but it's not without its downsides. Neither option (MSIX vs SelfContained) fully supplants the other which is why we support both :-)

Once again - Self-contained distribution is not what I want. That's why I wrote that. I wrote what I meant and I meant what I wrote.

I want unpackaged apps to just load a bunch of DLLs, rather than activate a package. That way it works when they're CreateProcessWithLogond.

That's possible today, but with a lot of hackery. Self-contained distribution demonstartes that it's possible, but self-contained distribution requires the bunch of DLLs to be located in the same folder as the EXE. WHICH IS NOT WHAT I WANT. I DON'T WANT TO DISTRIBUTE 60MB OF DLLS WITH MY PROGRAMS.

However, if a few calls to LoadLibraryExW are changed to use different paths and/or different LOAD_LIBRARY_XYZ flags, an unpackaged app can run without activating any packages AND without having the DLLs in the same folder as the EXE, but rather load them from a location shared with other programs.

I want the Windows App SDK to support it directly, without having to patch all those calls.

Whether or not this shared location is system-wide or user-specific I leave as an open question. Whether or not this shared location should be the Windows App Runtime package folder (but still loaded just using LoadLibrary!) or a separate folder I leave an open question.

But regardless of how you answer these questions it is possible for an unpackaged app written using the Windows App SDK to successfully load the Windows App Runtime from a location different than the one in which the EXE is located and without doing any package activation, and then subsequently successfully run.

The problem is that is requires patching the Windows App SDK to not require the DLLs be located in the same folder as the EXE. Please remove this requirement. This solves the runas issue.

DrusTheAxe commented 2 years ago

You touch on some complex issues. The TL;DR you possibly can achieve what you want in a couple of ways:

  1. Use Windows' Dynamic Dependencies APIs instead of the Bootstrapper
  2. Set an environment variable in your process and then call the Bootstrap API

Do either of these meet your needs?

Self-contained distribution...WHICH IS NOT WHAT I WANT

Just stating the facts, not trying to sell you SelfContained ;-) You don't need self-contained if you don't want AND you don't need the Bootstrapper with its related plumbing...if you only run on Win11. Alternatively, you may be able to use the Bootstrapper but avoid the issue with 'Run as different user'.

Solution #1 is actually quite simple:

Hmmm. That may not be well documented. I'll follow up on that.

The limitation is Windows' Dynamic Dependencies APIs require Win11. That's a problem if your app runs on Win10.

The alternative (solution #2)...

The limitation is this requires Windows >= 20H1 (it requires Windows' behavior not available on RS5 or 19H1).

WinAppSDK's bootstrap solution needs a process running with the identity of a main package that manifests a static dependency on WinAppSDK's framework package. There's a couple of ways to accomplish that:

  1. Packaged COM OOP server in Microsoft.WindowsAppRuntime.Main package
  2. Packaged app in Microsoft.WindowsAppRuntime.Main package

WinAppSDK 1.0 did #1 but Packaged COM isn't supported1 in elevated processes on older systems (<Win11) so WinAppSDK 1.1 added #2. The decision which to use is made in IsLifetimeManagerViaEnumeration() in dev/WindowsAppRuntime_BootstrapDLL/MddBootstrap.cpp line 541. The code refers to these as 'AppExtension' and 'Enumeration'. The decision logic:

  1. Windows <20H1? Use 'Enumeration' (older systems lack features required by 'AppExtension')
  2. MICROSOFT_WINDOWSAPPRUNTIME_DDLM_ALGORITHM environment variable =0 ('Enumeration') or 1 ('AppExtension') Use what it says
  3. Process' is not running in an AppContainer? Use 'Enumeration'
  4. We're in an AppContainer on >=20H1 and the envvar isn't set. Use 'AppExtension'

The limitations are (a) this requires Windows >= 20H1 and (b) doesn't support elevation if the servicing update isn't present.

1 Well, Packaged COM wasn't supported on <Win11. A Windows servicing update released recently (June?) addressed that. If a downlevel system has that update Packaged COM works for elevated processes.

I'll make a separate post regarding the other issues you raised and why this works the way it does.

DrusTheAxe commented 2 years ago

The problem is that is requires patching the Windows App SDK

It's a little more complicated than that. The problem here is...

I don't see how that's relevant to unpackaged EXEs loading unpackaged DLLs.

It's not. That's why WindowsAppSDKSelfContained=true doesn't involve the Bootstrapper or Dynamic Dependencies, as then WinAppSDK isn't an MSIX package.

it is possible...without doing any package activation, and then subsequently successfully run.

Absolutely. Just use the Windows Dynamic Dependencies APIs instead of the Bootstrapper (which under the covers uses WinAppSDK's Dynamic Dependencies APIs).

We have 2 implementations of Dynamic Dependencies. Windows' implementation makes changes across Windows to support dynamic dependencies. WinAppSDK's implementation uses Windows in perfectly valid (if uncommon) ways to reliably produce the same net effect, without changes in Windows.

I want unpackaged apps to just load a bunch of DLLs, rather than activate a package

Loading the DLL is the goal. The activation plumbing is an implementation detail, but our options are limited (see previous post)

The (long-standing) limitation was unpackaged apps cannot use packaged goods. Not until Dynamic Dependencies came along i.e. Win11. Technically, yes, a process can LoadLibrary(absolutepath) to a DLL in an MSIX package...but the Deployment stack doesn't know about that relationship. Deployment will think on one's using that package and is free to service it as necessary, up to and including removing the package from the system!

Servicing is the key. WinAppSDK's Dynamic Dependencies is all about giving unpackaged apps access to packaged goods in reliable ways Windows can understand. The Bootstrapper is just a specialized use of Dynamic Dependencies, to enable dynamic use of WinAppSDK (chicken/egg problem: DynDep API's in the framework package, how do you call it to use the framework package when you can't yet access the framework package... The Bootstrap API!).

Whether or not this shared location...

The problem is servicing. How do we get the necessary bits distributed, deployed (install, update etc) and reliably managed? That's not as easy as it sounds (well, assuming it even sounds easy :P). MSIX provides a strong solution here.

It's just <sic> a matter of balancing the requirements with the technical limitations.

But why isn't that enough? Why do you call IAAM->ActivateApplication instead of just LoadLibrary?

TL;DR because changing previously released versions of Windows (aka 'downlevel') isn't viable, so we trick existing Windows to work the way we need.

Deployment only understood 'static' dependencies

The Deployment stack in Windows knows not to service a package in use. HOW it knows is the key.

Deployment determines a package is in use if 1+ running process with package identity has the package in its package graph. For instance, if the calculator app in the Microsoft.WindowsCalculator package has a dependency on VCLibs then when you run the Calculator its package graph is [Calculator, VCLibs]. When running the app's process has a package identity in its process token (e.g. Microsoft.WindowsCalculator_10.2103.8.0_x64__8wekyb3d8bbwe) so the Deployment stack knows to connect the dots to recognize that package and its dependencies are in use and not to do things that would break the running process (don't service the Calculator package, don't remove that VCLibs package, etc).

Deployment knows the process' package graph because it computed the package graph when the package was registered for the user. Calculator's appxmanifest.xml declares

<PackageDependency Name="Microsoft.VCLibs.140.00" MinVersion="14.0.29231.0" Publisher="CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US"/>

When the Calculator package was registered for the user Deployment resolves this dependency to a specific package (version>=minversion, a compatible ProcessorArchitecture, etc) and saves the resolved package graph. During later Deployment operations Deployment checks resolved static package dependencies to determine if we're being asked to service a package that's in use and if so, don't proceed.2

2It's a little more involved (e.g. if the Force option's specified Deployment may terminate processes) but not significant for this discussion.

Notice the word 'static'. The package graph is resolved at install-time based on static manifested dependencies. Deployment had no concept of processes using packages without a static dependency.

Until Win11.

Win11 taught Windows to understand 'dynamic' dependencies

Dynamic Dependencies introduced in Win11 didn't just add some API functions. We also changed Windows - changed the Deployment stack - to know about packages in use dynamically.

That's why AddPackageDependency() has no mention of a 'bootstrapping' or helper processes -- we just changed Windows to understand this behavior.

That's great -- if you write apps that only work on >=Win11.

Lots of developers need to run on older (<Win11) systems. Windows App SDK supports Windows down to RS5. The question is how to accomplish that.

Backport Win11's dynamic dependencies?

One option is to service Windows. We could have backported Windows' Dynamic Dependencies work to older systems. But that's problematic for multiple reasons including

Make WinAppSDK work in ways Win10 understands

The alternative is to do things in ways downlevel Windows understands producing equivalent results. And thus, the bootstrapper and helper process. WinAppSDK refers to this as "polyfill" -- leverage Windows functionality where we can, and supplement with our own implementation where necessary. See Version support.

Future?

This leads to the obvious question, "Why not make WinAppSDK's Dynamic Dependencies use Windows' APIs on Win11 and only do the polyfill on Win10?" That's always been the long-term goal1 we just haven't done it (yet). But this won't help apps on Win10 so we've been focusing on some higher priority work first (e.g. elevation).

1 You may have noticed WinAppSDK's Dynamic Dependencies API is verrrry similar to Win11's, almost as if they were designed that way... ;-) That's not an accident.

I want unpackaged apps to just load a bunch of DLLs, rather than activate a package

Loading the DLL is the goal. The activation plumbing is an implementation detail, but our options are limited.

The (long-standing) limitation is unpackaged apps cannot use packaged goods. Not until Dynamic Dependencies came long i.e. Win11. Technically, yes, a process can LoadLibrary(absolutepath) to a DLL in an MSIX package...but the Deployment stack doesn't know about that relationship. Deployment will think on one's using that package and is free to service it as necessary, up to and including removing the package.

Servicing is the key. WinAppSDK's Dynamic Dependencies is all about giving unpackaged apps access to packaged goods and doing so reliably in ways Windows can understand (or at least well enough not to break apps). The Bootstrapper is just a specialized (but necessary) use of Dynamic Dependencies to to enable dynamic use of WinAppSDK.

Whether or not this shared location...

The problem is servicing. How do we get the necessary bits distributed, deployed (install, update etc) and reliably managed? That's not as easy as it sounds (well, assuming it even sounds easy :P).

MSIX provides a strong solution here.

'Run as different user' brings some unusual details to the equation. I'm investigating other options but nothing yet. As you may have guessed, navigating Windows behavior to achieve the desired result is a bit tricky.

conioh commented 2 years ago

@DrusTheAxe, I read your post a few times and I've also read a bunch of other issues and discussion under this project that deal with related problems and I couldn't find an answer to my question. Maybe it's my fault for broadening the issue.

So I'll leave this issue for the specific problem of runas and I'll ping once again the people you mentioned earlier (@jsidewhite @brialmsft @dhoehna) to see if they have something to share that would help here.

I may later open a separate issue for the broader matter, but before that I'd like to try one more time here, since this issue already exists and there's some history here.


I am asking that the Windows App SDK (i.e. the VSIX, NuGet package etc.), without modifying the Windows App Runtime in any way, allow completely unpackaged applications (i.e. not even using sparse packages, just "plain old Win32 applications") to use, without using any "package APIs" or relying on any other OS mechanism that doesn't support the runas scenario, the Windows App Runtime that is already present on a system rather than only a copy of the Windows App Runtime that's located in the same folder as the EXE of those applications.

Are you saying this this is impossible or is there any other reason why this feature can't find itself in the next point release of the SDK?

DrusTheAxe commented 2 years ago

without using any "package APIs" or relying on any other OS mechanism that doesn't support the runas scenario, the Windows App Runtime that is already present on a system rather than only a copy of the Windows App Runtime that's located in the same folder as the EXE of those applications.

So to summarize, you're asking for a solution that (1) enables unpackaged apps to use WinAppSDK (2) that's compatible with runas and (3) doesn't involve any app-local copy (i.e. not WinAppSDK/SelfContained) and (4) doesn't involve MSIX if MSIX doesn't support runas ?

And constraint #4 is no MSIX -if- MSIX doesn't support runas, but MSIX is OK if it does support runas? That runas without the app having its own private copy of WinAppSDK is the goal?

BTW are there Windows version constraints on your runas scenario? If, say, it worked on Win11 but not Win10 would that meet your needs? If it worked down to 20H1? If it worked on Desktop but not Server? If... Please elaborate.

conioh commented 2 years ago

So to summarize, you're asking for a solution that (1) enables unpackaged apps to use WinAppSDK (2) that's compatible with runas and (3) doesn't involve any app-local copy (i.e. not WinAppSDK/SelfContained) and (4) doesn't involve MSIX if MSIX doesn't support runas ?

And constraint #4 is no MSIX -if- MSIX doesn't support runas, but MSIX is OK if it does support runas?

What do you mean by "involve MSIX"? If you're talking about the application - I think that's precluded by the requirement for the app being unpackaged. If you mean the runtime - for the purposes of this issue† I don't mind it being distributed as an MSIX. If you think that non-MSIX runtime is the preferred solution I have no objections, but that is not the requirement here. However it is implemented is fine by me and there are ways that work with the current runtime distributions, which is MSIX-based.

That runas without the app having its own private copy of WinAppSDK is the goal? Yes, exactly. Private copies have obvious disadvantages. The most important two for me are size and updates.

BTW are there Windows version constraints on your runas scenario? If, say, it worked on Win11 but not Win10 would that meet your needs? If it worked down to 20H1? If it worked on Desktop but not Server? If... Please elaborate.

That's a somewhat complicated question to answer but the short answer is: We need to support Server SKUs and we need to support builds starting with 17763. Luckily that's the version you were supposed to support in the first place and the website and documentation still say that. My investigation show that it can work on Windows 10 1809 - I'm sure that it works on 17763.1577 and as far as I recall it works on 17763.107 - and I see no reason why the same shouldn't work on Server SKUs too.

The slightly longer answer is that our customers have 17 times more Server 2019 instances than Server 2022 instances. Obviously it would be better to also support Server 2016, but that ship has sailed. Assuming we can find a way to live with that (e.g. maintain two versions until pre-2019 goes away, use WASDK only for certain elements that would be offered only starting with 2019 etc.) 2019 is the bare minimum. If 2019 isn't supported that means nothing is.

† I think there are advantages to also distributing the runtime in an unpackaged form, but spreading too much here was probably wrong of me. In time I hope to address that in a separate issue or discussion, unless you convince yourself that a non-MSIX runtime is desirable before I get the chance.

ghost commented 2 years ago

So I'll leave this issue for the specific problem of runas

> MSIX - Does Not Support "INSTALL FOR ALL USERS" and by extension "RUN AS ANOTHER USER".

>> Since WindowsAppSDK uses MSIX based runtime, you simply can't leverage WindowsAppSDK features for "ALL USERS on the SAME MACHINE" in your Apps until MSIX limitations are fixed in the OS. Simple as that.

>>> Any attempt to support "ALL USERS" will essentially result in ditching MSIX in its current form.

>>>> See below {

  1. https://github.com/microsoft/WindowsAppSDK/issues/13 and
  2. https://techcommunity.microsoft.com/t5/msix-feedback/machine-wide-provisioning-install-for-all-users/idi-p/1781716

No, "Machine Wide Provisioning" does not count as it still registers/installs the app per User basis which is essentially "single user installation". }

DrusTheAxe commented 2 years ago

What do you mean by "involve MSIX"? ...I don't mind it being distributed as an MSIX. If you think that non-MSIX runtime is the preferred solution I have no objections, but that is not the requirement here. However it is implemented is fine by me and there are ways that work with the current runtime distributions, which is MSIX-based.

Yes, that's what I meant. Thank you for the detailed response.

That runas without the app having its own private copy of WinAppSDK is the goal? Yes, exactly. Private copies have obvious disadvantages. The most important two for me are size and updates.

Very true. The MSIX (framework-dependent) solution is recommended in this case.

There are OS limitations in runas+MSIX support causing the problem here. That's the heart of the issue and unfortunately I haven't been able to find a creative workaround.

For the OS limitation, please use FeedbackHub to submit your feedback about the issue to get it on the appropriate OS teams' radar.

+@mikebattista @MikeHillberg @kanismohammed as FYI

My investigation show that it can work on Windows 10 1809 - I'm sure that it works on 17763.1577 and as far as I recall it works on 17763.107 - and I see no reason why the same shouldn't work on Server SKUs too.

Server is similar to Desktop but can have variances due to release schedules, the underlying codebase/builds used for a release, servicing updates, system definition and configuration, conditional code in Windows binaries themselves (e.g. if (IsServer()) {...} or IsDesktop() etc) and other factors. So while you might assume they're equivalent and often be right, that's not always the case. Very much a devil's in the details question.

I think there are advantages to also distributing the runtime in an unpackaged form, but spreading too much here was probably wrong of me. In time I hope to address that in a separate issue or discussion, unless you convince yourself that a non-MSIX runtime is desirable before I get the chance.

Doubtful ;-) Aside from the obvious but surmountable issues (technical and non-technical) the hard nut is servicing. How do you update such a thing -- Distribute how? Apply the update when it's in use? Minimize disk space impact? Among other factors. "Install" something is easy (relatively speaking), it's "Update" that's hard. MSIX solves these issues.

Inventing a new solution is a non-trivial undertaking, and an ongoing tax of splintered redundant efforts (there's only so many devs and hours to go around). If MSIX has issues it's likely more sensible (and justifiable :-)) to address them than invent a new redundant divergent solution.

conioh commented 2 years ago

There are OS limitations in runas+MSIX support causing the problem here. That's the heart of the issue and unfortunately I haven't been able to find a creative workaround.

For the OS limitation, please use FeedbackHub to submit your feedback about the issue to get it on the appropriate OS teams' radar.

An omission on my part, since it was obvious to me and I forgot to specify it explicitly: I am not interested in anything that depends, requires or otherwise entails operating system updates. Whatever operating system we support, Windows 1w version 2xyz for any w, x, y, z, we need to support it starting from the "RTM" (i.e. for every build the first UBR that was publicly released rather than only as Insider). "We support Windows 10 20H2, but only if you have the October 11, 2022 update" is just as useless as "we support only Windows 11 build 25xyz" to me.

My machine is always updates but my customers' machine aren't necessarily, and it is on their machines I need to run. Their reasons may be poor but that's irrelevant. Judging their decisions on this issue is not what they're paying me for.

Again I remind that since it was called "Project Reunion" till this very day the Windows App SDK promised and promises "downlevel support" and "not relying on operating system servicing/updates" (paraphrases). If any bug is resolved with an OS update we're back to UWP. Again, one of the main supposed benefits of WASDK over UWP was supposedly its independence of OS updates.

Server is similar to Desktop but can have variances due to release schedules, the underlying codebase/builds used for a release, servicing updates, system definition and configuration, conditional code in Windows binaries themselves (e.g. if (IsServer()) {...} or IsDesktop() etc) and other factors. So while you might assume they're equivalent and often be right, that's not always the case. Very much a devil's in the details question.

In principle, generally, that's true. In practice, regarding the specific workaround I tried, I don't believe there's a dependency on workstation-specific behavior, but that's why I was careful and said that I've tested down to 1809 but haven't tested on Server yet. If any when I will get to operationalizing it from the "less than PoC" state it is now I will of course test it on Servers too.

marticliment commented 8 months ago

I can confirm this issue still happens under:

The error shown on Event Viewer: image