Skip to content

File Types, Associations, and App Capabilities ​

Design the end-to-end experience for how files are previewed, opened, edited, and printed using a single, unified model:

  • fileTypes: define what a file “is” and how to match it.
  • apps[].capabilities: let apps declare what file types and verbs they can handle.
  • fileAssociations: centrally curate the UX (defaults, Open With, previews, and print).

What You'll Learn

  • Single source of truth for file type matching (fileTypes)
  • Clear separation of concerns: capability (app) vs UX (routing)
  • Deterministic precedence and selection per verb
  • Built-in preview providers configured centrally

Overview ​

  • fileTypes (registry):
    • Central registry of recognizable file kinds with a single match definition (e.g., “pdf”, “word-docs”).
    • Case-insensitive extension matching.
    • Optional defaultPreviewProvider for built-in previews.
  • App Capabilities (per-app):
    • Apps declare which fileTypes they support and how to invoke verbs (open/edit/print).
    • Capabilities do not by themselves determine UI; they provide launch details when chosen by file associations.
  • File Associations (central UX):
    • Rules per fileType that define which handlers are available for each verb, which one is default, and whether entries appear in Open With.
    • Associations can reference apps by appRef or specify targetPath directly.
    • Built-in preview providers live here (or on the fileType via defaultPreviewProvider).

Security gating

  • Any association entry that references an application requires an enabled application policy with action: "allow" that matches the executable. Otherwise, that entry is ignored.
  • Association rules do not expand discovery scope; applications must still be discoverable via Start Menu/Desktop shortcut scan.

File Types (Registry) ​

Centralize file type recognition to avoid scattered literal extension lists.

Structure ​

json
{
  "fileTypes": [
    {
      "id": "pdf",
      "displayName": "PDF",
      "match": { "extensions": ["pdf"] },
      "defaultPreviewProvider": "builtInPdf"
    },
    {
      "id": "word-docs",
      "displayName": "Word Documents",
      "match": { "extensions": ["doc", "docx"] }
    }
  ]
}

Fields ​

  • id (string, required): kebab-case; unique and stable within fileTypes.
  • displayName (string, required): shown in UI where applicable.
  • match (required): a single match object:
    • extensions (string[]): one or more file extensions (no leading dot). Case-insensitive (e.g., pdf, PDF).
  • defaultPreviewProvider (string, optional): "builtInPdf" | "builtInImage" | "builtInText"

Case sensitivity

  • Extensions are matched case-insensitively.

App Capabilities (Per-App Declaration) ​

Apps declare the file types and verbs they support. Capabilities describe "can do X with Y fileType" plus the invocation details (arguments and optional flags). UI/selection is controlled by fileAssociations.

Structure ​

json
{
  "id": "ms-word",
  "displayName": "Microsoft Word",
  "enabled": true,
  "priority": 200,
  "visibility": "hidden",
  "matchAll": [
    { "type": "targetPath", "pattern": ".*WINWORD\\.EXE$", "patternType": "regex" }
  ],
  "action": "allow",
  "capabilities": [
    {
      "fileTypeRef": "word-docs",
      "verbs": {
        "open":  { "arguments": "\"%1\"" },
        "edit":  { "arguments": "/e \"%1\"" },
        "print": { "arguments": "/p \"%1\"" }
      }
    }
  ]
}

Fields ​

  • capabilities[].fileTypeRef (string, required): references fileTypes[].id.
  • capabilities[].verbs (dictionary, optional): maps verb names to invocation details. Supports standard verbs (open, edit, print) and custom verbs (e.g., extract).
    • arguments (string, optional): command string; supports variable substitution (%1, %~dp1, %~n1, %~dpn1).
    • vmFlags (string[], deprecated): additional flags for this verb. Deprecated: use runtime instead for structured settings.
    • runtime (Runtime, optional): additional runtime settings for this verb. Replaces vmFlags.

Notes

  • Capabilities do not create context menu entries or defaults by themselves; fileAssociations curate the UX.
  • Security gating still applies at launch time (the app must be discoverable and allowed).

File Associations (Central UX) ​

Routing rules determine the user experience per fileType: which actions exist, which is default, and whether entries appear in context menus. Built-in previews are configured as actions.

Structure ​

json
{
  "fileAssociations": [
    {
      "id": "pdf-routing",
      "displayName": "PDF",
      "enabled": true,
      "priority": 250,
      "fileTypeRef": "pdf",
      "actions": [
        { "verb": "preview", "displayName": "Preview", "provider": "builtInPdf", "default": true },
        { "verb": "open", "displayName": "Open", "appRef": "google-chrome", "showInContextMenu": true }
      ]
    }
  ]
}

Action Entry Fields ​

  • verb (string, required): verb name (e.g., preview, open, edit, print, extract). Must match a verb in the app's capabilities (or be preview for built-in preview).
  • displayName (string, required): label shown in menus.
  • appRef (string): id of an application policy to launch for this verb. Required for non-preview actions.
  • provider (string): built-in preview provider (builtInPdf, builtInImage, builtInText). Required for preview verb only.
  • default (boolean): marks this action as the default for double-click.
  • showInContextMenu (boolean): show in main context menu (default: true).
  • showInOpenWith (boolean): include in Open With submenu (default: true).
  • match (optional): narrows the action within the fileType (e.g., split doc vs docx).

Action and Capability Resolution ​

When an action references an app via appRef, invocation details come from the app's capabilities for that verb:

  • arguments: Retrieved from apps[].capabilities[].verbs[verbName].arguments
  • vmFlags (deprecated): Retrieved from apps[].capabilities[].verbs[verbName].vmFlags
  • runtime: Retrieved from apps[].capabilities[].verbs[verbName].runtime

Boolean Logic ​

  • An association rule applies when its fileTypeRef matches the file’s fileType (see resolution).
  • Per-handler match (optional) further narrows the handler within the fileType context.
  • To express OR across file types, author multiple routing rules, each with its own fileTypeRef; for OR within a fileType, use match.extensions with multiple values or separate handler entries with different match filters.

Variable Substitution ​

The following variables are available in arguments:

VariableDescriptionExample (Given C:\Downloads\MyArchive.zip)
%1Full path to the fileC:\Downloads\MyArchive.zip
%~dp1Drive and Path onlyC:\Downloads\
%~n1File name without extensionMyArchive
%~dpn1Derived Destination Path (Path + Name)C:\Downloads\MyArchive\

Quote Escaping

  • When a variable appears inside quotes (e.g., "%1"), all backslashes in the substituted value are escaped (\ → \\).
  • When a variable appears outside quotes, backslashes are not escaped.
  • To include a literal % character, use %%.

Resolution Algorithm ​

  1. Determine fileType:

    • Match the file against fileTypes[].match. If multiple fileTypes match, select by:
      • Highest fileTypes array order? No — use a stable deterministic rule:
        • Prefer the fileType whose match is more specific when determinable (for example, a single-extension type over a broader multi-extension type that also includes the same extension); otherwise fall back to fileType id alphabetical.
      • Matching is case-insensitive for extensions.
    • If no fileType matches, associations do not apply.
  2. Gather routing rules:

    • Collect all enabled fileAssociations rules where fileTypeRef equals the selected fileType id.
  3. For the requested verb (open, edit, print, preview):

    • Aggregate all handlers for that verb from the collected routing rules.
  4. Choose the default handler:

    • Any handler with default: true.
    • Else highest routing rule priority (descending).
    • Else stable alphabetical tie-break by routing rule id (fallback to displayName when id is missing).
  5. Open With menu:

    • Include handlers where showInOpenWith: true.
  6. Security gating:

    • If a handler references an app (appRef or targetPath), it is only considered valid if at least one enabled application policy with action: "allow" matches the executable. Otherwise the handler is ignored.

Resolution flow

Mermaid Diagram

Print

  • The Print action is available only when at least one print handler exists in applicable routing rules for the fileType.
  • If no association rule provides verbs.print, the Print action is not offered.

::: note Device-level vs UI-level

  • UI-level: include or omit verbs.print in routing to control whether the Launcher offers the Print action for a file type.
  • Device-level: enforce printer availability and restrictions via runtime runtime.devices or vendor-specific runtime.extensions (global or per-app). See: Device-level Settings and Schema Reference :::

Examples ​

Hidden Word with centralized routing and split doc vs docx

json
{
  "fileTypes": [
    { "id": "word-docs", "displayName": "Word Documents", "match": { "extensions": ["doc", "docx"] } }
  ],
  "apps": [
    {
      "id": "ms-word",
      "displayName": "Microsoft Word",
      "enabled": true,
      "priority": 200,
      "visibility": "hidden",
      "matchAll": [
        { "type": "targetPath", "pattern": ".*WINWORD\\.EXE$", "patternType": "regex" }
      ],
      "action": "allow",
      "capabilities": [
        {
          "fileTypeRef": "word-docs",
          "verbs": {
            "open":  { "arguments": "\"%1\"" },
            "edit":  { "arguments": "/e \"%1\"" },
            "print": { "arguments": "/p \"%1\"" }
          }
        }
      ]
    }
  ],
  "fileAssociations": [
    {
      "id": "word-docs-routing",
      "displayName": "Word docs",
      "enabled": true,
      "priority": 300,
      "fileTypeRef": "word-docs",
      "actions": [
        { "verb": "open", "displayName": "Open", "appRef": "ms-word", "match": { "extensions": ["docx"] }, "default": true, "showInContextMenu": true },
        { "verb": "open", "displayName": "Open (Compatibility Mode)", "appRef": "ms-word", "match": { "extensions": ["doc"] }, "showInContextMenu": true },
        { "verb": "print", "displayName": "Print", "appRef": "ms-word", "default": true }
      ]
    }
  ]
}

PDF with built-in preview and hidden Chrome for context menu

json
{
  "fileTypes": [
    { "id": "pdf", "displayName": "PDF", "match": { "extensions": ["pdf"] }, "defaultPreviewProvider": "builtInPdf" }
  ],
  "apps": [
    {
      "id": "google-chrome",
      "displayName": "Google Chrome",
      "enabled": true,
      "priority": 150,
      "visibility": "hidden",
      "matchAll": [
        { "type": "targetPath", "pattern": ".*chrome\\.exe$", "patternType": "regex" }
      ],
      "action": "allow",
      "capabilities": [
        { "fileTypeRef": "pdf", "verbs": { "open": { "arguments": "\"%1\"" } } }
      ]
    }
  ],
  "fileAssociations": [
    {
      "id": "pdf-routing",
      "displayName": "PDF",
      "enabled": true,
      "priority": 250,
      "fileTypeRef": "pdf",
      "actions": [
        { "verb": "preview", "displayName": "Preview", "provider": "builtInPdf", "default": true },
        { "verb": "open", "displayName": "Open", "appRef": "google-chrome", "showInContextMenu": true }
      ]
    }
  ]
}

Image previews (built-in only)

json
{
  "fileTypes": [
    { "id": "images", "displayName": "Images", "match": { "extensions": ["png", "jpg", "jpeg", "gif"] }, "defaultPreviewProvider": "builtInImage" }
  ],
  "fileAssociations": [
    {
      "id": "images-routing",
      "displayName": "Images",
      "enabled": true,
      "priority": 200,
      "fileTypeRef": "images",
      "actions": [
        { "verb": "preview", "displayName": "Preview", "provider": "builtInImage", "default": true }
      ]
    }
  ]
}

Disable Print for PDFs (omit print actions)

json
{
  "fileTypes": [
    { "id": "pdf", "displayName": "PDF", "match": { "extensions": ["pdf"] }, "defaultPreviewProvider": "builtInPdf" }
  ],
  "fileAssociations": [
    {
      "id": "pdf-no-print",
      "displayName": "PDF (no printing)",
      "enabled": true,
      "priority": 250,
      "fileTypeRef": "pdf",
      "actions": [
        { "verb": "preview", "displayName": "Preview", "provider": "builtInPdf", "default": true }
      ]
    }
  ]
}

Route DOC/DOCX Print to Word

json
{
  "fileTypes": [
    { "id": "word-docs", "displayName": "Word Documents", "match": { "extensions": ["doc", "docx"] } }
  ],
  "apps": [
    {
      "id": "ms-word",
      "displayName": "Microsoft Word",
      "enabled": true,
      "priority": 200,
      "matchAll": [
        { "type": "targetPath", "pattern": ".*WINWORD\\.EXE$", "patternType": "regex" }
      ],
      "action": "allow",
      "capabilities": [
        { "fileTypeRef": "word-docs", "verbs": { "open": { "arguments": "\"%1\"" }, "print": { "arguments": "/p \"%1\"" } } }
      ]
    }
  ],
  "fileAssociations": [
    {
      "id": "word-docs-print",
      "displayName": "Word docs (print via Word)",
      "enabled": true,
      "priority": 300,
      "fileTypeRef": "word-docs",
      "actions": [
        { "verb": "open", "displayName": "Open", "appRef": "ms-word", "default": true, "showInContextMenu": true },
        { "verb": "print", "displayName": "Print", "appRef": "ms-word", "default": true }
      ]
    }
  ]
}

Developer source files → hidden editor via routing

json
{
  "fileTypes": [
    {
      "id": "source-files",
      "displayName": "Source files",
      "match": { "extensions": ["txt","md","json","yml","yaml","xml","ini","cfg","log","js","ts","jsx","tsx","css","scss","less","py","rb","go","rs","java","c","cpp","h","hpp","cs"] }
    }
  ],
  "apps": [
    {
      "id": "code-editor",
      "displayName": "Code Editor",
      "enabled": true,
      "priority": 190,
      "visibility": "hidden",
      "matchAll": [
        { "type": "targetPath", "pattern": ".*(Code|notepad\\+\\+|sublime_text)\\.exe$", "patternType": "regex" }
      ],
      "action": "allow",
      "capabilities": [
        { "fileTypeRef": "source-files", "verbs": { "open": { "arguments": "\"%1\"" } } }
      ]
    }
  ],
  "fileAssociations": [
    {
      "id": "source-files-routing",
      "displayName": "Source files",
      "enabled": true,
      "priority": 280,
      "fileTypeRef": "source-files",
      "actions": [
        { "verb": "open", "displayName": "Open", "appRef": "code-editor", "default": true, "showInContextMenu": true }
      ]
    }
  ]
}

RDP and VNC clients + routing

json
{
  "fileTypes": [
    { "id": "rdp", "displayName": "RDP", "match": { "extensions": ["rdp"] } },
    { "id": "vnc", "displayName": "VNC", "match": { "extensions": ["vnc"] } }
  ],
  "apps": [
    {
      "id": "rdp-client",
      "displayName": "Remote Desktop Connection",
      "enabled": true,
      "priority": 160,
      "matchAll": [ { "type": "targetPath", "pattern": ".*mstsc\\.exe$", "patternType": "regex" } ],
      "action": "allow",
      "capabilities": [ { "fileTypeRef": "rdp", "verbs": { "open": { "arguments": "\"%1\"" } } } ]
    },
    {
      "id": "vnc-viewer",
      "displayName": "VNC Viewer",
      "enabled": true,
      "priority": 160,
      "matchAll": [ { "type": "targetPath", "pattern": ".*vncviewer.*\\.exe$", "patternType": "regex" } ],
      "action": "allow",
      "capabilities": [ { "fileTypeRef": "vnc", "verbs": { "open": { "arguments": "\"%1\"" } } } ]
    }
  ],
  "fileAssociations": [
    {
      "id": "rdp-routing",
      "displayName": "RDP",
      "enabled": true,
      "priority": 260,
      "fileTypeRef": "rdp",
      "actions": [ { "verb": "open", "displayName": "Open", "appRef": "rdp-client", "default": true, "showInContextMenu": true } ]
    },
    {
      "id": "vnc-routing",
      "displayName": "VNC",
      "enabled": true,
      "priority": 260,
      "fileTypeRef": "vnc",
      "actions": [ { "verb": "open", "displayName": "Open", "appRef": "vnc-viewer", "default": true, "showInContextMenu": true } ]
    }
  ]
}

ZIP extraction with custom extract verb and system tar utility

json
{
  "fileTypes": [
    {
      "id": "zip-archive",
      "displayName": "Compressed (zipped) Folder",
      "match": { "extensions": ["zip"] }
    }
  ],
  "apps": [
    {
      "id": "system-tar",
      "displayName": "System Tar",
      "targetPath": "%SYSTEMROOT%\\System32\\cmd.exe",
      "enabled": true,
      "priority": 60,
      "visibility": "hidden",
      "action": "allow",
      "capabilities": [
        {
          "fileTypeRef": "zip-archive",
          "verbs": {
            "extract": { "arguments": "/c mkdir \"%~dpn1\" & tar -xf \"%1\" -k -C \"%~dpn1\"" }
          }
        }
      ]
    }
  ],
  "fileAssociations": [
    {
      "id": "zip-extraction-routing",
      "displayName": "Extract ZIP archives",
      "enabled": true,
      "priority": 100,
      "fileTypeRef": "zip-archive",
      "actions": [
        { "verb": "extract", "displayName": "Extract", "appRef": "system-tar", "default": true }
      ]
    }
  ]
}

File Policies (Files Tab) ​

Control which file operations are allowed. Defaults:

OperationDefaultDescription
listAllowShow files in the file browser (Files tab)
importAllowImport files into sandbox
exportDenyExport files from sandbox
openAllowOpen files with configured routing
deleteAllowDelete files in sandbox

Structure ​

Define the referenced file type in fileTypes[] (for example, an executable entry that matches installer/PE extensions).

json
{
  "id": "deny-import-executables",
  "displayName": "Block executable imports",
  "enabled": true,
  "priority": 1000,
  "operation": "import",
  "fileTypeRef": "executable",
  "action": "deny"
}

Match Semantics (File Policies) ​

  • fileTypeRef must reference an entry in fileTypes[].
  • Resolution uses the same fileType matching rules as associations: prefer more specific fileTypes; ties break by fileType id (alphabetical). Conflicts across file policies resolve by rule priority (descending), then id alphabetical (fallback to displayName when id is missing).

List Operation (Files Tab) ​

  • Controls visibility in the Files tab listing; does not execute a verb.
  • action: "allow" shows matching items; action: "deny" hides them.
  • Conflicts resolve by rule priority (descending), then rule id alphabetical, consistent with other file operations.

Example (hide temp/backup files)

json
{
  "id": "hide-temp-and-backups",
  "displayName": "Hide temporary/backup files",
  "enabled": true,
  "priority": 900,
  "operation": "list",
  "fileTypeRef": "temp-and-backups",
  "action": "deny"
}

Choosing What to Author Where ​

  • fileTypes: define once, reuse everywhere. If you add or change extensions, do it here.
  • App Capabilities: let each app declare what it can handle and how (per verb).
  • fileAssociations: curate the user experience per fileType. Defaults, Open With presence, previews, and print are chosen here.

Rule of thumb

  • If users should have a consistent experience (previews, Open With, defaults, print) across apps → configure fileAssociations for that fileType.
  • If a single app “owns” a type and you don’t need multiple choices, you can still use fileAssociations with a single handler. Capabilities simply supply the invocation details.

Next Steps ​