Showing posts with label AX4. Show all posts
Showing posts with label AX4. Show all posts

Tuesday, September 30, 2008

View AOCP/RPC Interface Version used by an Arbitrary DAX Binary

First off a little bit of theory. Dynamics AX is a client-server application and utilizes a special protocol/interface for client-server communication. Namely versions prior to 4.0 used AOCP (Axapta Object Communication Protocol) implemented over TCP/IP and versions 4.0 and above have moved to an RPC interface. The client-server communication details inevitably change over time as kernel updates are released and obviously for robust Dynamics AX kernel operation it's vital to make sure that a client and a server understand each other precisely i.e. use the very same «dialect» of the communication protocol/interface. Hence an internal communication protocol/interface versioning is used in Dynamics AX kernel to find out if an arbitrary client can safely connect to and communicate with an arbitrary server. Those of you who has worked with Axapta 3 might remember that when you start a client with a kernel build number different from the AOS' kernel build number then the client most likely fails to connect to the AOS and complains about «Internal revision mismatch in Axapta Object Communication Protocol»; then it suggests to use the same kernel build for both client and Object Server. Why is it just a suggestion? First, the client has no idea if the server's kernel build matches it's own, and vice versa the AOS has no idea if a client attempting to connect has the same kernel build number as the AOS. Second, Dynamics AX clients and servers with non-matching kernel build numbers can connect and work with each other in case they use the same version of a communication protocol/interface. The first statement might look arguable. If you look in the User log (Administration/Inquiries/User log) you can find there some technical information about a user's session such as a client computer name, a client type and some kind of build number. Aha! So Object Server does know exactly the client's kernel build number, right? Wrong. A SysUserLog record which represents User log data is filled right in SysUserLog.insert() method. And while SysUserLog.Computername and SysUserLog.ClientType field values represent corresponding xSession object properties, SysUserLog.BuildNum field is initialized with a value returned by xInfo::buildNo() static method which has no explicit client or server modifiers. In 3-tier environment a table variable is generally located on the server side, hence SysUserLog.insert() and xInfo::buildNo() are executed on the server side and SysUserLog.BuildNum field receives server's kernel build number. So, once again, an AOS has no idea if a client attempting to connect to it has the same kernel build number or not. So when it comes to client/server interoperability, Dynamics AX kernel relies solely on the communication protocol/interface version, not kernel build numbers. And if that version is the same in client an server binaries then those binaries can be safely used together. But how can you know what communication protocol/interface version does an arbitrary Dynamics AX kernel binary use? Well, here is a utility for you: viewer for Dynamics AX AOCP/RPC interface version used by an given DAX kernel binary. Prior to a kernel binary file name you can pass these command line arguments:
  • -nosigcheck - omit Authenticode verification (useful for some legacy kernel builds that miss the Authenticode digital signature)
  • -debug - output additional technical information about the binary and print more detailed error messages if any
You now can easily find out (and check it out) that Dynamics AX 4.0 SP1 and SP2 binaries work together as they use the same RPC Interface version; and so do Dynamics AX 2009 TAP3 and RTM binaries...

Tuesday, October 30, 2007

Run DAX4 AOS as a console application

I've recently found an interesting feature of DAX4 Object Server: it can run not only as a service, but also as a console application started from command line. All you have to do is pass a <any_single_character>console parameter before the configuration number, e.g.

ax32serv.exe /console 01
This feature was probably added for debugging purpose as it's rather difficult to start a Windows service under a debugger. When started as a console application AOS can be terminated by pressing Ctrl-C or Ctrl-Break.

Tuesday, July 10, 2007

AX4 SysFileDeployment Fix

In Dynamics AX it's often necessary to install some custom files such as ActiveX components, DLLs, templates, etc (that are not part of the installation package) on each client computer. There's a couple of handy classes to accomplish this task: SysFileDeployer and SysFileDeployment (and it's descendant SysFileDeploymentFile). Unfortunately this mechanism has been completely broken in AX4 due to Code Access Security covering «dangerous API» usage on the server tier, see Writing Secure X++ Code.
Implementing Code Access Security Code access security must be implemented by the dangerous API owner and all consumers of the dangerous API. 1. The owner secures the dangerous API by implementing a specific type of permission class and calling the demand() method on that class 2. Each API consumer must explicitly request permission to invoke a secured dangerous API by calling the assert() method on the permission class. Application code will break unless both of these steps are completed.
And everything is ok with the demand() calls in the WinAPIServer class whereas SysFileDeployment* classes lack the assert() calls. Probably they were not tested thoroughly or something… To be precise, here is what I've found:
  • SysFileDeploymentFile.serverVersion() lacks corresponding assert() call before WinAPIServer::getFileModifiedDate();
  • SysFileDeployment.getServerFileTimeAccessed()/Modified()/Created() lack corresponding assert() calls before WinAPIServer::getFileTime();
  • SysFileDeployment.isNameValid() splits full file name via fileNameSplit() and after that adds a redundant dot between the name and the extension (fileNameSplit() already returns file extension with a leading dot) - as a result isNameValid() always returns false which in its place causes corresponding assert() calls not to happen;
  • Finally, SysFileDeployment.sourcePath() returns xInfo::directory(DirectoryType::Include) by default and the latter is known to return different results depending on which (client or server) tier it is called. Of course, SysFileDeploy* classes work in such a way that SysFileDeployment.sourcePath() is called on both tiers - and that completely ruins all the program logic
You can download a small fix from axaptapedia.com to make SysFileDeployment work again. Microsoft claims there's already a hot fix with a description "File deployment error FileIOPermission failed", so there's a hope we will see this fixed in AX4 SP2...