Windows App Development CLI (winapp CLI)

repository·main·Indexed 22 days ago

https://github.com/microsoft/winappcli

A command-line interface designed to simplify the lifecycle of Windows application development across frameworks including Electron, C++, .NET, Rust, Tauri, and Flutter. It provides tools for managing Windows SDKs, package identity (sparse packages), MSIX packaging, manifest generation, certificate signing, and UI automation. The CLI enables developers to access native Windows capabilities, such as interactive notifications and on-device AI, without requiring full MSIX packaging during debugging.

Tokens
139.7K
Snippets
434
Records
543
Agent score
72%

What's inside winapp CLI

  1. Overview of winapp CLI

    main

    The Windows App Development CLI (winapp CLI) is a command-line interface designed to manage Windows SDKs, packaging, app identity, manifests, certificates, and build tools across various app frameworks. It bridges the gap between cross-platform development (e.g., Electron, Rust, Qt, Flutter) and native Windows capabilities.

    Key capabilities include:

    • Modern Windows APIs: Automatic setup and code generation for Windows App SDK and Windows SDK.
    • Package Identity: Enables debugging and testing with package identity without requiring full MSIX packaging.
    • MSIX Packaging: Streamlined app packaging with signing and Store readiness.
    • Developer Tools: Management of manifests, certificates, assets, and build integration.

    This tool is particularly useful for developers wanting to access features like interactive native notifications, protocol handlers (yourapp://), on-device AI (Phi Silica), and controlled access to hardware (camera, microphone, location) within non-native frameworks.

  2. Overview of winapp CLI capabilities

    main

    The winapp CLI is a tool for managing Windows-specific app requirements across various frameworks (like .NET, C++, Electron, Rust, Tauri, and Flutter). It provides capabilities in the following areas:

    • Setup & SDKs: Managing Windows SDKs and build tools.
    • Package Identity: Adding package identity to apps for debugging and testing without full packaging. This unlocks features like notifications, OS integration, and on-device AI.
    • MSIX Packaging: Creating signed, Store-ready app packages.
    • Manifest Management: Generating and updating app manifests and assets.
    • Certificates & Signing: Generating and installing certificates for app signing.
    • UI Automation: Tools for UI-based testing/automation.
    • Framework Integration: Specialized commands for Node.js and Electron (e.g., creating addons or managing debug identity).
  3. Overview of winapp UI automation

    main

    The winapp ui command set allows you to inspect and interact with Windows application UIs via the command line using Windows UI Automation (UIA). It supports a wide range of application types including WPF, WinForms, Win32, Electron, and WinUI 3.

    Command Categories

    1. UIA-Pattern Based (Headless/CI Friendly): These commands drive the app through UIA patterns and do not require an interactive desktop. They work in locked sessions or CI environments.

      • inspect: View the UI tree.
      • search: Find specific elements.
      • get-property: Retrieve element metadata.
      • get-value: Retrieve element values.
      • wait-for: Wait for an element to appear.
      • set-value: Update an element's value.
      • invoke: Trigger an action on an element.
      • scroll: Scroll using --direction or --to.
      • screenshot: Capture the application UI.
    2. Input-Injection Based (Requires Interactive Desktop): These commands synthesize OS-level input (mouse, touch, keyboard) and require an unlocked, interactive desktop with the target window in the foreground. They will fail with no_interactive_desktop in locked or secure sessions (LogonUI/UAC).

      • click, hover, drag: Mouse simulation.
      • touch, pen: Synthesize touch and stylus input.
      • scroll --wheel: Mouse wheel simulation.
      • send-keys --via send-input: Keyboard input simulation.
  4. When to use Native Addons vs. JS Bindings in Electron

    main

    When integrating Windows capabilities into an Electron app, you must choose between using generated JavaScript bindings or creating a custom native addon.

    Use JS Bindings when:

    • You need to access Windows App SDK APIs.
    • You have enabled JS bindings during the winapp init process.
    • The API is already covered by the generated .winapp/bindings/ wrappers.

    Use a Native Addon when:

    • The required API is not covered by the generated JS bindings.
    • You need to interact with Win32 APIs.
    • You need to work with pure COM interfaces.
    • You need to use native C/C++ libraries.
    • You need to use managed .NET assemblies.

    Supported Addon Types:

    • C++ Addons: Useful for calling Windows App SDK notification APIs or other native C++ logic.
    • C# Addons: Ideal for using Phi Silica (local AI) or WinML (Windows Machine Learning) via managed code.
  5. Inspect and automate Windows UIs with winapp ui

    main

    The winapp ui command provides a suite of tools to interact with running Windows applications using UI Automation (UIA). You can target applications by name, title, or PID (-a, --app) or by a specific window handle (-w, --window <hwnd>).

    Core Capabilities:

    • Inspection: status, inspect (view element tree), get-focused, list-windows.
    • Interaction: invoke (click/toggle), click (mouse simulation), hover, drag, touch (gestures), pen (stylus), send-keys, set-value, focus, scroll-into-view.
    • Data Extraction: get-property, get-text, get-value.
    • Visuals: screenshot, record (video capture).
    • State Management: wait-for.
  6. Understand WinApp.CLI test coverage and limitations

    main

    The WinApp.CLI test suite uses a pragmatic approach to validate complex operations like code signing.

    What is verified

    • Command Parsing: Validation of arguments for Sign, Init, Package, and Manifest commands.
    • Certificate Services: Generation of real test certificates via PowerShell and validation of password protection.
    • End-to-End (E2E) Workflows: Simulating complete developer flows: dotnet new winforms $\rightarrow$ dotnet build $\rightarrow$ winapp init $\rightarrow$ winapp package $\rightarrow$ MSIX validation.
    • Service Integration: Integration with BuildTools, MSIX, Certificate, and Config services.

    Known Limitations

    • Code Signing: Actual code signing requires real PE executables. The test suite uses fake files which are intentionally rejected by signtool to test error handling.
    • Environment Dependencies: Tests may fail if BuildTools is not installed or if network-dependent features (like timestamp servers) are unreliable in CI environments.
  7. Compare `winapp run` and `create-debug-identity`

    main

    Choosing between winapp run and create-debug-identity depends on your development workflow and framework.

    • Best for: .NET, C++, Rust, Flutter, Tauri.
    • Mechanism: Registers a full loose layout package by copying files into an AppX layout directory.
    • Behavior: Simulates a real MSIX install. The app is launched by winapp via AUMID activation or an execution alias.
    • Usage: winapp run <build-output-folder>
    • Best for: Electron, or when you need full IDE debugger control (F5 startup debugging).
    • Mechanism: Registers a sparse package via Add-AppxPackage -ExternalLocation. The .exe stays in its original path.
    • Behavior: The executable is launched by you (IDE, terminal, etc.), but Windows recognizes it as having identity.
    • Usage: winapp create-debug-identity <path-to-exe>
  8. How the Electron sample is initialized with winapp

    main

    The Electron sample uses the @microsoft/winappcli package to integrate Windows App SDK and Windows SDK capabilities. The initialization process involves several key components:

    1. Project Initialization

    Running npx winapp init performs the following:

    • Creates a .winapp folder containing headers and libs for the Windows SDK and Windows App SDK.
    • Generates an appxmanifest.xml with required assets.
    • Installs the Windows App SDK runtime.
    • Creates a winapp.yaml file to track NuGet versions and project configuration.
    • Note: The .winapp folder is ignored by git. Use npx winapp restore to regenerate it.

    2. JS Bindings

    By opting in during npx winapp init, the project generates JS bindings. These allow calling Windows App SDK APIs directly from JavaScript without a native addon build step.

    • Bindings are located in .winapp/bindings/.
    • To regenerate bindings after editing winapp.jsBindings, run: npx winapp node generate-bindings.

    3. Native Addons

    • C++ Addon: Generated via npx winapp node generate-addon to call APIs from the Windows SDK and Windows App SDK.
    • C# Addon: Generated via npx winapp node create-addon --template cs. This uses node-api-dotnet and NAOT to produce a .node file that is trimmed and does not require the .NET runtime on the target machine.
  9. How `winapp run` selects projects in a solution

    main

    When you point winapp run at a .sln or .slnx file (or a directory containing one), it uses solution mode to automatically identify the correct project to execute.

    Selection Logic

    1. Classification: winapp inspects all projects in the solution and classifies them as an app, a library, or a test project based on evaluated properties like OutputType, IsTestProject, TestContainer capability, and test-framework package references.
    2. Selection Priority:
      • If there is exactly one runnable app, it is selected.
      • If there are no apps but exactly one test project, the test project is selected.
      • If the choice is ambiguous (e.g., multiple apps or multiple tests), winapp will error and list the candidates. You must then use the --project flag to disambiguate.
  10. Use selectors to target UI elements

    main

    When using inspect or search, the output provides selectors used to target specific elements in subsequent commands. There are three types of selectors:

    Selector TypeDescriptionExample
    AutomationIdDeveloper-set unique identifiers (AutomationProperties.AutomationId). Most stable.MinimizeButton
    Semantic SlugGenerated prefix-name-hash when no unique AutomationId exists.btn-close-d1a0
    Plain-textCase-insensitive substring search against Name or AutomationId.Submit

    Using Semantic Slugs

    Slugs follow the format prefix-normalizedname-hash (e.g., btn-ok-a1b2). They are shell-safe and include a 4-char hex hash to validate element identity. If the UI changes and the element is replaced, the CLI will warn: Element may have changed. Re-run inspect.

    Disambiguating Multiple Matches

    If a search (like winapp ui search Button) returns multiple results, the CLI will list them with their slugs. Use the specific slug to target the correct one:

    # If search shows: btn-ok-a1b2 "OK", btn-cancel-c3d4 "Cancel"
    winapp ui invoke btn-ok-a1b2 -a myapp

    Automatic Ancestor Resolution

    If you search for a non-invokable element (like a TextBlock), the CLI automatically surfaces the nearest invokable ancestor (like its parent Button). You can use that surfaced selector directly with invoke.

    # Example of using a slug for disambiguation
    winapp ui invoke btn-ok-a1b2 -a myapp
  11. Debug startup code using Create Debug Identity

    main

    The standard winapp launch/attach method might miss code executed during the very early stages of application startup. To debug from the first instruction, use the WinApp: Create Debug Identity command from the VS Code Command Palette (Ctrl+Shift+P).

    This command registers a sparse package for your executable using create-debug-identity. Once registered, the application carries its identity regardless of how it is launched, allowing you to use standard debugger launch configurations (like coreclr or cppvsdbg) directly on the executable path.

    {
        "name": "Launch (with identity)",
        "type": "coreclr",
        "request": "launch",
        "program": "${workspaceFolder}/bin/Debug/net8.0-windows10.0.22621/myapp.exe"
    }
  12. How manifest placeholders work

    main

    Generated manifests use $placeholder$ tokens that are resolved automatically during specific operations. This allows manifests to be portable across different tools (like Visual Studio).

    PlaceholderResolved to
    $targetnametoken$Executable name without extension (e.g., MyApp.exe)
    $targetentrypoint$Always resolved to Windows.FullTrustApplication

    Resolution Logic:

    • winapp pack: Resolves $targetnametoken$ using the --executable option or by auto-detecting the single .exe in the input folder.
    • winapp create-debug-identity: Resolves $targetnametoken$ from the provided entrypoint argument.
    • winapp manifest generate --executable: Extracts metadata from the executable, but the generated manifest still uses the $targetnametoken$.exe placeholder for later resolution.