Isolate Your Configuration Data Before Import Using PowerShell

Some applications for Dynamics 365, such as Field Service, Portals, and Unified Service Desk store their configuration data as records in Dynamics 365 – alongside your business data.

Microsoft’s Configuration Migration tool allows you to easily move configuration data between Dynamics 365 environments. One limitation of the export function, though, is the inability to separate configuration records from business records of the same type.

You can choose which types of records to export, but you can’t indicate which specific records to export.

For example, if you are using the tool to move your Portal configuration, you can choose to export all Note records, but you can’t choose to export only the Note records that are attached to Web File records. Instead, you’ll get every Note in the system, most of which are probably attached to Accounts, Contacts, Cases, or some other business record.

You almost certainly do not want to be moving business data across environments.

Another example is environment-specific configuration records. You may find it beneficial to prevent specific records – or just specific fields on specific records (e.g. the ‘Value’ field on Site Setting records that control the integration between your Portal and Azure AD B2C) from being included in your imports.


When data is exported, the Configuration Migration tool will place your data – along with some other files it requires – into a ZIP archive. Inside that ZIP archive you will find a file named data.xml. This is where your exported records live.

The data.xml file contains a <record> node for each record that will be imported. We can prevent records from being imported into other environments by simply removing their <record> nodes from the XML.

Removing a <record> node will not result in any record being deleted from Dynamics 365. It simply removes the record from the data that will be imported.

Similarly, can selectively remove <field> nodes from environment-specific records to prevent those fields from being overwritten in their target environments.


Rather than modify our data.xml files by hand, we can let PowerShell do this for us – ensuring that our edits are fast, accurate, and repeatable.

The example code below accepts a Path parameter that points to the data.xml file you have extracted from the ZIP archive. It then reads the XML and removes any Note (annotation) that is not attached to a Web File record. The modified XML is automatically saved back to data.xml.

The script can be easily modified to handle any number of record types or filtering logic you might need.

    $Path # Path to data.xml file extracted from .zip file created by Configuration Migration tool.

# Load the data XML file.

$xml = New-Object xml
$xml.PreserveWhitespace = $true

$changes = $false # Track if changes have been made.

# Iterate over each record set (grouped by entity type).
foreach ($type in $xml.entities.entity) {
    $name = $ # Name of entity type.
    Write-Verbose "Found entity type: $name"
    if ($name -eq 'annotation') {
		# Inside record set for Notes.
		# Iterate over each Note record and remove if not identified as configuration data (i.e. - attached to Web File record).
        $records = $type.records
        foreach ($record in $records.record) {
            Write-Verbose "Checking $name $($"
            # Get type of record Note is attached to.
            $regarding = $record.field | Where-Object { $ -eq 'objectid' }
            $regardingType = $regarding.lookupentity
            # Check if Note is attached to a Web File.
            if ($regardingType -ne 'adx_webfile') {
				# Note is not attached to a Web File - remove it from XML.
                Write-Host "Removing $name $($ (parent = $regardingType)"
                if ($record.PreviousSibling.NodeType -eq [System.Xml.XmlNodeType]::Whitespace) {
					# Remove the leading white space node.
                    $null = $records.RemoveChild($record.PreviousSibling)
				# Remove record node.
                $null = $records.RemoveChild($record)
                $changes = $true

if ($changes) {
	# Changes made - save back to original XML file.
    Write-Host 'Saving changes.'

Putting It Together

Following our previous use case of moving Portal configuration data between environments, here is a step-by-step look at the process:

  1. Save the code above to a new PowerShell script file (e.g. “Remove-NonConfigurationData.ps1”).
  2. Launch the Configuration Migration tool, and export your data as usual.
  3. Extract all files from the ZIP archive created by the Configuration Migration tool.
  4. Right-click on the PowerShell script you created and select Run in PowerShell.
  5. You will be prompted to supply the path to the data.xml file extracted from the ZIP archive.
  6. Let the script finish running – your data.xml file will be cleansed of any Notes that were not attached to Web Files.
  7. Select all files extracted from the ZIP archive, right-click, and select Send To > Compressed (zipped) folder. A new ZIP archive will be created.
  8. Launch the Configuration Migration tool, and import your data as usual – using the ZIP archive that contains your modified data.xml.

The process is the same regardless of application (Field Service, Portals, Unified Service Desk, etc.). The only differences are the record types and field names we are searching for in our PowerShell script.

Next Steps

Modify the PowerShell script to suite your ALM process. PowerShell can easily operate on any record or field that you find in your data.xml file.

For more information on working with XML see the System.Xml.XmlNode and System.Xml documentation.

Leave a Reply

Please log in using one of these methods to post your comment: Logo

You are commenting using your account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.