Skip to content

gotPaste/AutoPackager

Repository files navigation

Intune AutoPackager v3

This project streamlines packaging and updating Win32 apps in Microsoft Intune using winget metadata and recipe-driven automation.

Screenshots

Screenshot 2025-11-21 130434 Screenshot 2025-11-21 130447 Screenshot 2025-11-21 130133

Two ways to use:

  • Windows Forms GUI (recommended): Start-AutoPackagerGUI.ps1
  • Command line: AutoPackagerv2.ps1 with flags

This README provides a GUI quick start, CLI quick start, and a reference background process. The GUI Help tab loads this content.

Table of Contents


Prerequisites

  • Windows PowerShell 5.1
  • PowerShell modules: intunewin32app, powershell-yaml, Microsoft.winget.client
    • Example (run in an elevated PowerShell prompt and accept agreements):
      Install-Module intunewin32app
      Install-Module powershell-yaml
      Install-Module Microsoft.winget.client
  • Internet connectivity
  • For FullRun (Intune upload/updates):
    • Azure AD App Registration with DeviceManagementApps.ReadWrite.All, and credentials (Client Secret or Certificate thumbprint) via:
      • AZInfo.csv next to AutoPackager.ps1, or
      • AutoPackager.config.json (AzureAuth), or
      • CLI parameters to AutoPackager.ps1
    • Create a GitHub PAT Token (will be needed or you will hit api limits with GitHub when running AutoPackager)
    • Setup Automation
      • Automation Account
        • Create a local windows account or domain service account that can be used as the account for the scheduled task. System may work too, but if you do not choose a domain account you will not be able to archive to a network folder (setup in the autopackager.config.json file.
      • Scheduled task (#10-Scheduled-Task)
        • Create a new Scheduled task on a workstation or server that will run Autopackager and read the recipes nightly.

GUI Quick Start

Launch the GUI

  • Right-click Start-AutoPackagerGUI.ps1 and choose “Run with PowerShell”
  • Or run from console:
    powershell.exe -ExecutionPolicy Bypass -File .\Start-AutoPackagerGUI.ps1

Tabs and Workflow

1) Winget

  • Winget Search: Enter search criteria for the software you are looking for
  • Winget ID: Enter the package ID (e.g., zoom.zoom)
  • Locale: Defaults to en-US
  • Architecture: x64/x86/arm64 (sets appropriate download)
  • Installer Type: msi/exe (sets appropriate download)
  • Buttons:
    • Search Winget
      • Searches winget for the criteria entered and displays the output for selection
      • If only one package matches, it will auto-select and fill in the Winget ID field
    • Validate Winget ID
      • Executes:
        Find-WingetPackage -id <WingetID> -MatchOption Equals
      • Displays raw output and also parses plain text to extract
    • Show Installer YAML
      • Displays raw output of the installer YAML so you can determine which Architecture and Installer Types are available
    • Download Installer
      • Downloads the parsed InstallerUrl (if available) into:
        Testing\Publisher\Name\Version
        
      • Behavior:
        • Safe filename/path sanitation
        • TLS 1.2 where possible; sets a common User-Agent
        • Tries Invoke-WebRequest first; falls back to Start-BitsTransfer
        • Shows the destination and byte size on success

2) Intune App(s)

  • Winget ID is synchronized with Winget and Recipe tabs (editing in one updates the others)
  • Create App(s)
    • Icon: Pick an image (png/jpg/jpeg) to use as the app icon (when supported by auth method)
    • Create Primary App
    • Create Required Update App
      • Both use CreateWin32AppFromTemplate.ps1 to create minimal placeholder Win32 apps, using DisplayName derived from winget (Name + optional Version) and Publisher when available. The Required Update app appends a display name suffix from AutoPackager.config.json:
        • SecondaryRequiredApp.DisplayNameSuffix (preferred) or Secondary.DisplayNameSuffix (fallback)
      • The new AppId is detected from command output and written into:
        • Recipe tab (Primary IntuneAppId or SecondaryAppId)
        • Intune App(s) tab (read-only fields)
  • AppId(s)
    • Read-only Primary AppId and Required Update AppId fields reflect results from Create/Find actions
    • Reset AppId(s) clears those fields and the related fields on the Recipe tab
  • Select Existing App(s)
    • Search Name auto-populates with the vendor segment (e.g., jabra.direct -> jabra) when empty; user edits are preserved
    • Find Primary App / Find Required Update App:
      • Searches existing Win32 apps by “display name contains”
      • On multiple matches, a pick-list is presented
      • Selected AppId is written to both this tab and the Recipe tab
  • Output window shows echoed commands and results

3) Recipe

  • Create / Select
    • Winget ID (synced across tabs)
    • Create New Recipe: runs New-RecipeFromWinget.ps1 to generate a starter recipe file under .\Recipes
    • Browse Recipe…, Open in Notepad, Open recipe folder
  • Select Existing App(s)
    • Search Name and Find buttons behave like the Intune App(s) tab. When invoked here, the GUI switches to the Intune App(s) tab to show output/selection, then automatically returns
  • Quick Edit (IDs and Args)
    • Primary AppId (IntuneAppId), Required Update AppId (SecondaryAppId)
      • Note: The GUI does not enforce GUID format; it writes values as provided
    • Installer Scope: Writes InstallerPreferences.Scope in the recipe ("", machine, or user). Leave blank to honor defaults/CLI fallback
    • Architecture: Writes to recipe (used for application download selection)
    • Installer Type: Writes to recipe (used for application download selection)
    • InstallArgs / UninstallArgs
    • ForceUninstall (boolean)
    • ForceTaskClose (multiline; one process name per line; .exe extension is optional)
    • Notification Popup
      • Enabled
      • Timer (minutes)
      • Allow deferral
      • Deferral hours (see CLI notes for how deferral horizon is computed at runtime)
    • Required Update Deployment Rings
      • Pilot Group + Deadline (days)
      • UAT Group + Deadline (days)
      • GA Group + Deadline (days)
      • Load Default Groups: reads RequiredUpdateDefaultGroups from AutoPackager.config.json
    • Save Recipe Update(s)
      • Apply writes the current Quick Edit values back into the JSON (ConvertTo-Json -Depth 15)

4) Run

  • Mode
    • Package Only (Testing Output)
    • Full Run (Update Intune)
    • Optional: No Azure Authentication (adds -NoAuth to backend)
  • Target
    • Select Recipe File… (single .json file)
  • Run AutoPackager
    • Safely builds and executes AutoPackager.ps1 with the selected options
    • Output window shows stdout/stderr and a tail of AutoPackager.log when present
  • Notes
    • GUI Run tab targets one recipe file at a time. To process all recipes or run DryRun, use the CLI (see below) or set defaults in AutoPackager.config.json

5) Reset

  • Primary AppId Reset / Required Update AppId Reset
    • Uses IntuneApplicationResetAll.ps1 with -AppId when available
    • If an AppId is provided, the GUI attempts to run in-process and capture output; otherwise an external PowerShell window may open for prompts (especially for the secondary button when no AppId is provided)

6) Logs

  • Refresh Log: Tails AutoPackager.log (up to 500 lines)
  • Open Working Folder
  • Open Latest Summary CSV (Working\Summary_*.csv)

7) Config

  • Open AutoPackager.config.json
  • Open readme.txt (this file)
  • Open SystemConfigReadMe.txt

8) Prerequisite Check

  • Run Prerequisite Check

9) Help

  • Loads the content of readme.txt into the window

10) Scheduled Task

Wherever you setup the Scheduled task share the Recipe Folder in the Script location. This will be used for the Autopackager.config.json file for the RecipeNetworkFolder field.

  • Create a user with rights to all local folders and network paths listed in the AutoPackager.config.json file.
  • Create a Scheduled Task
    • General Tab
      • Name: AutoPackager - Nightly Run
      • Select User Account
      • Select Run whether user is logged on or not
      • Select Run with highest privledges
    • Triggers Tab
      • Select run schedule (I run it daily at 12:01 AM every day)
    • Actions Tab
      • Action: Start a program
      • Program/Script: c:\windows\system32\WindowsPowerShell\v1.0\powershell.exe
      • Add arguments (optional): -NoProfile -executionpolicy bypass -file ".\autopackagerv2.ps1" -fullrun -allrecipes
      • Start in (optional): (example: D:\AutoPackager)

Config-driven defaults (GUI)

On GUI startup, when AutoPackager.config.json is present the GUI reads and applies:

  • Run Mode default (PackagingDefaults.RunMode: PackageOnly or FullRun)
  • Winget defaults (PackagingDefaults.WingetSource, PackagingDefaults.DefaultScope)
  • Preferred architecture (PackagingDefaults.PreferArchitecture: x64/x86/arm64) for Winget parsing
  • Notification defaults (Notification.Defaults: Enabled, TimerMinutes, DeferralEnabled, DeferralHoursAllowed)
  • Default Required Update ring group names (RequiredUpdateDefaultGroups) via “Load Default Groups”

Note: Verification flags (SkipVerify, StrictVerify) are honored by the backend if configured, but they are not exposed as GUI toggles.


Command Line Quick Start

From the AutoPackager root folder:

Common patterns

  • Package only, single recipe (default mode without -FullRun):

    powershell.exe -ExecutionPolicy Bypass -File .\AutoPackager.ps1 -PathRecipes ".\Recipes\your.app.json"
  • Full run, all recipes in default Recipes folder:

    powershell.exe -ExecutionPolicy Bypass -File .\AutoPackager.ps1 -FullRun -AllRecipes
  • Full run, one specific recipe:

    powershell.exe -ExecutionPolicy Bypass -File .\AutoPackager.ps1 -FullRun -PathRecipes ".\Recipes\your.app.json"
  • Package-only without Intune authentication (skip connection):

    powershell.exe -ExecutionPolicy Bypass -File .\AutoPackager.ps1 -PackageOnly -PathRecipes ".\Recipes\your.app.json" -NoAuth
  • Dry Run (no download/wrap/upload; compares Intune vs winget):

    powershell.exe -ExecutionPolicy Bypass -File .\AutoPackager.ps1 -DryRun

Credential sourcing

  • AZInfo.csv (optional) next to AutoPackager.ps1:
    TenantId,ClientId,ClientSecret,CertificateThumbprint
    
    Non-empty values override CLI params; ClientSecret takes precedence over CertificateThumbprint.
  • Or configure AutoPackager.config.json (AzureAuth), or pass CLI parameters directly.

Useful options

  • -PreferArchitecture x64|x86|arm64
  • -DefaultScope machine|user
    Note: Recipe InstallerPreferences.Scope (if set) is honored first; -DefaultScope applies when recipe scope is blank.
  • -NoAuth (skip Intune connection for packaging/troubleshooting)
  • -SkipVerify / -StrictVerify (control post-upload verification)
  • -UpdateDetection / -NoUpdateDetection
  • -NoUpdateCmds (skip install/uninstall command updates)

Logs and Outputs

  • AutoPackager.log in the root (rotated/archived to Working\AutoPackager_yyyyMMdd_HHmmss.log)
  • Working\Publisher\Name\Version\Download for downloaded installers (+ generated install/uninstall scripts are copied here)
  • Working\Publisher\Name\Version\Scripts for generated scripts
  • Working\Publisher\Name\Version\Output\Package\*.intunewin
  • Working\Summary_*.csv for run summaries

Background Process (Reference)

1.0 Identify and verify winget package

  • Use the gui to locate winget packages by searching for part of the name.
  • Review the output and select the appropriate option
  • Select Show Installer YAML
  • Ensure you can target a machine-scope installer

2.0 Test Install and Uninstall

  • Test run the installer to gather and document the install silent switches for the recipe file
  • Test run the uninstaller to gather and document the uninstall silent switches for the recipe file
    Uninstall command lines can generally be found in the registry under:
    HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\
    HKLM\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\
    

3.0 Create Primary and Required Update placeholder apps

  • Option A (portal): Create two Win32 apps manually and record their AppId GUIDs
  • Option B (recommended): Use the GUI Intune App(s) tab “Create Primary App” and “Create Required Update App” buttons, optionally providing an icon. The GUI will write the new AppIds into the Recipe Quick Edit fields.

4.0 Create recipe

  • From GUI: Recipe tab -> “Create New Recipe” from a Winget ID
  • Or from console: run New-RecipeFromWinget.ps1 (prompted or -wingetid parameter)
  • The file is created in .\Recipes and can be edited in the GUI Quick Edit or a text editor

5.0 Edit recipe

Required fields to validate/fill for production:

  • IntuneAppId: Primary app GUID (if you intend FullRun)
  • SecondaryAppId: Required Update app GUID (if you intend FullRun with secondary)
  • InstallerPreferences.Scope: If you must force machine/user to resolve the correct installer
  • InstallArgs / UninstallArgs: Silent switches, restart behavior, etc.
  • ForceTaskClose: One process name per line that must be closed before install/upgrade/uninstall

Optional fields:

  • ForceUninstall: Uninstall previous version before installing
  • NotificationPopup:
    • Enabled
    • NotificationTimerInMinutes (default 2)
    • DeferralEnabled (default true)
    • DeferralHoursAllowed (default 24)
  • Rings (for the Required Update app):
    • Ring1/2/3: Group (display name) and DeadlineDelayDays (int)

6.0 Test PackageOnly and Recipe output files

  • GUI: Run tab -> Package Only -> select one recipe -> Run AutoPackager
  • CLI:
    powershell.exe -ExecutionPolicy Bypass -File .\AutoPackager.ps1 -PackageOnly -PathRecipes ".\Recipes\your.app.json"
  • Test run and validate successful Install/Uninstall/Detection/Requirement Scripts using PowerShell on a test machine
    • Install/Uninstall scripts are located in:
      <AutoPackager V3>\Working\Publisher\Name\Version\Download
      
    • Detection/Requirement scripts are located in:
      <AutoPackager V3>\Working\Publisher\Name\Version\Scripts
      

7.0 Verify Full Run and Test Intune Deployment

  • GUI: Run tab -> Full Run -> select the recipe file -> Run AutoPackager
  • CLI:
    powershell.exe -ExecutionPolicy Bypass -File .\AutoPackager.ps1 -FullRun -PathRecipes ".\Recipes\your.app.json"
  • Verify the Intune App Metadata and Detection Scripts are properly set on primary application
  • Verify the Intune App Metadata, Detection Script, and Requirement Script are properly set on secondary required application
  • Advertise Primary App to a test group and validate Intune Application Deployment
  • Advertise Secondary Required App to a test group and validate Intune Application Deployment

8.0 Reset placeholder apps (if needed for re-testing)

  • Use the GUI Reset tab or run:
    .\IntuneApplicationResetAll.ps1 -AppId <GUID>

9.0 Production updates

  • Update the recipe (InstallArgs, ForceTaskClose, NotificationPopup, Rings, etc.)
  • Full Run with appropriate assignments/groups and deadlines for the Required Update app
  • Confirm deployments and behavior through Intune for both Primary and Required Update Apps

10.0 Re-run reset (optional)

  • If you need to re-stage for more testing, reset the apps again:
    .\IntuneApplicationResetAll.ps1 -AppId <GUID>

Appendix: Recipe fields (overview)

  • WingetId: Required (e.g., "zoom.zoom")
  • IntuneAppId: Primary Win32 app GUID
  • SecondaryAppId: Required Update Win32 app GUID (or Secondary.IntuneAppId/AppId/Id)
  • InstallerPreferences:
    • Scope: "machine" | "user" | "" (blank for default behavior)
    • Architecture: "x64" | "x86" | "arm64" (optional)
  • InstallArgs / UninstallArgs: Silent switches for vendor installer/uninstaller
  • ForceUninstall: boolean
  • ForceTaskClose: array or multiline string of process names to close
  • NotificationPopup:
    • Enabled: boolean
    • NotificationTimerInMinutes: int
    • DeferralEnabled: boolean
    • DeferralHoursAllowed: int
  • Rings:
    • Ring1/2/3: { Group: "display name of Entra group", DeadlineDelayDays: int }

Notes and alignment with the current code

  • Winget parsing in the GUI uses plain-text parsing; scope in the Winget tab is a selection preference and not added to the winget command there. The backend (CLI) uses JSON where available and falls back to text, adding/removing --scope as needed for compatibility.
  • GUI Run tab supports PackageOnly and FullRun for a single selected recipe; use the CLI if you want -AllRecipes or -DryRun from the console.
  • Reset actions use IntuneApplicationResetAll.ps1 with -AppId. The GUI attempts inline execution when GUIDs are provided and falls back to an external PowerShell window if needed.
  • Quick Edit does not enforce GUID format; it writes values exactly as provided.
  • The GUI reads defaults from AutoPackager.config.json for run mode, winget preferences, and notification behavior.

About

This project streamlines packaging and updating Win32 apps in Microsoft Intune using winget metadata and recipe-driven automation.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published