在Windows中,我们使用Windows Key + R
访问运行框。然后我们可以按名称运行程序(例如firefox,snippingtool)。有没有办法按名称从PowerShell运行程序?
> run firefox
> run snippingtool
我已经尝试过Start-Process firefox
但它不起作用。
修改
奇怪的是,从PowerShell和Run框中,只需键入notepad
即可打开记事本。但是,键入firefox
或snippingtool
仅适用于“运行”框,而不适用于PowerShell。
答案 0 :(得分:3)
运行框使用PATH
环境变量,但它也使用一组注册表项。
键HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths
包含具有某些应用程序名称的子键,每个子键都有一个名为Path
的字符串值,其中包含可执行文件的路径。 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
}
}
此代码段将读取注册表并将所有这些条目添加为别名。它还添加了没有.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
。
我不确定如果你对其他代码有问题它是否适合你,但它对我来说效果很好,而且我很乐意写它。希望它对您或其他人有所帮助。
固定功能,因此它支持-WhatIf
。
Run-Application notepad
Run-Application firefox,chrome.exe
'notepad.exe','firefox.exe','snippingtool' | Run-Application -Whatif
Run-Application firefox -NoExtension # Should fail
答案 1 :(得分:3)
正如@briantist在他的回答(+1)中提到的那样:" Run"对话框(probably calls the ShellExecuteEx
function)除App Paths
环境变量中的路径外,还检查$env:PATH
注册表项的子项。
用于模拟" Run"的行为。然而,我会将文件夹添加到$env:PATH
,而不是为每个可执行文件创建别名:
$regkey = 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths'
$appPaths = Get-ChildItem $regkey |
Get-ItemProperty |
? { $_.'(default)' } |
select -Expand '(default)' |
Split-Path -Parent |
% { [Environment]::ExpandEnvironmentVariables($_.TrimStart('"')) } |
select -Unique
$env:PATH += ';' + ($appPaths -join ';')
通过将此添加到PowerShell profile(例如您的个人资料%UserProfile%\Documents\WindowsPowerShell\Microsoft.PowerShell_profile.ps1
),您启动的每个PowerShell实例的变量$env:PATH
都会使用注册表中的其他路径进行更新。但请注意,通过添加太多文件夹,您可能会遇到length restrictions。