Wednesday 28 December 2011

"An invalid directory structure for Microsoft Dynamics AX was detected"


Running AX 2009 Client raises error: "An invalid directory structure for Microsoft Dynamics AX was detected"
We came across an issue recently where the Microsoft Dynamics AX 2009 Client was installed ,However after deployment when the client is run from the desktop systems we got a pop window with an error and clicking ok closes the client down:


 Error in text:
An invalid directory structure for Microsoft Dynamics AX was detcted. The subdirectory \Client\bin does not exist.

Upon further investigation, when we ran regedit to look at the registry keys created for the AX Client configuration, indeed it had incomplete path to the client\bin folder. The cause of teh error message. The issue occured on any Windows XP/Vista/7/2003 R2/2008/2008 R2 platform whether its 32bit or 64bit. The paths recorded in the registry were:

[HKEY_CURRENT_USER\Software\Microsoft\Dynamics\5.0\Configuration\Original (installed configuration)]
"bindir"="\Client\Bin"
"datadir"="Client\Data"
"directory"="\Client"
and the correct registry paths should have been (on an x64 system):
[HKEY_CURRENT_USER\Software\Microsoft\Dynamics\5.0\Configuration\Original (installed configuration)]
"bindir"="C:\Program Files (x86)\Microsoft Dynamics AX\50\Client\Bin"
"datadir"="C:\Program Files (x86)\Microsoft Dynamics AX\50\Client\Data"
"directory"="C:\Program Files (x86)\Microsoft Dynamics AX\50\Client"
(x86 system):
[HKEY_CURRENT_USER\Software\Microsoft\Dynamics\5.0\Configuration\Original (installed configuration)]
"bindir"="C:\Program Files\Microsoft Dynamics AX\50\Client\Bin"
"datadir"="C:\Program Files\Microsoft Dynamics AX\50\Client\Data"
"directory"="C:\Program Files\Microsoft Dynamics AX\50\Client"
manually modifying the registry keys with correct values, resolves the issue and allows clients to be run without any errors.

Tuesday 13 December 2011

Find all display methods in a table


One of my colleague asked this question to me ,
I used the class  “SysDicttable” , to start with and it helped .
I came up with the job mentioned below ,


static void getListOfDisplayMethods (Args _args)
{
    SysDictTable dictTable;
    CustTable custtable;
    List methodList = new List(Types::String);
       ListEnumerator enumerator;
       int i;

    ;

   //77 is the ID of Custtable, you can replace this with out tableid/tablename
    dictTable = new SysDictTable(77);


    methodList =dictTable.getListOfDisplayMethods();
    enumerator = methodList.getEnumerator();
    while(enumerator.moveNext())
    {
    info(enumerator.toString());
    i++;
    }
  
    info(strfmt("no of methods %1",i));
     info(strfmt("no of methods %1",dictTable.objectMethodCnt()));

}

Happy DAXING  J

Cannot execute a data definition language command on (). The SQL database has issued an error.,


While Synchronizing the database , some times we get the  following error , without knowing the tables name ,which caused the issue


Run the below job , in order to get the table name
static void forceDbSynchronize(Args _args)
{
    Dictionary              dict;
    int                     idx, lastIdx, totalTables;
    TableId                 tableId;
    Application             application;
    SysOperationProgress    progress;
    StackBase               errorStack;
    ErrorTxt                errorTxt;
    ;

    application = new Application();
    dict = new Dictionary();
    totalTables = dict.tableCnt();
    progress = new SysOperationProgress();
    progress.setTotal(totalTables);
    progress.setCaption("@SYS90206");
    errorStack = new StackBase(Types::String);

    lastIdx = 0;
    try
    {
        for (idx = lastIdx+1; idx <= totalTables; idx++)
        {
            tableId = dict.tableCnt2Id(idx);
            progress.setText(dict.tableName(tableId));

            lastIdx = idx;
            application.dbSynchronize(tableId, false, true, false);
            progress.incCount();
        }
    }
    catch (Exception::Error)
    {
        errorTxt = strFmt("Error in table '%1' (%2)", tableId, dict.tableName(tableId));
        errorStack.push(errorTxt);
        retry;
    }

    setPrefix("@SYS86407");
    errorTxt = errorStack.pop();
    while (errorTxt)
    {
        error(errorTxt);
        errorTxt = errorStack.pop();
    }
}




Thursday 17 November 2011

Posting General Journal using code


How to do it...

  1. 1. Open AOT and create a new class called JournalPost with the following code (replace 000152_010 with your journal number):
    class JournalPost
    {
    }
    public static void main(Args _args)
    {
    LedgerJournalCheckPost jourPost;
    LedgerJournalTable jourTable;
    ;
    jourTable = LedgerJournalTable::find('000152_010');
    jourPost = LedgerJournalCheckPost::newLedgerJournalTable(
    jourTable,
    NoYes::Yes);
    jourPost.run();
    }
  2. 2. Run the class and notice the Infolog confirming that the journal was successfully posted:

Tuesday 1 November 2011

Coloring records in a Form

I was working on a request , where user want to have salesorder of having SalesStatus  cancel in Red color ,

I achieved this by overriding method Displayoption of datasource salestable as below :

public void displayOption(Common _record, FormRowDisplayOption _options)
{
    ;
    if(_record.(Fieldnum(salestable,salesstatus)) == SalesStatus::Canceled)
    {
        _options.backColor(WinAPI::RGB2int(255,100,100));
    }
    super(_record, _options);


Hope this will help , thanks
}



Thursday 27 October 2011

HTTP Error 404.3 - Not FoundThe page you are requesting cannot be served because of the extension configuration. If the page is a script, add a handle

While generating AIF service , I was not able to browse the service generated , I was getting below error :

HTTP Error 404.3 - Not FoundThe page you are requesting cannot be served because of the extension configuration. If the page is a script, add a handle ............

I googled , and as usual It helped me to find the root cause , that is we need to install WCF , using service model  as below  :



Make sure to use option  : servicemodelreg.exe -iru , not only -i as mentioned in various other blogs .

Happy daxing

Sunday 23 October 2011

Change File Ownership through X++ in Dynamics AX

Hi all , while working with AIF using file system adapter, it is very painful to update every time the owner of XML file , otherwise AX will not read the file and will throw the error , I have used icacls utility to update the ownership of file . I have modifed the class AIFFileSystemreceiveadapter , you can find it on skydrvie. https://skydrive.live.com/redir.aspx?cid=32417e20be1cdd11&resid=32417E20BE1CDD11!114

\
The changed code is as below  :


 select * from userInfo where userInfo.Id == curuserid();
 domain = System.Environment::get_UserDomainName();
 command = "/c" + " icacls " + filePath  + " /setowner "  +  domain + "\\" + userInfo.networkAlias;
 WinAPI::shellExecute("cmd.exe", command);


Thanks,

Wednesday 19 October 2011

Restricted Vs. Cascade+Restricted

 When we discuss about delete actions , it is very confusing Restricted/Casecade+Restricted . I am trying to explain here :
Suppose we have 3 table , table1 , table2 , table3 .

Scenario 1 :
Table1 is having a restricted delete actions with table2 and table3 is having a cascade delete action with table1.
Now if we try to delete the record in table3 , and if record exists in table2 , we will get error
"The record may not be deleted. Transactions exist in table 'Table2'."

Scenario 2:

Table1 is having a cascade + restricted delete actions with table2 and table3 is having a cascade delete action with table1.
Now if we try to delete the record in table3 , and if record exists in table2, records will be deleted from table 3 , table 1 and table 2 as well.

One more thing , if you will try to delete the data from table1 and record exist in table2 , you cannot delete the  data in table1 (now cascade + restricted will behave like restricted)




Will be back soon,
Thanks

Model driven architecture in AX 2012

AX 2012 has come up with a unique model driven architecture . A model is logical grouping of elements within a layer.This architecture helps in situation multiple projects /Solutions must operate together. We can consider the below scenario :


A company has two lines of business. They manufacture and sell medical products. They also manufacture, sell and service specialized equipment to produce medical products.

• Solution A is an advanced vertical solution for the production of
food and drug products. Among other things, this solution adds a
new field to the item table to store the government approval number.
This is stored in the ISV layer and in the model MEDICAL.

• Solution B is an advanced vertical solution for managing the ongoing
service of equipment which is sold to customers. Among other
things, this solution adds a new field to the item table for the default
service period. This is stored in the ISV layer and in the model
SERVICE.

• You can use models to view the modifications to the item table made
by all ISV solutions and easily see where each change originated.


How does Model helps :



  • The development environment for Microsoft Dynamics AX lets you create a project for each model that is installed. Therefore, you can quickly see all the installed customization in a layer for a given model.
  • When you import a model, elements in the model that you are importing may conflict with another model in the same layer. You can now create a conflict model in the patch layer that is associated with the layer that you are working in. You can then resolve the conflicts in the conflict model. In earlier versions, no warnings about conflicts were displayed. Instead, elements were just replaced.
  • You can now leave the rest of the layer intact when you uninstall a model. In earlier versions, if you wanted to uninstall customization, you had to either remove the customizations manually from the AOT or remove the layer.



Monday 10 October 2011

Could not load file or assembly 'Microsoft.Dynamics.AX.Fim.PaymentService, Version=5.0.0.0,


While deploying SSRS , I got the below error :
Could not load file or assembly 'Microsoft.Dynamics.AX.Fim.PaymentService, Version=5.0.0.0,………….
To overcome this issue, we need to add the above mentioned dll from client\bin  folder to GAC as below :
Go to Start -> All programs -> Microsoft visual studio 2008 -> visual studio  tools -> visual studio  command prompt , right click and run as administrator :
Run the below  command :
Gacutil /i “location of dll”

Upon successfully added , you will get the message , “Assembly added to the cache”.


Hope it helps you as well.

Sunday 9 October 2011

How to add date range in SSRS



·         Create two parameters FromDate and Todate with Datatype System.DateTime
·         Add one filter under design with name FromDate with below values :
i)        Value = =1
ii)       Expression = =iif(isnothing(Parameters!FromDate.Value) = false,
iif(Parameters!FromDate.Value <= Fields!yourfield.Value, 1, 0), 1)


                Add another filter with name todate
                with above values except the expression values will be now
                        Expression = =iif(isnothing(Parameters!FromDate.Value) = false,
iif(Parameters!FromDate.Value >= Fields!yourfield.Value, 1, 0), 1)

Now you are good to go

Friday 7 October 2011

Runas AX as a different user

While working with Workflow, many time there was situation where I would like to run AX as different user , But on Window 7 , "Run as" is not available ,when you right click.
There are two ways to overcome this :

1.Using command line :

When you want to open AX as a different user , go to Start -> Run 
and type cmd, Command prompt will open enter the below command :
runas /user:yourusername "C:\Program Files (x86)\Microsoft Dynamics AX\50\Client\Bin\Ax32.exe"

press enter , system will ask  about the credentials , pass these values ,and you can open AX with different user

2.Using Runas property :

Select the shortcut menu for AX , and while clicking right click , hold Shift key ,you will see , the Run As different user as well, as below 


Hope this will help you.
Thanks

Tuesday 4 October 2011

An error message occurs when you create a dataset that has a "Dimension" type field

While working on one SSRS project , I got the error "

Could not refresh the dataset since query 'SELECT CustTable.1.AccountNum,CustTable.1.City,CustTable.1.Dimension[1],CustTable.1.Dimension[2],CustTable.1.Dimension[3] FROM CustTable' could not be resolved in Dynamics AX"



The problem here was that we have selected Dimension fields in query  , and AX was not able to resolve it because , these fields in database are stored as  Dimension,Dimension1_  and so on ........ not like Dimension[1], Dimension[2],... .

Microsoft has provided the fix for this issue ,Please find the below link :

Make sure to install it on client and sever both machine, as well where you are developing SSRS.

will be back very soon

Thanks, 

How to debug AIF in AX 2009

Hi Friends,
This is my first post .
I was working on one AIF project . As you know , for any developer life starts with debugger , when I started debugging for AIF classes , to my surprise I was not able to debug the AIF classes , even I tried with "breakpoint" as well . As I struggled with this, I thought , it will be good to share this experience

We have to update the method runasWrapper of class AifInboundProcessingService as below :


public static void runAsWrapper(AifWindowsUser runAsUserId, container messageIdContainer)
{
    AifGatewayQueue   gatewayQueue;
    userId            axaptaUserId;
    AifMessageId      messageId;
    int               messageIdContainerIdx = 1;
    AifMessage        errorMessage;
    AifInfoLog        aifInfoLog;
    SysExceptionLog   exceptionLog;
    ;

    aifInfoLog = new AifInfoLog();
    try
    {
        // Convert to Axapta UserId
        axaptaUserId = AifEndpointUser::getAxaptaUser(runAsUserId).Id;

        new RunAsPermission(axaptaUserId).assert();

        // BP deviation documented
       /* runas(axaptaUserId,
                classnum(AifInboundProcessingService),
                staticmethodstr(AifInboundProcessingService, processAsUser),
                messageIdContainer);
*/
        AifInboundProcessingService::processAsUser(messageIdContainer);
        CodeAccessPermission::revertAssert();
    }

Here we have commented the runas (.....) and added AifInboundProcessingService::processAsUser(messageIdContainer);

Hope this will help you guys as well.

PS : Make sure you have enabled debugging in client and server configuration as well

Will be back very soon , happy DAXing.