Thursday, March 15, 2018

Lifecycle Service companion app

Here is a cool tool for LCS environment managers, written by Tomek Melissa from Microsoft.

The tool is unofficial and comes AS-IS.

Saturday, March 10, 2018

Generic function for switching line numbers on records

Tried to write a generic routine for switching line numbers on records, to help with functions that move records up or down according to a line number sequence.

Comments are welcome and I'll update the post according to the bugs you can find. However I only spent 10 minutes on this and it's provided to you for free, so please bear that in mind before you send me death threats in the comments.

public static void switchLineNumbers(
    Common      _currentTopRecord,
    Common      _currentBottomRecord,
    FieldName   _lineNumberFieldName)
    Common      currentTopRecordUpdate;
    Common      currentBottomRecordUpdate;
    LineNumber  topLineNumber;
    LineNumber  bottomLineNumber;
    FieldId     lineNumberFieldFieldId = fieldName2id(_currentTopRecord.TableId, _lineNumberFieldname);


        // Initialize correct table id on common
        currentTopRecordUpdate = new DictTable(_currentTopRecord.TableId).makeRecord();
        currentBottomRecordUpdate  = new DictTable(_currentBottomRecord.TableId).makeRecord();

        select firstOnly forUpdate currentTopRecordUpdate
            where currentTopRecordUpdate.RecId == _currentTopRecord.RecId;

        // Make a temporary line value, in case there is a unique index with line number,
        // making a free spot to update the currect bottom record with
        topLineNumber = currentTopRecordUpdate.(lineNumberFieldFieldId);

        currentTopRecordUpdate.(lineNumberFieldFieldId) = maxInt();

        select firstOnly forUpdate currentBottomRecordUpdate
            where currentBottomRecordUpdate.RecId == _currentBottomRecord.RecId;

        bottomLineNumber = currentBottomRecordUpdate.(lineNumberFieldFieldId);

        currentBottomRecordUpdate.(lineNumberFieldFieldId) = topLineNumber;

        currentTopRecordUpdate.(lineNumberFieldFieldId) = bottomLineNumber;


    catch (Exception::DuplicateKeyException)
        if (appl.ttsLevel() == 0)
            if (xSession::currentRetryCount() >= #RetryNum)
                throw Exception::DuplicateKeyExceptionNotRecovered;
            throw Exception::DuplicateKeyException;

Use at your own risk.

Wednesday, December 13, 2017

Find standard label translations

Microsoft aren't shipping the source standard label translations with the developer boxes. You only get the source for labels in en-us and the rest you only get as binary.

Here is what you can do if want to figure out how a particular label is translated.

First find the binary for the translated label file. This will be in the Resources folder under the package in question. For example, looking for the PRO labels from ApplicationSuite in Danish:

And next, open the dll in a tool allowing you to peek inside dll's. For example .NET Reflector.

Thursday, December 7, 2017

Misleading statements in 81215AE: X++ Programming and Advanced Topics in Microsoft Dynamics 365 for Finance and Operations, Enterprise edition

In Module 07 (and a few other places within same course) the importance of using the client / server modifiers and the RunOn property is discussed and emphasized.

However in D365 all X++ code is executed on the server. And thus the client / server keywords as well as the RunOn property are ignored.


I haven't tried the actual exam yet, so I don't know if this wrong assumption from the training material has sneaked into the exam as well. If there are questions on client/server settings, it probably has sneaked its way in since it's not of any importance anymore.

Wednesday, November 8, 2017

XQuery to save source code from all tables and classes

You can use this XQuery, with for example BaseX, to save all your source code from table and classes to an XML file:
  for $t in AxClass | AxTable  
  order by $t/local-name(.), $t/Name ascending

  for $y in ($t/SourceCode/Methods/Method)

  return <Code Type='{$t/local-name(.)}' Parent="{$t/Name/text()}" MethodName="{$y/Name/text()}" Source="{$y/Source/text()}"/>

Query range function: Less than date and not date null

There is a lessThanDate query function in AX, but it also selects blank dates.

Here is a suggestion for a similar function, that does not include the blank dates:
public static str lessThanDateAndNotNull(int relativeDays = 0)
    utcdatetime  currentDateTime;      

    currentDateTime = DateTimeUtil::applyTimeZoneOffset(DateTimeUtil::getSystemDateTime(), 

    return SysQuery::value(dateNull() + 1) + ' .. ' +            
           SysQuery::value(DateTimeUtil::date(DateTimeUtil::addDays(currentDateTime, relativeDays - 1)));  

Friday, November 3, 2017

XQuery to use with BaseX to find elements with no configuration key

Here is an XQuery that you can use with BaseX to find elements with no configuration key:
  for $t in AxTable | AxEnum | AxEdt | AxDataEntityView | AxMenuItemAction | AxMenuItemDisplay | AxMenuItemOutput
  order by $t/local-name(.), $t/Name ascending
  where fn:empty($t/ConfigurationKey)
  return <Element type='{$t/local-name(.)}' Name='{$t/Name/text()}' ConfigKey='{$t/ConfigurationKey}'/>

More on BaseX