Overview
SCCM to Intune App Migrator (SIM) is a workstation tool that migrates applications to Microsoft Intune from six application sources — SCCM, Network Share, WinGet community, Chocolatey, Intune Enterprise App Catalog preview, and UNC custom. It supports the three Intune application target types (Win32 LOB, Web Link, and Microsoft Store via winget), produces fully-compliant .intunewin packages using the official Microsoft IntuneWinAppUtil.exe (embedded as a resource — no separate download), and persists every migration to a per-tenant JSON audit trail that can be exported to CSV for Excel review or rendered as a self-contained HTML audit report for project documentation.
SIM is multi-tenant by design. MSPs and consultants who steward several Intune tenants add each tenant once and switch between them via a dropdown in the title bar. Each additional tenant gets its own isolated storage under %AppData%\TontonTools\AppMigrator\tenants\<id>\ with its own DPAPI-encrypted credentials, migration cart, history log, and Intune inventory cache. The Default tenant remains shared with the rest of the TontonTools suite; additional tenants never touch shared credentials.
SIM is also a post-migration lifecycle tool. Once applications are in Intune, the Update Manager scans the inventory against the six configured catalog sources and surfaces outdated apps as update candidates, patchable in place via two strategies (Replace content or Supersede with new app). The HTML audit report — generated in 10–30 seconds against a typical tenant — covers inventory with EOL badges (via the public endoflife.date registry), available updates by source, coverage progress, and the last 20 migrations.
SIM is delivered as a one-shot perpetual license at three tiers — Small (up to 50 apps per migration), Medium (up to 200 apps per migration), and Large (unlimited). Unlike the Essentials / Pro / Enterprise subscription tiers that gate access to other TontonTools products, the Migrator tiers gate only the number of applications that can be processed in a single execution of the migration cart. The license itself never expires.
Three Intune target types
Win32 LOB for full installers (MSI, EXE, scripts), Web Link for URL shortcut apps, and Microsoft Store via winget for hundreds of common applications already published by Microsoft. The right choice is per-app, not per-campaign.
Six application sources
SCCM Applications via WMI, Network Share scanning with MSI metadata auto-detection, WinGet community (138 635-package SQLite local index, 5–30 ms queries), Chocolatey community feed via OData, Intune Enterprise App Catalog preview (search-only in v1.2.0), and UNC custom manifest catalog. SCCM is optional — a share-only environment or a catalog-only environment is fully supported.
Native multi-tenant
A Tenants tab and a tenant dropdown in the title bar let MSPs and consultants manage multiple Intune environments from a single desktop. Per-tenant isolated storage, per-tenant credentials, per-tenant cart, per-tenant history. Drift detection aborts mid-batch if you accidentally switch tenants — in-flight jobs are protected.
Update Manager + EOL detection
After migration, scan the Intune inventory against the configured catalog sources and surface outdated apps. Two strategies per candidate — Replace content (keeps AppId, assignments and supersedence intact) or Supersede with new app. Every app is matched against endoflife.date (450+ products, weekly-refreshed local cache) with four risk levels: 🟢 Supported, 🟡 Approaching EOL, 🔴 EOL passed, ⚪ Unknown.
Idempotent cleanup on failure
If any step of the 9-step Win32 LOB pipeline fails — staging, packaging, encryption, upload, commit, or assignment — the partially-created Intune app shell is best-effort DELETE-d from the tenant. No orphan app records left behind.
Full audit trail — JSON, CSV, and HTML
Every migration job — success or failure — is appended to a per-tenant JSON history file with start time, completion time, duration, Intune App ID, portal URL, assignment summary, and error message if any. One-click CSV export for Excel and Power BI. A self-contained HTML audit report covers inventory, available updates, EOL risk, and coverage in 10–30 seconds.
The three Intune target types — and when to use each
A common assumption when migrating from SCCM to Intune is that every application must be rebuilt as a Win32 LOB package. This is rarely true. Intune supports three distinct application target types, and the right choice per application can dramatically reduce the work and the long-term maintenance burden.
| Target type | Best for | Effort | Intune complexity |
|---|---|---|---|
| Win32 LOB | Line-of-business applications with custom installers — MSI, EXE wrappers, PowerShell-driven setups, in-house tools. The flagship target for genuine application migrations. | Heavy — 9-step pipeline with packaging, AES-256 encryption, Azure Blob chunked upload, commit, and patch. | Full — install/uninstall commands, detection rules, return codes, requirements. |
| Web Link | Applications that are really just URLs — intranet portals, SaaS dashboards, web-based line-of-business apps, internal documentation sites. | Light — a single POST to Graph creates the app. | Minimal — just a display name, publisher, and a URL. |
| Microsoft Store (winget) | Common third-party applications already published in winget — Mozilla Firefox, 7-Zip, VLC, Notepad++, PowerToys, Visual Studio Code, Git, Adobe Reader, and hundreds more. | Light — a single POST to Graph creates the app. | Minimal — just a packageIdentifier (e.g. Mozilla.Firefox). |
In SIM, the target type is selected per migration job in the cart, not per campaign. A single bulk migration can mix Win32 LOB packages, Web Links, and winget references in any combination. The orchestrator dispatches each job to the correct pipeline (heavy for Win32 LOB, single POST for the other two) and reports back to a unified history.
For winget identifiers, the canonical source is the official Microsoft winget catalog. Common identifiers include Mozilla.Firefox, 7zip.7zip, Notepad++.Notepad++, Microsoft.PowerToys, Git.Git, and Microsoft.VisualStudioCode.
Six application sources — SCCM, Network Share, WinGet, Chocolatey, Intune EAC, UNC custom
SIM does not require SCCM. The tool can source applications from any combination of six sources, each accessible from its own tab in the main window. All six feed the same migration cart and the same migration pipeline — a single bulk migration can mix apps from SCCM, a network share, and the WinGet community catalog in any combination.
| # | Source | Best for | Requires SCCM? |
|---|---|---|---|
| 1 | SCCM Applications | Established Configuration Manager environments with a mature application catalog and curated metadata. | Yes (RPC) |
| 2 | Network Share | Small businesses, MSPs, or any environment with installer files on a share but no SCCM. Also useful as a complement to SCCM for apps not yet in the catalog. | No |
| 3 | WinGet community | Modernizing the catalog with Microsoft-maintained common third-party applications (Firefox, 7-Zip, Notepad++, VLC, etc.). The 138 635-package local SQLite index queries in 5–30 ms. | No |
| 4 | Chocolatey community | Apps that exist in the Chocolatey community feed but not in WinGet. SIM auto-generates the install/uninstall/detect PowerShell trio and ships it as a standard Win32 LOB. | No |
| 5 | Intune Enterprise App Catalog (preview) | Search-only in v1.2.0. Microsoft's curated catalog of pre-packaged Win32 apps. Direct import is planned for v1.2.1 — the Microsoft mobileApps / win32CatalogApp endpoint is still in preview. | No |
| 6 | UNC custom catalog | In-house line-of-business installers exposed via a private UNC share with a manifest.json per app. Zero-copy — the installer never leaves the share during selection. | No |
Source 1 — SCCM Applications via WMI
The SCCM Source Browser tab connects to your SCCM site via the standard WMI namespace root\sms\site_<X> (after verifying connectivity through SMS_ProviderLocation) and runs the WQL query SELECT * FROM SMS_Application WHERE IsLatest = 1 AND IsHidden = 0. Only the latest, non-hidden revisions are returned — the same scope you would see in the Configuration Manager console.
For performance, SDMPackageXML — the rich XML blob that holds every deployment type, every install command, every detection rule for an SCCM application — is parsed lazily. The initial listing is fast and returns just the display columns (name, publisher, version, count of deployment types). Full parsing happens only when an application is selected to be added to the migration cart.
Source 2 — Network Share scanning
The Share Browser tab recursively scans a UNC root path looking for installer files. The scanner uses a priority-based detection heuristic: an .msi file in a folder is the strongest signal, followed by named installers (setup.exe, install.exe, installer.exe, autorun.exe), and finally generic .exe files (which can be opted in or out via a checkbox).
When an installer is detected in a folder, the scanner does not recurse below that folder — the installer is assumed to belong to it. This prevents double-counting nested setup files and matches the convention of organized application repositories where each app version sits in its own folder.
Default scan options are reasonable for typical share layouts: depth 3 (root\publisher\app\version), accept any .exe enabled. For massive repositories, depth can be set to Unlimited; for tightly organized shares, depth 1 or 2 reduces noise.
Source 3 — WinGet community catalog
The WinGet Browser tab queries the official Microsoft WinGet source index — a SQLite database listing 138 635 packages maintained by Microsoft and the community. On first use, SIM downloads the 33 MB compressed source from cdn.winget.microsoft.com, extracts it locally to %AppData%\TontonTools\AppMigrator\winget\source.msix, and queries it directly. Subsequent searches complete in 5 to 30 milliseconds — no network call needed after the initial sync.
The search engine runs in three modes for the same query: an exact-ID fast path (e.g. "Mozilla.Firefox" — instant hit), multi-word tokenization for descriptive search (e.g. "firefox web browser"), and fuzzy substring matching as a final fallback. Per-installer-type uninstall command synthesis covers msi, wix, msix, inno, nullsoft, burn, and generic-exe installers. For packages where the WinGet index has only partial metadata, SIM falls back to the WinGet GitHub repository (https://github.com/microsoft/winget-pkgs) to fetch the missing fields.
Source 4 — Chocolatey community feed
The Chocolatey Browser tab queries the Chocolatey community feed via the supported /api/v2/Search() OData entry-set with searchTerm, targetFramework, and includePrerelease parameters. Results stream into the grid as they arrive. When an app is added to the migration cart, SIM auto-generates a 3-script PowerShell wrapper: install.ps1 bootstraps choco.exe if absent before invoking `choco install <id> --version=<v> -y`; uninstall.ps1 mirrors the install with `choco uninstall <id> -y`; detect.ps1 verifies the install. The whole bundle ships as a standard Win32 LOB app, deployable on any Intune-managed device without a pre-installed Chocolatey.
Source 5 — Intune Enterprise App Catalog (preview, search-only in v1.2.0)
The Intune EAC Browser tab searches Microsoft's Intune Enterprise App Catalog via Graph /beta/deviceAppManagement/mobileAppCatalogPackages. Results display alongside other catalogs in the cart's source filter. Direct EAC import is planned for v1.2.1 — the Microsoft mobileApps / win32CatalogApp endpoint is still in preview and currently throws NotSupportedException when invoked programmatically. Until then, use the Intune portal for direct EAC enrolment of the apps you discover here.
Source 6 — UNC custom catalog
The UNC Custom Browser tab points SIM at an internal network share where each subfolder represents a private application package. Each app folder contains a manifest.json with display name, publisher, version, install command, uninstall command, detection rule, and a relative path to the installer file. This is the recommended way to expose in-house line-of-business installers (proprietary line-of-business apps, vendor-specific tooling, ERP plugins) without committing them to a public catalog. The installer never leaves the UNC share during selection; the migration cart references the UNC path directly, and the file is copied to the staging directory only at packaging time.
Multi-tenant workspaces
SIM is multi-tenant by design. The Tenants tab at the right of the main window lists every Intune environment the operator has access to; a dropdown in the title bar switches the active tenant without restarting the tool. Every tab (six source browsers, the Migration Cart, the Migration Report, the Update Manager, the Audit Report) rebinds to the new tenant's storage instantly.
Per-tenant isolation guarantees
- Isolated storage path Each additional tenant has its own folder under %AppData%\TontonTools\AppMigrator\tenants\<id>\ — containing its own credentials.dat, its own cart.json, its own history.json, and its own Intune inventory cache. The Default tenant remains at the suite-wide %AppData%\TontonTools\ path, shared with the rest of the TontonTools products.
- Per-tenant credentials, DPAPI-encrypted Additional-tenant Graph and SCCM credentials are stored in TenantCredentialsStore under the per-tenant folder, encrypted via DPAPI with the same CurrentUser scope as the shared store. The Default tenant credentials are never copied into per-tenant stores — preventing accidental credential bleed across tenants.
- Per-tenant cart and history Adding an app to the cart on Tenant A and then switching to Tenant B shows an empty cart for B (B's own cart). Migration Report rebinds to B's history.json. Pre-v1.2 history files at the legacy path are read transparently as the Default tenant history — backward-compatible by design.
- Auto-detect tenant primary domain When adding an additional tenant, SIM resolves the primary domain via Graph /v1.0/organization at first switch, persists it to tenants.json, and displays it in the Tenants grid with a 🤖 badge. Best-effort and silent on failure — the operator can always type the domain manually.
- Auto-detect SCCM Site Server + Site Code In the Add/Edit Tenant dialog (3 cards: Identity, Graph, SCCM; with a pill toggle between Client Secret, Certificate, and Interactive auth modes), an Auto-detect button reuses the shared SccmDetector (registry ConfigMgr10 → WMI scan) to fill SCCM Server and Site Code without manual entry. If the operator's workstation has no SCCM console MRU registry entry, the SCCM card stays empty and the SCCM Source Browser tab will be disabled for that tenant.
Tenant drift detection — the safety net for MSPs
A typical MSP workflow involves switching tenants several times an hour. The dangerous scenario is: starting a bulk migration on Tenant A, walking away, then coming back and accidentally switching to Tenant B from the dropdown while the migration is still running. Without protection, the orchestrator would happily push the remaining apps to Tenant B — a cross-tenant data leak.
SIM blocks this scenario via TenantContext drift detection. Every long-running operation — bulk migration, audit report generation, catalog scan — snapshots its TenantContext (token, tenant ID, SCCM coordinates) at start and validates against the live ActiveTenant at each iteration. If a switch is detected mid-operation, the orchestrator aborts cleanly, surfaces a MessageBox naming both tenants ("Tenant switched during migration. Jobs already migrated stayed on the original tenant. X remaining job(s) are still Pending."), logs the drift as a red 🚨 entry in the UI panel ("🚨 TENANT SWITCHED DURING MIGRATION — Batch aborted."), and protects in-flight jobs on their original tenant. Already-migrated jobs remain ✅ Done with their IntuneAppId; pending jobs remain ⏳ Pending on the source tenant.
Post-drift state persistence — zero duplicate apps in Intune
Job state (Done / Failed / Pending) is persisted atomically per job to the per-tenant cart.json via UpsertJobForTenant, with write-through on every transition under a shared file lock. On reswitch back to the original tenant, completed jobs reappear ✅ Done with their exact IntuneAppId; a re-click on Start migration skips them via the `if (job.IsCompleted) continue;` guard, producing zero duplicate apps in Intune. This behavior is validated forensically by a triple test on 15 web-link jobs with a mid-batch tenant switch: in every iteration, the operator finds the same 15 apps on the original tenant after reswitching, and zero on the wrong tenant.
Pricing and tiering — Small, Medium, Large
The SCCM to Intune App Migrator is sold as a one-shot perpetual license at three tiers. Unlike the subscription-based Essentials, Pro, and Enterprise products which charge monthly or yearly, the Migrator license is a single purchase that never expires. The tier choice gates only the maximum number of applications that can be processed in a single execution of the migration cart.
| Tier | Apps per migration | Price | Best for |
|---|---|---|---|
| Small | Up to 50 | €3,500 | Small businesses or MSPs migrating ~10–100 applications, typically in one or two campaigns. Also the right choice for share-only environments without SCCM. |
| Medium | Up to 200 | €5,500 | Mid-size environments with ~100–500 applications. Covers most consolidation campaigns from SCCM in 1–3 large bulk migrations. |
| Large | Unlimited | €8,000 | Enterprise environments with 500+ applications, multi-site campaigns, or MSPs serving multiple tenants. No cap, no per-migration planning required. |
A 14-day trial is included with all three tiers and grants Small-equivalent access (up to 50 apps per migration). The trial uses the same code path as a paid Small license and is a faithful preview of the production experience. After the trial, license activation requires the order email and the license key delivered by Lemon Squeezy at purchase time.
Why use a tool instead of writing PowerShell
Migrating Win32 LOB applications to Intune via Microsoft Graph is possible in PowerShell — the API surface is public and well-documented in places. In practice, the moving parts that need to be implemented correctly to get a single Win32 LOB upload to succeed are surprisingly extensive. SIM solves all of them in a unified pipeline; an honest list of what would have to be reimplemented in a script appears below.
- .intunewin packaging via the official Microsoft IntuneWinAppUtil.exe Spawning the process with the correct -c/-s/-o/-q flags, capturing stdout and stderr, applying a sensible timeout (20 minutes), handling its exit codes, and resolving its path either from an override location or from an embedded resource. SIM ships the binary inside the executable so no separate download is needed.
- AES-256-CBC + HMAC-SHA256 + SHA-256 encryption per ProfileVersion1 Intune accepts only encrypted .intunewin uploads, in a specific format the documentation describes thinly: a 32-byte HMAC over (IV || ciphertext) prepended to a 16-byte IV prepended to the ciphertext, all under PKCS7 padding, with the encryption key, MAC key, IV, MAC, and a SHA-256 digest of the plaintext base64-encoded and sent in a separate JSON payload at commit time. The profileIdentifier string must be exactly "ProfileVersion1". One byte off and the commit step fails with the cryptic "fileInvalid" error.
- Azure Blob chunked upload via SAS URI The encrypted file must be uploaded in 6 MB blocks (configurable) to an Azure Blob Storage SAS URI provided by Graph, each block PUT with a base64-encoded block ID, the BlockBlob type header, and the correct comp=block query parameter. After all blocks are uploaded, a separate PUT with comp=blocklist commits the block manifest as an XML document. For large files, the SAS URI can expire mid-upload and must be renewed via a Graph call before the commit can proceed.
- Polling Graph for asynchronous state transitions Three separate polling loops are required: one for azureStorageUriRequestSuccess (the SAS URI is ready), one for azureStorageUriRenewalSuccess (the SAS URI was successfully renewed for the commit), and one for commitFileSuccess (the encryption parameters were validated). Each loop needs an exponential backoff strategy (2s → 60s ceiling), a configurable deadline (default 10 minutes), and distinct handling of the failure states (azureStorageUriRequestFailed, azureStorageUriRenewalFailed, commitFileFailed).
- MSI metadata extraction via Windows Installer COM Late binding to the WindowsInstaller.Installer ProgID, opening the database in read-only mode, querying the property table for ProductCode / ProductName / ProductVersion / Manufacturer / Language, reading the Template summary property for architecture detection, and releasing COM objects in the correct order to avoid handle leaks. No NuGet package — the implementation has to be a hand-rolled COM client.
- Idempotent cleanup of partially-created apps If the pipeline fails after the initial POST creates the Win32LobApp shell, the orphan record stays in the tenant forever unless explicitly deleted. SIM wraps the entire pipeline in a try/catch that DELETEs the shell on any failure. A script must do the same — and must reliably know which app ID to delete.
- Detection rule construction with priority logic Intune accepts several detection rule types — MSI ProductCode, file system existence, registry value, custom script. SIM prefers ProductCode when an MSI was detected (the most reliable rule), falls back to a file system rule pointing at %ProgramFiles%\<Publisher>\<Installer> when not, and includes the check32BitOn64System flag based on the detected architecture. A script needs the same decision tree, or every detection rule has to be hand-crafted.
- Persistent audit trail with success and failure records Every migration — succeeded or failed — should be tracked with start time, completion time, duration, Intune App ID (when available), portal URL, assignment summary, and error message. SIM persists this to JSON in %AppData% and exports to CSV on demand. A script can produce a log file, but a structured queryable history is more work.
- CMTrace-compatible logging with thread safety For SCCM administrators, CMTrace remains the canonical log viewer. SIM emits the exact CMTrace XML envelope format (time, date, component, context, type, thread, file) and serializes writes via a global lock. A script would either skip CMTrace formatting (and lose the colour coding) or reimplement it.
None of this is exotic, but the combined development and maintenance effort — including the discovery of the undocumented encryption format details — is what justifies a dedicated tool. SIM packages all of it behind a single "Start migration" button.
The Win32 LOB pipeline — 9 steps
For every Win32 LOB migration job, the orchestrator runs a 9-step pipeline. Each step is observable from the UI via the per-row progress bar and state column (📦 Staging → 🛠️ Packaging → 🆕 Creating app → 🔗 Requesting upload → ⬆️ Uploading → 💾 Committing → 🎯 Assigning → ✅ Done). The tabs at the bottom of the Bulk Migration grid keep a live log of every Graph and Azure Blob call.
- 1
1. Stage — copy source content to local working directory
The source content path (UNC share or local folder, inherited from SCCM or detected by the share scanner) is recursively copied to C:\TEMP\AppMigrator\job_<id>\stage. This isolates the packaging input from the source and lets the pipeline operate on stable local files regardless of network hiccups during packaging.
- 2
2. Package — invoke IntuneWinAppUtil.exe
Microsoft's official IntuneWinAppUtil.exe is invoked as a child process with the canonical flags (-c <stage> -s <installer> -o <output> -q). The 20-minute timeout protects against runaway packaging. Stdout and stderr are captured to the CMTrace log. The resulting .intunewin file is itself a ZIP archive containing the encrypted payload and a Detection.xml manifest.
- 3
3. Encrypt — AES-256-CBC + HMAC-SHA256
The .intunewin is encrypted to a temporary file with a freshly-generated 32-byte AES key, 32-byte HMAC key, and 16-byte IV (all from RNGCryptoServiceProvider). The output layout is exactly [HMAC 32 bytes][IV 16 bytes][AES-CBC ciphertext]. A SHA-256 digest of the original plaintext is also computed — this digest is sent in the commit payload and is what Intune uses to verify integrity end-to-end.
- 4
4. Create app shell — POST /deviceAppManagement/mobileApps
The Win32LobApp shell is created in Intune via a Graph POST with the @odata.type set to #microsoft.graph.win32LobApp. The shell carries the display name, publisher, description, install/uninstall command lines, install experience (system or user context, suppress device restart), minimum Windows release, applicable architectures, default MSI return codes (0/1707/3010/1641/1618), and the detection rules. The Intune App ID returned here is reused throughout the rest of the pipeline.
- 5
5. Create content version + declare file metadata
A new content version is created under the app, then the encrypted file is declared with its plaintext size, encrypted size, and a manifest placeholder. Intune responds with a file ID that drives the next polling loops.
- 6
6. Poll for Azure Storage SAS URI
Intune asynchronously provisions an Azure Blob Storage SAS URI that grants temporary write access to a dedicated container. The pipeline polls the file resource with exponential backoff (2s → 60s ceiling) until uploadState transitions to azureStorageUriRequestSuccess. The default deadline is 10 minutes, configurable in App.config.
- 7
7. Upload encrypted chunks to Azure Blob
The encrypted file is uploaded to the SAS URI in 6 MB blocks (configurable). Each block is PUT with a base64-encoded block ID, application/octet-stream content type, and the x-ms-blob-type BlockBlob header. Progress is reported to the UI in real-time (25% to 80% range). After all blocks are uploaded, a final PUT with comp=blocklist commits the block manifest as an XML document.
- 8
8. Renew SAS + commit with encryption info
For large files, the original SAS URI can be close to expiry by the time all chunks are uploaded. The pipeline calls renewUpload, polls for azureStorageUriRenewalSuccess, then POSTs the commit payload containing the fileEncryptionInfo (base64 encryption key, MAC key, IV, MAC, profileIdentifier "ProfileVersion1", file digest, and "SHA256" as the digest algorithm). Intune validates the encryption asynchronously; the pipeline polls for commitFileSuccess.
- 9
9. Patch the app with committedContentVersion
The final step PATCHes the Intune app to link the content version that just finished committing. Because .NET Framework 4.7.2 has no PatchAsync method, this uses an HttpRequestMessage with the PATCH verb. The app is now visible and assignable in the Intune portal.
Web Link and winget app types skip steps 1 through 9 entirely. A single Graph POST creates the app (with @odata.type set to #microsoft.graph.webApp or #microsoft.graph.winGetApp), and the orchestrator proceeds directly to optional group assignment. This is why these two target types complete in seconds rather than minutes.
Prerequisites
| Requirement | Minimum |
|---|---|
| Operating system | Windows 10 22H2 or Windows 11 (administrator workstation only — SIM is not installed on managed endpoints) |
| .NET Framework | 4.7.2 or later |
| Disk space | ~2× the largest source application — used for staging, packaging, and encryption working directories under C:\TEMP\AppMigrator. Cleaned up after each job. |
| SCCM connectivity (optional) | Required only if sourcing from SCCM Applications. RPC access (TCP 135 + dynamic high ports) to the SCCM site server. The Windows account running SIM must have at least Application Administrator role in SCCM. The Configuration Manager console does NOT need to be installed on the workstation — SIM uses raw WMI. |
| Microsoft Graph App Registration | An Entra ID App Registration with delegated or application permissions for DeviceManagementApps.ReadWrite.All and Group.Read.All. The Tenant ID, Client ID, and authentication method (Client Secret or Certificate) are entered once in the Credentials dialog and stored DPAPI-encrypted under the current Windows user profile. |
| IntuneWinAppUtil.exe | Bundled with SIM as an embedded resource. An optional override path is supported via App.config (default C:\TEMP\IntuneWinAppUtil.exe) for environments that want to pin a specific Microsoft release. |
| Network egress | Outbound HTTPS to graph.microsoft.com (Graph API, api-version=2025-07-02 for Win32 LOB and beta for Intune Enterprise App Catalog search), *.blob.core.windows.net (Azure Blob upload), cdn.winget.microsoft.com (WinGet source index download, ~33 MB on first use), api.endoflife.date (EOL registry refresh, weekly), community.chocolatey.org (Chocolatey OData feed), raw.githubusercontent.com (WinGet GitHub fallback for missing manifests), and api.lemonsqueezy.com (license validation, at most weekly). |
| Multi-tenant (optional) | No additional configuration required. Adding an additional tenant via the Tenants tab provisions its own isolated %AppData%\TontonTools\AppMigrator\tenants\<id>\ folder on the fly. Per-tenant Graph permissions are scoped against each tenant's own Entra App Registration. The Default tenant remains shared with the rest of the TontonTools suite. |
| License tier | Small / Medium / Large one-shot license, or active 14-day trial. The trial grants Small-equivalent access. |
For the full licensing model — trial mechanics, machine and tenant binding, moving a license between workstations, refunds — see the Licensing reference. For the exact Microsoft Graph permissions required and how to scope them tightly, see the Microsoft Graph permissions reference.
Initial configuration
On first launch, SIM follows a deliberate startup sequence that ensures licensing is resolved before any credentials are requested — there is no point asking for SCCM or Graph credentials from a user who is not licensed to use the tool.
- 1
1. License check
The license dialog appears first. Accepted license configurations include a 14-day Trial (Small-equivalent), Small (50 apps), Medium (200 apps), and Large (unlimited). The trial does not require an order email — it is granted immediately on first launch and persists DPAPI-encrypted on the workstation. Paid licenses are activated by entering the order email and license key from the Lemon Squeezy delivery email.
- 2
2. License tier banner
Once licensed, a permanent banner at the top of the window displays the current tier (Trial — copper background, Small/Medium — green, Large — premium violet). For Trial and Small/Medium tiers, an inline "Buy a license" button opens the license dialog for upgrade or activation. Large tier hides the button — no upsell.
- 3
3. Credentials dialog
The unified TontonTools credentials dialog opens with Graph + SCCM fields populated. SCCM server and site code are auto-detected silently when possible. Manual entry is offered as a fallback. Both Client Secret and Certificate authentication are supported for Graph.
- 4
4. Tenant resolution + Graph token cache
The Graph access token is acquired once and cached in the MainWindow shared context. The tenant display name and primary domain are fetched and shown in the header. From this point on, every tab reuses the same token until the user clicks the "Credentials" button to re-prompt.
- 5
5. Default tenant ready, additional tenants optional
On first launch, SIM operates against a single Default tenant — the one whose credentials are stored at the suite-wide %AppData%\TontonTools\credentials.dat path and shared across all TontonTools products. MSPs and consultants who manage multiple customer environments can later open the Tenants tab and click "Add tenant" to provision additional tenants. Each additional tenant gets its own isolated storage folder, its own Graph credentials, and (optionally) its own SCCM coordinates. Switching between tenants happens via the dropdown in the title bar; every tab rebinds automatically.
- 6
6. Tabs ready
The seven tabs (SCCM Source Browser, Share Browser, WinGet Browser, Chocolatey Browser, Intune EAC Browser, UNC Custom Browser, Manual Create, Migration Cart, Migration Report, Update Manager, Tenants) initialize their shared context and display their welcome messages. The status bar shows "Ready." and the migration cart is empty.
Main features — a tour of the tabs
The main window is organized as a TabControl whose tabs share a common context (Graph token, SCCM connection, license tier, migration cart, history store, active tenant). Each tab has a focused responsibility: pick a source, build jobs, run migrations, review results, patch what is outdated, audit the catalog, manage tenants. v1.2.0 introduces four new tabs on top of the original five — four new source browsers (WinGet, Chocolatey, Intune EAC, UNC custom), an Update Manager, and a Tenants management tab.
🔍 SCCM Source Browser
The first tab discovers applications already cataloged in SCCM. Clicking "Load SCCM apps" runs the WMI connectivity check, then enumerates SMS_Application via WQL and populates a sortable, filterable grid. The grid columns expose Display Name, Publisher, Version, Number of Deployment Types, Last Modified, and the Selection checkbox. A free-text filter narrows results across name, publisher, and version simultaneously. The footer counter shows visible / total counts as the filter is typed.
Selecting one or more rows and clicking "Add to cart" triggers lazy parsing of SDMPackageXML for each selected app. For every deployment type found, a separate migration job is created — Display Name combines the app name and the deployment type name (e.g. "Adobe Reader DC - x64"), Install/Uninstall commands inherit from the deployment type, ProductCode is captured when present, and the Source Content Path is set to the SCCM deployment type ContentLocation. The installer file name is best-effort extracted from the install command line (handles msiexec /i "<path>.msi" patterns and simple .exe invocations).
📁 Share Browser
The Share Browser tab scans a UNC root path for installer files. The toolbar exposes three knobs: Root path (defaults to \\srv-app\Apps$ but can be any UNC or local path), Depth (1 / 2 / 3 / Unlimited — defaults to 3, matching typical \\srv\Apps\Publisher\App\Version layouts), and "Accept any .exe" (when enabled, allows generic .exe files to be detected as installers; when disabled, only named installers like setup.exe / install.exe / installer.exe / autorun.exe count, plus MSI files which are always detected).
The scanner is asynchronous and reports its progress in the tab log every 10 folders (throttled to keep the UI smooth). The result grid exposes Display Name (auto-detected from MSI metadata when possible), Publisher, Version, Type (MSI / EXE / Script), Architecture, Installer file name, and Folder path. Adding selected apps to the cart inherits all auto-detected metadata — the operator can adjust anything in the Migration Cart tab before launching.
🎯 Manual Create
The Manual Create tab is for situations where neither SCCM nor a share scan is the right starting point — typically when migrating a single Web Link or a single winget app. A target type selector (Win32 LOB / Web Link / Microsoft Store via winget) progressively shows the relevant input fields and hides the irrelevant ones. Required fields are validated on submit; missing values produce an inline log entry rather than a popup.
For Win32 LOB, the required fields are Display Name, Publisher, Source Content Path, Installer file name, and Install command. Optional fields cover Description, Version, Uninstall command, ProductCode (for MSI detection rules), Architecture, Install context, and Minimum OS. For Web Link, only the Web URL is required. For winget, only the Package identifier (e.g. Mozilla.Firefox). All target types support optional group assignment in the same form.
Clicking "Run migration" executes the orchestrator inline (without going through the cart) and shows the live 9-step progress in a per-form progress bar. This is the fastest path for a single migration — no cart manipulation, just fill in the form and run.
🛒 Migration Cart
The Migration Cart is where bulk migrations are reviewed and launched. Every job added from the SCCM Source Browser, the Share Browser, or (programmatically) from any other source appears here as a row in the central DataGrid. The grid columns are Display Name, Publisher, Type (Win32 LOB / Web Link / winget), Source (SCCM / Share / Manual), Group (an inline ComboBox listing the available Entra security groups), Intent (Available / Required / Uninstall), State, Progress bar, and Last message.
Group assignment is configured per row, not per batch. Clicking "Load Entra groups" populates the ComboBox with all security-enabled groups from the tenant (paginated via @odata.nextLink up to 999 groups per page, sorted by display name). Selecting a group for a row updates that job's assignment summary. Rows without a group selected will skip the assignment step at the end of their pipeline — the app will be created in Intune but unassigned, ready for manual assignment in the portal.
The toolbar shows a live counter — for example "47 / 50 job(s) - Small tier" — that turns orange-red when the cart exceeds the tier limit. Clicking "Start migration" runs a pre-flight check against the tier limit before launching; if the cart is over the limit, the migration is blocked with a clear upgrade message rather than failing partway through.
When the batch completes, the toolbar summary shows ✅ success and ❌ failure counts. Already-completed jobs (Done or Failed) are not re-executed if the user clicks "Start migration" again — they are skipped. To remove all jobs from the cart and start fresh, the "Clear cart" button asks for confirmation and empties the ObservableCollection (the underlying jobs already persisted to history are preserved).
📊 Migration Report
The Migration Report tab is the audit-trail view. It loads the persisted history from %AppData%\TontonTools\AppMigrator\history.json and displays every recorded job — successes and failures — in a sortable grid. The columns include Job ID, Display Name, Publisher, Version, Target Type, Source Type, Source Label, State, Error message, Intune App ID, Intune Portal URL, Assignment Summary, Started At, Completed At, and Duration.
Double-clicking any row that has a successful Intune App ID opens the application directly in the Microsoft Intune admin portal (https://intune.microsoft.com — the URL is pre-built per record). This makes the report a live navigation surface, not just a static log.
The toolbar exposes four actions: 🔄 Refresh (re-read history.json from disk), 📤 Export CSV (semicolon-delimited export with all columns, named AppMigrator-history-<timestamp>.csv), 📋 Open log (opens the CMTrace log file C:\TEMP\AppMigrator.log in CMTrace.exe if installed, or the default associated viewer otherwise), and 🗑 Clear history (with confirmation — irreversible).
🔄 Update Manager
The Update Manager tab scans the Intune inventory of the active tenant, cross-references each app against the six configured catalog sources (SCCM, WinGet, Chocolatey, Intune EAC, UNC custom, Network Share), and surfaces outdated apps as update candidates. For each candidate, the operator chooses one of two strategies — Replace content or Supersede with new app.
- Replace content POST a new contentVersion on the existing Intune app, keeping the same AppId, assignments, supersedence relationships, and dependencies intact. The new content is uploaded through the same 9-step pipeline, then committed against the existing app. Devices already targeted by the old version will pick up the new content on their next assignment evaluation. Best fit for patch releases (a security patch on 7-Zip, a minor version on Firefox) where the ProductCode usually stays the same.
- Supersede with new app Create a fresh Win32 LOB app under a new AppId and declare a supersedence relationship to the predecessor — the operator can choose between uninstall-supersedence (old version is removed before the new one installs) and replace-supersedence (new installs over the old). Devices targeted at the old app will gradually receive the new app per Intune's standard supersedence policy. Best fit for major versions with a new ProductCode (e.g. Notepad++ 8.x → 9.x, Visual Studio Code annual versions).
- EOL detection per app Each app in the Intune inventory is matched against the public endoflife.date registry (450+ products, weekly-refreshed local cache at %AppData%\TontonTools\AppMigrator\eol\index.json). Four risk levels surface in the grid with colour-coded badges: 🟢 Supported, 🟡 Approaching EOL (within 6 months), 🔴 EOL passed, ⚪ Unknown. EOL information is informational — the Update Manager does not auto-quarantine EOL apps; the operator decides whether to upgrade, replace, or accept the risk.
📄 HTML Audit Report
The HTML Audit Report tab generates a single self-contained, print-ready HTML report (A4-formatted, brandable with the operator's logo via App.config) covering the state of the active tenant. Generation takes 10 to 30 seconds against a typical tenant; the output is saved to Documents\TontonTools\AppMigrator\Reports\Audit_<tenant>_<timestamp>.html and can be opened in any browser and exported to PDF via Ctrl+P.
- Cover page Tenant display name, tenant primary domain, report generation date, operator Windows user, AppMigrator version.
- Executive summary cards Total apps in Intune, total apps with available updates, total apps at or near EOL, total apps not found in any catalog (manual maintenance candidates), AppMigrator coverage progress (apps migrated by SIM vs total).
- Full Intune inventory Every app with display name, publisher, version, install context, supersedence chain, assigned groups + intents, EOL badge.
- Available updates by catalog source Outdated apps grouped by their catalog source (SCCM, WinGet, Chocolatey, Intune EAC, UNC custom), with the current Intune version and the latest catalog version side by side.
- EOL risk analysis A focused section listing every app at or near EOL with the EOL date, days remaining (or days past), and the recommended action (upgrade / supersede / retire).
- AppMigrator coverage progress A horizontal progress bar showing the share of the Intune inventory that was migrated by SIM vs. created manually or by other means. Useful for project managers tracking a migration campaign at the executive review.
- Last 20 migrations The 20 most recent jobs from the per-tenant history.json, with their state, target type, source, and timing. Provides recent-activity context without paging through the full audit log.
🏢 Tenants
The Tenants tab is the management surface for the multi-tenant architecture. It shows a grid of every tenant the operator has configured (Default + additional tenants), with columns for display name, primary domain, Graph auth mode (Client Secret / Certificate / Interactive), SCCM coordinates (if any), and last-used timestamp. Toolbar actions: ➕ Add tenant (opens the Add/Edit Tenant dialog), ✏️ Edit selected, 🗑 Remove selected (with confirmation, irreversible — removes the per-tenant folder), and 🔄 Refresh (re-reads tenants.json from disk).
The Add/Edit Tenant dialog is organized as 3 cards. Identity card — tenant display name, primary domain (auto-detectable via Graph /v1.0/organization with the 🤖 badge), tenant ID. Graph card — a pill toggle for the auth mode (Client Secret / Certificate / Interactive with PKCE), with the relevant fields appearing below. SCCM card — Site Server FQDN and Site Code, with an Auto-detect button that reuses the shared SccmDetector (registry ConfigMgr10 then WMI scan).
License & tiering banner
Because the Migrator license is a one-shot perpetual purchase with three distinct tiers, the running tier is shown permanently in a banner at the top of the window — not just at startup. The banner uses three distinct colour codes so that operators (and project managers reviewing screenshots) can recognize at a glance which tier is active.
| Banner state | Colour | Message | Buy button |
|---|---|---|---|
| Trial active | Copper (#A0623A) | Trial mode — Small tier (up to 50 apps) — N days remaining. Buy a license to unlock more. | Yes — primary |
| Trial expired | Copper (#A0623A) | Trial expired — please purchase a license to continue. | Yes — primary |
| Small tier | Sober green (#16783B) | Small tier — Up to 50 apps per migration. Need more? Upgrade to Medium or Large. | Yes — upsell |
| Medium tier | Sober green (#16783B) | Medium tier — Up to 200 apps per migration. Need unlimited? Upgrade to Large. | Yes — upsell |
| Large tier | Premium violet (#6F42C1) | Large tier — Unlimited apps per migration. Thank you for your purchase! | No |
Clicking the inline "Buy a license" button reopens the license dialog in an informational mode that lets the operator enter a Lemon Squeezy order email and license key for activation or upgrade. After activation, the tool prompts for a restart to reload the license context cleanly.
Typical workflow — a full migration campaign
The following walk-through illustrates a realistic mid-size SCCM-to-Intune application migration of about 30 applications, mixed Win32 LOB and winget targets. It assumes a Medium tier license is in place and that Graph + SCCM credentials have already been configured.
- 1
1. Audit the SCCM application catalog
Open the SCCM Source Browser, click "Load SCCM apps", and let SIM enumerate the latest applications. Use the filter to find common third-party apps — Mozilla Firefox, 7-Zip, Notepad++, VLC, Adobe Reader. These will become winget targets, not Win32 LOB. Note their display names and decide which ones to migrate via winget.
- 2
2. Build the winget batch in Manual Create
Switch to the Manual Create tab. For each common app identified in step 1, select "Microsoft Store (winget)" as the target, enter the display name and the package identifier (e.g. Mozilla.Firefox), and click "Run migration". Each winget app takes a few seconds to create in Intune. They will all appear in the Migration Report tab when done.
- 3
3. Add line-of-business apps to the cart from SCCM
Back in the SCCM Source Browser, select the genuinely in-house applications — the ones with custom installers, internal tooling, vendor-specific packages. Click "Add to cart". Each selected SCCM application produces one job per deployment type. Verify the cart counter — if you have 25 SCCM apps with an average of 1.6 deployment types each, the cart will show ~40 jobs.
- 4
4. Configure assignments per app in the cart
In the Migration Cart tab, click "Load Entra groups". Per row, pick the target group from the ComboBox (e.g. "All-Engineering" for developer tools, "All-Finance" for accounting software) and set the intent (Available for self-service, Required for mandatory installation). Rows left without a group will be created in Intune without assignment — appropriate for testing or staged rollouts.
- 5
5. Launch the bulk migration
Click "▶ Start migration". The pre-flight check confirms the cart is within the Medium tier limit (200 max). Migration starts. The per-row state column ticks through 📦 Staging → 🛠️ Packaging → ⬆️ Uploading → 💾 Committing → 🎯 Assigning → ✅ Done. Progress bars update in real-time. The log panel at the bottom records every Graph call and every Azure Blob block upload.
- 6
6. Review the campaign in the Migration Report
Once the batch completes, switch to the Migration Report tab. Sort by State to find any ❌ Failed jobs and read their ErrorMessage column. Double-click a successful row to open the app directly in the Intune portal and verify the install command, detection rule, and assignment. Click "📤 Export CSV" to produce a Excel-ready record of the campaign for the project documentation.
For very large campaigns spanning a Small license (say 300 apps to migrate, 50 per batch), the same workflow repeats over 6 successive runs of the cart. The license is perpetual, so this is exactly how SIM is designed to be used.
Limitations and design choices
SIM is deliberately scoped to do one thing well: move an application from SCCM (or a share) to Intune as a fresh, clean Intune app. Several SCCM concepts are intentionally not carried over because they either have no direct Intune equivalent, or because they create more problems than they solve when migrated automatically.
What is NOT migrated
- Application dependencies SCCM lets you declare that app A requires app B (cascade install). Intune has a different dependency model and the cascade behaviour is not equivalent. SIM does not attempt to translate dependencies automatically — the operator declares dependencies manually in the Intune portal after migration if needed.
- Supersedence relationships SCCM supersedence (app X replaces app Y on install) is not carried over. Intune has its own supersedence model that requires both the new and old apps to exist in Intune first; SIM creates fresh apps without superseding pre-existing Intune apps.
- Complex requirement rules SCCM requirement rules (minimum RAM, free disk space, registry key checks, AD group membership, OS architecture) are not translated. SIM populates only the minimum-OS and applicable-architectures fields from auto-detected metadata. Other requirements must be added manually in Intune after migration if needed.
- Custom detection script logic For SCCM applications using a custom PowerShell or VBScript detection method, the raw XML of the detection method is captured but is NOT automatically rewritten as an Intune detection rule. SIM falls back to a generic file-system rule pointing at %ProgramFiles%\<Publisher>\<Installer>. The operator should review and refine the detection rule in the Intune portal after migration.
- Maintenance windows and schedules SCCM maintenance windows are an SCCM-specific concept with no Intune equivalent. Intune handles installation timing differently (deadlines on Required assignments). Reconfigure timing per assignment after migration.
- User affinity and primary user rules SCCM user-device affinity is not translated. Intune scopes assignments to groups (devices or users), which is a different model.
- Distribution point preferences and content boundaries In Intune, content is hosted in Azure Blob Storage. There is no concept of distribution points. These SCCM settings are silently dropped — the migration produces a cloud-hosted Intune app, which is the point.
- Deployment status of pre-existing SCCM deployments SCCM tracks which devices have already received the app via deployment status. This deployment state is not carried to Intune. Once an Intune app is created and assigned, Intune starts its own assignment status tracking from scratch.
When SIM is not the right tool
Honest about the cases where SIM is the wrong choice — counter-intuitively, this is what enterprise buyers value most:
- Fewer than 10 apps to migrate, one time A perpetual €3,500 license for a one-off migration of 5 applications is overkill. A throwaway PowerShell script that runs through the 9-step pipeline for each app is the right tool. SIM exists to amortize the engineering effort across many migrations or many campaigns.
- Apps with critical dependency chains If your application portfolio relies heavily on SCCM dependency cascades that must work identically in Intune (which has a different model), SIM's clean-slate migration approach will leave gaps that need expert post-migration repair. In that case, plan for a full Intune redesign — SIM accelerates the technical migration, but does not replace the design work.
- Apps with bespoke MSI transforms or complex install scripts SIM does not transform install commands. The exact install command line in SCCM is carried verbatim to Intune. If the SCCM install command relies on environment-specific paths (UNC mappings, drive letters), those must be reviewed and rewritten for the Intune Win32 LOB execution context before migration.
- Pure user-targeted apps with no install context SIM defaults Win32 LOB to system context. For apps that must run in user context (some SaaS-installer wrappers, user profile customizations), this can be overridden per job, but verify that Intune's user-context execution model fits your use case before relying on it at scale.
v1.2 known limitations
A handful of items in v1.2.0 are deliberately scoped down or wait for a Microsoft API to come out of preview. They are surfaced here for transparency — the v1.2.1 release plan addresses them.
- Intune Enterprise App Catalog — search-only, not direct import The Microsoft EAC import endpoint (mobileApps / win32CatalogApp) is still in preview and currently throws NotSupportedException when invoked programmatically. SIM v1.2.0 supports search and metadata display but routes the actual enrolment through the Intune portal. Direct EAC import is planned for v1.2.1 once Microsoft stabilizes the API surface.
- SCCM supersedence relationships — not auto-propagated SCCM applications often declare supersedence (App X supersedes App Y on install). SIM v1.2.0 captures the relationship in the migration cart but does not auto-create the equivalent supersedence in Intune — the model is different and auto-translation produces wrong results more often than right. The Update Manager's Supersede with new app strategy is the supported path: pick a predecessor manually when creating the new app.
- Custom SCCM detection methods — captured, not auto-rewritten For SCCM applications using a custom PowerShell or VBScript detection method, the raw XML of the detection method is captured but is NOT automatically rewritten as an Intune detection rule. SIM falls back to a generic file-system rule pointing at %ProgramFiles%\<Publisher>\<Installer>. The operator should review and refine the detection rule in the Intune portal after migration. This is intentional — automated rewriting of custom scripts is high-risk for misdetection on the device.
- Application dependencies — manual in Intune SCCM dependency cascades (App A requires App B) are not auto-translated. Intune has a different dependency model that requires explicit declaration per app — declare dependencies manually in the Intune portal after migration where needed.
- EOL detection — informational, no auto-quarantine The Update Manager surfaces EOL apps with colour-coded badges but does not auto-disable them or auto-create supersession candidates. The operator decides — some EOL apps are kept on purpose (legacy line-of-business with no migration path). The Audit Report flags them; the action stays human.
Technical notes
Microsoft Graph endpoints used
| Operation | Endpoint |
|---|---|
| Create Win32 LOB app shell (v1.2 schema) | POST /v1.0/deviceAppManagement/mobileApps?api-version=2025-07-02 (rules + msiInformation) |
| Create content version | POST /v1.0/deviceAppManagement/mobileApps/{id}/microsoft.graph.win32LobApp/contentVersions |
| Declare file metadata | POST .../contentVersions/{cvId}/files |
| Poll file state | GET .../files/{fileId} |
| Renew Azure Storage SAS | POST .../files/{fileId}/renewUpload |
| Commit with encryption info | POST .../files/{fileId}/commit |
| Link committed content version to app | PATCH /v1.0/deviceAppManagement/mobileApps/{id} |
| Cleanup on failure | DELETE /v1.0/deviceAppManagement/mobileApps/{id} |
| Create Web Link app | POST /v1.0/deviceAppManagement/mobileApps (with #microsoft.graph.webApp) |
| Create winget app | POST /v1.0/deviceAppManagement/mobileApps (with #microsoft.graph.winGetApp) |
| List Entra security groups | GET /v1.0/groups?$filter=securityEnabled eq true&$top=999 |
| Assign app to group | POST /v1.0/deviceAppManagement/mobileApps/{id}/assign |
| Auto-detect tenant primary domain | GET /v1.0/organization |
| Replace content on existing app (Update Manager) | POST .../mobileApps/{id}/microsoft.graph.win32LobApp/contentVersions (new content version on same AppId) |
| Declare supersedence relationship (Update Manager) | POST .../mobileApps/{newAppId}/relationships |
| Search Intune Enterprise App Catalog (preview) | GET /beta/deviceAppManagement/mobileAppCatalogPackages |
Encryption format (ProfileVersion1)
- Algorithm AES-256-CBC for content, HMAC-SHA256 for integrity, SHA-256 digest of plaintext for end-to-end verification.
- Key generation RNGCryptoServiceProvider for the 32-byte AES key, 32-byte HMAC key, and 16-byte IV — all cryptographically random per file.
- File layout [HMAC 32 bytes][IV 16 bytes][AES-CBC ciphertext with PKCS7 padding] — exactly what Intune expects for ProfileVersion1.
- Commit payload All keys/IV/MAC base64-encoded, plus the plaintext SHA-256 digest, plus profileIdentifier="ProfileVersion1" and fileDigestAlgorithm="SHA256".
Configuration paths and constants
| Item | Default |
|---|---|
| Working directory | C:\TEMP\AppMigrator (overridable in App.config) |
| Azure Blob chunk size | 6 MB (overridable in App.config) |
| Polling timeout | 600 seconds (overridable in App.config) |
| HTTP client timeout | 20 minutes |
| Polling backoff | Exponential 2s → 60s ceiling |
| Graph throttling handling | Retry-After honored (cap 60s) + up to 5 retries with exponential backoff on 429 and 503 |
| CMTrace log path | C:\TEMP\AppMigrator.log (entries include active tenant display name) |
| Default tenant history JSON | %AppData%\TontonTools\AppMigrator\history.json (legacy path, shared with v1.0.0 install) |
| Additional tenant history JSON | %AppData%\TontonTools\AppMigrator\tenants\<id>\history.json |
| Additional tenant cart JSON | %AppData%\TontonTools\AppMigrator\tenants\<id>\cart.json |
| Additional tenant credentials | %AppData%\TontonTools\AppMigrator\tenants\<id>\credentials.dat (DPAPI CurrentUser, never copied to suite-wide store) |
| Tenants registry | %AppData%\TontonTools\AppMigrator\tenants.json (list of configured tenants, no secrets) |
| WinGet source index | %AppData%\TontonTools\AppMigrator\winget\source.msix (33 MB, refreshed manually) |
| EOL local cache | %AppData%\TontonTools\AppMigrator\eol\index.json (refreshed weekly from api.endoflife.date) |
| HTML audit report output | Documents\TontonTools\AppMigrator\Reports\Audit_<tenant>_<timestamp>.html |
| IntuneWinAppUtil.exe override | C:\TEMP\IntuneWinAppUtil.exe (if present), else embedded resource |
| Default tenant credentials storage | DPAPI-encrypted under %AppData%\TontonTools\credentials.dat (shared with all TontonTools products on the same user account) |
Operational details
- TLS 1.2 forced at startup For Windows Server 2016 compatibility, the application explicitly sets ServicePointManager.SecurityProtocol to TLS 1.2 before any network call.
- JSON parser JavaScriptSerializer (System.Web.Extensions) — no Newtonsoft, no NuGet, no external JSON dependency. MaxJsonLength is raised to 50 MB to handle large Graph responses.
- Authentication Microsoft Graph token obtained via Client Secret or Certificate (JWT Client Assertion). The token is acquired once at startup and cached in the MainWindow shared context.
- CMTrace logger Thread-safe (global lock), writes the canonical CMTrace XML envelope with time, date, component, context, type, and thread ID. Opens cleanly in CMTrace.exe with severity colour coding.
- No telemetry, no agent SIM runs entirely from the administrator workstation. The only outbound connections are graph.microsoft.com, *.blob.core.windows.net, and api.lemonsqueezy.com for license validation (at most weekly).
SIM writes a CMTrace-compatible log to C:\TEMP\AppMigrator.log. Every Graph call, every Azure Blob block upload, every state transition, and every license check is logged with timestamp, executing Windows user, severity, and verbatim response. Open with CMTrace.exe (shipped with SCCM) for coloured real-time viewing.
For a full inventory of the Microsoft Graph permissions used by SIM and the rest of the TontonTools suite, see the Microsoft Graph permissions reference. For the licensing model and trial mechanics, see the Licensing reference. For security and data-handling principles across the suite, see Security & Data Handling.