≡ Menu

How to Control Part Numbers with User Exits

Share the knowledge

Previously we looked at how to control part numbers with Naming Rules. Naming rules work great for many cases, but they do have limitations. The counters they use to generate a part number when a user clicks the Assign button are limited, and naming rules cannot make any corrections, other than case, of the values entered. Fortunately, they are not the only tool in the Teamcenter administrator’s toolbox. To get to the next level of control over part numbers you can develop your own user exit functions to customize how part numbers are generated and validated. So, let’s review how User Exits work, the types of things you can do with them, and how to customize them.

What is a User Exit?

A User Exit is an ITK function that Teamcenter calls during the course of its operation and which customers can override by writing their own ITK code to replace the default behavior. The user exits functions are prefixed USER_ and are defined in the user_exits.h header file. Some of the ones that are useful as an alternative (or in addition) to naming rules are:

  • USER_validate_item_rev_id()
  • USER_new_item_id()
  • USER_new_revision_id()
  • USER_new_dataset_name()
  • USER_new_folder_name()
  • USER_new_form_name()

USER_validate_item_rev_id() is used to validate the item_id and item_revision_id fields of a newly created item, and the USER_new_* user exits are used to supply a new ID or name value when a user clicks on an Assign button. Note: user exits aren’t just for generating and validating ID and name fields; there are many others besides these that are related to completely different areas of Teamcenter, such as CAE, BOM comparisons, and validation results.

Why Use User Exits?

If you understand how naming rules work already you may be asking why you’d use user exits instead. After all, naming rules already perform the task of validating item_id and item_revision_id, AND you can define counters to generate new IDs upon demand, so what’s so great about user exits?

The answer, is flexibility.

Consider some examples:

  1. Your naming authority for issuing new part numbers is something other than Teamcenter. This system has a web service for issuing part numbers. Typically users use a web application to obtain the next available number and then manually key that into Teamcenter. Using a user exit for USER_new_item_id you could automate this process. Your user exit could call the web service, obtain the next part number, and provide that to the user automatically. A naming rule could not do that.
  2. Dataset names typically default to item_id/revision_id, so if the item ID is 100-20000 and the revision ID is 01, then the dataset is named “100-20000/01″.In Teamcenter Engineering the width of the item ID field was 32 characters, and the width of the dataset name field was… 32 characters. Do you see the Problem? What if the item ID was 30 characters long? Then the default dataset name would be 33 characters wide (30 for the item ID + “/01″ = 33). I have seen this happen while migrating legacy data into Teamcenter; it isn’t pretty.

    A solution is to create your own user exit for USER_new_dataset_name that checks the length of the item ID before generating the dataset name, abbreviating the name if necessary. Note: in Teamcenter 8+ the size of the fields is much larger, 128 characters, so the problem isn’t as likely — but I wouldn’t bet on it not happening

  3. Besides simply validating the proposed item IDs, USER_validate_item_rev_id also allows you to alter the item ID and either propose the updated ID to the user or force the user to accept it. For example, you could force a mandatory prefix or suffix on all item IDs (do nothing if the user already added it, but add if for them if they didn’t) or you could replace illegal characters, such as replacing all spaces with underscores. All naming rules cand do is convert the ID to either uppercase or lowercase.

How to Customize a User Exit

There are two ways to do this:

Option A: Rebuild libuser_exits.dll

You have the option of editing some sample source code files provided with Teamcenter and then recompiling the default user exit shared library, libuser_exits.dll/so/sl. user_part_no.c contains the code for the user exits we’re discussing today. That method is documented in the User Exits module documentation (from the HTML documentation for Teamcenter, Customizing Teamcenter → Integration Toolkit (ITK) Function Reference → Modules → User Exits). If that method appeals to you, go read that. Personally, I don’t like that method at all. For one thing, the source files you edit have a lot in them; more than I’ve ever needed to customize, and I’m afraid of unintentionally altering the behavior of a user exit that’s entirely unrelated to my intended task. Mucking around with a DLL supplied by the vendor just seems like a bad idea to me.

So, I prefer…

Option B: Registering a Custom Replacement Function

In a nutshell, what you do is write your own function to perform the task of the user exit, and then call another ITK function to register your function as a replacement for the user exit. The actual process is very similar to how your go about setting up PDM Server.

  1. Pick a name for a customization library. In the examples below I’m using libplmdojo
  2. In your preferences, register your customization library by adding its name, without the file extension, to the preference TC_customization_libraries. When Teamcenter starts it will look for the libraries mentioned by this preference and load them.
  3. Create the actual user exit library. This is a shared library (i.e. a DLL on Windows) that you write yourself. At a minimum it will contain the functions described below.
  4. Within your custom library implement the actual function that will replace the user exit you’re overriding. Example:
    extern "C" // for C++ compilation
    DLLAPI int PLMDOJO_validate_item_rev_id(
        int *decision, va_list args)
       // whatever you want to do...
  5. A function named your_library_name_register_callbacks(). This function needs to call CUSTOM_register_exit() to register the function defined above as the callback function for USER_invoke_pdm_server.
    // Example: Registering a user exit callback function
    extern "C" // for C++ compilation
    DLLAPI int libplmdojo_register_callbacks()
            // my library name
            // the user exit we're customizing
            // the callback function
        return 0;

    When the library is loaded at launch (because it was listed in the TC_customization_libraries preference), the _register_callbacks function is executed. This will make sure that your customizations are registered to be called in place of the default user exit.

  6. Within your own function, extract the parameters passed to the callback from the va_listargument using the standard C va_arg() macro. 

    The specific parameter list you’ll expand will match that of the user exit you’re replacing and the way you use them will be the same. So if one of the parameters of the original user exit is an in/out parameter that you can modify, then the corresponding argument of the va_list will also be an in/out parameter that you can modify.

  7. Set the decision input parameter to ALL_CUSTOMIZATIONS, ONLY_CURRENT_CUSTOMIZATION, or NO_CUSTOMIZATION, as appropriate.For example, you may just set it to ALL_CUSTOMIZATIONS so that your code is always invoked, or you may do something like check the item type and then set ALL_CUSTOMIZATIONS for engineering types but NO_CUSTOMIZATION for manufacturing types so that they use the default implementation instead.


Using Naming Rules and User Exits

Some quick points:

    1. You can still attach a naming rule to an item ID if you are providing your own callback function for USER_validate_item_rev_id(); the naming rule will be evaluated after the user exit completes (see the diagram below). This might be useful if you’re primarily using the user exit to modify the input before passing control back to Teamcenter and the naming rule validation.
    2. User exit sequence

      Sequence of user input, user exits, and naming rule checks during item creation (click to enlarge)

    3. There is a NR_ module for using naming rules in ITK, so you can invoke a naming rule from a user exit, which could be used to validate the input against the naming rules and then to modify it if it fails.
    4. User exits don’t just work in the Teamcenter user interface. For example, they are invoked by the Assign button in the NX new part dialog as well. I believe (but haven’t verified) that they are called by the ITK function ITEM_create_item when the item_id parameter is NULL. (The documentation states that if the item_id is null that, “the system will automatically generate an Item ID.” I presume that involves calling the user exit and not just a naming rule)

    Studying user_part_no.c

    Although I don’t like the approach of editing the source files provided with Teamcenter, it is very instructive to study them, especially user_part_no.c. They can be found under %TC_ROOT%/sample. You’ll get a much clearer understanding of how exactly your custom callback functions are invoked by the user exits.

    Where Naming Rules Have an Advantage

    Before Teamcenter “Unified”, naming rules could only validate a few fields, primarily item and revision IDs. Now, however, naming rules can be attached to pretty much any string attribute, which greatly increases their uses. User exits, however, only exist for a few specific fields.

  • https://twitter.com/Skinning_Door Prashant Shrivastava

    very good article.. An ITK programmer should already know such customizations. still a good learning.
    Thanks PLMDOJO!!

    • http://plmdojo.com Scott Pigman

      The dojo says, you’re welcome :-)

      FWIW, I’ve had conversations with a couple of different Siemens PLM employees that made similar comments: that they’ve seen a lack of understanding and appreciation for user exits and what they can do from people who come from a TC Enterprise background (including their own SPLM colleagues) , so I thought it’d be a good idea to post something trumpeting their value.

  • Rickygw

    Very nice article, indeed. Should be included in the standard documentation!

    • http://plmdojo.com Scott Pigman

      Thank you! I try to write articles that I wish I could have read before I went and did the thing I’m writing about :-)

  • Anonymous

    then I compiled and customize linked my C file. After that I setted the option named “TC_customization_libraries”.

    I restarted my TC server and login in TC by Thin client 4 tier. I created new item, click the button ‘assign’ to get a new item id. Noting happend , I did’t get the result(9999)  as I want to get . I got a message from the console of server manage on TC server. The message is ” process customization blizzard_new_item_id——“.

    Why can’t the customize hook generate a new id(9999) into to the client when I create a new item and assign a new id?

    Thks for any reply.

    • http://plmdojo.com Scott Pigman

      did you create a function called your_library_name_register_callbacks() and call  CUSTOM_register_exit within it? Did you install you DLLs on your 4-tier server?

      FWIW, I find it easier to develop using a 2-tier client myself; I can mess around with DLLs locally w/out affecting anyone else.

  • Anonymous

    Sorry I forgot some words in the above.  I read the article, very nice.  I’m studying in PLM programming and business operation. I come from China. I made a example as the following code:
    extern __declspec(dllexport) int blizzard_new_item_id (int *decision,va_list args){ char *new_id; tag_t old_item = va_arg (args,tag_t); tag_t item_type = va_arg (args,tag_t); logical* mod = va_arg (args, logical*); char** id = va_arg (args, char **);
     printf(“process customization blizzard_new_item_id——n”); *decision = ONLY_CURRENT_CUSTOMIZATION; *id=”2012001″; *mod=true; return(ITK_ok);}

    • http://plmdojo.com Scott Pigman

      hmm, did you MEM_alloc some space for *id to hold your string? And use strcpy to fill it.

      • Anonymous

        Thks for your help. I fixed my c file as you metioned. Now I can get the result I want.

  • Anonymous

    add a referenced image.

  • Mark

    How bout some discussion on RegEx rules.
    I’ve used them but get the feeling nobody else does because there have been myriad PRs on them.
    Also, it would be really nice if Siemens would allow a custom message when the naming rule fails.
    The only way to do that now is to code user_part_no.c with custom error strings.

    • http://plmdojo.com Scott Pigman

      I do use regex’s myself, albeit sparingly. The main one I’m using these days is “%^[^ ].*[^ ]$” i.e. “anything goes, just as long as it doesn’t start or end with a space.” I’ve found that it’s really difficult to distinguish between “12345”, “12345 “, and ” 12345″.

      I’ve filed a couple of those PRs. I think the last one was to ask them to please document which flavor of regex syntax they are actually using.

      I agree 1000% about the naming rule error messages.

      I’m going to see if I can’t put something together about regular expressions for the home page.

  • Prabhu Prabhu

    Hello Scott
    I am quite new to TC and I was trying to understand the Naming rule concept.  I have a very basic question….Does TC8.3 have any maximum limit on number of ID’s that can be generated(consider running number with no pattern defined).
    If I write a while loop calling GetNextIds(standard SOA), Will TC reach the maximum limit?Or does it have a reset mechanism?  Note we are targetting 32-bit system.

    If you know of a blog / website where Naming rule concept is well documented, do let me know


    • http://plmdojo.com/ Scott Pigman

      My apologies for not responding sooner, Prabhu. Evidently I lost track of what questions I hadn’t yet responded to.

      The limit is determined by the your naming rule pattern. nnn would let you use 000–999, annnnn would let you use A00000–Z99999, etc.

      Once you’ve requested an ID the system won’t re-supply the same ID; there’s a counter stored in one of the DB tables that keeps track of the last value used.

      That said, you can trick the naming rules into resetting. You do that by detaching and then re-attaching the naming rule to the field (at least, that would work in TC Engineering, I haven’t tried it yet in TC 8.3). The mechanism for generating IDs is smart enough that it will verify that an ID it proposes hasn’t already been used. If there the number has already been used it will pull the next number and try that until it finds a number that doesn’t exist already.

  • TonyC

    Excellent Article  Thanks very much PLMDOJO

    Can User exits be also used for standard Item Naming?
    We have 50 users and they all call things the wrong names :(

    • http://plmdojo.com/ Scott Pigman

      Ha! I know how you feel. Don’t worry, from my experience and from all I’ve heard, you’re users are not atypical. Wait, maybe that is a reason to worry…

      I’m presuming that by “standard Item” you mean standard hardware parts, such as mil-specs. We’ve dealt with the same issue. I don’t think user exits lend themselves to a good solution. I suggest looking into implementing a pre-condition check of the part number that would go out and verify the submitted part number against some external record of valid part numbers and block item creation if it didn’t conform.

  • geekay

    Hi Scott,
    Never came across such a beautiful illustration.
    Nice piece of work.

  • Björn Andersson

    I´ve got a problem that´s been bothering me for some time. We have a customization for the New Item dialog of one of our Item Type. Through this we get a Item ID from our ERP system via a webservice. This works fine in Rich Client. However, when a mechanical engineer wants to create a new item for his CAD model he has to first create the Item in Rich client and then go to Autodesk Inventor and through TCAI add the cad data. If he hits the assign button for Item ID in TCAI he gets a number from Teamcenter internal generator. Is there a way to customize the fetching of Item ID so that TCAI uses it to. Making the life of our mech folks a bit easier?? We use TC and TCAI 10.1.
    Thankfull for any information!

    • http://plmdojo.com/ Scott Pigman

      Hi Bjorn,

      It sounds like your customizations are on the client side, as a Java plugin for the rich client, rather than the server side as a ITK user exit. The problem with client customizations is that they only customize the single rich client interface. I think if you try implementing some custom ITK code that pulls from your ERP system and registering it for USER_new_item_id() you’ll get the customized behavior in Inventor.

  • Teamcenter Heretic

    BTW, USER_validate_item_rev_id not executed in V10.1.

    Reference PR 6928317.

  • Pingback: PLM Weekly News: September 15, 2011 - Zero Wait State()

  • Pingback: User & Server Exits()

  • srini


    Nice article !
    how to generate ItemId using USER_new_item_id (custom code) for a item having multiple naming rules in TC version 10.1 User will select the naming rule and clicks on assign button

  • Milind

    I am not able to build custom exit DLL. Source file I am using is amongst the examples provided by GTAC. It compiles fine.But during link I get linker errors.
    For compile I am using.
    compile -debug -64bit -DIPLIB=gtac_custom_exits.cxx
    link_custom_exits gtac

    I have function defined as
    extern “C” DLLAPI int gtac_register_callbacks() {


    I am receiving linker errors as
    error LNK2001: unresolved external symbol __GSHandlerCheck
    error LNK2019: unresolved external symbol __imp_printf referenced
    in function “void __cdecl ECHO(char *,…)” ([email protected]@YAXPEADZZ)

    Can you please help me to resolve these errors?


    • shivlogic

      The way I look at it, it needs some changes:
      1: Don’t use extern “C” just use DLLAPI. [DLLAPI already covers this]
      2. During compile do not supply any libraries that is DIPLIB=none
      there are few issues in ECHO function which are not published here so I am not able comment on them.
      Please try this and let me know.
      With Regards

Optimization WordPress Plugins & Solutions by W3 EDGE