【发布时间】:2019-08-14 16:41:31
【问题描述】:
start 搜索了哪些路径?此路径列表是否可通过 WMI、注册表、WSH shell 文件夹常量、.NET 方法或任何其他 Windows API 查询?
在cmd 控制台中,start 命令有点神奇。假设您的默认网络浏览器是 Firefox。您还安装了 Chrome 和 Opera,但它们既没有设置为默认值,也没有与任何文件类型关联,也没有在您的 %PATH% 中。考虑以下示例:
start "" opera https://stackoverflow.com
...为什么会这样?
这很重要的原因是,尽管start 命令的所有优势,当应用程序以start 启动时检索应用程序的PID 或窗口句柄仍然是危险的。在cmd 环境中,我更愿意在for /F 循环中使用wmic process call create 来捕获PID。那么有没有一种方法可以让wmic process call create 在不完全限定drive:\\path\\to\\executable 的情况下像start 那样启动“opera”或“iexplore”或“outlook”或“winword”或其他应用程序?
我认为我正在通过递归扫描 HKLM\Software\Clients 以查找 shell\open\command,然后将每个引用的位置临时添加到 %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%
这工作得相当好,但它仍然达不到 start 可以访问的内容。例如:
start "" wordpad
有效,而
wmic process call create "wordpad.exe"
失败。
【问题讨论】:
-
如果我没记错的话,启动命令将搜索这个注册表路径。
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths -
同时输入
path、path /?和dpath /?(最后一个用于使Dos 1程序与Dos 2操作系统一起工作)。 -
如果您发现可执行文件的多个位置,您的计划是什么?
-
@lit 我正在编写的提示这个问题的脚本已经使用 PowerShell 混合代码来实现 P/Invoke 函数。我接受了 Noodles 的建议并使用
ShellExecute(通过Start-Processcmdlet)作为start的替代品。我猜它按当前工作目录的顺序排列,然后是 %path%,然后是 App Paths。基本上,我并没有有意识地计划,只是把它留给机会,并相信用户如果不喜欢它会从一个短码头走很长一段路。
标签: batch-file winapi cmd