windowspowershellappx

How to open installed Microsoft Store apps from powershell?


I'm getting the list of installed Microsoft Store apps with this command:

Get-AppxPackage -AllUsers

And then I try to open an app:

powershell -Command "Start-Process 'C:\Program Files\WindowsApps\Microsoft.Windows.Photos_2021.21070.22007.0_x64__8wekyb3d8bbwe\Microsoft.Photos.exe' -Verb runAs"

I get an access error:

This command cannot be run due to the error: Access is denied.

Solution

  • # Use the URI scheme of the Microsoft.Photos application.
    # Note: Unfortunately, -Wait does *not* work in this case.
    Start-Process ms-photos:
    
    # Wait for the process to exit (from what I can tell there's only ever 1
    # Microsoft.Photos process).
    # The relevant process name was obtained with: Get-Process *Photos*
    (Get-Process Microsoft.Photos).WaitForExit()
    

    Note: That Start-Process -Wait (and -PassThru) cannot be used with at least some Microsoft Store applications is unfortunate; the problem has been reported in GitHub issue #10996.

    Using a URI protocol scheme such as ms-photos: is the simplest approach, although discovering a given Microsoft Store's application's protocol(s) is non-trivial - see this answer, which provides a helper function, Get-AppXUriProtocol, which builds on the standard
    Get-AppXPackage cmdlet; e.g.:

    # Note: 
    #  * Requires custom function Get-AppXUriProtocol from the linked answer.
    #  * Must be run in *Windows PowerShell*, because the AppX module
    #    isn't supported in PowerShell (Core), as of v7.1.
    PS> Get-AppXUriProtocol *Photos* | Format-List
    
    PackageFullName : Microsoft.Windows.Photos_2021.21070.22007.0_x64__8wekyb3d8bbwe
    Protocols       : {ms-wcrv, ms-wpdrmv, ms-photos, microsoft.windows.photos.crop...}
    

    As you can see, the Microsoft Photos application has several protocol schemes associated with it, but the obvious candidate for simply launching the application is ms-photos:, which indeed works.


    Launching Microsoft Store applications that do not have a URI protocol scheme defined:

    If a given application doesn't define a URI protocol scheme, you must - somewhat obscurely - launch it via its AppId (application ID), and the general shell: URI protocol scheme and the virtual AppsFolder shell folder; e.g., to launch Calculator:

    Start-Process shell:AppsFolder\Microsoft.WindowsCalculator_8wekyb3d8bbwe!App
    

    Finding an application's AppID:

    The AppID is composed of the family package name (e.g. Microsoft.MicrosoftEdge_8wekyb3d8bbwe) followed by ! and a package-internal identifier, which is typically - but not always !App; two notable exceptions:

    It's fair to assume for launching the application interactively that the first entry must be used, though I'm not clear on whether there are official rules.

    To demonstrate the technique using Microsoft Photos:

    # Get the package family name (the assumption here is that only *1* package matches).
    # Note: While you must run the Get-AppXPackage from *Windows PowerShell*
    #       you can use the resulting package name to launch the application
    #       from PowerShell (Core) too.
    $packageFamilyName = (Get-AppXPackage *Photos*).PackageFamilyName
    
    Start-Process "shell:AppsFolder\$packageFamilyName!App"
    

    Note that since the executable is then launched indirectly, the actual target process (Microsoft.Photos in this case) isn't guaranteed to exist yet when Start-Process returns, so more work is needed to first wait for it to come into existence, and then wait for it to exit.

    In the simplest - but not fully robust - case, insert a Start-Sleep command, to sleep as long as you would expect creation of the target process to take at most (the actual timing varies with system load):

    Start-Process "shell:AppsFolder\$packageFamilyName!App"
    
    Start-Sleep -Seconds 5 # Wait for the Microsoft.Photos process to be created.
    (Get-Process Microsoft.Photos).WaitForExit()
    

    A fully robust approach would require more work.


    Passing arguments to Microsoft Store applications: