Skip to main content

AOS crashed due corrupted node in the AOT

Warning: this post is only informative, do not try to replicate the problem described here in a production environment. !!!!

The problem:

The problem occurred when we created a 'View' with one circular reference. After that, every time we tried to click over "Data Dictionary\Tables" or "Data Dictionary\Views", the AOS crashes.

How to reproduce the problem:

Warning: this post is only informative, do not try to replicate the problem described here in a production environment. !!!!

0. Make a backup. Also, make a copy of the AxCus.AOD file.
1. Create a simple view (ex. View1).
2. Add a new DataSource manually. Then, open DataSource's properties dialog and specify in the table field the name of the view you have created (ex. View1).
3. STOP at this point if you dont want to crash the AOS !!!.
4. Expand the DataSource node. Drag the field CreatedBy to the view's fields. It will create the CreatedBy1 field.
5. Save it if you are sure you want to continue. After this action, your AOS will crash. (oops !)

You can try to recover the error by deleting the corrupted node (ex. View1 or CreatedBy1 field) using this method: How to delete AOT objects (AX/Axapta) or this other: How to delete AOT nodes by code (UtilIdElements solution). None of them will work!!!.

The solution:

After several tries, the only solution was open the AxCus.AOD file in a binary editor (Visual Studio is enough) and perform the next steps.

Warning: Serious problems might occur if you modify the AxCus.AOD file using this or another method. Modify system files at your own risk.

0. Make a backup. Also, make a copy of the AxCus.AOD file.
1. Stop the AOS and open the AxCus.AOD in a binary editor.
2. Locate the "CreatedBy1" field data (or your corrupted node's name). Normally, it should be near to the end of the file. (Look at pictures for details).
3. Change the reference data. It is above the field's name. Put the value FF FF (65,535) in the parent and field ids.
4. Save the file.
5. Delete the index file axapd.aoi.
6. Start the AOS again.
7. Delete the corrupted view.

Image with the corrupted node:



Image with the fixed node:



It is probable the corrupted node stays alive in the AOT, so you can try the following code to remove it:


static void Job1(Args _args)
{
UtilIdElements utilElement;
;

ttsbegin;

select utilElement
where utilElement.id == 65535; // Invalid ID we have writed in the AxCus.AOD file

if (utilelement)
{
utilElement.delete();

ttscommit;
info('Record should be deleted now.');
}
else
{
ttsAbort;
info('Could not delete record, or it was not found.');
}
}

Popular posts from this blog

Dynamics Axapta: Sales Orders & Business Connector

Well, again folllowing my same idea of writting close to nothing and pasting code, I'll paste in some code to create a sales order from some basic data and the invoice it. I'll try to explain more in the future. AxaptaObject axSalesTable = ax.CreateAxaptaObject("AxSalesTable"); AxaptaRecord rcInventDim = ax.CreateAxaptaRecord("InventDim"); AxaptaRecord rcCustTable = ax.CreateAxaptaRecord("CustTable"); rcCustTable.ExecuteStmt("select * from %1 where %1.AccountNum == '" + MySalesOrderObject.CustAccount + "'"); if (MySalesOrderObject.CurrencyCode.Trim().Length == 0) MySalesOrderObject.CurrencyCode = rcCustTable.get_Field("Currency").ToString().Trim(); string sTaxGroup = rcCustTable.get_Field("taxgroup").ToString().Trim(); //set header level fields axSalesTable.Call("parmSalesName", MySalesOrderObject.SalesName.Trim()); axSalesTable.Call("parmCustAccount", M

Passing values between form and class

Class name is EmplDuplication and Form is EmplTable . void clicked() {    MenuFunction mf;    args args = new Args();    ;     args.record(EmplTable);     mf = new menufunction(identifierstr(EmplDuplication), MenuItemType::Action); mf.run(args); } Meanwhile, in the main() method of the EmplDuplication class, we need to put this Axapta x++ code to get the datasource: static void main(Args args) {     EmplDuplication EmplDuplication; EmplTable localEmplTable; ;     if(args.record().TableId == tablenum(EmplTable)) localEmplTable = args.record();     ... }