-
Notifications
You must be signed in to change notification settings - Fork 3
PsfFtaCom
PsfFtaCom is a secondary kind of launcher program for the PSF. When added as a new Application element to the AppXManifest, it acts as an Application holding element to house all FTA Shell Verbs, FTA Shell Extensions, as well as COM related application extensions. This allows you to overcome restrictions for uniqueness in the package as a whole that are imposed by the AppxManifest Schemas. (a given FTA type may only be listed in a single application, a COM CLSID may be only listed in a single application). This also allows you to overcome Schema restrictions for inclusiveness (if a Shell Extension references a COM CLSID it must be included in the same application).
- Your package contains two executables, and defines its own unique filetype. It wants to register an "Open" verb to one executable, and an "Edit" verb to the other. Withoug PsfFtaCom you are restricted to supporting only one of these FTA shell verbs.
- Your package contains two executables, and defines two unique filetypes. The first application wants the first file type to have shell verb, plus a DragAndDrop handler Shell extension. The second application wants the second file type to have shell verb, plus a Context Menu Shell Extension. Both Shell Extensions must point to the same COM CLSID. Without PsfFtaCom you can get both shell verbs, but only one of the Shell Extensions.
PsfFtaCom does not replace the need for PsfLauncher for the original applications, but all FTA and COM related application-level extensions may be consolidated under this new application.
PsfFtaCom is available in both 32 and 64 bit. It can launch the target command of either bitness.
The specific command that will be executed for a shell verb is the executable associated with the Application element it is listed under. The trick to using PsfFtaCom is to encode the targeted executable for the shell verb in the Arguments parameter of the AppXManifest entry when placed in an application element with the PsfFtaCom.exe as shown in the example manifest that follows.
Like PsfLauncher, the Applications section of the json identifies applications by matching to the Application Id field of an application in the AppXManifest file and not necessarily the actual name of the exe process. While other third party tooling may use different naming schemes for the creation of the Id field in the AppXManifest file, the Microsoft MSIX Packaging Tool uses a munging of the process name that you can see in this partial AppXManifest file:
<Package ...>
...
<Applications>
<Application Id="PSFLAUNCHEROne" Executable="PsfLauncher1.exe" EntryPoint="Windows.FullTrustApplication">
<uap:VisualElements BackgroundColor="transparent" DisplayName="AppOne" Square150x150Logo="Assets\AppOne-Square150x150Logo.png" Square44x44Logo="Assets\AppOne-Square44x44Logo.png" Description="App One">
<uap:DefaultTile Wide310x150Logo="Assets\AppOne-Wide310x150Logo.png" Square310x310Logo="Assets\AppOne-Square310x310Logo.png" Square71x71Logo="Assets\AppOne-Square71x71Logo.png" />
</uap:VisualElements>
...
</Application>
<Application Id="PSFLAUNCHERTwo" Executable="PsfLauncher2.exe" EntryPoint="Windows.FullTrustApplication">
...
</Application>
<Application Id="PSFFTACOMSixFour" Executable="PsfFtaCom64.exe" EntryPoint="Windows.FullTrustApplication">
<uap:VisualElements BackgroundColor="transparent" DisplayName="PsfFtaCom" Square150x150Logo="Assets\AppOne-Square150x150Logo.png" Square44x44Logo="Assets\AppOne-Square44x44Logo.png" Description="PsfFtaCom launcher" AppListEntry="none">
<uap:DefaultTile Wide310x150Logo="Assets\AppOne-Wide310x150Logo.png" Square310x310Logo="Assets\AppOne-Square310x310Logo.png" Square71x71Logo="Assets\AppOne-Square71x71Logo.png" />
</uap:VisualElements>
<Extensions>
<uap3:Extension Category="windows.fileTypeAssociation">
<uap3:FileTypeAssociation Name="xyz">
<uap:SupportedFileTypes>
<uap:FileType>.xyz</uap:FileType>
</uap:SupportedFileTypes>
<uap:Logo>Assets\xyz.png</uap:Logo>
<uap2:SupportedVerbs>
<uap3:Verb Id="open" Parameters=""VFS\ProgramFilesX64\Vendor\AppOne.exe" "%1"">open</uap3:Verb>
<uap3:Verb Id="edit" Parameters=""VFS\ProgramFilesX64\Vendor\AppTwo.exe" "%1"">edit</uap3:Verb>
</uap2:SupportedVerbs>
</uap3:FileTypeAssociation>
</uap3:Extension>
...
</Extensions>
</Application
</Applications>
</Package>
Note the following details about the above Manifest:
- You would only ever add one PsfFtaCom application entry in the Manifest.
- Since you don't want it to be the default application identified for launch by the AppInstaller, add it as the last Application entry.
- You can just copy the VisualElements from another Application record, but be sure to add the AppListEntry="none" so as to not add anything to the start menu.
- Typically you just move all FTA and Application-level COM extensions to this new app, whether needed or not. Do not move Package-level COM extensions.
- In each of the Shell Verbs, add the relative path to the desired executable, but place that path in an additional set of quotation marks, then add a space before any additional arguments to pass to that executable. If the arguments do not include the "%1" (placeholder for the file the user right clicked on) it is automatically added.
For the package Manifest above, the package might have a Config.json file with an applications section such as this:
"applications": [
{
"id": "PSFLAUNCHEROne",
"executable": "VFS\\ProgramFilesX64\\Vendor\\AppOne.exe",
"arguments": "",
"workingDirectory": "VFS\\ProgramFilesX64\\Vendor"
},
{
"id": "PSFLAUNCHERTwo",
"executable": "VFS\\ProgramFilesX64\\Vendor\\AppTwo.exe",
"arguments": "",
"workingDirectory": "VFS\\ProgramFilesX64\\Vendor"
},
{
"id": "**PSFFTACOMSixFour**",
"arguments": "",
"workingDirectory": "",
"hasShellVerbs": true
}
],
Notes about the Json file:
- The config.json file entry for PsfFtaCom only really uses the new hasShellVerbs entry, which is a boolean and should be set to true.
- The arguments and workingDirectory field apply to the launching of PsfFtaCom, which will ignore the arguments (at this time) and doesn't care about the working directory, so just set them to an empty string as shown.