Automating Chocolatey with Intune

A

Intune allows to automatically have software installed on target devices. I found a nice write-up on using this in conjunction with Chocolatey, but realized it could be made much easier. First we’ll prepare the files locally which needs to be done only once, instead of for each application.

There are three things i am trying to accomplish. First one is to deploy a Chocolatey application from intunet, the second is to auto update the appications and the third is to use an Intune application detection script that uses Chocolatey.

Install chocolatey

You will need the following Microsoft tool:

GitHub – microsoft/Microsoft-Win32-Content-Prep-Tool: A tool to wrap Win32 App and then it can be uploaded to Intune

Frist we need to create a powershell script that will install Chocolatey. Save the code below to an install.ps1 file.

Set-ExecutionPolicy Bypass -Scope Process -Force; [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1'))

Now let’s create a .intunewin file for our Chocolatey install. In the directory run the following in Powershell:

.\IntuneWinAppUtil.exe -c .\ -s install.ps1 -o .\

This creates an .intunewin file which we can re-use in Intune for each application we wish to install using Chocolatey.

Create a new Windows app (Win32) in intune and select the .intunewin we just created and use the following commands. Now i didn’t make an uninstall.ps1 for Choco because i didn’t see the need to uninstall Choco but you can make one if you want and add it to the .intunewin

Install command
powershell.exe -executionpolicy bypass .\install.ps1

Uninstall command
powershell.exe -executionpolicy bypass .\uninstall.ps1

Install behavior
System

Device restart behavior
App install may force a device restart

Return codes
0 Success
1707 Success
3010 Soft reboot
1641 Hard reboot
1618 Retry

For the detection rule of Chocolatey .

Path
C:\ProgramData\

File or folder
chocolatey

Detection Method
File or folder exist

64bit
Yes

Add a choco application

Save the script below as install.ps1 in an empty directory, and download IntuneWinAppUtil.exe into that directory as well.

param(
    [string]$package = "",
    [switch]$uninstall = $false
)

if ($uninstall) {
    choco uninstall $package -y
} else {
    choco upgrade $package -y
}

upgrade will install the package if it isn’t yet installed. Two fish

You can use this script directly by running ./install.ps1 <package name> [-uninstall]. We’ll use Intune to automate installation of packages.

Now let’s create a generic .intunewin file for all our Chocolatey apps. In the directory run the following in Powershell:

.\IntuneWinAppUtil.exe -c .\ -s install.ps1 -o .\

This creates an .intunewin file which we can re-use in Intune for each application we wish to install using Chocolatey.

Create an intune app

When creating an Intune app, set it as a Windows app (Win32) and during the wizard set the install command to

powershell.exe -executionpolicy bypass .\install.ps1 <package name>

And the uninstall command to

powershell.exe -executionpolicy bypass .\install.ps1 <package name> -uninstall

Detection

We can also use Chocolatey to detect our package. For this we check using choco if the app exists locally. For that, create the following script:

choco feature enable --name="'useEnhancedExitCodes'" -y
$PackageName = "PACKAGENAME"
choco list -e $PackageName --local-only
exit $LastExitCode

Be sure to replace PACKAGENAME with the name of the package, as used by Chocolatey.

Set the detection rules format to Use a custom detection script, and upload the just created script. Make sure Enforce script signature check and run script silently is set to No.

The above script does some fancy things:

  • It enables the useEnhancedExitCodes feature, which ensures the exit code is 2 when the package doesn’t exist. Else it will return 0 because it had no issues checking that the package didn’t exist. This setting just needs to be set once, but we place it here to always be sure it is enabled.
  • --local-only ensures it uses the local index of apps, else it will always return true because the package exists in the Chocolatey repository.
  • Explicitly exit using the chocolatey given exit code, as powershell may not properly pass this to InTune.

AutoUpdate

So the easiest way to update all your choco apps would be to deploy a scheduled task from a powershell script with intune that will run a choco upgrade all command in powershell. I’ve came up with the following solution that works for our situatiion.

What i did is to add a New-ScheduledTaskAction with an Execute ‘Powershell.exe’ -Argument ‘-NoProfile -WindowStyle Hidden so that there is no visual output when running. The command is a simple – “choco upgrade all. Its nice to ouput a log from this action so that the servicedesk can check a logging if there where any problems with a new application. So i gave a Out-File -FilePath C:\Windows\Logs\choco-update-log.txt”‘ .

I’ve set the trigger of running this script at login ($trigger = New-ScheduledTaskTrigger -AtLogOn) because we are mainly targtting laptops so a night timed schedule isnt possible and i dont want users to get a update during daytime. But you can change this variable to whatever suits your situation.

I let the task run under the Local Service Account System $STPrin = New-ScheduledTaskPrincipal -UserId “SYSTEM” -LogonType ServiceAccount

Finaly i’ve added al the variables in one line to register the task. You can change the -Taskname and – Description. to whatever suits you. Also this tasks only runs when logging in and the machine is connected to a powersupply.

$action = New-ScheduledTaskAction -Execute 'Powershell.exe' -Argument '-NoProfile -WindowStyle Hidden -command "choco upgrade all | Out-File -FilePath C:\Windows\Logs\choco-update-log.txt"'

# Set the trigger to be at any user logon
$trigger =  New-ScheduledTaskTrigger -AtLogOn

# Specifies that Task Scheduler uses the Local Service account to run tasks, and that the Local Service account uses the Service Account logon. The command assigns the **ScheduledTaskPrincipal** object to the $STPrin variable.
$STPrin = New-ScheduledTaskPrincipal -UserId "SYSTEM" -LogonType ServiceAccount

# Create the scheduled task
Register-ScheduledTask -Action $action -Trigger $trigger -TaskName "Update Choco all @ Login" -Description "Dit voert een choco update all commando uit in powershell tijdens inloggen van de user onder het system account." -Principal $STPrin

Save your script to a powershell file and upload it to Intune under Devices – Scripts. Use the following script settings.

Dependencies

Finally, make sure to set Chocolatey as a dependency for all your choco applications.

About the author

10 Comments

  • Thank you for the tutorial on this. However when I run one of these in intune, it fails with the following error, “The application was not detected after installation completed successfully (0x87D1041C)”.

    Any ideas.

    • Please correct me if I am wrong here. I will delete this comment.

      Its looks the author forgot to mention “command” in the CREATE THE INTUNE APP section

      Installation Command should be:

      powershell.exe -executionpolicy bypass command .\install.ps1

      while it shows in the steps

      powershell.exe -executionpolicy bypass .\install.ps1

      Same applies for Uninstallation command

  • Hello thankyou for this article!

    I’m having difficulty getting applications to install.

    From the company portal it says downloading and installing how it then says that it has failed. The only thing I believe I’ve changed from your article is the name of the file from install.ps1 to InstallApp.ps1

    powershell.exe -executionpolicy bypass .\InstallApp.ps1 Firefox
    powershell.exe -executionpolicy bypass .\InstallApp.ps1 Firefox – uninstall

    Any ideas on where I’m going wrong?

    • Thats strange.

      What if you run the detection script local on the computer, dus i give a valid output ?

  • Great guide, thanks for sharing!

    Just a quick note that some applications have dependencies when installed with Chocolatey. As a result, they will display as two separate packages. For example:
    7zip 21.7
    7zip.install 21.7

    To successfully and completely uninstall these, the chocolatey command should be:
    choco uninstall $package -y –removedependencies

  • Hi, thanks for this blog.
    I seem to notice a problem.
    In the log I get the notification that it checks the versions, it downloads the new packages but the software version on the computer is still the older one.
    It seems like everything is being downloaded but not installed.

    I get the following:
    first progress…% till 100

    and then

    the package x wants to run chocolateyinstall.ps1
    Note: if you don’t run this script; the installation will fail
    note: to confirm automatically next time, use ‘-y’ or consider:
    choco feature enable -n allowGlobalConfirmation

    I have no knowledge of this…do I need to add anything to the script our users don’t have admin rights.

    • Hi,

      I would advice move to the new winget deployment method. This is already partly supported in intune as the new app deployment method.

      You can find a lot of guides how to implement winget.

By Semi

Semi

Get in touch

Quickly communicate covalent niche markets for maintainable sources. Collaboratively harness resource sucking experiences whereas cost effective meta-services.