DosTips.com

which.exe - The best of Windows where.exe and Unix which, and some more

which.exe - The best of Windows where.exe and Unix which, and some more

Posted: 26 Mar 2019 12:54

by jfl

Announcing which.exe, a tool for searching which programs will run at the command.com, cmd.exe, or PowerShell prompts.
This which.exe program strives to implement the best of both Unix which and Windows where.exe, and a bit more!

Features:

Allows passing just the base name of a command, and uses the PATHEXT environment variable to infer possible extensions.
(Like Windows' own where.exe, but unlike all Windows ports of Unix which.)

Uses Unicode internally, and outputs file pathnames correctly in any code page. (Provided that the console font has the necessary characters!)
(Again, Windows ports of Unix which all fail at that if a pathname contains non-ASCII characters.)

Knows about command.com, cmd.exe, and PowerShell specific rules. For example, the latter searches for *.ps1 before trying extensions from PATHEXT.
Also command.com and cmd.exe search in ".", whereas PowerShell does not. (Both where.exe and Windows ports of Unix which fail at that!)

By default outputs only the first match. Use option -a to display all matching programs. (Like Unix which)

A -i option allows to efficiently detect cmd.exe doskey macros, and PowerShell aliases.
Run 'which -?' to get help on how to configure both shells for this to work.
(where.exe has no equivalent; Unix which has this option for Unix shells, but Windows ports don't support that in Windows.)

A unique -v option displays verbose comments about why some seemingly obvious programs will NOT run.
For example in Vista and later, with cmd.exe variable NoDefaultCurrentDirectoryInExePath set, cmd does not search in ".". In Linux, it'll report name case errors.

A unique ability to search for names with wildcards. This is useful when you don't quite remember the exact name of a program.

Avoids listing twice the same executable when a path appears multiple times in the PATH.

Last, but not least, a single .exe that runs in all versions of DOS and Windows, from DOS 3 16-bits to Windows 10 64-bits. Including Windows 95 and XP.

which.exe is available in a zip file here:http://jf.larvoire.free.fr/progs/which_v1.14.zip
Note that the zip file contains multiple versions of which.exe: The one at the root, which runs in all MS OSs, as explained above; And several stripped down versions, that run just in DOS, or in particular versions of Windows respectively.
There's also a build for Linux. It is usable in the Windows 10/64 LinuX SubSystem, or in any x86_64 distribution of Linux. Caution : Do not to overwrite the original Linux which from your Linux distribution!

Note about the option -i introduced in version 1.12, for listing cmd doskey aliases:
As discussed in this thread, capturing the doskey macros for the current cmd shell is tricky.
Piping the 'doskey.exe /macros' output to 'which.exe -i' will not work. It is necessary to use a doskey macro for which itself:

And the best way to define doskey macros in an extensible way is to use the AutoRun.cmd script.
See this post on this forum for explanations on how to use AutoRun.cmd, and how it works.
For PowerShell, the problem is very similar, and it is necessary to define a which function invoking which.exe.
Run 'which -?' to get help on how to configure both shells for this to work.

The source code is available on GitHub in the SysToolsLib repository: which.c
But note that the which.exe version in the last (as of this writing) SysToolsLib release is an older one.
Use the version in the zip file above to get the latest which.exe features documented here.

If you find any problem with this which.exe, please report it on GitHub in SysToolsLib issues.

Versions history:

1.14 2019-09-26 Added the ability to search names with wildcards. Added a verbose msg about case-independent matches in Unix.

1.13 2019-06-22 Avoid searching twice in the same directory. Added program properties, visible in the .exe properties box Details tab.

That's a neat tool, I like it
I have a question as to how option -a is intended to work. If I run 'which -a cmd.exe' I was expecting that more than one file was found on my Win10 x64. Also if I run it in the WOW64 subsystem, it reports that cmd.exe was found in System32, which isn't wrong since I know that System32 is the virtualized SysWOW64 folder in this case. Is there a way to see the real path? Same maybe if a path gets redirected via junction?

I have a question as to how option -a is intended to work. If I run 'which -a cmd.exe' I was expecting that more than one file was found on my Win10 x64. Also if I run it in the WOW64 subsystem, it reports that cmd.exe was found in System32, which isn't wrong since I know that System32 is the virtualized SysWOW64 folder in this case. Is there a way to see the real path? Same maybe if a path gets redirected via junction?

The -a option will not report all programs on your system, but all that are accessible in the PATH to the which.exe application you use.
The System32 directory is indeed a tricky case. The 32 and 64 bits versions of which.exe will indeed NOT see the same cmd.exe executable in the %windir%\System32 directory.
But in both cases, they have a single cmd.exe executable in their respective PATH. So I chose to report just that.

a single .exe that runs in all versions of DOS and Windows, from DOS 3 16-bits to Windows 10 64-bits. Including Windows 95 and XP.

What kind of black magic did you apply here Windows Defender didn't like that witchcraft. I had to restore it from quarantine several times

There's no black magic . It's because the WIN32 version does not use the default DOS stub. (The one displaying "This program cannot run in DOS mode".)
Instead, it uses the DOS version of which.exe as the DOS stub for the WIN32 version. So the DOS version runs in MSDOS, and the WIN32 version runs in 32 and 64-bits versions of Windows.

If this triggers your Windows Defender, it's a false positive: The DOS version in the DOS stub does exactly the same as the Win32 version, but using int 21h calls!
I'm surprised this triggers your Windows Defender, because it does not trigger it on any of my systems.
But, on the other hand, the funny thing is that at work, the 64-bits debug version of which.exe (which I did not include in the zip file above) triggers the McAffee antivirus on one of my systems!?!
As a workaround, in the likely case that you have a 64-bits version of Windows, try using the WIN64 version of which.exe instead.

Yes that was already clear to me. My question was rather how you were able to mount the 32 bit machine code to the DOS code without screwing up the addresses/offsets. But I'm afraid the answer to this question is off topic in this forum.

Oh I trust you. As I wrote, I restored the tool every time. It was just for letting you know.
My OS is Win10 Home x64 v. 10.0.17763.379 if that does help you somehow. And yes, the 64 bit version of WHICH has never been quarantined. Don't worry too much about that.

:: USAGE:
:: which [-a] [--] name [...]
::
:: -a Print all available matchings accordingly the description below.
::
:: For each of the names the script looks for and displays a doskey macro,
:: the internal command information or the full path to the executable
:: file in this order. The script doesn't mimic of the Unix command having
:: the same name. It assumes specifics of the Windows command prompt.
::
:: First of all, it looks for doskey macros because they have the higher
:: priority in the prompt. The next step is a looking for internal
:: commands from the known list of the commands. If the command is
:: identified as internal the searching is stopped.
::
:: If nothing has been found previously, the script continues searching of
:: external commands in the current directory and the directories from the
:: PATH environment. If no extension is specified, the PATHEXT variable is
:: used for attempts to find the nearest filename corresponding the
:: provided name.
::
:: ENVIRONMENT:
:: PATH, PATHEXT
::
:: SEE ALSO:
:: DOSKEY /?
:: HELP /?
:: http://ss64.com/nt/
::
:: COPYRIGHTS
:: Copyright (c) 2010, 2014 Ildar Shaimordanov
@echo off

Re: which.exe - The best of Windows where.exe and Unix which, and some more

Posted: 26 Sep 2019 05:45

by jfl

Here's version 1.14 of my which.exe program for DOS and Windows:http://jf.larvoire.free.fr/progs/which_v1.14.zip
Note that this zip file contains multiple versions of which.exe: The one at the root, which runs in all Microsoft OSs, as explained in the opening post; And several stripped down versions, that run just in DOS, or in various versions of Windows (x86/amd64/arm64).
There's also a build for Linux. It is usable in the Windows 10/64 LinuX SubSystem, or in any x86_64 distribution of Linux. Caution : Do not to overwrite the original Linux which from your Linux distribution!

New in this which.exe version 1.14:

It can now search for names with wildcards. This is useful when you don't quite remember the exact name of a program.
Example:

The .exe property sheet details tab now reports lots of information about the program, and where it comes from.

@aGerman: I hoped that this would prevent false positives with some anti-virus, but unfortunately this did not
A few anti-virus still refuse to let it run

I've joined a Linux build. Obviously Linux does not need it, as it already has its own which program. This is more like a demonstration of the source portability.
There's one useful thing though: The -v option will output a comment for every program that matches with the wrong case - A common error in Linux!
Warning: Be cautious not to overwrite the original Linux which with this one: The original one is critical for lots of system management scripts, and mine probably isn't fully compatible.
Recommendation: Rename it as Which (with a capital W), for example, to avoid overwriting the original Linux which.

I've joined an ARM64 build for Windows 10/arm64. I've never tested it as I don't have access to such a machine. If you do, please give it a try and tell me how it works!

Version 1.13 had a minor improvement: It avoided to report a program multiple times, when its path appears multiple times in a PATH. (A common problem in Windows, apparently)

Note that I failed to attach the version 1.14 zip file, as I did for version 1.12.
The upload says: "http error"
Maybe this is because it's larger, due to the other builds included. Is there an upload size limit?
Anyway, I've posted it on my ISP personal home page instead.

Re: which.exe - The best of Windows where.exe and Unix which, and some more

@aGerman: I hoped that this would prevent false positives with some anti-virus, but unfortunately this did not
A few anti-virus still refuse to let it run

That's normal. Unfortunately some established AVs still fire false positives. Also don't overdo. E.g. file version and product version usually contain the same data and they may expect to see a version string in both cases.
However, I still believe the combination of DOS and Windows 32 machine code makes the AV engines nervous.