Intune + Chocolatey: A Match Made in Heaven
Table of Contents
Recently, I have been doing a lot of Microsoft Intune deployments and write up’s. One of the most time-consuming tasks with Intune is the application portion, where you package applications up to deploy to your end-user machines. Currently, if the application is bundled as an executable (exe), the steps to get it into Intune is as follows:
- Grab the installation executable
- Find the install switches – most common one is the silent switch, but some applications may have other switches you will need as well
- Find the install directory or registry key to tell Intune if it installed correctly or not
- Find the uninstall executable and any switches it has as well
- Wrap the executable in an ‘INTUNEWIN’ format
- Import file into Intune
- Configure the application with the install and uninstall switches as well as the directory it creates to Intune knows if it installed correctly or not
This process may need to be replicated when the application is upgraded, and you want to push out the updated app to your Intune devices.
However, if we used Chocolatey, a package manager and installer for software packages, we could considerably speed up the Intune application package deployment process because we would no longer need to:
- Find any install switches
- Grab the installation executable
- Find the uninstall process and switches
- Configure the application with any install switches, or uninstall switches within the Intune blade
If you decided to use Intune configuration PowerShell scripts, you also would not need to wrap anything in the INTUNEWIN format or specify install directories. However, I like to have my applications all under the Intune Applications blade instead of the configuration blade for ease of management and administration purposes. This method will also allow me to specify chocolatey as a dependancy for my applications, so if chocolatey present and I am installing VSCode using chocolatey, it will automatically install it prior to the VSCode installation.
INTUNEWIN Deployment Packages Overview
First, let’s take a look at the INTUNEWIN file format so we can understand how we will get all of this to work properly. To deploy applications that get installed via an executable you would need to wrap it in an INTUNEWIN wrapper and import that into Intune. Think of an INTUNEWIN file as an encrypted zip file that contains all of your installation files for your application. To wrap your install directory in an INTUNEWIN format, you will need to use the Microsoft Win32 Content Prep Tool. “The packaging tool converts application installation files into the .intunewin format. The packaging tool also detects the parameters required by Intune to determine the application installation state. After you use this tool on your apps, you will be able to upload and assign the apps in the Microsoft Intune console.”1
1 – Deploy Chocolatey with Intune
Chocolatey will be the package manager that will end up installing all of our applications via Intune. As mentioned earlier, this is much better than manually getting all the installs yourself and preparing it for Intune as you no longer need to research any command-line switches to install or uninstall, nor do you need to re-package the application when it gets updated.
First, we need to create our Chocolatey deployment for Intune. In the same directory as your IntuneWinAppUtil.exe from the Microsoft Win32 Content Prep Tool, create a new directory called Chocolatey
Save the PowerShell script below in your Chocolatey directory and name it install.ps1.Â
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'))
In PowerShell or CMD, navigate to the directory with the IntuneWinAppUtil.exe and start the executable.
Next, we will need to specify the source folder that has our install files, the setup file (which is our install.ps1 file), and the output folder where it will spit out the INTUNEWIN file.
Here we see that it successfully created our INTUNEWIN file to import into Intune.
Next, in Intune blade go to Client Apps >Â Apps > + Add
Select Windows App (Win32)
Import your install.intunewin file you created earlier. In the App Information pane, you can modify the application info, including name, description, publisher, and even give it a proper logo to display in the Company Portal.
For the install command put: powershell.exe -executionpolicy bypass .\install.ps1
You can put anything for the uninstall command as we did not configure an uninstall script. If you did create one, you could dot-source it like the install.ps1 file.
Note: If you notice, we don’t need to specify silent install switches with chocolatey or its packages. This is because its all done silently by default
For our detection rules, we will tell Intune that Chocolatey is installed if the Chocolatey folder is present under C:\ProgramData\
In the end, we can review our new Intune application. In my example, I just deployed it to all users and all devices
2 – Install Applications Using Intune + Chocolatey – Examples
In the next section, I will show you how to use Chocolatey + Intune to install and uninstall applications. The method is the same for each application, so if your application is not listed, you can follow the same instructions for your app. You will need to locate the package on the Chocolatey repository.
NOTE: All applications that are shown below, as well as more, are all available at this central repository, which includes the install/uninstall scripts and the applications intunewin file.
Google Chrome
Looking in the Chocolatey repository, I can see the install command for Google Chrome is:Â choco install googlechrome
So my install script (install.ps1) for Google Chrome will look like the following:
$localprograms = choco list --localonly if ($localprograms -like "*googlechrome*") { choco upgrade googlechrome } Else { choco install googlechrome -y }
I put the IF statement in there in case it’s already installed I’m just telling Intune to update the application
And my uninstall.ps1 file will look like the following:
choco uninstall googlechrome -y
Run the Microsoft Win32 Content Prep Tool (IntuneWinAppUtil.exe)
Which will spit you out this file that you can download here
Finally, you would configure your new Win32 application in Intune the same way we did Chocolatey, but the detection rules would be
My app configuration would look like the following
Mozilla Firefox
Looking in the Chocolatey repository, I can see the install command for Firefox is: choco install firefox
So my install script (install.ps1) for Firefox will look like the following:
$localprograms = choco list --localonly if ($localprograms -like "*firefox*") { choco upgrade firefox -y } Else { choco install firefox -y }
I put the IF statement in there in case it’s already installed I’m just telling Intune to update the application
And my uninstall.ps1 file will look like the following:
choco uninstall firefox -y
Run the Microsoft Win32 Content Prep Tool (IntuneWinAppUtil.exe)
Which will spit you out this file that you can download here
Finally, you would configure your new Win32 application in Intune the same way we did Chocolatey, but the detection rules would be
My app configuration would look like the following
Microsoft Edge
Looking in the Chocolatey repository, I can see the install command for Microsoft Edge is: choco install microsoft-edge
So my install script (install.ps1) for Firefox will look like the following:
$localprograms = choco list --localonly if ($localprograms -like "*microsoft-edge*") { choco upgrade microsoft-edge -y } Else { choco install microsoft-edge -y }
I put the IF statement in there in case it’s already installed I’m just telling Intune to update the application
And my uninstall.ps1 file will look like the following:
choco uninstall microsoft-edge -y
Run the Microsoft Win32 Content Prep Tool (IntuneWinAppUtil.exe)
Which will spit you out this file that you can download here
Finally, you would configure your new Win32 application in Intune the same way we did Chocolatey, but the detection rules would be
My app configuration would look like the following
Adobe Acrobat Reader
Looking in the Chocolatey repository, I can see the install command for Adobe Reader is: choco install adobereader
So my install script (install.ps1) for Firefox will look like the following:
$localprograms = choco list --localonly if ($localprograms -like "*adobereader*") { choco upgrade adobereader -y } Else { choco install adobereader -y }
I put the IF statement in there in case it’s already installed I’m just telling Intune to update the application
And my uninstall.ps1 file will look like the following:
choco uninstall adobereader -y
Run the Microsoft Win32 Content Prep Tool (IntuneWinAppUtil.exe)
Which will spit you out this file that you can download here
Finally, you would configure your new Win32 application in Intune the same way we did Chocolatey, but the detection rules would be
My app configuration would look like the following
3 – Create an Application Dependancy
One of the benefits of deploying the application as a Win32 is that we can specify application dependencies. Since I am deploying my applications using Chocolatey, I want to set the Chocolatey app as a dependency, so if it’s not found on the machine, it will auto-install it for me.
In the Intune Portal, I can edit the application and select Dependencies and specify the Chocolatey app and force it to auto-install if it is not present. You can also specify dependencies when you are creating the application in Intune.
Sources
My name is Bradley Wyatt; I am a 5x Microsoft Most Valuable Professional (MVP) in Microsoft Azure and Microsoft 365. I have given talks at many different conferences, user groups, and companies throughout the United States, ranging from PowerShell to DevOps Security best practices, and I am the 2022 North American Outstanding Contribution to the Microsoft Community winner.
26 thoughts on “Intune + Chocolatey: A Match Made in Heaven”
Thanks Brad for the great tutorial! I am getting “Status Failed – The application was not detected after installation completed successfully 0x87D1041C” and the applications are not being installed. I followed the instructions for the intunewin deployment package and If I manually transfer the powershell script and run it, then the applications install. Chocolatey was the only one that installed properly. Any suggestions?
Sounds like it is not finding whatever you specified as your detection rules.
also could be relying on choco install first. make sure you configure choco as a dependancy
Choco is installed on all devices and I’m following the same detection rules for file/folder just like you provided.
I found that once I fully qualified the path in the install.ps1 script all was ok. So c:\programdata\chocolatey\choco.exe install 7zip.install
also
powershell.exe -executionpolicy bypass -command .\install.ps1 does the trick, it forces the commands to run in sequence, not parallel.
Thanks.
adding -command did the trick!
thx Jay & Brad
Hey all,
I know I’m bumping a post that’s nearly a year old, but I’m just now going through this process myself and I wanted to express my thanks to everyone for the advice.
I also had the issue of apps failing to install because it couldn’t be detected afterwards. The combination of adding powershell.exe -executionpolicy bypass -command .\install.ps1 as the install command, as well as specifying the full path in the install.ps1 to chocolatey ( c:\programdata\chocolatey\choco.exe install) has worked for me and FINALLY after many days of trial and error, all of my apps are installing without a hitch.
Thanks again to all, you are much appreciated.
Hi Brad,
Great article! The only suggestion I would have is to look at hooking it up to an internal repo that is caching Chocolatey packages from the community repo at the very least, and possibly show it deploying your own applications from another internal repository. Nexus is one way to show this. Have a look at https://chocolatey.org/install#organization to get started!
I’ve been having some issues using this deployment strategy with Autopilot.
It hangs on App installation. Any recommendations?
what do your logs show
Hello,
Thanks for the write-up, it’s been working great from OOBE and Company Portal.
Have you ever tested this from Autopilot White Glove? All the applications published using this method fail in White Glove with:
Error code: 0x87D1041C
The application was not detected after installation completed successfully
Suggested remediation
Couldn’t detect app because it was manually updated after installation or uninstalled by the user.
It says the application installed successfully, but when I check it’s missing.
Thanks!
how is the check being performed, what folder, or file is it looking for
Bear in mind that the Intune powershell runs in 32-bit powershell.
This means that, among others, when setting registry settings and possibly using system variables, it will look in the WOW64 locations.
There is a way to set Powershell to x64 when it detects a 64-bit processor architecture automatically. Use this on top of your script to circumvent this issue.
Nice – thanks Brad! The approach works really well.
One follow on question I am fighting with is how to tell intune to perform an update on client machines for the already installed packages. For example, I have used your approach to deploy Adobe Reader DC – all good. Now some vulnerabilities have been found and I need to force an update to the client PCs. Do you have any pointers on how to achieve that? I get the logic of the if…then in the install.ps1 files, but cannot find a way to tell intune to run the script again on all PCs.
Thanks in advance for the help.
Simon
deploy a ps1 with the choco upgrade command
thanks for the quick reply. Just so I am clear, I’d end up with more than one entry for Adobe Reader DC in intune – the original one and then one with the upgrade choco command? Cheers.
You could re-deploy the ps1 to have logic in there that says IF its installed then try upgrade, if not installed then install – that way there is no need to re-deploy
Thanks Brad.
This probably straying off into Intune management usage now rather than anything to do with your original article, so feel free to leave this thread (but I’ll ask my question anyway :-)!).
I did put the if…then install/update statements per your article into each install.ps1 script. The question I am struggling with is how to trigger the update / redeploy from the intune portal? I can’t see a way to tell Intune to re-run the script because the “is installed” detection rules are being met (for example, a directory exists because a previous version is already installed, therefore it is installed, therefore no need to run the install.ps1 again).
What bit of knowledge am I missing?
Thanks,
Simon.
when I last deployed chocolatey to end user computers, the main challenge was restricting them to self install whatever they wanted from the choco repository. This soon became a nightmare scenario to keep all self installed 3rd party apps up to date as well as moderate what was going on the desktops.
Without a good application allowlisting solution in place, I would recommend to manage this very carefully.
Your post relay helped me. Thanks alot!
In the meantime I extended the install and validation routine to meet my requirements and allow to quickly create new packages based on a template. Also, I created a package for auto updating.
If you like to check it out: https://scloud.work/en/chocolatey-programm-installation/
If I wanted to install multiple apps in one script without having to create a seperate app for each one would the script for example be like the following:
$localprograms = choco list –localonly
if ($localprograms -like “*ruby*”, “*rubymine*”, “*openoffice*”, “*git*”)
{
choco upgrade ruby
choco upgrade rubymine
choco upgrade openoffice
choco upgrade git
}
Else
{
choco install ruby –version 3.1.2.1 -y
choco install rubymine –version 2022.2 -y
choco install openoffice –version 4.1.13 -y
choco install git –version 2.37.1 -y
}
What does the Install.ps1 script look like when specifying the full path to chocolatey? Sorry, am new to powershell and having trouble inserting that into the script provided in the article.
Thanks,
Nate
I’m late to the party here, but I love this.
I expanded the script a little to accept command line arguments:
$appname = $args[0]
$localprograms = choco list –localonly
if ($localprograms -like “*$appname*”)
{
choco upgrade $appname -y
}
Else
{
choco install $appname -y
}
That way, I can resuse the same intune package, but supply it with an argument like:
powershell.exe -executionpolicy bypass -command .\install.ps1 googlechrome
Lazy be what lazy does. 🙂
(did the same for the uninstall script, so that it accepts command line arguments.
$appname = $args[0]
choco uninstall $appname -y)
Can we use Chocolatey in a commercial environment?
To make things easier there is no need for the IF block.
CHOCO UPGRADE will either install or upgrade the app if it’s already there so a simple oneliner is all that is needed:
CHOCO UPGRADE “package” -r -y –no-progress
This means you don’t even need to create a seperate intunewin file
I’ve found a reboot is needed after the initial install for the CHOCO command to work but as others have suggested using the full path %PROGRAMDATA%\CHOCOLATEY\CHOCO.EXE gets around that