3

I am building a self-contained Chocolatey package. The package folder contains: app.nuspec, app.exe, app.nupkg, and the tools subfolder. The chocolateyInstall.ps1 is like this:

$packageName = 'app'
$fileType = 'exe'
$silentArgs = '/VERYSILENT'
$url = '../app.exe' # the location of the file relative to the tools folder

Install-ChocolateyPackage $packageName $fileType $silentArgs $url

When I run:

choco install app -y

I get:

Copy-Item : cannot find the path C:\ProgramData\app.exe because does not exist

How can I make this work? I've read a bit about 'create self-contained package with shims' but I don't really get how to use that? Any help? thank you

EDIT 1

I have found also this other solution here (http://patrickhuber.github.io/2015/03/19/creating-enterprise-versions-of-public-chocolatey-packages.html) that does work. So in my case that would be:

$directory = $PSScriptRoot
$packageName = 'app'
$fileType = 'exe'
$silentArgs = '/VERYSILENT'
$url = Join-Path $directory '..\app.exe'     


Install-ChocolateyPackage $packageName $fileType $silentArgs $url 

I was wondering what is the $PSScriptRoot variable?

Anthony Mastrean
  • 21,850
  • 21
  • 110
  • 188
diegus
  • 1,168
  • 2
  • 26
  • 57
  • It doesn't work with relative paths. Take a look at Gary's answer below. Also keep in mind that `choco new pkgname` generates all that you need for getting this right. – ferventcoder Mar 23 '16 at 04:07
  • 1
    `$PSScriptRoot` is the same as `$(Split-Path $MyInvocation.MyCommand.Path)` but an automatic variable that is available in PowerShell v3+. We recommend you use the older method - if only only have machines that are 3+ (aka Windows 8/Windows 2012 and up or have upgrade WMF on all of your other machines), then you are fine to use `$PSScriptRoot` without issue. – ferventcoder Mar 23 '16 at 14:54

2 Answers2

3

For doing a Chocolatey Package that contains the exe/msi, you can use the Install-ChocolateyInstallPackage helper method, rather than the Install-ChocolateyPackage helper method. This is documented on the Chocolatey Wiki here

This works in very much the same way as the other helper method, with the exception that it doesn't want/need to download the exe/msi. It uses the path that it is provided, and installs from there.

You can find a complete example of what is required in the ChocolateyGUI package, which does a very similar thing.

The crux of it is shown below for reference:

$packageName = 'ChocolateyGUI'
$fileType = 'msi'
$silentArgs = '/quiet'
$scriptPath =  $(Split-Path $MyInvocation.MyCommand.Path)
$fileFullPath = Join-Path $scriptPath 'ChocolateyGUI.msi'

Install-ChocolateyInstallPackage $packageName $fileType $silentArgs $fileFullPath
Gary Ewan Park
  • 17,610
  • 5
  • 42
  • 60
2

Somehow we're still missing the explanation of script- and caller-relative paths. In this case, Chocolatey is executing from

%PROGRAMDATA%\Chocolatey\choco.exe

Your script is telling it to go up one level and look for app.exe, that's

%PROGRAMDATA%\app.exe

What Gary's answer implies, by using $MyInvocation is that you need to construct this path relative to the script's location, not the caller's location. You found another method of doing that by joining the path with $PSScriptRoot.

Both of these variables are known as "Automatic variables".

$MyInvocation

Contains an information about the current command, such as the name, parameters, parameter values, and information about how the command was started, called, or "invoked," such as the name of the script that called the current command.

$MyInvocation is populated only for scripts, function, and script blocks. You can use the information in the System.Management.Automation.InvocationInfo object that $MyInvocation returns in the current script, such as the path and file name of the script ($MyInvocation.MyCommand.Path) or the name of a function ($MyInvocation.MyCommand.Name) to identify the current command. This is particularly useful for finding the name of the current script.

And

$PSScriptRoot

Contains the directory from which a script is being run.

In Windows PowerShell 2.0, this variable is valid only in script modules (.psm1). Beginning in Windows PowerShell 3.0, it is valid in all scripts.

Anthony Mastrean
  • 21,850
  • 21
  • 110
  • 188