当我调用以下代码时:
Start-Process Firefox
然后 PowerShell 打开浏览器。我可以用其他几个程序来做到这一点,并且它可以工作。我的问题是:如果我键入 Firefox,PowerShell 如何知道要打开哪个程序?我的意思是,我没有使用具体的路径或其他东西......
我虽然它与环境变量有关......但我找不到任何称为Firefox的变量......他怎么知道?
当我调用以下代码时:
Start-Process Firefox
然后 PowerShell 打开浏览器。我可以用其他几个程序来做到这一点,并且它可以工作。我的问题是:如果我键入 Firefox,PowerShell 如何知道要打开哪个程序?我的意思是,我没有使用具体的路径或其他东西......
我虽然它与环境变量有关......但我找不到任何称为Firefox的变量......他怎么知道?
我追踪了它的两半,但我不能让它们在中间相遇。
Process Monitor 显示它检查 PATH,并最终检查HKLM\Software\Microsoft\Windows\CurrentVersion\App Paths\firefox.exe
,这就是我如何找到安装位置并运行它的答案。
该注册表项用于应用程序注册,其中显示:
当调用 ShellExecuteEx 函数并在其 lpFile 参数中使用可执行文件的名称时,该函数会在多个位置查找该文件。我们建议在 App Paths 注册表子项中注册您的应用程序。
- 在以下位置查找该文件:
- 当前工作目录。
- 仅 Windows 目录(不搜索子目录)。
- Windows\System32 目录。
- PATH 环境变量中列出的目录。
- 推荐:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\App 路径
这意味着 PowerShell 调用 Windows ShellExecuteEx 函数,该函数将 FireFox 查找为已注册的应用程序,或者它在内部尝试相同类型的搜索。
换一种方式来尝试确认,Start-Process
cmdlet 有一个名为UseShellExecute
. 该帮助的“注释”说:
此 cmdlet 是通过使用 System.Diagnostics.Process 类的 Start 方法实现的。有关此方法的更多信息,请参阅
Process.Start
方法
尝试通过 GitHub 上的源代码进行跟踪:
这是Start-Process
.
在这里,在这一行,它尝试使用 查找$FilePath
参数CommandDiscovery.LookupCommandInfo
。
在这里它检查else if (ParameterSetName.Equals("UseShellExecute"))
然后这是.Start()
启动它的函数ShellExecute
或Process.Start()
好的,不确定 ShellExecute 和 ShellExecuteEx 的行为是否相同,但可能是 PS 调用 Windows,它正在搜索“FireFox”。
进入CommandSearcher.LookupCommandInfo
此处并遵循此处TryNormalSearch()
实现的内容并立即启动具有状态机的状态机用于它将搜索的内容CommandSearcher
我迷路了。我现在不能再继续下去了。
唔。
使用Process Monitor我能够跟踪 PowerShell。它首先搜索$env:path
变量,然后搜索$profile
变量。在我的情况下firefox
没有找到,然后它在注册表中搜索了很多内容并以某种方式找到了它。它可能与系统上安装 Firefox 的方式有关。