Skip to content

Commit

Permalink
(GH-366) Enhance package templates
Browse files Browse the repository at this point in the history
- Make the install template more readable
- Enhance the uninstall template to require almost no intervention for
the maintainers.
  • Loading branch information
ferventcoder committed Jul 25, 2015
1 parent 050ce14 commit d45c3ed
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 47 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,10 @@ public class ChocolateyInstallTemplate
$ErrorActionPreference = 'Stop'; # stop on all errors
[[AutomaticPackageNotesInstaller]]
$packageName = '[[PackageName]]' # arbitrary name for the package, used in messages
$toolsDir = ""$(Split-Path -parent $MyInvocation.MyCommand.Definition)""
$url = '[[Url]]' # download url
$url64 = '[[Url64]]' # 64bit URL here or remove - if installer is both, use $url
$packageName= '[[PackageName]]' # arbitrary name for the package, used in messages
$toolsDir = ""$(Split-Path -parent $MyInvocation.MyCommand.Definition)""
$url = '[[Url]]' # download url
$url64 = '[[Url64]]' # 64bit URL here or remove - if installer is both, use $url
$packageArgs = @{
packageName = $packageName
Expand All @@ -40,11 +40,11 @@ public class ChocolateyInstallTemplate
silentArgs = ""/qn /norestart /l*v `""$env:TEMP\chocolatey\$($packageName)\$($packageName).MsiInstall.log`"""" # ALLUSERS=1 DISABLEDESKTOPSHORTCUT=1 ADDDESKTOPICON=0 ADDSTARTMENU=0
validExitCodes= @(0, 3010, 1641)
#OTHERS
#silentArgs ='[[SilentArgs]]' # ""/s /S /q /Q /quiet /silent /SILENT /VERYSILENT -s"" # try any of these to get the silent installer
#silentArgs ='[[SilentArgs]]' # /s /S /q /Q /quiet /silent /SILENT /VERYSILENT -s - try any of these to get the silent installer
#validExitCodes= @(0) #please insert other valid exit codes here
# optional
registryUninstallerKey = '[[PackageName]]' #ensure this is the value in the registry
# optional, highly recommended
softwareName = '[[PackageName]]*' #part or all of the Display Name as you see it in Programs and Features. It should be enough to be unique
checksum = '[[Checksum]]'
checksumType = '[[ChecksumType]]' #default is md5, can also be sha1
checksum64 = '[[Checksum64]]'
Expand All @@ -69,22 +69,31 @@ public class ChocolateyInstallTemplate
#Install-ChocolateyVsixPackage @packageArgs
# see the full list at https://github.com/chocolatey/choco/wiki/HelpersReference
# downloader that the main helpers use to download items
# if removing $url64, please remove from here
#Get-ChocolateyWebFile $packageName 'DOWNLOAD_TO_FILE_FULL_PATH' $url $url64
# installer, will assert administrative rights - used by Install-ChocolateyPackage
# use this for embedding installers in the package when not going to community feed or when you have distribution rights
#Install-ChocolateyInstallPackage $packageName $fileType $silentArgs '_FULLFILEPATH_' -validExitCodes $validExitCodes
# unzips a file to the specified location - auto overwrites existing content
#Get-ChocolateyUnzip ""FULL_LOCATION_TO_ZIP.zip"" $toolsDir
# Runs processes asserting UAC, will assert administrative rights - used by Install-ChocolateyInstallPackage
#Start-ChocolateyProcessAsAdmin 'STATEMENTS_TO_RUN' 'Optional_Application_If_Not_PowerShell' -validExitCodes $validExitCodes
# add specific folders to the path - any executables found in the chocolatey package folder will already be on the path. This is used in addition to that or for cases when a native installer doesn't add things to the path.
#Install-ChocolateyPath 'LOCATION_TO_ADD_TO_PATH' 'User_OR_Machine' # Machine will assert administrative rights
# add specific files as shortcuts to the desktop
#$target = Join-Path $toolsDir ""$($packageName).exe""
# Install-ChocolateyShortcut -shortcutFilePath ""<path>"" -targetPath ""<path>"" [-workDirectory ""C:\"" -arguments ""C:\test.txt"" -iconLocation ""C:\test.ico"" -description ""This is the description""]
# outputs the bitness of the OS (either ""32"" or ""64"")
#$osBitness = Get-ProcessorBits
#Install-ChocolateyEnvironmentVariable -variableName ""SOMEVAR"" -variableValue ""value"" [-variableType = 'Machine' #Defaults to 'User']
#Install-ChocolateyFileAssociation
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,59 +20,60 @@ public class ChocolateyUninstallTemplate
public static string Template =
@"#NOTE: Please remove any commented lines to tidy up prior to releasing the package, including this one
# REMOVE ANYTHING BELOW THAT IS NOT NEEDED

This comment has been minimized.

Copy link
@dtgm

dtgm Jul 26, 2015

Contributor

Make it easier to quickly remove all comments:

@"
# IMPORTANT: Before releasing this package, copy/paste the next 2 lines into PowerShell to remove all comments from this file:
#   $f='c:\path\to\thisFile.ps1'
#   gc $f | ? {$_ -notmatch "^\s*#"} | % {$_ -replace '(^.*?)\s*?[^``]#.*','$1'} | Out-File $f+".~" -en utf8; mv -fo $f+".~" $f

Also should be able to remove # REMOVE ANYTHING BELOW THAT IS NOT NEEDED because all commented lines are removed.

This comment has been minimized.

Copy link
@ferventcoder

ferventcoder Jul 27, 2015

Author Member

Neat, do you want to file a new issue with this?

This comment has been minimized.

Copy link
@ferventcoder

ferventcoder Jul 27, 2015

Author Member

nevermind, we'll just add it to #366

# If this is an MSI, cleaning up comments is all you need.
# If this is an exe, change installerType and silentArgs
# Auto Uninstaller should be able to detect and handle registry uninstalls (if it is turned on, it is in preview for 0.9.9).
$ErrorActionPreference = 'Stop'; # stop on all errors
$packageName = '[[PackageName]]'
# registry uninstaller key name is the key that is found at HKLM:\Software\Windows\CurrentVersion\Uninstall\ THE NAME
$registryUninstallerKeyName = '[[PackageName]]' #ensure this is the value in the registry
$msiProductCodeGuid = '{insert it here}'
$shouldUninstall = $true
$local_key = ""HKCU:\Software\Microsoft\Windows\CurrentVersion\Uninstall\$registryUninstallerKeyName""
# local key 6432 probably never exists
$local_key6432 = ""HKCU:\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\$registryUninstallerKeyName""
$machine_key = ""HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$registryUninstallerKeyName""
$machine_key6432 = ""HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\$registryUninstallerKeyName""
$file = @($local_key, $local_key6432, $machine_key, $machine_key6432) `
| ?{ Test-Path $_ } `
| Get-ItemProperty `
| Select-Object -ExpandProperty UninstallString
$softwareName = '[[PackageName]]*' #part or all of the Display Name as you see it in Programs and Features. It should be enough to be unique
$installerType = 'MSI'
#$installerType = 'EXE'
if ($file -eq $null -or $file -eq '') {
Write-Host ""$packageName has already been uninstalled by other means.""
$shouldUninstall = $false
$silentArgs = '/qn /norestart'
# https://msdn.microsoft.com/en-us/library/aa376931(v=vs.85).aspx
$validExitCodes = @(0, 3010, 1605, 1614, 1641)
if ($installerType -ne 'MSI') {
# The below is somewhat naive and built for EXE installers
$silentArgs = '/S' # /s /S /q /Q /quiet /silent /SILENT /VERYSILENT -s - try any of these to get the silent installer

This comment has been minimized.

Copy link
@dtgm

dtgm Jul 26, 2015

Contributor

List various EXE installers?

if ($installerType -ne 'MSI') {
  # Uncomment matching EXE type (sorted by most to least common)
  #$silentArgs = '/S'               # NSIS
  #$silentArgs = '/VERYSILENT /SUPPRESSMSGBOXES /NORESTART /SP-' # Inno Setup
  #$silentArgs = '/s'               # InstallShield
  #$silentArgs = '/s /v"/qn"'       # InstallShield with MSI
  #$silentArgs = '/s /f1"$issPath"' # InstallShield, requires uninstall.iss file
  #$silentArgs = '/s /a /s /sms /f1"$issPath"' # InstallShield's PackagefortheWeb (PFTW), requires uninstall.iss file
  #$issPath = $true # if using $issPath in silentArgs
  #$silentArgs = '/s'               # Wise InstallMaster
  #$silentArgs = '-q'               # Install4j
  #$silentArgs = '-s -u'            # Ghost
  # Note that some installers, in addition to the silentArgs above, may also need assistance of AHK to achieve silence.
  #$silentArgs = ''                 # none; make silent with input macro script like AutoHotKey (AHK)
                                    #       https://chocolatey.org/packages/autohotkey.portable
  $validExitCodes = @(0)
}

if ($issPath) {
  $toolsDir   = ""$(Split-Path -parent $MyInvocation.MyCommand.Definition)""
  $issFileName = "uninstall.iss"
  $issPath = Join-Path $toolsDir $issFileName
}

This comment has been minimized.

Copy link
@ferventcoder

ferventcoder Jul 27, 2015

Author Member

Might be too much...

This comment has been minimized.

Copy link
@ferventcoder

ferventcoder Jul 27, 2015

Author Member

Might not be.

$validExitCodes = @(0)
}
# The below is somewhat naive and built for EXE installers
#$installerType = 'EXE'
#$silentArgs = '/S'
#$validExitCodes = @(0)
$uninstalled = $false
#if (!(Test-Path $file)) {
# Write-Host ""$packageName has already been uninstalled by other means.""
# $shouldUninstall = $false
#}
Get-ItemProperty -Path @($machine_key6432,$machine_key, $local_key) `
-ErrorAction SilentlyContinue `
| ? { $_.DisplayName -like ""$softwareName"" } `
| Select -First 1 `

This comment has been minimized.

Copy link
@dtgm

dtgm Jul 26, 2015

Contributor

I think maybe this should be handled differently; if you have more than 1 object to select from, that's probably not a good sign....maybe:

$key = Get-ItemProperty -Path @($machine_key6432,$machine_key, $local_key) `
                        -ErrorAction SilentlyContinue `
         | ? { $_.DisplayName -like ""$softwareName"" }

if ($key.Count -eq 1) {
  $key | % { 
    $file = ""$($_.UninstallString)""

    if ($installerType -eq 'MSI') {
      # The Product Code GUID is all that should be passed for MSI, and very 
      # FIRST, because it comes directly after /x, which is already set in the 
      # Uninstall-ChocolateyPackage msiargs (facepalm).
      $silentArgs = ""$($_.PSChildName) $silentArgs""

      # Don't pass anything for file, it is ignored for msi (facepalm number 2) 
      # Alternatively if you need to pass a path to an msi, determine that and 
      # use it instead of the above in silentArgs, still very first
      $file = ''
    }
    Uninstall-ChocolateyPackage -PackageName $packageName `
                                -FileType $installerType `
                                -SilentArgs ""$silentArgs"" `
                                -ValidExitCodes $validExitCodes `
                                -File ""$file""
  }
} elseif ($key.Count -eq 0) {
  Write-Warning ""$packageName has already been uninstalled by other means.""
} elseif ($key.Count -gt 1) {
  Write-Warning ""$key.Count matches found!""
  Write-Warning ""To prevent accidental data loss, no programs will be uninstalled.""
  Write-Warning ""Please alert package maintainer the following keys were matched:""
  $key | % {Write-Warning ""$_.DisplayName""}
}

This comment has been minimized.

Copy link
@ferventcoder

ferventcoder Jul 27, 2015

Author Member

It may mean that you have multiple things with similar names and your Display Name search is not specific enough. I agree that throwing an error instead (warnings are still treated as successful uninstall) would likely be more beneficial.

| % {

This comment has been minimized.

Copy link
@dtgm

dtgm Jul 26, 2015

Contributor

Expand aliases for transparency of code to users unfamiliar with posh?

%ForEach-Object
SelectSelect-Object
?Where-Object

This comment has been minimized.

Copy link
@ferventcoder

ferventcoder Jul 27, 2015

Author Member

Those are generally accepted shortcuts for POSH. Thoughts?

This comment has been minimized.

Copy link
@ferventcoder

ferventcoder Jul 27, 2015

Author Member

Unfamiliar but it's in the template in a section you don't need to touch.

$file = ""$($_.UninstallString)""
if ($installerType -eq 'MSI') {
# The Product Code GUID is all that should be passed for MSI, and very
# FIRST, because it comes directly after /x, which is already set in the
# Uninstall-ChocolateyPackage msiargs (facepalm).
$silentArgs = ""$($_.PSChildName) $silentArgs""
# Don't pass anything for file, it is ignored for msi (facepalm number 2)
# Alternatively if you need to pass a path to an msi, determine that and
# use it instead of the above in silentArgs, still very first
$file = ''
}
# The below is somewhat naive and built for MSI installers
$installerType = 'MSI'
# The Product Code GUID is all that should be passed for MSI, and very FIRST,
# because it comes directly after /x, which is already set in the
# Uninstall-ChocolateyPackage msiargs (facepalm).
$silentArgs = ""$msiProductCodeGuid /qn /norestart""
# https://msdn.microsoft.com/en-us/library/aa376931(v=vs.85).aspx
$validExitCodes = @(0, 3010, 1605, 1614, 1641)
# Don't pass anything for file, it is ignored for msi (facepalm number 2)
# Alternatively if you need to pass a path to an msi, determine that and use
# it instead of $msiProductCodeGuid in silentArgs, still very first
$file = ''
Uninstall-ChocolateyPackage -PackageName $packageName `
-FileType $installerType `
-SilentArgs ""$silentArgs"" `
-ValidExitCodes $validExitCodes `
-File ""$file""
$uninstalled = $true
}
if ($shouldUninstall) {
Uninstall-ChocolateyPackage -PackageName $packageName -FileType $installerType -SilentArgs $silentArgs -validExitCodes $validExitCodes -File $file
if (!($uninstalled)) {
Write-Warning ""$packageName has already been uninstalled by other means.""
}
## OTHER HELPERS
## https://github.com/chocolatey/choco/wiki/HelpersReference
#Uninstall-ChocolateyZipPackage
Expand Down

0 comments on commit d45c3ed

Please sign in to comment.