Using FMUpgradeTool to Patch FileMaker Apps

Claris released a patching tool several years ago as a developer preview, which they named the App Upgrade Tool. With the recent release of FileMaker 22, Claris has made significant changes to this tool, including renaming it to FMUpgradeTool so that it’s more consistent with the other two available command-line tools: FMDeveloperTool and FMDataMigration.

The use case for the tool is to deploy code changes to a production file by applying a patch that describes those changes. If a large amount of code changes needs to be deployed, it’s recommended to still use the Data Migration Tool. The FMUpgradeTool is meant more for smaller hotfixes.

Bundled With FileMaker Server

The previous versions of the command-line tools—App Upgrade Tool (now FMUpgradeTool), FMDeveloperTool, and FMDataMigration—were released as single, standalone files. These tools are now bundled as part of FileMaker Server because they have dependencies on the libraries that are also used by the server executables. The primary motivator for this change is so that the tools can load plugins during execution.

For example, consider if I apply a patch with a stored calculation field that uses a plugin to calculate the result. If the patch tool isn’t able to load the plugin when it runs, we can deploy the field calculation change, but the result won’t be calculated and stored in all records. However, if the patch tool can load the plugin, then it can not only deploy the schema change to the field but also the stored calculation result.

For this reason, it’s best not to move the tools out of their folders.

Patching Hotfixes

At a high level, deploying a hotfix using the patch tool looks like this:

  1. Make a development change in your DEV environment.
  2. Generate a Save as XML (SaXML) file of your DEV and PROD database files.
    • This can be done using the FMDeveloperTool, FileMaker Pro, Data API, etc.
  3. Build a patch file.
    • This currently needs to be done manually.
  4. Apply the patch to the production file using FMUpgradeTool.

Change Types and Combinations 

At an atomic level, we can make one of three types of changes:  

  • Add something.
  • Delete something.
  • Replace something.

We can then combine these to create more complex changes. For example, a single patch file could do these operations:

  • Add table.
  • Add field to table.
  • Add custom function.
  • Replace field with a version of it that uses the custom function in its auto-enter calculation.

Example: Add Script

Let’s get a feel for how this works. We will:

  1. Add a “HelloWorld” script.
  2. Rename the script to “HelloWorld2” and modify its script steps.
  3. Delete the script.

To create the patch file to add the script, we’ll follow these steps:

Create the script in your DEV file.

  1. Save the file as XML.
  2. Find the script definition in the XML.
  3. Create the patch file using the XML snippets.
  4. Use the FMUpgradeTool to apply the patch.
  5. Open the patched file and confirm that the patch worked.

For step #3, we’ll need information for both the script (without any steps) and for the script steps. Those can be found in ScriptCatalog and StepsForScripts respectively. Think of this as asking the tool to create a script stub first (no steps yet) and then add the steps to the stub.

Here’s the script we created in our DEV file:

Script created in the DEV file

Next, we’ll create the patch file using this structure: 

<?xml version="1.0"?> 
<FMUpgradeToolPatch version="2.2.3.0"> 
  <Structure> 
    <AddAction> 
      <ScriptCatalog> 
        <!-- Information about the script STUB goes here (no steps) --> 
      </ScriptCatalog> 
      <StepsForScripts> 
        <Script> 
          <!-- A reference to the script stub goes here  --> 
          <ObjectList membercount="2"> 
            <!-- Information about the script STEPS goes here --> 
          </ObjectList> 
        </Script> 
      </StepsForScripts> 
    </AddAction> 
  </Structure> 
</FMUpgradeToolPatch> 

Here’s the XML snippet for creating the script stub (no script steps yet): 

<ScriptCatalog> 
  <!-- Information about the script stub (no steps) --> 
  <Script id="6" name="HelloWorld"> 
    <UUID modifications="5" userName="Mislav" accountName="Admin" timestamp="2025-06-11T18:50:49">
      CAD05CAF-86CE-4D51-A4B8-D6FCF08E34FE
    </UUID> 
    <Options hidden="False" access="ReadWrite" SiriShortcutVisible="False" 
      runwithfullaccess="False" compatibility="0">
      0
    </Options> 
  </Script> 
</ScriptCatalog> 

And here is the one for the script steps (there are just two steps in our script): 

<StepsForScripts> 
  <Script> 

    <!-- Reference to script --> 
    <ScriptReference id="6" name="HelloWorld" UUID="CAD05CAF-86CE-4D51-A4B8-D6FCF08E34FE"></ScriptReference> 

    <ObjectList membercount="2"> 

      <!-- 1st step --> 
      <Step hash="30FEA1F4AAF00B37403BFB2AFF8C55C2" index="0" id="89" name="# (comment)" enable="True"> 
        <UUID>7D5E493D-E6B3-476C-9D24-7D64EDC9EFAE</UUID> 
        <OwnerID></OwnerID> 
        <Options>4</Options> 
        <DDRREF kind="StepText" hash="C9F4AE319EF4BB69E846E7AC7F37C0FE">_7D5E493D-E6B3-476C-9D24-7D64EDC9EFAE</DDRREF> 
        <ParameterValues membercount="1"> 
          <Parameter type="Comment"> 
            <Comment value="A simple hello world script"></Comment> 
          </Parameter> 
        </ParameterValues> 
      </Step> 

      <!-- 2nd step --> 
      <Step hash="1A1A90115AA1B8F416548BAA69C014EB" index="1" id="87" name="Show Custom Dialog" enable="True"> 
        <UUID>76D9B1F5-6F0C-434C-90CF-03784EC3005C</UUID> 
        <OwnerID></OwnerID> 
        <Options>16389</Options> 
        <DDRREF kind="StepText" hash="1A378256222347FC81B49B9993AF13BE">_76D9B1F5-6F0C-434C-90CF-03784EC3005C</DDRREF> 
        <ParameterValues membercount="4"> 
          <Parameter type="Message"> 
            <Calculation datatype="1" position="1"> 
              <Calculation> 
                <DDRREF kind="ChunkList" hash="B743D1FC7650CF81B8022188B3304AF0">_76D9B1F5-6F0C-434C-90CF-03784EC3005C_1</DDRREF> 
                <Text><![CDATA["Hello world!"]]></Text> 
              </Calculation> 
            </Calculation> 
          </Parameter> 
          <Parameter type="Button1" value="OK"> 
            <Boolean type="Commit" value="True"></Boolean> 
          </Parameter> 
          <Parameter type="Button2"> 
            <Boolean type="Commit" value="False"></Boolean> 
          </Parameter> 
          <Parameter type="Button3"> 
            <Boolean type="Commit" value="False"></Boolean> 
          </Parameter> 
        </ParameterValues> 
      </Step> 

    </ObjectList> 
  </Script> 
</StepsForScripts> 

Once we have our patch file, we can apply the patch by running this command: 

➜ FMUpgradeTool --update
-src_path TestFile_prod.fmp12
-src_account admin
-src_pwd admin
-patch_path patchFile_script_add.xml
-dest_path TestFile_patched.fmp12

Note that you will most likely need to specify the full path to the patch tool and to each file.

Example: Modify (Replace) Script

Next, let’s modify the script.

Here’s the updated script in our DEV file. We renamed it and changed each of the steps.

Upgraded script created in the DEV tool

To create the patch file, we’ll follow a similar set of steps:

  1. Save the file as XML.
  2. Find the script definition in the XML.
  3. Create the patch file.
  4. The rest of the steps are the same.

For step #2, this time, we’ll need information for just the script steps. Those can be found in <StepsForScripts>.

Here’s our patch file with some of the details removed to make it easier to grok the structure of the file. We will use the <ReplaceAction> and <Replace> elements. 

<?xml version="1.0"?> 
<FMUpgradeToolPatch version="2.2.3.0"> 
  <Structure> 
    <ReplaceAction> 
      <Replace type="Script" UUID="CAD05CAF-86CE-4D51-A4B8-D6FCF08E34FE"> 
        <Script> 
          <ScriptReference id="6" name="HelloWorld2" UUID="CAD05CAF-86CE-4D51-A4B8-D6FCF08E34FE"></ScriptReference> 
          <ObjectList membercount="2"> 
            <Step> 
              <!-- details removed --> 
            </Step> 
            <Step> 
              <!-- details removed --> 
            </Step> 
          </ObjectList> 
        </Script> 
      </Replace> 
    </ReplaceAction> 
  </Structure> 
</FMUpgradeToolPatch> 

Here’s the full patch file. This one contains the full description for each of the two script steps.

<?xml version="1.0"?> 
<FMUpgradeToolPatch version="2.2.3.0"> 
  <Structure> 
    <ReplaceAction> 
      <Replace type="Script" UUID="CAD05CAF-86CE-4D51-A4B8-D6FCF08E34FE"> 
        <Script> 

          <ScriptReference id="6" name="HelloWorld2" UUID="CAD05CAF-86CE-4D51-A4B8-D6FCF08E34FE"></ScriptReference> 

          <ObjectList membercount="2"> 

            <!-- 1st step --> 
            <Step hash="7D79B2121942C414F3FBE7D653898FB2" index="0" id="89" name="# (comment)" enable="True"> 
              <UUID>7D5E493D-E6B3-476C-9D24-7D64EDC9EFAE</UUID> 
              <OwnerID></OwnerID> 
              <Options>4</Options> 
              <ParameterValues membercount="1">
		<Parameter type="Comment"> 
                  <Comment value="A simple hello world script - renamed"></Comment> 
                </Parameter> 
              </ParameterValues> 
            </Step> 

            <!-- 2nd step --> 
            <Step hash="5FE8772A75901E8CD6CAA1BF273CF2FC" index="1" id="87" name="Show Custom Dialog" enable="True"> 
              <UUID>76D9B1F5-6F0C-434C-90CF-03784EC3005C</UUID> 
              <OwnerID></OwnerID> 
              <Options>16389</Options> 
              <ParameterValues membercount="4"> 
                <Parameter type="Message"> 
                  <Calculation datatype="1" position="1"> 
                    <Calculation> 
                      <Text><![CDATA["Hello world renamed!"]]></Text> 
                    </Calculation> 
                  </Calculation> 
                </Parameter> 
                <Parameter type="Button1" value="OK"> 
                  <Boolean type="Commit" value="True"></Boolean> 
                </Parameter> 
                <Parameter type="Button2"> 
                  <Boolean type="Commit" value="False"></Boolean> 
                </Parameter> 
                <Parameter type="Button3"> 
                  <Boolean type="Commit" value="False"></Boolean> 
                </Parameter> 
              </ParameterValues> 
            </Step> 

          </ObjectList> 
        </Script> 
      </Replace> 
    </ReplaceAction> 
  </Structure> 
</FMUpgradeToolPatch> 

Example: Delete Script 

Our last example will be to delete the script we just modified. 

The delete patch is the simplest one to create. We just need to let the tool know what kind of item we’re deleting (in this case, it’s “ScriptReference”) and what its UUID is. 

Here, we will need the XML from the PROD file, not the DEV file, so that we can look up the UUID of the script that we deleted. Because the script no longer exists in the DEV file, we can’t use that file’s XML to look up the UUID.

<?xml version="1.0"?> 
<FMUpgradeToolPatch version="2.2.3.0"> 
  <Structure> 
    <DeleteAction> 
      <ItemReference UUID="CAD05CAF-86CE-4D51-A4B8-D6FCF08E34FE" type="ScriptReference"> 
      </ItemReference> 
    </DeleteAction> 
  </Structure> 
</FMUpgradeToolPatch> 

Catalog Items 

So, what kind of items can we add, replace, and delete? 

Here’s a list of the high-level catalog objects and their direct child objects that are available in the XML. The items listed as “child objects” are the ones that we can patch.

High-Level ObjectsChild Objects
AccountsCatalogAccount
BaseDirectoryCatalog
BaseTableCatalogBaseTable
CalcsForCustomFunctionsCustomFunctionalCalc
CustomFunctionsCatalogCustomFunction
CustomMenuCatalogCustomMenu
CustomMenuSetCatalogCustomMenuSet
ExtendedPrevilegesCatalogExtendedPrivilege
ExternalDataSourceCatalogExternalDataSource
FieldsForTablesFieldCatalog
FileAccessCatalog
LayoutCatalogLayout
LibraryCatalogBinaryData
OptionsForValueListsValueList
PrivilegeSetsCatalogPrivilegeSet
RelationshipCatalogRelationship
ScriptCatalogScript
StepsForScriptsScript
TableOccurrenceCatalogTableOccurrence
ThemeCatalogTheme
ValueListCatalogValueList
FieldsForTablesFieldCatalog
LayoutCatalogLayout

Items With Dependencies

Some of the catalog items are simpler to manipulate. For example, an account stands alone, meaning that its definition doesn’t depend on any other items.

In contrast, a script step can have multiple dependencies. For example, it belongs to a script and might have a reference to a layout or a field. That script, layout, and field need to be accounted for in the patch file. Either they’re already present in the target PROD file, in which case they can simply be referenced in the patch file using their UUIDs, or they need to be included in the patch file.

We Want More!

The FMUpgradeTool can now start to be used for deploying changes for most types of solution elements. This puts us closer to being able to automate deployments of hotfixes. Previously, deploying a hotfix required manually recreating each change in the production file. This is a very cumbersome and error-prone process.

There are still some missing pieces, though, so I encourage you to let Claris know you would like to see those created as well.

One of these missing pieces has to do with building the patch file. Currently, this has to be done manually. We’d love to see Claris develop a tool to automate that process.

Another area that can be improved is making the process of applying the patch file less manual. Currently, applying a patch requires these manual steps:

  1. Close the target file.
  2. Remote into the server.
  3. Run the command to apply the patch.
  4. Open the target file.

We can imagine a world where all of these steps are combined into a single FileMaker Server Admin API endpoint. We could then simply provide the patch file to FileMaker Server, and it does all the rest.

Launching New FileMaker 22 Features

Our team has already hit the ground running with FileMaker 2025, helping our clients understand the best way to upgrade and the most impactful features to launch in their systems. Need help? Contact our team to talk with an experienced FileMaker consultant.

Don’t miss our other FileMaker 2025 blog posts. Our team is weighing in on critical changes and the best new features for your application.

Leave a Comment

Your email address will not be published. Required fields are marked *

GET OUR INSIGHTS DELIVERED

Scroll to Top