Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Discussion: Decouple MSIX from AppContainer #55

Open
stevenbrix opened this issue May 29, 2020 · 14 comments
Open

Discussion: Decouple MSIX from AppContainer #55

stevenbrix opened this issue May 29, 2020 · 14 comments

Comments

@stevenbrix
Copy link

Discussion: Decouple MSIX from AppContainer

Currently, there is no way to run an app in an AppContainer without it being packaged into an MSIX. This has a few major downsides:

  1. Slow inner loop. VS has to do the loose file deployment every time you build/F5.
  2. Can't run an app container app from the command line.

It would be great if MSIX was solely a technology for packaging and submitting apps to the store (or sideloading), and didn't have an impact on the runtime behavior of the app.

With Project Reunion and WinUI3, we now are trying to support 3 different app models:

  1. Packaged Desktop
  2. Unpackaged Desktop
  3. Packaged UWP

It would make tooling simpler to just have a single build/deploy model for all of these.

Related Links

microsoft/microsoft-ui-xaml#2500 (comment)

@rgwood
Copy link

rgwood commented May 31, 2020

Seconding this - the deploy time is really noticeable during development of UWP apps, anything that can be done to improve it would be greatly appreciated.

@maxkatz6
Copy link

maxkatz6 commented May 31, 2020

It would be great to allow unpackaged UWP apps (not only Win32 with WinUI) running at least for debugging.

@jonwis
Copy link
Member

jonwis commented May 31, 2020

Thanks, so the request is to support "create this process in an appcontainer defined in X way", and then use that to apply to debugging & development & testing & command-line access.

Maybe we can avoid redeploying until its manifest changes? Just changing some bits (DLLs, EXEs, assets not referenced by the app's manifest) shouldn't impact what registration does.

@andreww-msft , I think this one's for you.

@stevenbrix
Copy link
Author

stevenbrix commented Jun 1, 2020

@jonwis improving incremental build times is certainly part of it.

The other more meta issue is unifying these models so that our tooling can be simplified. Having to do the loose file registration just to run an app in an AppContainer adds complexity. Package registration is not always reliable, and we run into scenarios where people are unable to debug an app they are working on just because some part of the package registration process failed. But maybe avoiding redeploying unless the manifest changes would address a lot of these issues?

Could we do something like the SxS manifest and just have an .exe with an AppxManifest.xml file next to it that can be used to run the app in the appropriate container?

@AdamBraden
Copy link

Will need to dig up the history here to see why deployment needs to run if you haven't changed the manifest.

I would need more information about the scenario being envisioned where an app runs in AppContainer w/o deployment. Is this the case where taking an existing desktop app, and want to see if it can be tested under appcontainer? That may be viable. However, once the app starts taking on dependencies in the platform and declarative registration (eg: extensions, appdata folder) or Identity (notifications, backgroundtasks, etc), such an app would likely fail with different errors if the deployment pipeline was not executed.

@andreww-msft andreww-msft removed their assignment Jun 8, 2020
@stevenbrix
Copy link
Author

I would need more information about the scenario being envisioned where an app runs in AppContainer w/o deployment. I would need more information about the scenario being envisioned where an app runs in AppContainer w/o deployment.

No, the primary motivator is to make the development environments, inner-loop workflows, and packaging+deployment 100% identical for both AppContainer and Desktop scenarios. Unifying these paradigms will greatly simplify tooling, and allow us to have quicker inner loop workflows for our customers.

However, once the app starts taking on dependencies in the platform and declarative registration (eg: extensions, appdata folder) or Identity (notifications, backgroundtasks, etc), such an app would likely fail with different errors if the deployment pipeline was not executed.

What aspect of the "deployment pipeline" needs to be executed for this scenarios? I'm still thinking that the app would have all these declarations, and identity would be granted by a ProjectReunionManifest.xml file that is read when the .exe launches.

@DrusTheAxe
Copy link
Member

DrusTheAxe commented Sep 17, 2020

An appcontainer process requires the appcontainer be defined to Windows e.g. system registration via CreateAppContainerProfile(). That does some filesystem work, add rules to the firewall for network enforcement, etc. There's more to defining an AppContainer than just creating a process. MSIX does this under the covers as part of package registration.

P.S. There's also 'uninstall' work to remove an AppContainer definition e.g. call DeleteAppContainerProfile.

What aspect of the "deployment pipeline" needs to be executed for this scenarios?

By "this scenario" do you mean "create a process running in an appcontainer" or "create a process running in an appcontainer with package+application identity and able to use features" like any registered MSIX packaged app can/does today?

@rgwood
Copy link

rgwood commented Nov 26, 2020

FYI "Improve inner-loop performance for .NET developers" is a big epic for .NET 6, with stories for improving this in many different technologies (not just the "core" CLI/SDK/MSBuild).

This issue greatly impacts the inner-loop for .NET developers working with AppContainers, perhaps it should have a story too?

@just1a-person
Copy link

Will this allow command line apps to be packaged using MSIX (without showing up in the start menu)?

@DrusTheAxe
Copy link
Member

Will this allow command line apps to be packaged using MSIX (without showing up in the start menu)?

That's independent of the app's trustlevel.

Apps don't have to be listed in the Start Menu. In appxmanifest.xml specify <uap:VisualElements AppListEntry="none"....> and the application is defined and can be activated, but won't appear in the applist (e.g. Start Menu).

It also won't be enumerable via Windows.ApplicationModel.Package.GetAppListEntries[Async]() for the rather obvious reason :P

@JaiganeshKumaran
Copy link
Contributor

@DrusTheAxe Isn't AppListEntry="none" for internal usage only?

@DrusTheAxe
Copy link
Member

DrusTheAxe commented Jan 12, 2021

@DrusTheAxe Isn't AppListEntry="none" for internal usage only?

It's publicly documented

Attribute Description Data type Required Default value
AppListEntry The entry in the All Apps List. This attribute can have one of the following values: default none No default

There's explicit guidance on docs.microsoft.com about it, among other posts across the internet if you search like this one.

I don't know if Store has submission restrictions for packages with this but from Windows-the-OS' perspective it's a feature any package can use (no Capability or other magic incantation required).

It has its uses, e.g. you want an application invoked for some extension point and don't want the app itself appearing as a tile for direct user activation. The application's still activatable programmatically (e.g. ApplicationActivationManager.ActivateApplication(...applicationusermodelid...)) but no tile for the user makes it unlikely to be directly run by the user.

@stevenbrix
Copy link
Author

stevenbrix commented Feb 26, 2021

An appcontainer process requires the appcontainer be defined to Windows e.g. system registration via CreateAppContainerProfile(). That does some filesystem work, add rules to the firewall for network enforcement, etc. There's more to defining an AppContainer than just creating a process. MSIX does this under the covers as part of package registration.

P.S. There's also 'uninstall' work to remove an AppContainer definition e.g. call DeleteAppContainerProfile.

What aspect of the "deployment pipeline" needs to be executed for this scenarios?

By "this scenario" do you mean "create a process running in an appcontainer" or "create a process running in an appcontainer with package+application identity and able to use features" like any registered MSIX packaged app can/does today?

@DrusTheAxe i appreciate learning how this works! I actually had no idea and this is a lot more clear now. I imagine that something similar to sparse packages could be done, where the exe detects it’s unregistered, registers itself, and then restarts. This should all be done by the tooling (just like the dynamic dependencies work), where we generate the main method that does this, so the dev should be none the wiser. Would this be doable?

@DrusTheAxe
Copy link
Member

DrusTheAxe commented Feb 26, 2021

something similar to sparse packages could be done, where the exe detects it’s unregistered, registers itself, and then restarts

Sure. That's actually an overt scenario for SparsePackages/ExternalLocation, for XCOPY-install type apps -- in main() check if you're running with package identity and if not, register your package and restart. Similar in this case, in main() check if you're running in an appcontainer and if not, define one and restart.

The 'restart' part is slightly more complicated than the SparsePackage case. For a SparsePackage you just need to register and since you have a <msix> in your SxS manifest CreateProcess knows you want to run packaged and there's a matching package registered for the user and voila. Doesn't matter how CreateProcess is called as Windows does the heavy lifting. For AppContainer you'd need to explicitly create the process in an appcontainer e.g.

int main()
{
    if not GetTokenInformation(TOKEN_IS_APPCONTAINER)
        exe = GetModuleFileName(null)
        STARTUPINFOEX siex;
        UpdateProcThreadAttribute(siex.lpAttributeList, ..., PROC_THREAD_ATTRIBUTE_SECURITY_CAPABILITIES, ...)
        CreateProcess(exe, GetCommandLine(), ..., siex, ...)
        ExitProcess()
    ...
}

Probably need more in there, e.g. if you're not running in an AppContainer then check if the desired AppContainer exists and create it if need be before CreateProcess. But sure, looks pretty straight forward.

A quick net search for PROC_THREAD_ATTRIBUTE_SECURITY_CAPABILITIES found several posts (Microsoft and not) with more detailed code.

Another complication is cleanup. If an app does this register-on-the-fly and then is deleted without any sort of uninstall or cleanup there's leftover artifacts awaiting explicit removal. In the SparsePackage case it's possible for a user to clean up as registered packages show up in Add/Remove Programs. AppContainer definitions don't show up in ARP or other like user affordance. If your AppContainer'd app, say, downloaded videos to its temp directory, that could be a lot of disk space a user would have no (reasonable/easy) way to reclaim. Not fata, but something to be aware of.

It's certainly possible for a Project Reunion RestartCurrentProcessAsAppContainerIfNecessary() API to shrink-wrap the restart logic. I don't see any need for tooling here. Dynamic Dependencies needs the DDLM to prevent Windows from unknowningly breaking dynamic apps. No durable artifact necessary to accomplish this, just code.

Thoughts?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests