J
jonasoh
Hi, Jonas here!
Or as we say in the north of Germany: "Moin Moin!"
I’m a Microsoft Cloud Solution Architect and a while back I was asked on how to migrate ConfigMgr apps to Intune. The result is a PowerShell script which can be used to analyze ConfigMgr apps and migrate them to Intune.
This article starts with a general overview about the process and contains an FAQ section instead of long text sections explaining everything in detail.
If you haven’t seen my other articles yet, feel free to check them out here: Core Infrastructure and Security Blog
Preparation
Before running any migration step, it is important to validate if a migration makes sense and saves time and resources compared to new apps created in Intune.
That decision depends on the following factors:
- How many apps need to be migrated
- If the apps we want to migrate can be migrated at all
- If the migration would save time and resources compared to creating new apps in Intune
- If there is an automated process in place to create apps in ConfigMgr, it might be better to change the process to automatically create the same apps in Intune and not migrate anything from ConfigMgr
- If you are licensed to use the Intune Enterprise App Catalog. Take a look at the catalog and make sure to not migrate already existing applications. Read more about the Intune Enterprise App Catalog here
Migration process and prerequisites
The script I created to migrate apps from ConfigMgr to Intune has three modes which should run one after the other.
Process diagram
NOTE: The script does not require admin permissions as long as it has write permissions to the export folder (applies to all three modes). See “Process steps” for more details.
- Step1 GetConfigMgrAppInfo
- Exports ConfigMgr application metadata to a given folder.
- This step will also analyze the metadata for any incompatible settings. See FAQ section for more details.
- Requirements for this mode:
- At least application read permissions in ConfigMgr
- ConfigMgr admin console or ConfigMgr PowerShell CmdLets are not required.
- Step1.1 Manually analyze the application metadata
- While this is not a step of the script, it is important to validate the script output before going forward. More information can be found in the next section and the FAQ section down below.
- Step2 CreateIntuneWinFiles
- The step will compress the ConfigMgr app source data to create an intunewin file. (Required to be able to create win32apps in Intune)
- Requirements for this mode:
- The script will download the IntuneWinAppUtil.exe tool if not already present. See FAQ section for manual instructions.
- At least read permissions for ConfigMgr app source path.
- Connection to ConfigMgr not required.
- Step3 UploadAppsToIntune
- Creates a win32app in Intune and uploads the previously created intunewin file.
- Requirements for this mode:
- The script will install module: “Microsoft.Graph.Authentication” if not already present. See FAQ section for manual instructions.
- The script requires the “DeviceManagementApps.ReadWrite.All” permission in the Microsoft Graph PowerShell Entra ID app. The script will ask to approve the permission if not already done. See FAQ section for more details. (Custom app registration possible)
- Connection to ConfigMgr not required.
As already mentioned, please also have a look at the FAQ section further down below to better understand the script and its logic.
Get the script from here: Invoke-ConfigMgrAppMigrationToIntune.ps1
Process steps:
- Run the script in “Step1GetConfigMgrAppInfo” mode like this:
IMPORTANT: Change all parameter values to match your environment for all commands mentioned in this blog post.
.\Invoke-ConfigMgrAppMigrationToIntune.ps1 -Step1GetConfigMgrAppInfo -Sitecode 'P02' -Providermachinename 'CM02.contoso.local' -ExportFolder 'E:\ExportToIntune'
NOTE: This step will first create the export folder if not already there and some sub-folders explained in the FAQ section.
Example Grid-View of step 1
Select some or all apps to let the script analyze if a migration would be possible.
In most cases it makes sense to select all apps to get as much data as possible.
- Metadata for each selected app will then be exported into the defined export folder.
Read more about the folders and files in the FAQ section.
- There are multiple options to read the result of the analysis done by the script.
IMPORTANT: It is important to validate the output to understand why it might not be possible to migrate an app. Also, some settings will be ignored by the script and the app might look and behave differently in Intune.
Option 1: Open the exported CSV file in Excel. “<ExportFolder>\AppDetails\AllAps.csv”
Each column starting with “Check” contains information about one of the many checks done by the script.
Read more about the checks in the FAQ section.
Option 2: Open the JSON file: “<ExportFolder>\AppDetails\AllAps.json” in a text editor and validate the result there.
Option 3: View the results in a PowerShell Grid-View.
Follow the next instruction to open the result in a PowerShell Grid-View.
- Now run the script in “Step2CreateIntuneWinFiles” mode with the following parameters to create intunewin files for selected apps.
.\Invoke-ConfigMgrAppMigrationToIntune.ps1 - Step2CreateIntuneWinFiles -ExportFolder 'E:\ExportToIntune'
NOTE: If not already present, this step will download the “IntuneWinAppUtil.exe” tool to “<ExportFolder>\Tools”
NOTE: The export folder can also be copied to another system. Just make sure that the parameter “-ExportFolder” points to a folder with previously exported data.
- All the checks are shown in the Grid-View. Scroll to the right in order to see the check results.
Either hit “Cancel” to close the window or “OK” to create intunewin files for selected apps.
NOTE: Only apps marked with “AppImportToIntunePossible = Yes” can be imported to Intune. Validate the check results to find the exact reason in case an import is not possible. Checks are marked with “NO IMPORT” in that case.
- The last step is to run the script in “Step3UploadAppsToIntune” mode.
.\Invoke-ConfigMgrAppMigrationToIntune.ps1 -Step3UploadAppsToIntune -ExportFolder 'E:\ExportToIntune'
NOTE: If not already present, this step will install PowerShell module: “Microsoft.Graph.Authentication”.
“Nuget” will also be installed in case we need to download “Microsoft.Graph.Authentication”.
NOTE: Only apps marked with “IntunewinFileExists=Yes” and “AppImportToIntunePossible = Yes” can be imported to Intune.
- Select one or all apps and hit “OK” to start the app import to Intune.
Repeat the steps as often as needed and also check out the FAQ section down below.
FAQ section
This section should help understand the solution better and what it can and cannot do.
What type of app can the script export from ConfigMgr?
At the moment the script can only handle exe/script apps and no other type like imported MSI files or appx packages.
Does the script require admin permissions to run?
No. The script can run as long as it has write permissions to the export folder.
Do I need the ConfigMgr console installed or ConfigMgr PowerShell cmdlets to run the script?
No, the script will make a direct call to the SMS Provider.
Can I download the IntuneWinAppUtil.exe tool manually?
Yes. If you need to run step2 (create intunewin files) on a machine without internet access, download the tool from here: GitHub - microsoft/Microsoft-Win32-Content-Prep-Tool: A tool to wrap Win32 App and then it can be uploaded to Intune and place it in a “Tools” folder in the export folder.
What temp folder does the IntuneWinAppUtil.exe tool use?
The tool will compress the source files to the users temp folder. (The user running the script)
Currently the tool does not have a parameter to change the path. So, make sure the C:\ drive has enough space to compress the files.
Example path: “C:\Users\<UserName>\AppData\Local\Temp”
Can I install PowerShell module Microsoft.Graph.Authentication manually?
Yes. Run: “Install-Module -Name Microsoft.Graph.Authentication”
Or consult the documentation here: Install the Microsoft Graph PowerShell SDK
What does “AppImportToIntunePossible = No” mean?
The script detected a hard blocker and cannot import the app into Intune.
The reason is visible in one of the check columns and marked with: “NO IMPORT”
See section: “What checks will the script run against ConfigMgr app metadata?” for more details.
What does “AllChecksPassed = No” mean?
The script does a series of checks to validate if an app can be migrated without a difference.
If one of the checks failed, the app will be marked with “AllChecksPassed = No”.
It is still possible to create the app in Intune, but the app might behave differently.
Make sure to understand the implications of the specific check result.
Either change the app in ConfigMgr or copy and change the new app to avoid any issues with the app.
See section: “What checks will the script run against ConfigMgr app metadata?” for more details.
What does “IntunewinFileExists=No” mean?
No means, step2 of the script has not yet run to create an intunewin file for the app.
Only apps with content can be migrated by the script.
Re-run the script with parameter “-Step2CreateIntuneWinFiles” to create the files for the apps.
What files and folders will the script create?
The following table contains all the folders and files the script will create.
File or folder | Description |
<ExportFolder>\AppDetails | Folder containing data related to ConfigMgr apps |
AllApps.json | JSON file containing a list of all selected apps with typical ConfigMgr data and Intune related data for a later import in Intune. It also contains the result of the analyze step to be able to validate if an app can or cannot be imported to Intune. The JSON format is just to make it easier to read and parse with the human eye. The file is not used by the script in any other way and is just created for convenience. |
AllApps.xml | Contains the same information as in the JSON but also contains object type information. Therefore the file can easily be “re-used” with command “Import-Clixml” in any PowerShell session. It is used when the script runs in any of the other modes as a base. When the contents of the export folder has been copied to another system for example. |
AllApps.csv | The same info as in the AllApps.json file but in csv format. That way the data could be analyzed and filtered in Excel. The file is not used by the script in any other way and is just created for convenience. |
Application_<ConfigMgr App GUID>.json | The same info as in the AllApps.json but for a single app. The file is not used by the script in any other way and is just created for convenience. |
Application_<ConfigMgr App GUID>.xml | The same info as in the AllApps.xml but for a single app. The file is not used by the script in any other way and is just created for convenience. |
Application_<ConfigMgr App GUID>-Intune.json | JSON file containing the Intune JSON definition to create a win32app in Intune. The file is not used by the script in any other way and is just created for convenience. To be able to troubleshoot or use the file to create the app manually in Graph Explorer Graph Explorer | Try Microsoft Graph APIs - Microsoft Graph for example. |
<ExportFolder>\Icons | Folder containing app icons |
Icon_<Icon-ID>.png | If the exported ConfigMgr app has an icon, the icon will be exported to be able to upload the icon to Intune. |
<ExportFolder>\Scripts | Folder containing detection scripts |
DeploymentType_<DeploymentType-GUID>.ps1" | If the app’s deployment type has a detection script set, the script will be exported to the “Scripts” folder. Note: Script Global Conditions used as requirements are not handled by the script. |
<ExportFolder>\Tools | Folder containing tools. The script will download the IntuneWinAppUtil.exe file to be able to create “.intunewin” files to the tools folder. |
<ExportFolder>\Win32Apps | Folder containing created intunewin files. |
<ConfigMgr App GUID>\ <DeploymentType-GUID>.intunewin | The intunewin file per deployment type created by step two of the script. Each app has its own folder. |
<ConfigMgr App GUID>\ <DeploymentType-GUID>.log | Log file created by the IntuneWinAppUtil.exe tool containing the result of the compress operation. |
What happens if the script runs again?
That depends on the step/mode the script runs in.
- Step1GetConfigMgrAppInfo
- If the export folder exists, the script will load the existing AllApps.* files and replace any existing applications. That way the files should always contain accurate data about ConfigMgr apps.
- NOTE: That will reset the state: “IntunewinFileExists=Yes” and the content needs to be compressed into an intunewin file again.
- Step2CreateIntuneWinFiles
- The script will simply replace any previous created intunewin files for selected applications.
- Step3UploadAppsToIntune
- The script can be run in this mode as often as needed and does not act differently when run twice or more.
- Existing applications will not be overwritten. Instead a new application with the same name will be created in Intune.
- In case of an error, delete the application in Intune and run the script again. Maybe fix the error if you can.
What checks will the script run against ConfigMgr app metadata?
The following list contains the checks made by the script and a list of unsupported scenarios.
Unsupported can either mean not implemented in the script or unsupported by Intune.
Supersedence and dependencies
While Intune supports supersedence and dependencies in Win32Apps, the script currently does not. Set any dependency or supersedence after an app has been imported in Intune.
Tags
The script currently ignores tags.
Custom return codes
While Intune supports custom return codes, the script will ignore them.
Add them later to the Intune Win32App if required.
Requirements
While Intune supports requirements, the script will ignore ConfigMgr requirements at the moment. But since Intune requires at least a selection for architecture type and minimum operating system version, the script will set a requirements for x86 and x64 bit as well as Windows 10 1607 as a minimum.
Consider the use of a PowerShell script as a replacement for complex ConfigMgr requirements.
More than one deployment type
Intune does not support multiple DeploymenTypes and therefore the script will mark the app with: “AppImportToIntunePossible = No”.
As a workaround copy the app in ConfigMgr and remove any DeploymentTypes except one and re-run the script to import the app in Intune.
Logon requirement other than: “Whether or not a user is logged on”
There is no option to wait for a user to logon in Intune. The app can still be imported, but the setting is ignored.
Allow Interaction
There is no option to allow interaction in Intune. The app can still be imported, but the setting is ignored. As a workaround the ServicesUI.exe from the Microsoft Deployment Toolkit (MDT) can be used to allow some form of interaction with the end-user.
Program visibility other than “hidden” or “normal”
There is no option for program visibility in Intune. The app can still be imported, but the setting is ignored.
Unknown setup file extension
If the setup command is missing a known file extension the script will mark the app with: “AppImportToIntunePossible = No”.
Example: “install” and not “install.exe”
Different uninstall content
If the uninstall content is not the same as the install content the app can still be imported, but the uninstall content is ignored.
As a workaround copy the app and copy the uninstall content into the install content folder. Then re-run the script to import the app in Intune.
Missing uninstall command line
An uninstall string is required to create the app in Intune. Therefore the script will mark the app with: “AppImportToIntunePossible = No”.
Repair command
Intune currently does not have a repair command option. The app can still be imported, but the setting is ignored.
SourceUpdateProductCode for MSI repairs
Intune currently does not have an option for SourceUpdateProductCode. The app can still be imported, but the setting is ignored.
Exe to close before execution
Intune currently does not have an option to close an exe before running the installation. The app can still be imported, but the setting is ignored.
As a workaround use a script to close an exe before running an installation command and use that as a single script to install the app.
Detection rules with OR operator and limited support for rules with groups
In ConfigMgr it is possible to create detection rules arranged in groups and with the OR operator. While Intune does support multiple detection rules, it does not currently support the OR operator for them.
In that case all detection rules will be created in Intune, but the OR operator will be ignored.
The app should either be corrected before or after the upload.
Consider the use of a detection script with the same check logic instead.
Detection rules with unsupported operators
Some operators are not available in Intune at the moment. Like “EndsWith” for example.
The app can still be created, but the detection rule with an unsupported operator will be ignored.
Consider the use of a detection script with the same check logic instead.
The script will replace UNC install strings with just the command
In case an app directly runs an install command from an UNC path (which typically should not be the case) the script will set the UNC path as the source path.
Does the script account for all the possible ConfigMgr app configurations?
Unfortunately not. While I tried to integrate as many different options for detection methods and other app settings, I cannot guarantee a complete integration of every settings combination.
That also means you should always double check any imported app into Intune.
Is the script meant for large scale app migrations?
The script was designed to migrate a specific set of apps and is not capable of accounting for all the possible ConfigMgr app configurations. It should work even with a large list of ConfigMgr apps, but I never tested to export more than 1000 apps.
It is also not designed to run as a task nor track changes in ConfigMgr and keep apps in Intune up to date.
Can the script run in silent mode in the background?
No, it is designed for user input. But since it is a PowerShell script, it could be changed to run silently if that is what you need.
What Entra ID permission is required to import applications in Intune?
The script needs the “DeviceManagementApps.ReadWrite.All” permission in order to create new win32apps.
What Entra ID app registration will the script use?
The script will use the default Microsoft Graph PowerShell Modules Entra ID app.
Typically called: "Microsoft Graph Command Line Tools" (Other names possible)
AppID = 14d82eec-204b-4c2f-b7e8-296a70dab67e
Can I use a custom Entra ID app registration to run the script?
Yes, create an Entra ID app registration with the following permission: “DeviceManagementApps.ReadWrite.All”
Then run the script with the “-EntraIDAppID” parameter and use the app ID as the value.
You also need to add the tenant ID or domain name via parameter: “-EntraIDTenantID”
The full command would look like this:
.\Invoke-ConfigMgrAppMigrationToIntune.ps1 -Step3UploadAppsToIntune -ExportFolder 'E:\ExportToIntune' -EntraIDAppID '365908cc-fd28-43f7-94d2-f88a65b1ea21' -EntraIDTenantID 'contoso.onmicrosoft.com'
What happens if I change any of the files created by the script manually?
Only the AllApps.xml file will be used by the script to create intunewin files and to upload data to Intune. For example, if you change an app name in that file, a new Intune win32app will later have that name.
All other files are just there for convenience.
Changes to the ".intunewin" content files will not be checked. So make sure to store them safely or create them directly before the upload to Intune.
What data is stored in an .intunewin file?
The generated .intunewin file contains all source setup files in an compressed and encrypted form and the encryption information itself. Please keep it in a safe place as your source setup files.
Read more about it here
How can I get more information about the script?
Either open the script in a text editor and have a look at the description or run the script without any parameters.
Disclaimer
Always validate the script output and make sure the Intune applications look and behave the same way as the original applications in ConfigMgr.
Do test every application before deploying the application to production systems.
Also, this sample script is not supported under any Microsoft standard support program or service. This sample script is provided AS IS without warranty of any kind. Microsoft further disclaims all implied warranties including, without limitation, any implied warranties of merchantability or of fitness for a particular purpose. The entire risk arising out of the use or performance of this sample script and documentation remains with you. In no event shall Microsoft, its authors, or anyone else involved in the creation, production, or delivery of this script be liable for any damages whatsoever (including, without limitation, damages for loss of business profits, business interruption, loss of business information, or other pecuniary loss) arising out of the use of or inability to use this sample script or documentation, even if Microsoft has been advised of the possibility of such damages.
I hope you enjoyed reading this blog post.
If you have any questions or concerns, please let me know in the comments or create an issue or pull request on GitHub.
Get the script from here: Invoke-ConfigMgrAppMigrationToIntune.ps1
Stay safe!
Jonas Ohmsen
Continue reading...