Adding Software To Intune with PsADT

My company is shifting to using Microsoft Entra ID ( Formerly Asure AD ) and Microsoft Intune to handle deploying our desktop and laptop computers. This change will ultimately be a great change, Right now there’s a lot to do when it comes to adding all of the software we use to the company portal. Here are some of my requirements: 

  • Consistent look & feel
  • Easy to add additional packages
  • Use best practices where applicable

Let Me show you what I figured out...

Overview

After doing several tests and trying to understand the best way of adding software to our company portal I put together the following process: This process starts with PsADT or the PowerShell App Deployment Toolkit which as its name implies, helps you deploy apps. (It’s nice when names of things describe what they do right?) 

The one thing that Is inconvenient when using the PsADT is that you need to include all of the files that come packaged with PsADT in every software package you are deploying. Which means that either we have to adapt PsADT each time we want to make a new package or we can customize it one time and then reuse that template for each new package we want to deploy.

Enter Post Haste a software to help you create templates out of a folder and set of files. Using Post Haste we can quickly get our template coppied into our local deployment package folder including an output folder where we will hold our intune win file, and a folder for any downloads we might have acquired in putting this package together. 

After we have put everything together we can use Microsoft’s Content Prep Tool to compile our setup file.

Once we have an .intunewin file we want to test it and make sure that it works which is where we will use the Windows Sandbox in conjunction with Run-In-Sandbox to create a throw-away sandbox to test our new app package. We will also use this opportunity to capture the MSI Install code that we will use in the next step…

With everything there happy, We can upload our app package to the Intune Portal, assign it to a group of users, and Bob’s your uncle. 

Installing Required Software

🤓 Install Post Haste

1. Go download post haste from the Digital Rebellion website, It’s Free!

2. Click through the installer. 

3. Open It up. 

4. Tap Templates

5. Remove all the predefined templates, (Unless they appeal to you and you want to use them)

6. Tap on the Add button

7. Right Click & Show in Explorer

9. You can rename the template here, remember to leave the .pht at the end of the foldername I went with PsADT Package.

 

10. Navigate into your new .pht folder (PsADT Package.pht) and then into the folder called Files. It will be empty but anything you put in this folder will be templated to your projects’ files. In the next phase we will get the PsADT files and put them here. 

 

11. There are two things left to setup Post Haste, The first is to specify where we will add each of these folders. Personally I chose C:\PsADT\ but you can choose any folder you like. Head over to Preferences and put in that folder location into the Project Tab, under Fixed project location:

12. Lastly, we are going to up date the parameters. You can set these to whatever you like, I have App Name and App Version as well as an auto-incrementing number. This doesn’t influence anything other than the name of the folder when its generated. 

📓 Download PsADT from Github.

1. Lets Add a few new folders namely, Downloads & Output to our Files folder. 

2. Lets download and copy the Toolkit folder from the PsADT zip to our files folder. You can download the latest release of the Ps App Deploy Toolkit from GitHub here.

 

3. Copy the Toolkit Folder from the zip into our files folder. 

4. In the end your files should look like this:

5. Navigate to Toolkit > AppDeployToolkit. You will want to use a photoshop type application to change the logo, and the banner 

  • AppDeployToolkitBanner.png
  • AppDeployToolkitLogo.icon
  • AppDeployToolkitLogo.png

 

Each of these need to maintain the exact same name or they will not be picked up by the deploy script.  Additionally I keep the original ones by renaming them to original. 

This will brand your deployments and allow the prompts to show your company information as they do their things. 

🚀 Customize PsADT for speed

1. Add a pack.ps1 powershell script to the files folder so that you don’t have to type it out every time you want to compile your intune win file. When you are setting up each project you will want to change Setup.exe to whatever the name of your setup file is.

/pack.ps1
.ps1
				
					intwin -c .\Toolkit -s .\Toolkit\Files\Setup.exe -o .\Output -q
				
			

2. Add a text file called Start_Commands.txt to the root of the file so that you have an easy copy/paste reference for starting running your .intunewin file. 

/Start_Commands.txt
.txt
				
					// for testing in the sandbox.
powershell.exe -executionpolicy bypass -command "set-executionpolicy remotesigned -Force"; powershell.exe -file ".\PreLaunch.ps1" 


// for running in intune
powershell.exe -executionpolicy bypass -file ".\PreLaunch.ps1"
powershell.exe -executionpolicy bypass -file ".\PreLaunch.ps1" -DeploymentType "Uninstall"
				
			

3. While we are inside the Sandbox, after a package has been installed, we want to be able to collect the MSI Installation code. Here’s a small PowerShell script we can use to identify packages that have been installed. This file goes into the Output folder of our package so that it’s not included in our compiled package but we can access it when we open our intune win file inside the sandbox. 

/Output/getmsi.ps1
.ps1
				
					param($Work)

# restart PowerShell with -noexit, the same script, and 1
if (!$Work) {
    powershell -noexit -executionpolicy bypass -file $MyInvocation.MyCommand.Path 1
    return
}

echo " Checking MSI Code:"

$Installer = New-Object -ComObject WindowsInstaller.Installer; $InstallerProducts = $Installer.ProductsEx("", "", 7); $InstalledProducts = ForEach($Product in $InstallerProducts){[PSCustomObject]@{ProductCode = $Product.ProductCode(); LocalPackage = $Product.InstallProperty("LocalPackage"); VersionString = $Product.InstallProperty("VersionString"); ProductPath = $Product.InstallProperty("ProductName")}} $InstalledProducts
				
			

4. Most of the time you will be launching the installation package using the “System” context so that your installation has administrator permission. But when doing that all of the prompts or notifications will then be displayed to the SYSTEM user and our logged-in user will never see them. We can use the Microsoft-Provided ServiceUI.exe when a user is logged in to have the best of both worlds, Our script will run with administrator permission, and display the notifications to the user. 

This particular pre-launch script can be found over at GitHub here. to make it easy I have also included it here. 

Note: I renamed it from `Win32App_PSADT_PreLaunch.ps1` to the simpler `PreLaunch.ps1`and made a few adjustments. 

/Toolkit/PreLaunch.ps1
.ps1
				
					[CmdletBinding()]
param (
    [Parameter(Mandatory = $false)]
    [ValidateSet('Install', 'Uninstall')]
    [String]$DeploymentType = 'Install'
)

#This will log the script and how it goes
Start-Transcript -Path "C:\ProgramData\Microsoft\IntuneManagementExtension\Logs\Win32App_PSADT_PreLaunch.log"

#Below will get the active user logged in, if no user logged in, it will return variable as null.
$CheckUser = Get-CimInstance -ClassName Win32_ComputerSystem | Select-Object -ExpandProperty UserName

if ($env:USERNAME -eq "WDAGUtilityAccount"){
	$CheckUser = "WDAGUtilityAccount"
}

If ($CheckUser -eq $null)
{
	Write-Host "No User is Logged into Computer, running in Non-Interactive mode"
	If ($DeploymentType -eq "Install")
	{
		Write-Host "INSTALL DEPLOYMENT TYPE: No user logged in so run in Non-Interactive mode"
		Start-Process Deploy-Application.exe -Wait -ArgumentList '-DeployMode "NonInteractive"'
	}
	If ($DeploymentType -eq "Uninstall")
	{
		Write-Host "UNINSTALL DEPLOYMENT TYPE: No user logged in so run in Non-Interactive mode"
		Start-Process Deploy-Application.exe -Wait -ArgumentList '-DeployMode "NonInteractive" -DeploymentType "Uninstall"'
	}
}
else
{
	Write-Host "USERNAME in Variable is $CheckUser"
	If (($CheckUser -match "defaultuser0") -and (((Get-Process -Name 'wwahost' -ErrorAction 'SilentlyContinue').count) -gt 0))
	{
		Write-Host "DefaultUser0 is logged in and wwahost process running, this means OOBE/ESP/Autopilot is running - Will Run without ServiceUI.exe"
		If ($DeploymentType -eq "Install")
		{
			Write-Host "INSTALL DEPLOYMENT TYPE: DefaultUser0 is logged in so run in Non-Interactive mode"
			Start-Process Deploy-Application.exe -Wait -ArgumentList '-DeployMode "NonInteractive"'
		}
		If ($DeploymentType -eq "Uninstall")
		{
			Write-Host "UNINSTALL DEPLOYMENT TYPE: DefaultUser0 is logged in so run in Non-Interactive mode"
			Start-Process Deploy-Application.exe -Wait -ArgumentList '-DeployMode "NonInteractive" -DeploymentType "Uninstall"'
		}
	}
	else
	{
		Write-Host "$CheckUser is logged in (NOT DefaultUser0) to the computer, so will run with ServiceUI.exe to give user UI."
		If ($DeploymentType -eq "Install")
		{
			Write-Host "INSTALL DEPLOYMENT TYPE:  User is logged in.  Will run with ServiceUI.exe, in install mode."
			.\ServiceUI.exe -Process:explorer.exe Deploy-Application.exe
		}
		If ($DeploymentType -eq "Uninstall")
		{
			Write-Host "UNINSTALL DEPLOYMENT TYPE:  User is logged in.  Will run with ServiceUI.exe, in uninstall mode."
			.\ServiceUI.exe -Process:explorer.exe Deploy-Application.exe -DeploymentType Uninstall
		}
	}
}
Write-Output "Install Exit Code = $LASTEXITCODE"
Stop-Transcript

Exit $LASTEXITCODE
				
			

4. As mentioned above, we must add ServiceUi.exe to our PsADT Toolkit to make the PreLaunch script happy. The same GitHub Repo that we got the script from also has ServiceUI.exe available to download. Let’s download it and put it inside our Toolkit folder.

When we are finished our Toolkit should look something like this: 

Review: At this point, We have put together our template for new packages using Post Haste & PsADT. 

Our Template has some nice features. like using the ServiceUI and PreLaunch Script to display everything to the logged-in user and quality-of-life scripts for our testing. 

Setting Up the testing environment

Windows Sandbox is a “throw-away” virtual machine that comes with Windows 10 and 11. It is perfect for applications where you want a fresh start every time you start the VM and completely erase everything that happens on it after you close the VM. We are going to use it to automatically decrypt and run our intunewin files so that we can test to make sure there are no errors. 

🖥️ Install Windows Sandbox

1. You can find all of the instructions for turning on this Windows feature at the Microsoft Learn Website. The cliff notes version is a simple PowerShell command run from an admin shell.  

PowerShell
				
					Enable-WindowsOptionalFeature -FeatureName "Containers-DisposableClientVM" -All -Online
				
			

You could also enable Windows Sandbox through the Windows Features settings page. 

With that enabled you should be able to start a sandbox by searching for it in the start menu. 

🔐 Install Run-in-Sandbox

You can find the zip for Run-in-Sandbox here. The github can be found here.

We are going to download the zip file for this and then extract it 

open an Admin Powershell terminal and cd into your unzipped folder. 

Then you can run the following command to add the context menu we will use. 

PowerShell
				
					powershell.exe -noexit -executionpolicy bypass -file ./Add_Structure.ps1
				
			

With that added, we should now be able to right click on an .intunewin file and get a context menu that says “Run Intunewin in Sandbox”. If you are on windows 11 you may have to click the “Show more options” to get back to the windows 10 style context menu. 

👔 Install Microsoft's Content Prep Tool

We are making excellent progress toward our goal of adding packages to Microsoft Intune. The last thing to install is Microsoft’s Content Prep tool. This application takes our setup files and PowerShell scripts then compresses and encrypts the files into a single intunewin file that we can upload to Microsoft Intune. 

 

You will find the GitHub repo for the content prep tool here. 

Download the latest release as a .zip and then unzip the file.

I like to put this executable into someplace that will be available on my profile. And then create an alias for it so that I can use the much shorter intwin command on the terminal.

Below is a simple script that will add a hidden folder .bin to your user profile and then open the folder in Explorer so that you can copy the Content Prep Tool there. If you would rather just invoke the content prep tool with a full path to the executable you can put the full path to the tool into the pack.ps1 file you added earlier. 

makeProfileBin.ps1
.ps1
				
					
# Define the folder path you want to add
$profileBin = "$($env:UserProfile)\.bin"
# Exmaple: "C:\Users\<username>\.bin"


# Check if the folder exists
if (-not (Test-Path -Path $profileBin)) {
    # Create the folder if it does not exist
    New-Item -ItemType Directory -Path $profileBin -Force
    Write-Host "Folder '$profileBin' created."
} else {
    Write-Host "Folder '$profileBin' already exists."
}

# Get the path to the PowerShell profile
$profileContent = Get-Content -Path $profile
$aliasCommand = "Set-Alias -Name intwin -Value `"$profileBin\IntuneWinAppUtil.exe`""

# Check if the alias command already exists in the profile, if not add it.
if ($profileContent -notcontains $aliasCommand) {
    Add-Content -Path $profile -Value $aliasCommand
    Write-Host "Alias added to the profile."
} else {
    Write-Host "Alias already exists in the profile."
}

# Open the folder in File Explorer
write-host "Opening folder '$profileBin'..."
write-host "Copy the IntuneWinAppUtil.exe to this folder."

Invoke-Item $profileBin
				
			

Now you should be able to invoke the intwin program by running 

PowerShell
				
					intwin -h
				
			

This should display the help information for the content prep tool. 

Build Your First Package!

It’s quite the process to get to this point, but we now have everything we need to quickly and efficiently add new packages to our company portal. Our process now looks like this:

  1. Run PostHaste to make a deployment folder.
  2. Locate & Copy the installer file for the package we want to install. 
  3. Check that we have the correct silent install command by sharing our install files with the sandbox. 
  4. Get the MSI Install code after the initial install.
  5. Filling out the info in our PsADT deploy script. 
  6. Compiling our intunewin file with the .\pack command
  7. Test that the deployment works correctly inside our sandbox.
  8. Upload our intunewin file to Intune. 
  9. Test on a deployed computer. 
 

For this example I will be adding Autodesk Autocad 2025 to our company portal. I will fetch the install files from manage.autodesk.com. 

 

1. Run Post Haste.

Open Post Haste and fill out the relevant parameters. Then hit Create Project. 

That should open the folder in your explorer where you can make some edits to the files. 

2. Get Installer Files.

Download and extract installer files. 

Sometimes the installer maybe as simple as a single executable that will install your software, other times it may be a whole folder that is needed to do the install. 

In the case of Autodesk we will get the download for the software at Manage.Autodesk.com. 

 

We can download this installer file to the Downloads folder inside our package folder. 

We will run the downloader from here and it will extract our files to a folder. 

These are all the files required for installing Autocad 2025. Lets copy all of these files and past them into our Deployment Folder here> PackageRoot/ PsADT / Files

If you are doing other software just copy all of the files required to install your software into the Files Folder here. 

3. Silently Install the Software Manually.

Every software is a little different so you will need to read the documentation, or do some googling to figure out what the silent install command is for the software. 

For example fo this software the silent install command is:

PowerShell
				
					setup.exe -q
				
			

Your software will be different, so this is the opportunity to make sure your command will work. Lets test this out by sharing all of the install files into the windows sandbox and running that command inside a terminal to see what happens. Right Click on the Files and select Share this folder in a Sandbox. ( if you are on windows 11 you may have to select the see more options first )

A Folder will show up on the desktop of the Sandbox that has the folder (and files) we need to install the software. 

We need to run a powershell command to install the software so we will Right-Click on the start menu and select Windows PowerShell (Admin) then type cd and drag the file folder to the terminal, which will put the location of that folder into the terminal, then hit Enter

Once you have changed the directory into our files folder lets try running the install command: 

PowerShell
				
					.\setup.exe -q
				
			

Once you have changed the directory into our files folder lets try running the install command: 

Checking in the task manager I can see that there are Autodesk installation tasks running (silently)

After some time, The AutoCAD icon shows up on the desktop and the installers disapear from the Task Manager.

We have figured out the correct silent install command for this software. If required you can close the sandbox and try again to install if your particular software needs to be installed again, or you need to test it again for some reason. 

Go ahead and close your sandbox, indicating that your ok with the box being cleaned up. 

 

4. Fill out PsADT Information in VsCode

I use VsCode as my text editor, you can get it from the vsCode website or use your own text editor. Right Click on the Package Folder (0037_Autocad_2025 in this case)  and select Open with Code or simply open vscode and navigate to the folder. 

I use VsCode as my text editor, you can get it from the vsCode website or use your own text editor. Right Click on the Package Folder (0037_Autocad_2025 in this case)  and select Open with Code or simply open vscode and navigate to the folder. 

Update pack.ps1

The setup file needs to be added to the intune pack command. You will change Setup.exe in the first line to whatever the name of your setup file is. For this example the setup file is actually called setup.exe so I will leave it be.

Update the Deploy-Application.ps1 inside the PsADT folder

We are going to update 3 things in this file. The Variable declaration the install command, and the uninstall command.  Fill out the relevant fields here for your application:

PowerShell
				
					    ##*===============================================
    #region VARIABLE DECLARATION
    ##*===============================================
    ## Variables: Application
    [String]$appVendor = 'Autodesk'
    [String]$appName = 'Autocad'
    [String]$appVersion = '2025'
    [String]$appArch = 'x64'
    [String]$appLang = 'EN'
    [String]$appRevision = '01'
    [String]$appScriptVersion = '1.0.0'
    [String]$appScriptDate = '10.14.2024'
    [String]$appScriptAuthor = 'John Kraczek'
    ##*===============================================
				
			

Next we need to update the install and uninstall commands. Locate the line that says <Perform Installation Tasks Here> then update the line to utilize the silent install command you figured out earlier. 

PowerShell
				
					        ## <Perform Installation tasks here>
        Execute-Process -Path "$dirFiles\Setup.exe" -Parameters "-q"
				
			

Finally we want to update the uninstall command. If the installer comes with a silent uninstall command we can update this line to use that, otherwise we can use the MSI code of the software to uninstall it. 

PowerShell
				
					        ## <Perform Uninstallation tasks here>
        Execute-MSI -Action Uninstall -Path "{}" ## MSI Code
				
			

If you don’t have the MSI uninstall code just yet, we can get it in the next testing step. You will need to come back and put that in here. 

5. Compile your package with your pack.ps1 script.

From your terminal cd into the root of your package and run the following command:

PowerShell
				
					./pack.ps1
				
			

This will run the command: intwin -c .\PsADT -s .\PsADT\Files\Setup.exe -o .\output -q which we added to the pack.ps1 script earlier. 

It will output your intunewin file into the output folder. 

6. Test our Setup.intunewin inside the sandbox.

The first step in testing our package is to get the powershell command that will be run inside the sandbox to kick off the install. You can find that in the start_commands.txt file, I have also supplied it here. Copy it to the clipboard. 

PowerShell
				
					powershell.exe -executionpolicy bypass -command "set-executionpolicy remotesigned -Force"; powershell.exe -file ".\PreLaunch.ps1" 
				
			

Right Click on the intunewin file in our output folder and select Run in Sandbox

A window will open asking for you to put in the launch command, paste the command you coppied just above. 

The Windows Sandbox will open. It will take some time for the intunewin file to be decrypted inside the sandbox and if you are curious if it is still running you can check the task manager. Look to see if powershell is running silently.

After the intunewin file has been decrypted and decompressed it will launch the user prompts showing that it is currently installing. 

When it is finished, The icon will show up on the desktop and the notifications will indicate that the software was successfully installed. 

If your installation does not go as planned, you can adjust your scripts, recompile and then try the sandbox installation again. 

7. Get the MSI Install code

open the output folder thats on the desktop and launch the getmsi.ps1 script that is inside. 

Look through the list and find the installation code for your product. In this example, we can see that the AutoCAD 2025 – English has a code of 
{28B89EEF-8101-0409-2102-CF3F3A09B77D}
We will use this in the uninstall command of our PsADT script and the detection rule when we put this package onto Intune. 

There are other ways to get the install code, This seems to be the easiest for me. 

8. Upload the package to Intune.

This is the easiest part of the process. Navigate to https://intune.microsoft.com/ and login with your admin account. Then navigate to Apps -> All Apps -> + Add

Choose Windows App (Win32) from the dropdown. 

Navigate to your output folder and choose your intunewin file. 

Page 1: Fill out the App Information on the first page including the logo. 
Page 2: Insert the install & uninstall commands from start_commands.txt 
PowerShell
				
					powershell.exe -executionpolicy bypass -file ".\PreLaunch.ps1"
powershell.exe -executionpolicy bypass -file ".\PreLaunch.ps1" -DeploymentType "Uninstall"
				
			

Use the first as the install command and the second as the uninstall command. 

Page 3: State the requirements for the software. 
Page 4: Add your detection rule.

If you were able to get the MSI install code that seems to be the easiest to use, otherwise you can use the other methods or even a custom powershell script. 

Page 5 & 6: If your software depends on or supercedes other software in the company portal you can add that here.
Page 7: On the assignments page you can choose the groups that can access this software. For my company most software is available to be installed by anyone if they need it, so I click All Users.
Page 8: Review all of the information you have put into intune and click Create.

9. Test the package on a deployed computer.

Finally we can open company portal on a deployed computer and hit that install button to confirm that everything installs as expected. 

Conclusion

We were able to install all of the software required to develop Intune Software Packages, Fetch some software from Autodesk, Package it up, and Test it inside the Windows Sandbox. Finally, we uploaded it to Microsoft Intune and installed it on a target device. 

Thanks for coming with me on this journey, and hopefully you will be able to get all of your software into your Company Portal successfully. 

 

If you enjoyed this post, let me know by commenting below. 

On This Page

5 1 vote
Article Rating
Subscribe
Notify of
1 Comment
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
1
0
Would love your thoughts, please comment.x
()
x