Call operator (&) runs command in new window when omitting ".cmd" if a file with the same name exists in the same directory

Viewed 313

If I omit the suffix ".cmd" in a command, it gets opened in a new window. Why is this? What triggers the new window to open?

In Powershell 5 and Powershell Core 7, the first of the following causes a new window to open, while the other three show the outputs in the same window:

  1. & 'C:\some_path\node_modules\.bin\ava' 'help'
  2. & '.\node_modules\.bin\ava' 'help' (used cd C:\some_path before)
  3. & 'C:\some_path\node_modules\.bin\ava.cmd' 'help'
  4. & 'C:\some_path\node_modules\.bin\ava.ps1' 'help'

Meanwhile in cmd all three programs show their output in the same window, no new window gets opened at all:

  1. C:\some_path\node_modules\.bin\ava help
  2. .\node_modules\.bin\ava help (used cd C:\some_path before)
  3. C:\some_path\.bin\ava help

I used the help command only as example, finally I like to use ava debug --serial someFile.js


SW-Versions:

  • Windows: Windows 10, Version 2004 (Build 19041.388)
  • Node: v12.18.3
  • AVA: 3.11.0

There are three relevant files located in the .bin directory:

ava.cmd

@ECHO off
SETLOCAL
CALL :find_dp0

IF EXIST "%dp0%\node.exe" (
  SET "_prog=%dp0%\node.exe"
) ELSE (
  SET "_prog=node"
  SET PATHEXT=%PATHEXT:;.JS;=;%
)

"%_prog%"  "%dp0%\..\ava\cli.js" %*
ENDLOCAL
EXIT /b %errorlevel%
:find_dp0
SET dp0=%~dp0
EXIT /b

ava.ps1

#!/usr/bin/env pwsh
$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent

$exe=""
if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) {
  # Fix case when both the Windows and Linux builds of Node
  # are installed in the same directory
  $exe=".exe"
}
$ret=0
if (Test-Path "$basedir/node$exe") {
  & "$basedir/node$exe"  "$basedir/../ava/cli.js" $args
  $ret=$LASTEXITCODE
} else {
  & "node$exe"  "$basedir/../ava/cli.js" $args
  $ret=$LASTEXITCODE
}
exit $ret

ava

#!/bin/sh
basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")

case `uname` in
    *CYGWIN*|*MINGW*|*MSYS*) basedir=`cygpath -w "$basedir"`;;
esac

if [ -x "$basedir/node" ]; then
  "$basedir/node"  "$basedir/../ava/cli.js" "$@"
  ret=$?
else 
  node  "$basedir/../ava/cli.js" "$@"
  ret=$?
fi
exit $ret

Since the call is done by visual studio code debugging an AVA script with the proposed configuration, my influence on the used commands is limited.


$env:PATHEXT equals .COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;.MSC;.CPL


If I rename the file ava to ava_2, no new window gets opened anymore. If a create an empty file named ava, the command & 'C:\some_path\node_modules\.bin\ava' 'help' opens a new window again.

2 Answers

Why not use Start-Process instead, so you can control whether it opens a new window or not?

Start-Process -FilePath 'C:\some_path\node_modules\.bin\ava' -ArgumentList 'help' -NoNewWindow -Wait

Add .cmd to pathext would fix it if it were missing. Ava is a package for node.js javascript runtime.

$env:PATHEXT += ';.CMD'
C:\Windows\System32\node_modules\.bin\ava.cmd help

Adding it to the path would fix it:

$env:path += ';C:\Windows\System32\node_modules\.bin'
ava help

This same folder that has ava.cmd, has a file named ava that's a shell script, and a file named ava.ps1 that's a powershell script. For some reason hiding or renaming the "ava" shell script fixes it as well.

Referring to the current directory also works:

.\Windows\System32\node_modules\.bin\ava help

Minimal reproducible example:

'' | set-content hi
'echo cmd:hi' | set-content hi.cmd
& $pwd\hi  # pops open another window for a split second
Related