Skip to content

Windows: detected launchers (venv, mvnw, gradlew, bin/rails) do not run in cmd.exe #8

Closed

Description

@kgilpin

Found by reading the code while reviewing #5. Not yet reproduced on a Windows machine.

Problem

When commands.runner is unset, frameworks.mjs picks a launcher for the project. Three of the choices do not run on Windows, where the record command goes through cmd.exe (runShell in manage.mjs uses shell: true, which is %ComSpec%).

Framework Launcher chosen today Why it fails on Windows
pytest, unittest .venv/bin/appmap-python .venv/bin/pytest venvBin looks for .venv/Scripts/appmap-python, but the file is appmap-python.exe, so the venv is never found and the plain appmap-python pytest runs instead. If it were found, cmd.exe would still refuse .venv/Scripts/appmap-python (see the ./ note below).
maven ./mvnw test cmd.exe reads ./mvnw as the command . with a switch /mvnw: '.' is not recognized as an internal or external command.
gradle ./gradlew appmap test Same.
rails-test bin/rails test bin/rails has no extension, so PATHEXT does not help, and the slash breaks the lookup the same way. It needs ruby bin/rails test.

Note on the wrappers: cmd.exe does add the PATHEXT suffixes when it looks up a command, and searches the current directory first. So mvnw test alone finds mvnw.cmd, and gradlew appmap test finds gradlew.bat. The ./ prefix is the only problem. (This works in PowerShell and Git Bash, but the engine runs cmd.exe.)

Suggested fix

Give resolveRunner and the detectRunner functions a platform parameter (default process.platform), the way detectMaxCommandLength already takes one.

On win32:

  • venvBin also checks for appmap-python.exe, and pythonLauncher returns .venv\Scripts\appmap-python .venv\Scripts\pytest.
  • maven returns mvnw test when mvnw.cmd exists (no ./).
  • gradle returns gradlew appmap test when gradlew.bat exists (no ./).
  • rails-test defaults to ruby bin/rails test.

Also update the runner: example in appmap-gold-traces/SKILL.md (it shows .venv/bin/appmap-python pytest) to mention the Windows form.

Test cases needed

Unit tests in frameworks.test.mjs, next to the existing detect: tests, passing platform: 'win32' so they run on any machine. Each one builds a temp directory with the marker files:

  • A dir holding .venv/Scripts/appmap-python.exe gives .venv\Scripts\appmap-python .venv\Scripts\pytest.
  • The same for venv/ and for unittest (... python -m unittest).
  • A dir holding both mvnw and mvnw.cmd gives mvnw test on win32 and ./mvnw test elsewhere.
  • The same for gradlew and gradlew.bat.
  • A dir holding only mvnw (no .cmd) falls back to mvn test on win32.
  • rails-test gives ruby bin/rails test on win32 and bin/rails test elsewhere.
  • An explicit commands.runner is still never overridden on win32.
  • uv, Poetry and Pipenv detection is unchanged on win32.

One test that runs on the real shell, to settle the cmd.exe behaviour with evidence (CI runs the tests on Windows now, #11): make a temp dir with a mvnw.cmd that exits 0, run mvnw test and ./mvnw test through spawnSync(command, { shell: true }), and assert that the first starts and the second does not. On macOS and Linux the same test can use a mvnw script and assert that ./mvnw test starts.

Activity

  1. dividedmind commented on Sep 22, 2026

    @dividedmind
    Contributor

    FWIW as far as I know ./mvnw and ./gradlew should automatically route to bat/cmd files due to how cmd.exe looks up commands – it looks for executable files by adding suffixes and plain mvnw/gradlew don't have an executable suffix; it does need double-checking on Windows to confirm. venv/ruby issues are probably legit.

  2. kgilpin commented on Sep 22, 2026

    @kgilpin
    ContributorAuthor

    Agreed on the suffix lookup: mvnw test alone finds mvnw.cmd, so the fix does not need to name the .cmd/.bat file. The problem is the ./ prefix: cmd.exe reads ./mvnw as the command . with a switch /mvnw ('.' is not recognized as an internal or external command). PowerShell and Git Bash accept it, but the engine runs the record command with shell: true, which is %ComSpec% = cmd.exe. So on Windows the launcher should be mvnw test and gradlew appmap test with no ./.

    I've updated the issue with that, and added a test that runs mvnw test and ./mvnw test through the real shell on the Windows CI runner, so this is checked with evidence rather than memory.

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions