【问题标题】:Executing a file that may reside at two different locations using PowerShell使用 PowerShell 执行可能位于两个不同位置的文件
【发布时间】:2020-01-15 20:33:43
【问题描述】:

我的 $PROFILE 中有一个可爱的小脚本,帮助我从显示我选择的文件的脚本启动 Notepad++。

function Edit{
  param([string]$file = " ")
  Start-Process "C:\Program Files\Notepad++\notepad++.exe" -ArgumentList $file
}

直到最近,我在不同的系统之间跳转时效果很好。我发现 NPP 在某些系统上安装在 C:\Program Files 中,但在其他系统上安装在 C:\Program Files (x86) 中。我可以编辑适应它的脚本,但这样做了无数次(即 5 次),我厌倦了它,意识到我必须自动化这种疯狂。

对脚本知之甚少,我想知道我应该用谷歌搜索什么。最佳实践是在这种情况下使用exception handling,还是更适合使用conditional expressions

根据 Get-Host |选择对象版本 我正在运行 5.1 版,如果它有任何意义的话。也许有一种我不知道的更简洁的方法?依赖环境变量?我也不想使用在旧版本的 PS 中有效的方法,虽然可以工作,如果在以后的方法中有更方便的方法。 (根据我在这方面的经验,我无法区分鸭子和鹅。)

【问题讨论】:

    标签: powershell windows-10 powershell-5.0


    【解决方案1】:

    我会为此使用条件。 一种选择是直接测试路径,如果您确定它位于特定位置。

    硬编码路径:

    function Edit{
      param([string]$file = " ")
    
    $32bit = "C:\Program Files (x86)\Notepad++\notepad++.exe"
    $64bit = "C:\Program Files\Notepad++\notepad++.exe"
    
    if (Test-Path $32bit) {Start-Process -FilePath $32bit -ArgumentList $file}
    elseif (Test-Path $64bit) {Start-Process -FilePath $64bit -ArgumentList $file}
    else {Write-Error -Exception "NotePad++ not found."}
    }
    

    另一个选项是从注册表项中提取路径信息,如果它们可用的话:

    function Edit{
      param([string]$file = " ")
    
    $32bit = (Get-ItemProperty -Path 'HKLM:\SOFTWARE\Notepad++\' -ErrorAction SilentlyContinue).("(default)")
    $64bit = (Get-ItemProperty -Path 'HKLM:\SOFTWARE\WOW6432Node\Notepad++\' -ErrorAction SilentlyContinue).("(default)")
    
    if ($32bit) {Start-Process -FilePath "$32bit\notepad++.exe" -ArgumentList $file}
    elseif ($64bit) {Start-Process -FilePath "$64bit\notepad++.exe" -ArgumentList $file}
    else {Write-Error -Exception "NotePad++ not found."}
    }
    

    【讨论】:

      【解决方案2】:

      基于@BoogaRoo 的大力帮助(谁应该得到一些 +1 的努力),并要求发布我自己的答案版本,我反对我因为强烈的感觉而不愿意发布自己的问题的答案粘性。

      我的最终版本,考虑到缺少 NP++ 但仍希望显示一些类型的编辑器的系统。

      function Edit{
        param([string]$file = " ")
      
        $executable = "Notepad++\notepad++.exe"
        $32bit = "C:\Program Files (x86)\" + $executable
        $64bit = "C:\Program Files\" + $executable
        $target = "notepad"
      
        if(Test-Path $32bit) { $target = $32bit }
        if(Test-Path $64bit) { $target = $64bit }
      
        Start-Process $target -ArgumentList $file
      }
      

      【讨论】:

        【解决方案3】:

        让我提供一个还支持传递多个文件的简化版本:

        function Edit {
        
          param(
           # Allow passing multiple files, both with explicit array syntax (`,`-separated)
           # or as indiv. arguments.
           [Parameter(ValueFromRemainingArguments)]
           [string[]] $File
          )
        
          # Construct the potential Notepad++ paths.
          # Note: `-replace '$'` is a trick to append a string to each element
          #       of an array.
          $exePaths = $env:ProgramFiles, ${env:ProgramFiles(x86)} -replace '$', '\Notepad++\notepad++.exe'
        
          # See which one, if any, exists, using Get-Command.
          $exeToUse = Get-Command -ErrorAction Ignore $exePaths | Select-Object -First 1
        
          # Fall back to Notepad.
          if (-not $exeToUse) { $exeToUse = 'notepad.exe' }
        
          # Invoke whatever editor was found with the optional file(s).
          # Note that both Notepad++ and NotePad can be invoked directly
          # without blocking subsequent commands, so there is no need for `Start-Process`,
          # whose argument processing is buggy.
          & $exeToUse $File
        
        }
        
        • 一个潜在可执行路径的数组被传递给Get-Command,它为找到的每个实际可执行文件(如果有)返回一个命令信息对象。

          • -ErrorAction Ignore 悄悄地忽略任何错误。

          • Select-Object -First 1Get-Command 输出中提取first 命令信息对象(如果存在);这对于防止(可能不太可能)可执行文件存在于两个位置的情况是必要的。

        • $exeToUse 接收$null(有效)如果Get-Command 不产生输出,在这种情况下布尔表达式-not $exeToUse 计算为$true,导致回退到notepad.exe 生效。

        • 命令 names(字符串)和 command-info 对象System.Management.Automation.CommandInfo 或派生类的实例,由 Get-Command 返回)都可以通过&call operator 执行。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2021-09-08
          • 1970-01-01
          • 2011-12-09
          • 2015-09-10
          • 1970-01-01
          • 2016-06-13
          • 1970-01-01
          相关资源
          最近更新 更多