Installed script is not found as executable

Viewed 450

There is a script named Get-Stuff.ps1 that is headed it with a PSScriptInfo block. The script is published to a NuGet repository. It is then installed to the expected location, C:\Users\lit\Documents\WindowsPowerShell\Scripts\Get-Stuff.ps1. Get-InstalledScript reports that it is installed. However, it is not found to be an executable. The C:\Users\lit\Documents\WindowsPowerShell\Scripts\ directory is not in $Env:PSModulePath.

What step did I miss to make this command executable after installation?

PS C:\> (Get-ChildItem -Recurse -File -Path 'C:\' -Filter 'Get-Stuff*' -ErrorAction SilentlyContinue).FullName
C:\src\Modules\scripts\Get-Stuff.ps1
PS C:\> Test-ScriptFileInfo -Path 'C:\src\Modules\scripts\Get-Stuff.ps1'

Version              Name                      Author               Description
-------              ----                      ------               -----------
1.0.0.1              Get-Stuff                 lit                  Get-Stuff produces .csv files of record counts from tables.


PS C:\> Publish-Script -Path 'C:\src\Modules\scripts\Get-Stuff.ps1' -NuGetApiKey 'yanon' -Repository 'yrepo'
PS C:\> Find-Script -Name Get-Stuff

Version              Name                                Repository           Description
-------              ----                                ----------           -----------
1.0.0.1              Get-Stuff                           yrepo                Get-Stuff produces .csv files of record counts from tables.


PS C:\> Find-Script -Name Get-Stuff | Install-Script
PS C:\> (Get-ChildItem -Recurse -File -Path 'C:\' -Filter 'Get-Stuff*' -ErrorAction SilentlyContinue).FullName
C:\src\Modules\scripts\Get-Stuff.ps1
C:\Users\lit\Documents\WindowsPowerShell\Scripts\Get-Stuff.ps1
C:\Users\lit\Documents\WindowsPowerShell\Scripts\InstalledScriptInfos\Get-Stuff_InstalledScriptInfo.xml
PS C:\> Get-InstalledScript -Name Get-Stuff

Version              Name                                Repository           Description
-------              ----                                ----------           -----------
1.0.0.1              Get-Stuff                           yrepo                Get-Stuff produces .csv files of record counts from tables.


PS C:\> Get-Command Get-Stuff
Get-Command : The term 'Get-Stuff' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of
the name, or if a path was included, verify that the path is correct and try again.
At line:1 char:1
+ Get-Command Get-Stuff
+ ~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : ObjectNotFound: (Get-Stuff:String) [Get-Command], CommandNotFoundException
    + FullyQualifiedErrorId : CommandNotFoundException,Microsoft.PowerShell.Commands.GetCommandCommand

PS C:\> $PSVersionTable.PSVersion.ToString()
5.1.17763.1490
1 Answers

It is $env:PATH that matters with respect to by-file-name-only invocations of *.ps1 files (script files), not $env:PSModulePath, which only applies to modules.

Unfortunately, earlier versions of the PowerShellGet module did not offer to add the directories targeted by the Install-Script cmdlet to $env:PATH persistently, but as of at least v2.2.4 they do (a prompt is presented), the next time you call Install-Script to perform an actual installation.

Try updating your PowerShellGet version with either Update-Module PowerShellGet or, if that fails, Install-Module -Force PowerShellGet (which in Windows PowerShell requires elevation, unless you specify -Scope CurrentUser).


If you want to make these $env:PATH additions yourself, run the following code:

Note:

  • Modifying $env:PATH persistently, via the registry, is only supported on Windows (on Unix, mechanisms for defining persistent environment variables differ across platforms).

  • However, on Unix too the in-session $env:PATH variable is updated.

& {
  
  Write-Verbose -vb "Adding Install-Script install directories to `$env:PATH..."
  
  $isWin = $env:OS -eq 'Windows_NT'
  $isAdmin = if ($isWin) { [bool] (net session 2>$null) } else { 0 -eq (id -u) }

  $ErrorActionPreference = 'Stop'

  # Determine the locations: current-user, all-user.
  $scriptDirs = (Join-Path (Split-Path ($PROFILE, "$HOME/.local/share/powershell/Modules")[$env:OS -ne 'Windows_NT']) Scripts),
                (Join-Path (Split-Path ("$env:ProgramFiles\$(if ($PSVersionTable.PSEdition -ne 'Core') { 'Windows' })PowerShell\Modules", '/usr/local/share/powershell/Modules')[$env:OS -ne 'Windows_NT']) Scripts)

  if (-not $isWin) {
    # Note: There's no unified mechanism across macOS and Linux.
    Write-Warning "On Unix, this script only supports modifying the *current session*'s `$env:PATH variable."
  } elseif (-not $isAdmin) {
    Write-Warning "Since this session isn't elevated, only the *current-user* location will be added *persistently*."
  }

  $pathVarSep = [IO.Path]::PathSeparator

  $i = 0
  foreach ($dir in $scriptDirs) {
    # Always update the in-session variable.
    Write-Verbose -vb "-- Adding $dir..."
    if ($env:PATH -split $pathVarSep -notcontains $dir) { 
      $env:PATH = ($env:PATH -replace "$pathVarSep`$") + $pathVarSep + $dir 
    } 
    else { 
      Write-Verbose -vb "Already present in-session: $dir" 
    }
    # On Windows, also try to update the *persistent* definitions
    if ($isWin) {
      $scope = ('User', 'Machine')[$i++ -eq 1]
      if ($scope -eq 'Machine' -and -not $isAdmin) { break } # skip due to lack of permissions
      # Note: We query the registry directly, so as to preserve unexpanded REG_EXPAND_SZ values.
      $currVal = Get-ItemPropertyValue ('registry::HKEY_CURRENT_USER\Environment', 'registry::HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment')[$scope -eq 'Machine'] Path
      if ($currVal -split $pathVarSep -notcontains $dir) { 
        [Environment]::SetEnvironmentVariable('Path', (($currVal -replace "$pathVarSep`$") + $pathVarSep + $dir), $scope)
      } else {
        Write-Verbose -vb "Already present persistently in the $scope scope: $dir"
      }
    }
  }

  Write-Verbose -vb 'Done.'

}
Related