运行框使用PATH 环境变量,但它也使用一组注册表项。
HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths 键包含具有特定应用程序名称的子键,每个子键都有一个名为 Path 的字符串值,其中包含可执行文件的路径。 Powershell 和命令提示符不使用这些。
在 Powershell 中模拟这个
$allCommands = Get-Command -CommandType All | Select-Object -ExpandProperty Name
Get-ChildItem 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths' | Where-Object { $_.Property -icontains 'Path' } | ForEach-Object {
$executable = $_.Name | Split-Path -Leaf
$shortName = $executable -creplace '\.[^.]*$',''
$path = $_ | Get-ItemProperty | Select-Object -ExpandProperty Path
$fqPath = $path | Join-Path -ChildPath $executable
if ( ($allCommands -icontains $executable) -or ($allCommands -icontains $shortName) ) {
Write-Verbose "Skipping $executable and $shortName because a command already exists with that name."
} else {
Write-Verbose "Creating aliases for $executable."
New-Alias -Name $executable -Value $fqPath
New-Alias -Name $shortName -Value $fqPath
}
}
这个 sn-p 将读取注册表并将所有这些条目添加为别名。它还添加了不带 .exe 的 EXE 名称,以便您可以使用短名称。
它预先检查现有命令以确保它不会破坏任何现有命令(任何类型)。
编辑
我还创建了一个函数,您可以使用它来执行任意应用程序,而无需修改整个环境:
function Run-Application {
[CmdletBinding(SupportsShouldProcess=$true)]
param(
[Parameter(
Mandatory=$true,
ValueFromPipeline=$true
)]
[ValidateNotNullOrEmpty()]
[String[]]
$Name ,
[Parameter()]
[Switch]
$NoExtension
)
Begin {
if (!$NoExtension -and $env:PATHEXT) {
$exts = $env:PATHEXT -csplit ';'
} else {
$exts = @()
}
$regStub = 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths'
}
Process {
:outer
foreach($app in $Name) {
$cmd2run = $app
if (Get-Command -Name $cmd2run -ErrorAction Ignore) {
if ($PSCmdlet.ShouldProcess($cmd2run)) {
& $cmd2run
}
continue :outer
} elseif ($app -cnotlike '*.*') {
foreach($ext in $exts) {
$cmd2run = "$app$ext"
if (Get-Command -Name $cmd2run -ErrorAction Ignore) {
if ($PSCmdlet.ShouldProcess($cmd2run)) {
& $cmd2run
}
continue :outer
}
}
}
$thisReg = $regStub | Join-Path -ChildPath $cmd2run
$regItem = $thisReg | Get-Item -ErrorAction Ignore
if ($regItem -and $regItem.Property -icontains 'Path') {
$thisPath = $regItem | Get-ItemProperty | Select-Object -ExpandProperty Path | Join-Path -ChildPath $cmd2run
if ($PSCmdlet.ShouldProcess($thisPath)) {
& $thisPath
}
continue :outer
} elseif ($app -cnotlike '*.*') {
foreach($ext in $exts) {
$cmd2run = "$app$ext"
$thisReg = $regStub | Join-Path -ChildPath $cmd2run
$regItem = $thisReg | Get-Item -ErrorAction Ignore
if ($regItem -and $regItem.Property -icontains 'Path') {
$thisPath = $regItem | Get-ItemProperty | Select-Object -ExpandProperty Path | Join-Path -ChildPath $cmd2run
if ($PSCmdlet.ShouldProcess($thisPath)) {
& $thisPath
}
continue :outer
}
}
}
}
}
}
您可以通过参数或管道提供一个或多个名称,带或不带扩展名。
如果该值没有扩展名,它将使用PATHEXT 并尝试所有组合。您也可以使用 -NoExtension 禁用它。
我使用Run-Application 表示动词-名词语法,但如果您愿意,您始终可以将其别名为run。
如果您在使用其他代码时遇到问题,我不确定它是否适合您,但它对我来说效果很好,而且我写得很开心。希望对您或其他人有所帮助。
编辑 2
固定功能,支持-WhatIf。
示例
Run-Application notepad
Run-Application firefox,chrome.exe
'notepad.exe','firefox.exe','snippingtool' | Run-Application -Whatif
Run-Application firefox -NoExtension # Should fail