Tuesday, June 27, 2017

Run code based on configuration key in dynamics AX 2012

Sometimes you need to run code based on your configuration keys 

Code:


  if  (isConfigurationKeyEnabled (configurationkeynum(keyname)))
   {
                     // Code goes here..
   }
   else
   {
                // do something else
    }



Happing daxing

Facing error while deploying from Visual studio

You get the error when trying to deploy a report either by using VS2013 reporting tool or through AOT


The "GenerateRdlTask" task failed unexpectedly.
System.IO.FileLoadException: Loading this assembly would produce a different grant set from other instances. (Exception from HRESULT: 0x80131401)

Resolution:
1. Go to Control Panel\System and Security\System
2. Open Advanced system settings and open Environment Variables
3. Create a New Variable
4.Variable name: COMPLUS_LoaderOptimization ; Variable value: 1
5. Click OK
6. Logout from the server and logon again.
7. Open the report using Visual Studio 2013 and deploy the AX report.
8. The report can also be deployed from AOT

Deploy SSRS Report through Power Shell

Here is the command to deploy SSRS Report Through Power Shell

Deploy Single Report

 To deploy a specific report, enter the name of the report. For example, to deploy the CustTransList report, enter  the following command:
Command : Publish-AXReport -ReportName CustTransList

Deploy Multiple Report

To deploy two or more specific reports, enter the names of the reports. For example, to deploy the CustTransList and CustTransOpenPerDate reports, enter the following command:
Command : Publish-AXReport -ReportName CustTransList, CustTransOpenPerDate

Deploy All Report

To deploy all reports, enter the following command:
Command  : Publish-AXReport –ReportName 

Create financial dimension through x++

Here is the code to create/find financial dimension in x++

static RecId findCreateDimension(str _project, str _department)
{
    RecId                               ret;

    DimensionAttributeValueSetStorage   dimStorage;
    DimensionAttributeValue             dimensionAttributeValue;
    DimensionAttribute                  dimensionAttribute;
    ;
    if (_project || _department)
    {
        dimStorage              = new DimensionAttributeValueSetStorage();
        if (_project)
        {
            dimensionAttribute      = AxdDimensionUtil::validateFinancialDimension("project");
            dimensionAttributeValue = AxdDimensionUtil::validateFinancialDimensionValue(dimensionAttribute, _project);
            dimStorage.addItem(dimensionAttributeValue);
        }
        if (_department)
        {
            dimensionAttribute      = AxdDimensionUtil::validateFinancialDimension("Department");
            dimensionAttributeValue =    AxdDimensionUtil::validateFinancialDimensionValue(dimensionAttribute,    _department);
            dimStorage.addItem(dimensionAttributeValue);
        }
        ret = dimStorage.save();
    }
    return ret;
}

Deploy Report through x++ code

Here is the code to deploy SSRS report in Microsoft Dynamics AX.

static void deployReport(Args _args)
{
    SRSReportManager srsRptMgr = new SRSReportManager();
    SSRSReportConceptNode node = new SSRSReportConceptNode();

    node = TreeNode::findNode(@"\\SSRS Reports\Reports\SalesInvoice");

    srsRptMgr.deploymentStart();
    srsRptMgr.deployReport(node);
    srsRptMgr.deploymentEnd();
}

Refresh,Reread,Research,ExecuteQuery in dynamics AX

Refresh,Reread,Research,ExecuteQuery in dynamics AX
1. Refresh()
refreshes the user view with whats stored in the caches. This does not touch the DB.
Use this after any form change has been made through code.
2. ReRead()
 fetches only the current record from database and does not re read the complete datasource.
Use this when you need to update only the current record after modifying any value.
3 . ReSearch() 
  will execute the same query again and fetch the results from the database.
Use this if you need to get the current most data from database.
4 . ExecuteQuery()
 will run the query again just like research does but it will also take any query changes into account.
Use this is you have modified the query on run-time and need the updated results according to the new query.

Difference among Research() and Research(true) in AX 2012

Difference among Research() and Research(true) in AX 2012

Research
Calling research() will return the existing form query against the database, therefore updating the list with new/removed records as well as updating all existing rows. This will honor any existing filters and sorting on the form, that were set by the user.
Research(true)
The research method starting with AX 2009 accepts an optional boolean argument_retainPosition. If you call research(true), the cursor position in the grid will be preserved after the data has been refreshed. This is an extremely useful addition, which solves most of the problems with cursor positioning (findRecord method is the alternative, but this method is very slow).

Unit of Work Framework in Microsoft Dynamics AX 2012

Unit of Work Framework in Microsoft Dynamics AX 2012

Unit of Work Framework is use to commit number of records in a single Transaction. The main reason for introducing unit of work is that it is impossible to insert the lines table record before its header table because there is a relation between the header table and the lines table. The “Recid” of the header table is comes as a foreign key in the child table.

Let’s took an example as you can see in the Microsoft dynamics ax there are two tables i.e. MTQUnitOfWorkTable and MTQUnitOfWorkLine. These two tables are related with each other “MTQUnitOfWorkTable” is the parent table and “MTQUnitOfWorkLine” is the child table.

As you can see in the below image about these two tables and there relations.




CreateNAvigationPropertyMethods“should be set to Yes         
Then create Class name as “MTQDemoClass” and then add Method, and write following piece of code.


Now Create New Job, call “demo” method.

Result: You can see that the records are crated in the child table having the id of the parent table

References:

https://msdn.microsoft.com/en-us/library/gg846338.aspx

Create Purchase Requisition through x++

Here is the code for creating purchase requisition through x++

public static void createPurchaseReq (Args _args)
{
    PurchReqTable   purchReqTable;
    PurchReqLine    purchReqLine.;
 
    purchReqTable.clear();
    purchReqTable.initValue();

    purchReqTable.PurchReqId    =                                NumberSeq::newGetNum(PurchReqTable::numRefPurchReqId()).num();
    purchReqTable.PurchReqName  = 'Requisition';

    purchReqTable.insert();

    purchReqLine.clear();
    purchReqLine.initValue();

    purchReqLine.InventDimId = 'Dim-0001';
    purchReqLine.LineNum     = 1;

    purchReqLine.initFromPurchReqTable(purchReqTable);

    purchReqLine.ItemId              = 'Test-001';
    purchReqLine.BuyingLegalEntity   = CompanyInfo::find().RecId;
    purchReqLine.InventDimIdDataArea = curext();
    purchReqLine.PurchQty            = 2;

    purchReqLine.modifiedField(fieldNum(purchReqLine,ItemId));
 
    purchReqLine.insert();
 
}

Error 1 Loading this assembly would produce a different grant set from other instances. (Exception from HRESULT: 0x80131401)

You get the error when trying to deploy a report either by using VS2013 reporting tool or through AOT


The "GenerateRdlTask" task failed unexpectedly.
System.IO.FileLoadException: Loading this assembly would produce a different grant set from other instances. (Exception from HRESULT: 0x80131401)

Resolution:
1. Go to Control Panel\System and Security\System
2. Open Advanced system settings and open Environment Variables
3. Create a New Variable
4.Variable name: COMPLUS_LoaderOptimization ; Variable value: 1
5. Click OK
6. Logout from the server and logon again.
7. Open the report using Visual Studio 2013 and deploy the AX report.
8. The report can also be deployed from AOT


Create Sales Order through code

I found few good sample code for creating sales order in a book and I was able to compile a code for posting sales order invoice. I thought I should share on my blog. It might be useful for some one.
Code for creating Sales order
SalesTableType and SalesLinetype. Insert() should be called for creating the sales order. Example is as follows. I am currently looking for code that can contains example code of creating invoice from scratch. I will send you the code in an hour.
static void createSalesTable(CustAccount _custAccount)
{
SalesTable salesTable;
NumberSeq NumberSeq;
;
NumberSeq =
NumberSeq::newGetNumFromCode(SalesParameters::numRefSalesId
().numberSequence);
salesTable.SalesId = NumberSeq.num();
salesTable.initValue();
salesTable.CustAccount = _custAccount;
salesTable.initFromCustTable();
salesTable.insert();
}
Example: Create a Sales Line
static void createSalesLine(SalesId _salesId, ItemId _itemId)
{
SalesLine salesLine;
;
salesLine.clear();
salesLine.SalesId = _salesId;
salesLine.ItemId = _itemId;
salesLine.createLine(NoYes::Yes, // Validate
NoYes::Yes, // initFromSalesTable
NoYes::Yes, // initFromInventTable
NoYes::Yes, // calcInventQty
NoYes::Yes, // searchMarkup
NoYes::Yes); // searchPrice
}
Code for posting Sales order Invoice
static void createSalesOrder(Args _args)
{
SalesFormLetter formLetterObj;
formLetterObj = SalesFormLetter::construct(DocumentStatus::Invoice);
formLetterObj.update(SalesTable::find(“SO-101248”));
}

Create/Post Sales order Invoice through x++

Hi,

Today i am going to show you how to create/post sales order invoice in x++

static void createPostSalesOrderInvoice(Args _args)
{
        SalesFormLetter salesFormLetter;
        salesFormLetter=SalesFormLetter::construct(DocumentStatus::Invoice);
       salesFormLetter.update(SalesTable::find('SO-ASC0001'));
       info(strFmt("%1 Sales Order Posted and Final Status is Invoiced",salesTable.SalesId));
}

now run this job

Confirm Sales Order through code

Hi,

Today i am going to show you how to conform sales order through code

static void confirmSalesOrder (Args _args)
{
        SalesTable salesTable;
        SalesFormLetter salesFormLetter ;
     
        SalesTable = SalesTable::find('SO-ASC0001');

        salesFormLetter = SalesFormLetter::construct(DocumentStatus::Confirmation);

        salesFormLetter.update(salesTable);

}

now run this code,

Post/Create Sales order Packing slip x++

Hi Folks,

Today i am going to show you code how to create and post Packing slip through x++;

static void createPostSalesPackingSlip(Args _args)
{
    SalesTable salesTable;
    SalesFormLetter salesFormLetter;

    salesTable = SalesTable::find('SO-ASC001');
      //Posting Sales Order 
    salesFormLetter=SalesFormLetter::construct(DocumentStatus::PackingSlip);
    salesFormLetter.update(SalesTable::find(sid));
       salesFormLetter.update(salesTable,systemDateGet(),SalesUpdate::All,AccountOrder::Non e, NoYes::No,NoYes::Yes);
    info("Sales Order Status is Delivered");
}

run this job.

Create Sales Order in x++

Hi,
Today i am going to show you code how to create sales order in x++.
static void CreateSalesOrder(Args _args)
{
//declaring variables
SalesTable salesTable;
SalesLine salesLine;
NumberSeq numberSeq;
ttsBegin;
//creating sales order header
//getting sales order id from number sequence
numberSeq = NumberSeq::newGetNum(SalesParameters::numRefSalesId());
numberSeq.used();
salesTable.SalesId = numberSeq.num();
salesTable.initValue();
salesTable.CustAccount = ‘Demo-001′;
salesTable.initFromCustTable();
//validate
if (!salesTable.validateWrite()) {
throw Exception::Error;
}
salesTable.insert();
//creating sales order line
salesLine.SalesId = salesTable.SalesId;
salesLine.ItemId = ‘DM0012′;
salesLine.SalesQty = 2;
salesLine.LinePercent = 1;
salesLine.createLine(true, // Validate
true, // initFromSalesTable
true, // initFromInventTable
true, // calcInventQty
true, // searchMarkup
true  // searchPrice
);
ttsCommit;

//displaying sales order id
info(salesTable.SalesId);
}
And THEN run this job

X++ code to create Purchase Order Packing slip

X++ Code to Post the Purchase Order Packing Slip.

Following Job post the Packing Slip by using PurchFormLetter class.

static void CreatePOPackingSlip(Args _args)
{

    PurchFormLetter purchFormLetter;
    PurchTable          PurchTable;
    ttsbegin;
   PurchTable = PurchTable::find('PO-Demo');
   purchFormLetter = purchFormLetter::construct(DocumentStatus::PackingSlip);
   purchFormLetter.update(purchtable, // Purchase record Buffer
                           "Inv_"+purchTable.PurchId, // Invoice Number
                             systemdateget()); // Transaction date
ttscommit;
if (PurchTable::find(purchTable.PurchId).DocumentStatus ==           DocumentStatus::PackingSlip)
{
    info(strfmt("Posted Packing Slip for purchase order %1",purchTable.PurchId));
}
}

Now run the CreatePOPackingSlip job.

X++ code to create Purchase Order Invoice

X++ Code to Post the Purchase Order Invoice.

 

Following Job post the invoice by using PurchFormLetter class.

static void CreatePOInvoice(Args _args)
{

    PurchFormLetter purchFormLetter;
    PurchTable          PurchTable;
    ttsbegin;
   PurchTable = PurchTable::find('PO-Demo');
   purchFormLetter = purchFormLetter::construct(DocumentStatus::Invoice);
   purchFormLetter.update(purchtable, // Purchase record Buffer
                           "Inv_"+purchTable.PurchId, // Invoice Number
                             systemdateget()); // Transaction date
ttscommit;
if (PurchTable::find(purchTable.PurchId).DocumentStatus ==           DocumentStatus::Invoice)
{
    info(strfmt("Posted invoiced journal for purchase order %1",purchTable.PurchId));
}
}

Now run the CreatePOInvoice job.

Create Purchase Order in x++

X++ Code to creating PO/Purchase Order

Here we use AXPURCHTABLE AND AXPURCHLINE class for creating purchase order and purchase line
static void createPO(Args _args)
{
PurchTable purchTable;
PurchLine purchLine;
InventDim inventDim;
NumberSeq numberSeq; //add by fanddy
AxPurchTable axPurchTable;
AxPurchLine axPurchLine;
//END //create PO Header
purchTable.clear();
purchTable.initFromVendTable(VendTable::find(TECPOGroupHeader.VendAccount ));
purchTable.DefaultDimension = InventTable::find(POGroupLine.ItemId).DefaultDimension; axPurchTable = axPurchTable::newPurchTable(purchTable);
axPurchTable.parmPurchId(NumberSeq::newGetNum(PurchParameters::numRefPurchId()).num());
axPurchTable.parmPurchaseType(PurchaseType::Purch);
axPurchTable.parmDocumentStatus(DocumentStatus::PurchaseOrder);
axPurchTable.parmAccountingDate(systemDateGet());
axPurchTable.parmDeliveryDate(systemDateGet());
axPurchTable.parmPurchStatus(PurchStatus::Backorder);
axPurchTable.save(); info(strFmt('Create PO %1', Purchtable.PurchId)); //create PO Line
purchLine.clear();
purchLine.initValue();
purchLine.initFromPurchTable(purchTable);
purchLine.initFromInventTable(InventTable::find(POGroupLine2.ItemId));
axPurchLine = AxPurchLine::newPurchLine(purchLine);
axpurchLine.parmItemId('YOUR ITEMID');
axPurchLine.parmPurchQty(YOUR QTY);
axPurchLine.parmPurchPrice(YOUR PRICE);
axPurchLine.parmInventDimId('YOUR INVENTDIMID');
axPurchLine.save(); }
Run this job now.

Compile Application through AXBUILD utility with multiple workers (fastest)


AXBUILD Utility in Dyanmics AX

AxBuild.exe can accomplish a full compile of all X++ code, into AX p-code, many times faster than the traditional compile that you start from the MorphX client menu. AxBuild.exe is run on the Application Object Server (AOS) tier at a cmd.exe command prompt. This topic explains what AxBuild.exe does and how to use it.
The AxBuild.exe utility program involves compiles to p-code only, and it does not go further by compiling to .NET Framework CIL.
AxBuild.exe became available in cumulative update 7 for Microsoft Dynamics AX 2012 R2.
Caution noteCaution
You should stop the AOS service before you start AxBuild.exe. Otherwise in certain scenarios, the AxBuild.exe service might provide outdated metadata or outdated p-code to the compile process.

A.  General Architecture

Dn528954.collapse_all(en-us,AX.60).gifA.1  Compiling on the Server Tier

AxBuild.exe is installed in the same directory with ax32serv.exe, which is the program name for the AOS. Despite the 32 in its name, ax32serv.exe is a 64 bit program. As a 64 bit program, ax32serv.exe can address much more active memory than the 32 bit client ax32.exe can. The larger amount of active memory might be important for full X++ compiles that involve an extremely large amount of X++ source code.
AxBuild.exe starts several new but temporary instances of the AOS. From the Registry, each temporary AOS uses the same configuration information that is used by a permanent AOS that you identify with the /aos parameter. This is one reason why AxBuild.exe must be run by an account that has no less security authority than the account that runs the permanent AOS has.
Server config displays the AOS instance number
Server configuration displays the AOS instance number for the /aos parameter
AxBuild.exe coordinates the work of every temporary AOS that it starts. It tells each AOS which pieces of the full X++ compile to accomplish. It gathers the results from each AOS and reports them to the console and a log file.
X++ on the AOS tier with AxBuild.exe
Architecture of the X++ compile on the AOS tier
An earlier compile option involved new but temporary instances of ax32serv.exe to which you could pass a now obsolete parameter. The obsolete parameter is shown in the following command line:
 ax32serv.exe -startupcmd=CompileAll.

Dn528954.collapse_all(en-us,AX.60).gifA.2  Contrast with Compiling on the Client

In the past to accomplish a full X++ compile you had to click a menu in the MorphX client, such as Build > Compile. This is a three tier operation which is burdened with transferring data between the client and the AOS. In contrast, theAxBuild.exe approach is only a two tier operation. One reason the AxBuild.exe approach is faster is that it eliminates the data transfers over the network, or over local RPCs, between the AOS and the client.
Compiling on the client does not provide any way to share the workload among several applications. In contrast,AxBuild.exe starts several AOS applications which all run concurrently, which all accomplish parts of the full compile.
As a matter of common practice, the AOS host computer hardware is often more powerful than client computers are. The AOS host typically has more active memory, and has more cores for parallel processing.
Architecture of X++ compile on the client tier
Architecture of the X++ compile on the client tier
The MorphX client you can quickly compile an individual X++ method. These partial compilations are extremely efficient for the developer who is adding and fixing a method through cycles of coding then testing. In contrast,AxBuild.exe cannot compile any mere subset of the X++ code on the system.
The MorphX client remains the only option for compiling AX p-code to .NET CIL.

B.  Performance Gain

In this section we present performance data for AxBuild.exe. Every environment is different, and the performance speeds we see in our tests probably differ from what you see.
In our performance test of AxBuild.exe, we measured a 92% reduction in the wall clock time that was necessary to complete a full X++ compilation. Stated another way, AxBuild.exe completed the compilation 13 times faster than the MorphX client did on the same hardware. The software and hardware specifications for our test were as follows:
  • One server computer that had both AX client and AOS installed, and had SQL installed:
    • Microsoft Dynamics AX 2012 R2 with cumulative update 7.
    • Microsoft SQL Server 2012 SP1 Enterprise (no limit on memory).
    • Microsoft Windows Server 2012.
  • The computer hardware had the following specifications:
    • 4 processor cores, at 3.7 gigahertz.
    • Hyper-threading enabled, which logically doubles the number of cores.
    • 32 gigabytes of active memory.
    • 6.0 gigabits SATA controller.
    • Virtual page caching disabled.
Given the hardware available, AxBuild.exe decided to start 9 temporary AOS workers.
The wall clock time for AxBuild.exe was compared to the time for a legacy client-side full X++ compile. The results were as follows:
  • AxBuild.exe:    10.7 minutes.
  • MorphX client:    146.0 minutes.
  • 146.0  /  10.7  =  13.6
From another measurement we took, a single AOS worker runs 28% faster for not having to transfer information to the MorphX client and back during the full compile.

C.  How to Run AxBuild.exe

Preparations
The following preparations are necessary before you can run AxBuild.exe:
  • You must have completed the installation of cumulative update 7 for Microsoft Dynamics AX 2012 R2. This must include a re-initialization of the model store database that you run manually, by using either axutil.exe schema or the newer PowerShell equivalent. For more information, see Apply updates to database, AOS, and clients or How to: Create, Drop, or Reinitialize a Model Store.
  • You must ensure that the account which will run AxBuild.exe has no less authority than has the account that runs the permanent AOS.
  • You must ensure that the option for the hot-swapping of .NET assemblies is turned off in the AOS configuration you choose to use. See the /aos parameter on AxBuild.exe.
  • You must establish and populate the directory that will be referred to by the /altbin parameter.
Example Command Line
Here is an example command line for AxBuild.exe that might match the command line you need in your particular environment. The line is artificially wrapped here for better display.
axbuild.exe  xppcompileall  /s=01
     /altbin="C:\Program Files (x86)\Microsoft Dynamics AX\6.0\Client\Bin"

D.  Outputs from AxBuild.exe

Dn528954.collapse_all(en-us,AX.60).gifD.1  Outputs to the Console

AxBuild.exe reports its progress to the console through the stdout handle. The stderr handle is not used.
Each AOT element is reported at the moment it is compiled. Some elements can be reported repeatedly at different times before they successfully compile. These repetitions are sometimes necessary because full metadata is not always available to satisfy all dependencies until later phases of the compilation.

Dn528954.collapse_all(en-us,AX.60).gifD.2  Output Log Files

AxBuild.exe generates two log files. You can control where the log files are written by using the /log parameter. By default the files are written to the Server\...\Log\ subdirectory under the installation directory of the AOS. Here is a common example of what the specific default path might be:

 C:\Program Files\Microsoft Dynamics AX\60\Server\MicrosoftDynamicsAX\Log\
The following table describes the two log files.
File name
Description
AxCompileAll.html
Contains the final list of compile errors in XML format.
You can import the file into the MorphX development environment by following these steps:
  1. In the AOT, right-click any method node under a class, and click Compile.
    This displays the Compiler output pane.
  2. Click the >> icon on the Compiler output pane.
    The icon is located near the upper-right on the pane. The icon might be hidden if your pane size is too narrow.
  3. Click Import.
    This displays the Import compile log dialog.
  4. Navigate to the Server\...\Log\ directory to find the log file, and then click Open.
After the log file is imported, you can examine and fix each compile error just as if the errors had been logged by the compiler on the client tier.
AOTCompile.log
Contains information that partly duplicates the information that is written to the console.

Dn528954.collapse_all(en-us,AX.60).gifD.3  Temporary Files

AxBuild.exe writes temporary files to the %TEMP% directory. These files include many details about the process. By default these files are deleted by AxBuild.exe shortly before it ends. However, you can keep the files by using the/nocleanup parameter.

E.  Parameters for AxBuild.exe

The parameter names are not case-sensitive.
In all cases where the parameter name takes an accompanying value, an = sign is used to join them together, as for example /aos=01.
AxBuild.exe always returns 0.

Dn528954.collapse_all(en-us,AX.60).gifE.1  Description of Each Parameter

The following table describes the parameters that you can or must pass into AxBuild.exe.
Name
Alias
Required?
Description
xppcompileall
No short alias.
Required.
Tells the program do a full compile on all X++ code, which creates all new p-code to be stored in the model store database.
This parameter name has no accompanying value, and no leading '/'.
This parameter is a command to tell the program the type of action to perform. So far it is the only command parameter.
/altbin
/a
Optional.
Path to the folder on the local AOS host computer that has the DLL files which are installed with an ax32.exe client.AxBuild.exe verifies that ax32.exe is in the directory before it proceeds with the compile action.
A good path to use might be the path that the client install would typically create. You must confirm the exact correct path for your particular environment:

 C:\Program Files(x86)\Microsoft Dynamics AX\6.0\Client\Bin\
One way to create and populate such a directory path is to install the client onto the AOS host computer, even though maybe no person would use the client on that host.
Thereafter, any developers who add a third party DLL to their own client directory must ensure that the DLL is manually copied to this corresponding directory on each AOS where this program might be run.
If the ax32.exe client is not installed onto the AOS host computer, this manually created directory must be initially populated manually with all the DLL files from a client installation on another computer.
If you omit this parameter, AxBuild.exe examines the Microsoft Dynamics AX client configuration information in the Windows Registry in an attempt to find the correct path.
/aos
/s
Often optional.
Instance number of an AOS that is installed on the same computer where this program runs.
If you omit this parameter, AxBuild.exe examines the Microsoft Dynamics AX server configuration information in the Windows Registry. If the Registry contains information about exactly one AOS instance, that information is used as the default value for this parameter.
The temporary instances of the AOS all use the same configuration specifications that this AOS instance number uses.
To see a list of all available instance numbers, run the Microsoft Dynamics AX Server Configuration Utility,AxSrvCfg.exe. At the top of its window is a drop-down list that is labeled Application Object Server Instance. Perhaps the most commonly used value is 01, as in /aos=01.
The parameters /dbserver and /modelstore are available in case you need to override those parts of the AOS instance configuration information.
/compiler
/c
Sometimes required.
This /c parameter might be absent from the report that is generated by the /help parameter, but /c is fully supported.
You need this parameter only when the current directory is not the directory where ax32serv.exe resides. In this case the value of the parameter must be the name ax32serv.exepreceded by its directory path. A realistic example might be the following value:

 /compiler="C:\Program Files\Microsoft Dynamics AX\6.0\Server\bin\ax32serv.exe"
Full compiles that are started by automation might be relatively likely to need this parameter.
/dbserver
/d
Optional.
The name of the Microsoft SQL Server instance that manages the AX model store database.
Typically this parameter is not used. Instead the program is allowed to obtain this information from the configuration it obtains from the AOS instance that is referenced by the /aos parameter.
/help
/h or /?
Optional.
Writes brief descriptions about all parameters to the stdout handle of the console.
This parameter name has no accompanying value.
This parameter is implied if no parameters are supplied.
If there are any discrepancies between this topic and the /help output, this topic is correct.
/log
/l
Optional.
Specifies the directory path to which the two log files are written.
The default path is the Server\...\Log\ directory under the installation location of the AOS. More exactly, the default value is stored in the Registry at the following location:
 HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\services\
 Dynamics Server\6.0\01\Original (installed configuration) , in logdir.
The /log parameter does not specify the name of a file. It specifies a path.
The /verbose parameter affects how much information is written to this log file.
/modelstore
/m
Optional.
Name of the model store database.
Typically this parameter is not used. Instead the program is allowed to use the value it obtains from the configuration as directed by the /aos parameter.
/nocleanup
/n
Optional.
Tells the program to keep the temporary files it writes under the %TEMP% directory.
This parameter name has no accompanying value.
Without this parameter, the default behavior is for the program to delete the temporary files immediately before it ends its run.
/verbose
/v
Optional.
Tells the program to write all the tracing and diagnostic information that it has to stdout, and to the AOTComp.log file. Without this parameter, less information is written.
This parameter name has no accompanying value.
Usually the program writes only the subset of information that a person typically might want to watch scroll by on the screen in the cmd.exe window.
/workers
/w
Optional.
Number of parallel or concurrent AOS workers for the compilation and build processes.
The program calculates a sensible integer value based on the number of available processor cores. But you might want to fine tune this value. A rough approximation might be 1.4 workers per core.

F.  Constraints of Compiling on the AOS

Dn528954.collapse_all(en-us,AX.60).gifF.1  .NET Objects Cannot be Instantiated

When the X++ compiler starts, it performs special compiles on a few special classes. These classes includeApplicationInfolog, and ClassFactory. When these special classes are compiled during a compile on the AOS tier, they fail if any custom code has been added to them that makes interop calls to the .NET Framework.
We generally recommend that you not customize the methods in these special classes.

Dn528954.collapse_all(en-us,AX.60).gifF.2  Calls to COM Objects Cannot be Chained

In X++ you can sometimes chain together a series of method calls by using the following syntax:

 myThing.method8().method9();

This chaining syntax is valid only if the return type from method8 has a method named method9.
When you compile by using AxBuild.exe, the syntax of method chaining cannot be used with COM objects. The compiler cannot ascertain whether the COM object that is returned by method8 has a method named method9.
The simple solution is to use another common syntax that explicitly gives the compiler the type information it needs to validate the call to method9. The situation is explained in the following table.
Outcome
Explanation
Code example
Example that Fails
This X++ code example syntactically chains themethod2 call to the end of themethod1 call. The server compiler reports an error for the method2 call.
Underlying Details: Often COM objects that are called by X++ code are installed only on the client tier, and are not installed on the server tier. In the preceding code example, the underlying problem is that the server compiler cannot know the return type from method1. Its return type could be another COM object or just an integer. If the return type from method1were an integer, the chained call to method2 would certainly be invalid. The compiler issues an error because it cannot prove that method1 returns another COM object.
void methodXpp()
{
    COM comInstanceA = new COM("MyCOMType_A");
    comInstanceA.method1().method2();
}
Example thatSucceeds
This X++ code example eliminates the chain, and succeeds.
Underlying Details: In the preceding code example, the server compiler is told by an explicit type declaration that variable comInstanceB is a COM object. This gives the compiler justification to insert a call to the dispatch method for method2.
void methodXpp()
{
    COM comInstanceA = new COM("MyCOMType_A");
    COM comInstanceB;
    comInstanceB = comInstanceA.method1();
    comInstanceB.method2();
}

G.  Screenshots during Execution of AxBuild.exe

This section contains screenshots that were taken during a test run of AxBuild.exe. The run was to test for correct functional behavior on a minimal virtual machine that has only one processor. For the test we specified /workers=2to tell AxBuild.exe to start two temporary AOS workers. Therefore, for this test we expected the compilation to take a long time.
The following screenshot shows the cmd.exe console in which AxBuild.exe was started, including its output which mentions each phase.
Console for AxBuild.exe
The next screenshot shows the cmd.exe console that was started for a temporary AOS worker.
Console for a temporary AOS, for AxBuild.exe
The next screenshot shows the AxBuild.exe and temporary AOS processes in Task Manager.
Task Manager displaying two temporary AOS's
The next screenshot shows the browser that displays the contents of the AxCompileAll.html log file, which reported two warnings.
Display of AxCompileAll.html log file
The next screenshot shows a list of the temporary files that AxBuild.exe created in the %TEMP% directory. These*.tmp files were kept only because the /nocleanup parameter was specified.
Files in the %TEMP% dir kept by /nocleanup

H.  MorphX Client Menus for Compiling

AxBuild.exe adds one more mechanism that you can use to compile X++ code. In the MorphX client there are several menus that you can use to compile X++. The following table describes these menus.
Menu path
Description
Save button on the X++ code editor
Incremental compile of the X++ source code that is in the editor pane. The compile is to AX p-code.
However, no compile occurs if the source code has not changed after it was most recently compiled.
AOT > Classes > YourClass > YourMethod. Right-click YourMethod, and then clickCompile.
Incremental compile of the targeted X++ source code to AX p-code.
The compile does occur even if the code has not changed after it was most recently compiled.
Menu Build > Compile, or press F7.
Full compile of X++ to AX p-code.
The full compile occurs regardless of whether the X++ source code has changed after it was most recently compiled.
This is the client option that is most similar to AxBuild.exe.
Right-click AOT, and then click Compile.
Same as menu Build > Compile.
Right-click AOT, and then click Add-Ins, and finally click either of the following:
  • Full CIL generation from X++
  • Incremental CIL generation from X++
The CIL generation takes as input the AX p-code, not any X++ source code.
These CIL generations occur even if the p-code has not changed after the p-code was most recently compiled from X++.