Objects ignored by Code Upgrade Tool

When testing my new rule for code upgrade tool, I found that certain objects are skipped and rules are not checked for them. That makes the tool significantly less useful, because you can’t be sure that it found everything.

This blog post explains why it happens, but unfortunately doesn’t provide any reasonable workaround, except making the problem more visible. You should be simply aware of it until Microsoft provides a fix. (Please let me know if there already is a fix that I missed.)

I created a rule to check for a certain code pattern and I added the pattern to a few objects for testing. Although the rule seemed to work, some objects were not included (SalesLine table, for instance). Soon I discovered that it happened due to an exception thrown when checking rules for these objects. You can see the exception in the debugger, but it’s not displayed anywhere in the UI, unless you make the following one-lin change in SysUpgradeRuleRunner.processUtilElement():

if(Microsoft.Dynamics.AX.Framework.Tools.CodeUpgradeTool.Parser.Severity::Fatal == xppParserSeverity)
{
    error = diagnosticItem.ToString();
    error(error); // new code to display the error
    continue;
}

If you use the Code Upgrade Tool, I would recommend to add this modification to your application. It will at least let you know that an object was skipped.

This is the error message I got:

An error happened while executing PipelineTypeResolverPipelineEntryCould not load file or assembly ‘Microsoft.Dynamics.Retail.StoreConnect.TransAutomClient, Version=0.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35’ or one of its dependencies. The given assembly name or codebase was invalid. (Exception from HRESULT: 0x80131047)

What’s going on? First let me explain what happens when you run the Code Upgrade Tool:

  1. It finds all code in the current layer
  2. Each application object (such as a class) is loaded for analysis. Note that the whole object is loaded, not just the code in the current layer.
  3. In some cases, especially when a .NET type is used in code, AX loads all assemblies listed under AOT > References (so it can later look for types in these assemblies). It’s normally done just once and cached for subsequent calls.

The problem is that one of these references can’t ever be loaded. It’s the reference called TransAutomClient_x64, which refers to assembly Microsoft.Dynamics.Retail.StoreConnect.TransAutomClient for processor architecture AMD64. Dynamics AX client is a 32-bit process and it can’t load this assembly, therefore such as attempt must fail. I believe that Code Upgrade Tool would work without any problem if this reference was removed from AOT (but I can’t prove it, because it requires deleting a SYS-layer object).

AX tries to load .NET assemblies in several cases. For instance, if a .NET type is used in variable declaration or as method return type. It also happens when a static method is called on a .NET type, or when AX suspects it might be such a call. I noticed that even calls to table map methods (such as inventItemPrice.InventPriceMap::pcsPrice()) triggers loading of assemblies, because the syntax is exactly the same as for .NET calls (compare with System.Environment::GetLogicalDrives(), for example).

What can be done about it? I don’t think we can do anything by ourselves. What Microsoft should do is simply skipping assemblies that can’t be loaded. The process might fail later, if some code actually uses types defined in that assembly, but that’s inevitable. What happens now is much worse – it fails even if the library isn’t used by any code at all. There is still a potential issue that the tool loads assemblies even if no .NET types are needed (because of table maps calls, as above), but it wouldn’t really cause any harm if assembly loading behaved reasonably.

I simultaneously logged this issue on Connect (link). I really hope that Microsoft will address it soon, because it significantly affects usefulness of this great tool.

One Comment

Leave a Reply

Your email address will not be published.