rojo
rojo

Reputation: 24466

Is there an API which exposes the paths searched by the start command?

What paths are searched by start? Is this path list queryable via WMI, the registry, WSH shell folder constants, .NET methods, or any other Windows API?

In a cmd console, the start command is sort of magic. Say your default web browser is Firefox. You also have Chrome and Opera installed, but they are neither set as default, nor associated with any file types, nor in your %PATH%. Considering the following example:

start "" opera https://stackoverflow.com

... why does that work?

mind blown

The reason this matters is that, for all the start command's strengths, it is still perilous to retrieve an application's PID or window handle when that application was launched with start. In a cmd environment I'd prefer to use wmic process call create in a for /F loop to capture the PID. So is there a way I can teach wmic process call create to launch "opera" or "iexplore" or "outlook" or "winword" or other applications as start can without fully qualifying the drive:\\path\\to\\executable?

I thought I was on to a solution by scanning HKLM\Software\Clients recursively for shell\open\command, then adding each referenced location temporarily to %PATH%:

rem // temp add installed clients to %PATH% to make "call :display" behave like "start"
setlocal enabledelayedexpansion
for %%a in (HKLM HKCU) do for /f "tokens=2*" %%I in (
    'REG QUERY %%a\Software\Clients /s /f command /k /ve ^| find "(Default)"'
) do if "%%~I"=="REG_EXPAND_SZ" (
    if /i "%%~xJ"==".exe" (
        if "!PATH:%%~J\..=!"=="!PATH!" path !PATH!;%%~J\..
    ) else for %%# in (%%J) do if /i "%%~x#"==".exe" (
        if "!PATH:%%~#\..=!"=="!PATH!" path !PATH!;%%~#\..
    )
) else (
    if /i "%%~xJ"==".exe" (
        if "!PATH:%%~dpJ=!"=="!PATH!" path !PATH!;%%~dpJ
    ) else (
        for %%# in (%%J) do if /i "%%~x#"==".exe" (
            if "!PATH:%%~dp#=!"=="!PATH!" path !PATH!;%%~dp#
        )
    )
)
endlocal & path %PATH%

That works reasonably well, but it still falls short of what start can access. For example:

start "" wordpad

works, whereas

wmic process call create "wordpad.exe"

fails.

Upvotes: 3

Views: 195

Answers (2)

Noodles
Noodles

Reputation: 194

Edit2

This may be of interest regards to what you are doing (as opposed to why something works the way it does).

From a previous answer

Can I create shorthand names for use inside cmd?

See Doskey /?.

You could do this doskey cddesk=cd "%userprofile%\desktop"

Then type cddesk.

By putting all your macros in a batch file you can autoload. Of course you could do this with batchfiles too.

From Technical Reference to the Windows 2000 Registry, Microsoft, 2000.

AutoRun HKCU\Software\Microsoft\Command Processor

Data type Range Default value

REG_SZ list of commands There is no default value for this entry.

Description

Contains commands which are executed each time you start Cmd.exe.

Also see this batchfile https://pastebin.com/A2qLw8r3 that list special names.

In a command prompt start shell:desktop

Or in Start - Run (Winkey + R) just shell:desktop

Edit

I'll just add some caveats here.

This is about opening executables using Start command. A massive amount of rules apply to non executable files.

Not using Start CMD pre-processes the command line and sends a FQFN to CreateProcess - so it's CMD that searches the path not CreateProcess.


https://learn.microsoft.com/en-us/windows/desktop/shell/launch is the documentation for ShellExecute. Everything ends up calling CreateProcess https://learn.microsoft.com/en-us/windows/desktop/api/processthreadsapi/nf-processthreadsapi-createprocessw. Plus CMD preprocessing is detailed here https://books.google.com.au/books/about/Windows_NT_Shell_Scripting.html?id=jrdQAAAAMAAJ&redir_esc=y. Also start /? provides documentation for all three ways to start files. A summary is here Command to run a .bat file

Some fun facts. CMD if it can't recognise a file extension will attempt to execute it. ShellExecute will content sniff unknown files https://learn.microsoft.com/en-us/windows/desktop/com/filetype-key.

quote from rojo: Thanks for the link dump. I'm struggling to understand how ShellExecute can save me from having to fully qualify path names though. That was my primary question. "To use ShellExecute or ShellExecuteEx, your application must specify the file or folder object that is to be acted on, and a verb that specifies the operation." It's the "specify the file or folder object" part that I'm asking about.

It uses the 6 steps under CreateProcess and if that turns up nothing it uses App Paths. If a verb is not specified the default verb is used (usually Open). See my answer here How do i automate the simulation of right clicking a file and selecting the first option using vbscript.

So it an intersection of 4 technologies. Compatibility with MSDos, changes made by IBM for OS/2 and updated by Microsoft for Windows 2000, the standard windows way of starting programs CreateProcess, and with Windows 95 we got shell functions which are based on OLE

quote from rojo: Snap! You're right! In PowerShell I was able to create a System.Diagnostics.Process object, set $ps.StartInfo.UseShellExecute = $true, and then start "wordpad" without any file extension or fully qualified path. Setting the .UseShellExecute property to $false caused the execution to fail. How interesting!

Upvotes: 3

Squashman
Squashman

Reputation: 14290

I remember a discussion about this very topic either on DosTips.com or here on SO but I cannot find it. Hopefully somebody does so we can mark this question as a duplicate.

We know that the batch files will search the current directory and then the path variable to find an executable. The START command also searches the following Registry path

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths

So you have a few options to find the executable.

You can use the WHERE command which searches the current directory and the directories in the PATH variable.

where notepad.exe

You can also just search the path variable with a FOR command.

for %%I in (notepad.exe) do echo %%~$PATH:I

And of course you can search the registry path as I mentioned above by doing a REG QUERY.

Upvotes: 3

Related Questions