Goal: Read all joins within a MXD file and its relevant information. This should include: origin layer name, origin attribute name, destination table name, destination table attribute.

To solve this, I used the code snippet from the following post: Seeing all existing joins in any MXD layer in one place?

It all works so far. I am able to read the origin layer name and attribute name. However I'm only able to read the table name of the join table (destination table name), not the name of the attribute which is used to build the join (RelationshipClass.DestinationForeignKey is always empty). The joins are between FeatureClasses and geodatabase tables (enterprise and file-based). I'm probably missing something...

My code looks like this:

# Main Function
def get_lyr_join_fields(self, display_table, layer_name):
    return_list = []
    while self.__try_cast(display_table, db.IRelQueryTable):
        source_table_name = layer_name
        rel_query_table = self.__try_cast(display_table, db.IRelQueryTable)
        rel_class = rel_query_table.RelationshipClass

        # Join Source Tabelle
        source_table = rel_query_table.SourceTable
        source_dataset = self.__try_cast(source_table, db.IDataset)
        source_class = rel_class.DestinationClass
        source_att = rel_class.OriginForeignKey

        # Join Destination Tabelle
        dest_table = rel_query_table.DestinationTable
        dest_class = rel_class.OriginClass
        dest_table_name = dest_dataset.Name
        dest_att = rel_class.DestinationForeignKey # <--- ALWAYS Empty!

        # Build retrun-List
        return_list.append("{}:{},{}:{}".format(source_table_name, source_att, dest_table_name, dest_att)) 

        # Get other joins
        display_table = source_table
    return return_list

# Cast-Method (for COM-Objects)
def __try_cast(self, obj, interface):
        new_obj = obj.QueryInterface(interface)
        return new_obj
        return None

While debugging the code I get the following output for the RelationshipClass (join Attribute of the origin is read but not for the destination):

enter image description here

  • 1
    Please include the actual code, not a picture of it. When you include an image, you force each person who wants to help to retype your code (or, more likely, vote to close the question for lack a code sample). You have this tagged ArcObjects, but there is no AO code.
    – Vince
    Commented May 19, 2020 at 12:08
  • Thanks for your comment Vince. I'll post the code. If you look closer you will be able to see that there is ArcObjects used in Python. For this Function I use the following com-types: 'esriCarto as carto' and 'esriGeoDatabase as db'. As you can see one of the parameters is 'display_table' (IDisplayTable). I further use IRelQueryTable, RelationshipClass, SourceTable, IDataset, and more ArcObject-Com-Pointers.
    – GeoSj
    Commented May 20, 2020 at 7:07
  • Please edit your question to show us what the output does actually look like, that may provide some insight?
    – Hornbydd
    Commented May 20, 2020 at 10:40
  • I created a standalone python script, which could be run on any machine with arcgis installed. Is there a possibility to share it in this post (other than post the code directly into the question, as it would be a lot of code where only the above mentioned method is relevant)? It's my first question in this forum and I'm not familiar with the best practices...
    – GeoSj
    Commented May 20, 2020 at 13:18

1 Answer 1


If you read the ArcObjects help for the property DestinationForeignKey you will see the following statement in the remarks section:

... This property is null except in the case of attributed relationship classes ...

If your relationship is not one of these attributed relationships then I don't think you will ever get a value in that property.

  • 1
    That explains it, thank you! It's a bit weird though. The joins made and saved in a MXD-File are made correctly in ArcMap, so there must be a way of reading this information. I'll post it when I find something.
    – GeoSj
    Commented May 25, 2020 at 6:16

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.