Let us say we want to set 'Caption' table property to a Sample Table
......................................................
static void setTableProperty(Args _args)
{
str Property;
TreeNode TreeNode;
str Name;
;
Name = "aa_primval";
TreeNode = TreeNode::findNode("Data Dictionary\\Tables\\" + Name);
if (TreeNode)
{
Property = TreeNode.AOTgetProperties();
Property = SetProperty(Property, "Label", "RaghuSample");
TreeNode.AOTsetProperties(Property);
TreeNode.AOTcompile();
TreeNode.AOTsave();
}
}
---------------
Get table properties
Let us say we want to get 'Security key' table property for all tables. Here is a sample code -
......................................................
static void getTableProperty(Args _args)
{
#AOT
str Property;
TreeNode TreeNode;
identifiername identifiername;
str Name;
;
TreeNode = TreeNode::findNode(#TablesPath);
TreeNode = TreeNode.AOTfirstChild();
while (TreeNode)
{
Name = TreeNode.AOTname();
Property = TreeNode.AOTgetProperties();
identifiername = findproperty(Property, 'SecurityKey');
info (strfmt("%1, %2", Name, identifiername));
treenode = TreeNode.AOTnextSibling();
}
}
Monday, June 02, 2008
Windows XP can hadle Dynamics AX Clients
Windows XP Professional Operating System can handle Axapta Clients i.e. If you are having Windows xp in your machine, you can able to give access permissions to other users who can be your axapta clients. I think most of the people are aware about how to give access permissions to ax clients, the procedure is same,instead you have to stop Windows Firewall/Internet Connection Sharing Service in your services list.
Note:- Stopping the Windows Firewall/Internet Connection Sharing Service to Stop state indirectly leads to less security ( Virus Attacking )
for your system and Windows XP Professional OS is not preferrable to production environment.
Note:- Stopping the Windows Firewall/Internet Connection Sharing Service to Stop state indirectly leads to less security ( Virus Attacking )
for your system and Windows XP Professional OS is not preferrable to production environment.
Giving Colors to ComboBox values according to selection
1. Select the combobox control and set the property ColorScheme as RGB
2. then add the following codes in the modified method of the control
for example : i use a enum type ABCModel.(give some integer values for the foreground)
public boolean modified()
{
boolean ret;
ABCModel aBCModel;
;
ret = super();
switch( Str2Enum(aBCModel, ComboBox.valueStr()) )
{
case ABCModel::ContributionMargin :
ComboBox.foregroundColor(255);
break;
case ABCModel::Link :
ComboBox.foregroundColor(-400);
break;
case ABCModel::Revenue :
ComboBox.foregroundColor(100);
break;
case ABCModel::Value :
ComboBox.foregroundColor(156);
break;
}
return ret;
}
2. then add the following codes in the modified method of the control
for example : i use a enum type ABCModel.(give some integer values for the foreground)
public boolean modified()
{
boolean ret;
ABCModel aBCModel;
;
ret = super();
switch( Str2Enum(aBCModel, ComboBox.valueStr()) )
{
case ABCModel::ContributionMargin :
ComboBox.foregroundColor(255);
break;
case ABCModel::Link :
ComboBox.foregroundColor(-400);
break;
case ABCModel::Revenue :
ComboBox.foregroundColor(100);
break;
case ABCModel::Value :
ComboBox.foregroundColor(156);
break;
}
return ret;
}
start and stop services from x++ code
First in the AOT- Refrences node add a reference " System.ServiceProcess " Version is "2.0.0.0"
then write this job.
static void start_stop_Service(Args _args)
{
System.ServiceProcess.ServiceController controller = new System.ServiceProcess.ServiceController();
;
controller.set_MachineName('.');
controller.set_ServiceName("IISADMIN");
controller.Stop();
sleep(50);
controller.Start();
}
then write this job.
static void start_stop_Service(Args _args)
{
System.ServiceProcess.ServiceController controller = new System.ServiceProcess.ServiceController();
;
controller.set_MachineName('.');
controller.set_ServiceName("IISADMIN");
controller.Stop();
sleep(50);
controller.Start();
}
Create Report from x++ code
static void MakeReportJob(Args _args)
{
#AOT
str reportName = 'sampleReportfromcode';
tableid custTableId = tablenum(CustTable);
TreeNode reportNode = TreeNode::findNode(#ReportsPath);
Report areport;
ReportDesign design;
ReportAutoDesignSpecs specs;
ReportSection section;
ReportRun run;
;
// Delete the report if it already exists
areport = reportNode.AOTfindChild(reportName);
if (areport)
areport.AOTdelete();
// Build the report
areport = reportNode.AOTadd(reportName);
areport.query().addDataSource(custTableId);
design = areport.addDesign('Design');
specs = design.autoDesignSpecs();
section = specs.addSection(ReportBlockType::Body, custTableId);
section.addControl(custTableId, fieldnum(CustTable, AccountNum));
section.addControl(custTableId, fieldnum(CustTable, Name));
// Now the report will not prompt for user input
areport.interactive(false);
areport.query().interactive(false);
areport.AOTcompile();
run = ClassFactory.reportRunClass(new Args(reportName));
run.init();
run.run();
}
{
#AOT
str reportName = 'sampleReportfromcode';
tableid custTableId = tablenum(CustTable);
TreeNode reportNode = TreeNode::findNode(#ReportsPath);
Report areport;
ReportDesign design;
ReportAutoDesignSpecs specs;
ReportSection section;
ReportRun run;
;
// Delete the report if it already exists
areport = reportNode.AOTfindChild(reportName);
if (areport)
areport.AOTdelete();
// Build the report
areport = reportNode.AOTadd(reportName);
areport.query().addDataSource(custTableId);
design = areport.addDesign('Design');
specs = design.autoDesignSpecs();
section = specs.addSection(ReportBlockType::Body, custTableId);
section.addControl(custTableId, fieldnum(CustTable, AccountNum));
section.addControl(custTableId, fieldnum(CustTable, Name));
// Now the report will not prompt for user input
areport.interactive(false);
areport.query().interactive(false);
areport.AOTcompile();
run = ClassFactory.reportRunClass(new Args(reportName));
run.init();
run.run();
}
Optimized Search In Chart Of Accounts Master table
Added Optimized search in the Chart Of Accounts master table in Ax.
To accomodate the above new text box have been added in the form. The text box have been added to filter the list.
Ex. When the user types part of the number or part of Chart of Account 100, it will display only the accounts that starts with 100.
Coding : Use these methods in your FORM StringControl that we have added and Achieve your Optimized Search
1. public void textChange()
{
;
super();
element.delAutoCompleteString(this);
qbrName.value(......);
LedgerTable_ds.executeQuery();
}
2. public void enter()
{
#define.WM_KEYDOWN (0x0100)
#define.VK_END (0x23)
#define.VK_DOWN (0x28)
int i;
super();
if (this.text())
{
WinApi::sendMessage(.........);
}
}
3. public boolean modified()
{
boolean ret;
;
ret = super();
qbrName.value(.................);
LedgerTable_ds.executeQuery();
return ret;
}
To accomodate the above new text box have been added in the form. The text box have been added to filter the list.
Ex. When the user types part of the number or part of Chart of Account 100, it will display only the accounts that starts with 100.
Coding : Use these methods in your FORM StringControl that we have added and Achieve your Optimized Search
1. public void textChange()
{
;
super();
element.delAutoCompleteString(this);
qbrName.value(......);
LedgerTable_ds.executeQuery();
}
2. public void enter()
{
#define.WM_KEYDOWN (0x0100)
#define.VK_END (0x23)
#define.VK_DOWN (0x28)
int i;
super();
if (this.text())
{
WinApi::sendMessage(.........);
}
}
3. public boolean modified()
{
boolean ret;
;
ret = super();
qbrName.value(.................);
LedgerTable_ds.executeQuery();
return ret;
}
How to change Background color of the forms depending on the company you are in (Differentiate The Companies U login in AX)
add a field- color (integer type) , in the table CompanyInfo
give some values (ex -255)
and add the following codes in the class
SysSetupFormRun
public void run()
{
FormDesign formDesign = this.design();
container con;
;
#WinAPI
super ();
if (FormDesign)
{
FormDesign.colorScheme(2);
if(CompanyInfo::find().Color != 0)
{
FormDesign.backgroundColor(CompanyInfo::find().Color);
}
else
{
con = winapi::getSysColor(#COLOR_BTNFACE);
FormDesign.backgroundColor(winapi::RGB2int(conpeek(con,1),
conpeek(con,2), conpeek(con,3)));
}
FormDesign.caption(CompanyInfo::find().Name);
}
}
1. login in to the company accounts open AOT and open table browser for CompmanyInfo Table and give some values for the field "color" eg(255)
2. then log in to another company and repeat the above step
Check the difference
give some values (ex -255)
and add the following codes in the class
SysSetupFormRun
public void run()
{
FormDesign formDesign = this.design();
container con;
;
#WinAPI
super ();
if (FormDesign)
{
FormDesign.colorScheme(2);
if(CompanyInfo::find().Color != 0)
{
FormDesign.backgroundColor(CompanyInfo::find().Color);
}
else
{
con = winapi::getSysColor(#COLOR_BTNFACE);
FormDesign.backgroundColor(winapi::RGB2int(conpeek(con,1),
conpeek(con,2), conpeek(con,3)));
}
FormDesign.caption(CompanyInfo::find().Name);
}
}
1. login in to the company accounts open AOT and open table browser for CompmanyInfo Table and give some values for the field "color" eg(255)
2. then log in to another company and repeat the above step
Check the difference
Send message to online user in Dynamics AX 4.0
Remember also to replace the "curuserid()" with the user id you want the alert to be sent to.
static void sendAlert(Args _args)
{
EventInbox inbox;
EventInboxId inboxId;
inboxId = EventInbox::nextEventId();
inbox.initValue();
inbox.ShowPopup = NoYes::Yes;
inbox.Subject = "Message to online user";
inbox.Message = "Hi team, i want to restart my aos service, please save your work";
inbox.SendEmail = false;
inbox.UserId = curUserid();
inbox.InboxId = inboxId;
inbox.AlertCreatedDate = systemdateget();
inbox.AlertCreateTime = timeNow();
inbox.insert();
}
static void sendAlert(Args _args)
{
EventInbox inbox;
EventInboxId inboxId;
inboxId = EventInbox::nextEventId();
inbox.initValue();
inbox.ShowPopup = NoYes::Yes;
inbox.Subject = "Message to online user";
inbox.Message = "Hi team, i want to restart my aos service, please save your work";
inbox.SendEmail = false;
inbox.UserId = curUserid();
inbox.InboxId = inboxId;
inbox.AlertCreatedDate = systemdateget();
inbox.AlertCreateTime = timeNow();
inbox.insert();
}
Read and alter registry settings in Axapta
Here is a sample code of increasing max. open cursors during run-time. But, please note that its purpose is only to show you how to read and write registry. If you encounter any open cursors problem, it is recommended to optimize the SQL statement rather than changing the setting for maximum open cursors.
static void IncreaseMaxOpenCursors(Args _args)
{
#winapi
container regRet;
int readReg;
int writeReg;
str keyValue, keyPath, configName;
int maxOpenCursors;
;
//Specify your Axapta configuration utility name here
configName = "LocalMachine";
//New maximum open cursor, default is 90
maxOpenCursors = 120;
keyPath = @"SOFTWARE\Navision\Axapta\3.0\" + configName;
readReg = WinAPI::regOpenKey( #HKEY_CURRENT_USER, keyPath, #KEY_READ);
if (readReg)
{
regRet = WinAPI::regGetValue(readReg, 'opencursors');
keyValue = conpeek(regRet,1);
info(keyValue);
if (str2int(keyValue) < maxOpenCursors)
{
writeReg = WinAPI::regOpenKey(#HKEY_CURRENT_USER, keyPath, #KEY_WRITE);
if (writeReg)
{
WinAPI::regSetValueEx(writeReg, 'opencursors', #REG_SZ , maxOpenCursors);
WinAPI::regCloseKey(writeReg);
}
Info("Max open cursors: " + int2str(maxOpenCursors));
}
WinAPI::regCloseKey(readReg);
}
}
static void IncreaseMaxOpenCursors(Args _args)
{
#winapi
container regRet;
int readReg;
int writeReg;
str keyValue, keyPath, configName;
int maxOpenCursors;
;
//Specify your Axapta configuration utility name here
configName = "LocalMachine";
//New maximum open cursor, default is 90
maxOpenCursors = 120;
keyPath = @"SOFTWARE\Navision\Axapta\3.0\" + configName;
readReg = WinAPI::regOpenKey( #HKEY_CURRENT_USER, keyPath, #KEY_READ);
if (readReg)
{
regRet = WinAPI::regGetValue(readReg, 'opencursors');
keyValue = conpeek(regRet,1);
info(keyValue);
if (str2int(keyValue) < maxOpenCursors)
{
writeReg = WinAPI::regOpenKey(#HKEY_CURRENT_USER, keyPath, #KEY_WRITE);
if (writeReg)
{
WinAPI::regSetValueEx(writeReg, 'opencursors', #REG_SZ , maxOpenCursors);
WinAPI::regCloseKey(writeReg);
}
Info("Max open cursors: " + int2str(maxOpenCursors));
}
WinAPI::regCloseKey(readReg);
}
}
Creating Word Document through Ax
static void CreatingWordDoc(Args _args)
{
COM wordApplication;
COM wordDocuments;
COM wordDocument;
COM wordRange;
;
wordApplication = new COM("word.application");
wordApplication.visible(TRUE);
wordDocuments = wordApplication.Documents();
wordDocument = wordDocuments.add();
wordDocument.saveas("c:\\YourDocument.doc");
wordDocument.activate();
wordRange = wordDocument.range(0,0);
wordRange.insertafter("Naresh Kumar.Ch");
wordRange = wordDocument.range(6,19);
wordRange = wordDocument.range(11,26);
wordRange.italic(true);
wordDocument.save();
wordDocument.close();
wordApplication.quit();
}
{
COM wordApplication;
COM wordDocuments;
COM wordDocument;
COM wordRange;
;
wordApplication = new COM("word.application");
wordApplication.visible(TRUE);
wordDocuments = wordApplication.Documents();
wordDocument = wordDocuments.add();
wordDocument.saveas("c:\\YourDocument.doc");
wordDocument.activate();
wordRange = wordDocument.range(0,0);
wordRange.insertafter("Naresh Kumar.Ch");
wordRange = wordDocument.range(6,19);
wordRange = wordDocument.range(11,26);
wordRange.italic(true);
wordDocument.save();
wordDocument.close();
wordApplication.quit();
}
Failed to create object on AX 4.0 AOS
You may come across this issue when attempt to initialize a COM object on AX 4 AOS server side:
static server void ActivateCOMOnAOS()
{
#define.Word('Word.Application')
COM com;
InteropPermission permission = new InteropPermission(InteropKind::ComInterop);
;
permission.assert();
//BP deviation documented
com = new COM(#Word);
CodeAccessPermission::revertAssert();
}
And an error message will appear:
COM object of class 'Word.Application' could not be created. Ensure that the object has been properly registered on computer 'ComputerName'.
It is because by default, Microsoft Word as a COM object can not be launched by the user NT AUTHORITY\NETWORK SERVICE.
The way to resolve this issue is to modify the Activation permission for Word Application using the Component Services administrative tool.
Configure DCOM (Windows 2003)
*
Start -> All programs -> Administrative Tools -> Component Services.
*
Expand Component Services
*
Expand Computers
*
Expand My Computer
*
Select the DCOM Config item
*
Select the Microsoft Word Document item.
*
Right click and select Properties
*
Under Launch and Activation Permissions select the Customize option.
*
Click the Edit button
*
Click the Add button to add a new account to the list.
*
Click the OK button
*
On the dialog that is displayed enter Network Service as the account name.
*
Grant Network Service the launch and activate permission.
static server void ActivateCOMOnAOS()
{
#define.Word('Word.Application')
COM com;
InteropPermission permission = new InteropPermission(InteropKind::ComInterop);
;
permission.assert();
//BP deviation documented
com = new COM(#Word);
CodeAccessPermission::revertAssert();
}
And an error message will appear:
COM object of class 'Word.Application' could not be created. Ensure that the object has been properly registered on computer 'ComputerName'.
It is because by default, Microsoft Word as a COM object can not be launched by the user NT AUTHORITY\NETWORK SERVICE.
The way to resolve this issue is to modify the Activation permission for Word Application using the Component Services administrative tool.
Configure DCOM (Windows 2003)
*
Start -> All programs -> Administrative Tools -> Component Services.
*
Expand Component Services
*
Expand Computers
*
Expand My Computer
*
Select the DCOM Config item
*
Select the Microsoft Word Document item.
*
Right click and select Properties
*
Under Launch and Activation Permissions select the Customize option.
*
Click the Edit button
*
Click the Add button to add a new account to the list.
*
Click the OK button
*
On the dialog that is displayed enter Network Service as the account name.
*
Grant Network Service the launch and activate permission.
DatabaseVersionNumbers of ur system
Run this job to get the databaseVersionNumbers of ur system
static void databaseVersionNumbers()
{
#define.SQL_DBMS_NAME(17)
#define.SQL_DBMS_VER(18)
#define.SQL_DATABASE_NAME(16)
#define.SQL_DRIVER_ODBC_VER(77)
#define.SQL_DRIVER_VER(7)
#define.SQL_ODBC_VER(10)
Connection mainConnection = new Connection();
;
setPrefix("Information about database and ODBC version numbers.");
info(strFmt("Name of the database product: '%1",
mainConnection.odbcGetInfoStr(#SQL_DBMS_NAME)));
info(strFmt("Name of the database: '%1",
mainConnection.odbcGetInfoStr(#SQL_DATABASE_NAME)));
info(strFmt("Database version number: '%1",
mainConnection.odbcGetInfoStr(#SQL_DBMS_VER)));
info(strFmt("ODBC driver version: '%1",
mainConnection.odbcGetInfoStr(#SQL_DRIVER_VER)));
info(strFmt("ODBC Driver Manager version: '%1",
mainConnection.odbcGetInfoStr(#SQL_DRIVER_ODBC_VER)));
info(strFmt("ODBC API version: '%1",
mainConnection.odbcGetInfoStr(#SQL_ODBC_VER)));
}
static void databaseVersionNumbers()
{
#define.SQL_DBMS_NAME(17)
#define.SQL_DBMS_VER(18)
#define.SQL_DATABASE_NAME(16)
#define.SQL_DRIVER_ODBC_VER(77)
#define.SQL_DRIVER_VER(7)
#define.SQL_ODBC_VER(10)
Connection mainConnection = new Connection();
;
setPrefix("Information about database and ODBC version numbers.");
info(strFmt("Name of the database product: '%1",
mainConnection.odbcGetInfoStr(#SQL_DBMS_NAME)));
info(strFmt("Name of the database: '%1",
mainConnection.odbcGetInfoStr(#SQL_DATABASE_NAME)));
info(strFmt("Database version number: '%1",
mainConnection.odbcGetInfoStr(#SQL_DBMS_VER)));
info(strFmt("ODBC driver version: '%1",
mainConnection.odbcGetInfoStr(#SQL_DRIVER_VER)));
info(strFmt("ODBC Driver Manager version: '%1",
mainConnection.odbcGetInfoStr(#SQL_DRIVER_ODBC_VER)));
info(strFmt("ODBC API version: '%1",
mainConnection.odbcGetInfoStr(#SQL_ODBC_VER)));
}
New Layers in Dynamics AX 2009

4 layers have been renamed in Dynamics AX 2009 . DIS / DIP / LOS / LOP have become HFX / SL1 / SL2 / SL3 respectively. HFX is reserved for releasing hot fixes, and the 3 new solution layers (SL1/SL2/SL3) will be used to release Microsoft Dynamics Industry Solutions.
The purpose of having 3 solution layers is to enable side-by-side install of Industry Solutions. At deployment time any SL1 layer can be renamed to SL2, SL3, BUS or BUP through a regular file rename. The AOS will recognize the layer, and honor its position in the layer stack. This will enable installing up to 3 Industry Solutions on the same system (or up to 5 Industry Solutions if the BUS and BUP layers are vacant.)
Another aspect of side-by-side installation is conflicting names and IDs in the model. The AX platform requires unique names and IDs of all model elements, we will ensure uniqueness across Industry Solutions through our engineering processes. Naturally there will be logically overlayering conflicts for certain elements; but as the Industry Solutions by nature are verticals we anticipate very few of these. These conflicts will need to be resolved; one way is to reclaim one of the SLx layers as an adaptation layer. More information on this will be available as the Industry Solutions become available.
Why not just support an unlimited numbers of layers?
Frequent feedback we get is to add more layers; and open them up for consumption by the partners. And heck, why we are at it why not have an unlimited number of layers?
Currently; there is an upper limit on the number of layers the kernel can support. This number is 16. The technical explanation has to do with referencing of the elements in the model. Each model element is stored in a record in the AOD file. The RecId for model elements is a 32 bit integer. 4 of these bits denote the layer; the remaining 28 bits are used to calculate the offset into the AOD file where the record is located. In version 3.0 (and previously) the block size was 1 byte. This basically mean the maximum size of an AOD file is about 256MB (2^28). In version 4.0 we moved this limit by denoting one of the 28 bits to control the block size. When the bit is not set, the 27 bits is the direct offset in to the file. When the bit is set, a block size of 48 bytes is used to calculate the offset in the file. This enables AOD files with sizes up to about 6.5 GB (2^27 * 49), while enabling binary backwards compatibility with 3.0 AOD files (with sizes less than 128MB (2^27)).
If we decide to use one bit more to denote the layer (giving us 32 layers); it means we are only backwards compatible with AOD files with sizes less than 64MB (2^26). As that is not acceptable; tools to align the contents in AOD files would be needed. For 6.0 we are investigating options to tear down these limitations once and for all.
Differnt types of Range value formats
Usually in forms we filter date as per the given ranges.We specify the Ranges using queryBuildrange class.
Here is a collection of different range formats.
Range in String format
1) if(element.args().dataset() == tableNum(CustTable)
{
adrTableid.value(strfmt('%1', CustTable.TableId));
adrRecid.value(strfmt('%1', CustTable.RecId));
}
2)this.query().dataSourceNo(1).addRange(fieldnum(COSCalcTrans, RecId)).value('!' + queryValue(COSCalcTrans.RecId));
3) case DM_AllWOStatus::All :
qbrStatus.value(queryvalue(WOStatus::Openorder) + ","
+ queryvalue(WOStatus::WIP) + ","
+ queryvalue(WOStatus::Completed) +","
*
queryvalue(WOStatus::Invoice ));
4)this.query().dataSourceTable(tablenum(LedgerJournalTrans)).range(1).value(strfmt('((%1 == "%3") || (%2 == "%3"))',
fieldstr(LedgerJournalTrans,AccountNum),
fieldstr(LedgerJournalTrans,OffsetAccount),
ledgerTable.AccountNum));
Date Range
1)criteriaBOMToDate1.value(queryRange(fromDate,dateMax())); fromdate = some specific date
2)reconciledDate.value('>' + date2StrXpp(dateNull()));
3)criteriaBOmToDate2.value(queryValue(dateNull()));
4)criteriaBOMFromDate.value('');
Enum as Range
1)qbrStatus.value(queryvalue(DM_WOStatus::Invoice));
2)criteriaOpen.value('0..1');
Form Control value as Range
1)typeRange.value(ctrlTypeRange.text() ? ctrlTypeRange.text() : SysQuery::valueUnlimited());
Here is a collection of different range formats.
Range in String format
1) if(element.args().dataset() == tableNum(CustTable)
{
adrTableid.value(strfmt('%1', CustTable.TableId));
adrRecid.value(strfmt('%1', CustTable.RecId));
}
2)this.query().dataSourceNo(1).addRange(fieldnum(COSCalcTrans, RecId)).value('!' + queryValue(COSCalcTrans.RecId));
3) case DM_AllWOStatus::All :
qbrStatus.value(queryvalue(WOStatus::Openorder) + ","
+ queryvalue(WOStatus::WIP) + ","
+ queryvalue(WOStatus::Completed) +","
*
queryvalue(WOStatus::Invoice ));
4)this.query().dataSourceTable(tablenum(LedgerJournalTrans)).range(1).value(strfmt('((%1 == "%3") || (%2 == "%3"))',
fieldstr(LedgerJournalTrans,AccountNum),
fieldstr(LedgerJournalTrans,OffsetAccount),
ledgerTable.AccountNum));
Date Range
1)criteriaBOMToDate1.value(queryRange(fromDate,dateMax())); fromdate = some specific date
2)reconciledDate.value('>' + date2StrXpp(dateNull()));
3)criteriaBOmToDate2.value(queryValue(dateNull()));
4)criteriaBOMFromDate.value('');
Enum as Range
1)qbrStatus.value(queryvalue(DM_WOStatus::Invoice));
2)criteriaOpen.value('0..1');
Form Control value as Range
1)typeRange.value(ctrlTypeRange.text() ? ctrlTypeRange.text() : SysQuery::valueUnlimited());
Args class
Args-Object
The Args-class defines the communication between running application objects.The application object that initiates the communication (the caller), is initializing an args object that has information and passes it to the application object that is called:
Caller --------> Args ---------> Called
Different Methods of Args Class
Caller ----------> A handle to the caller object.With this it is possible for the application object called to activate methods on the caller.
EX:
if (!element.args().caller())
{
//The form cannot be called directly.
throw error("@SYS96590");
}
dataset ---------------> The Id of the table that the caller object currently is working on. This information is typically used to verify which type of record that is transferred.
record ------------------> A handle to the record that the caller currently is working on.This information is typically used to access the values of the caller’s
record. Remember to check the table before you assigns this handle into a specific table variable.
EX:
if (element.args().dataset() == tablenum(custTable))
{
custTable = element.args().record();
}
parmEnumType -------------> The Id of the enum that is specified on the command.
parmEnum ---------------> The entry of the enum that is specified on the menu item.
parm ---------------> A string which can be used to transfer information. It is best practice not to use this method. Try to build the communication
on the information above.
EX:
ItemType itemType;
str parm;
if(element.args().parmEnumType() == enumNum(ItemType))
{
itemType = element.args().parmEnum(); // itemType (ITEMS,BOM,SERVICE)
parm = element.args().parm(); // to access the parm string given on Menuitem
}
To call a form Ffrom X++
Args args = new Args();
args.name(formstr(salesTable));
args.caller(this);
args.record(custTable); //a specific custtable record
formRun = classfactory.formRunClass(args);
formRun.init();
formRun.run();
formRun.wait();
To call a form's menuitem from X++
Args args;
FormRun formRun;
;
args = new Args();
args.caller(this);
args.record(_record);
args.parmObject(_formRun);
formRun = new MenuFunction(menuitemdisplaystr(custTable), MenuItemType::Display).create(args);
The Args-class defines the communication between running application objects.The application object that initiates the communication (the caller), is initializing an args object that has information and passes it to the application object that is called:
Caller --------> Args ---------> Called
Different Methods of Args Class
Caller ----------> A handle to the caller object.With this it is possible for the application object called to activate methods on the caller.
EX:
if (!element.args().caller())
{
//The form cannot be called directly.
throw error("@SYS96590");
}
dataset ---------------> The Id of the table that the caller object currently is working on. This information is typically used to verify which type of record that is transferred.
record ------------------> A handle to the record that the caller currently is working on.This information is typically used to access the values of the caller’s
record. Remember to check the table before you assigns this handle into a specific table variable.
EX:
if (element.args().dataset() == tablenum(custTable))
{
custTable = element.args().record();
}
parmEnumType -------------> The Id of the enum that is specified on the command.
parmEnum ---------------> The entry of the enum that is specified on the menu item.
parm ---------------> A string which can be used to transfer information. It is best practice not to use this method. Try to build the communication
on the information above.
EX:
ItemType itemType;
str parm;
if(element.args().parmEnumType() == enumNum(ItemType))
{
itemType = element.args().parmEnum(); // itemType (ITEMS,BOM,SERVICE)
parm = element.args().parm(); // to access the parm string given on Menuitem
}
To call a form Ffrom X++
Args args = new Args();
args.name(formstr(salesTable));
args.caller(this);
args.record(custTable); //a specific custtable record
formRun = classfactory.formRunClass(args);
formRun.init();
formRun.run();
formRun.wait();
To call a form's menuitem from X++
Args args;
FormRun formRun;
;
args = new Args();
args.caller(this);
args.record(_record);
args.parmObject(_formRun);
formRun = new MenuFunction(menuitemdisplaystr(custTable), MenuItemType::Display).create(args);
Use of AVI files (Animate files)
The Avi Macro Files can be used in Ax to make it look more cool.
Run the following job and check it out.
static void Animate(Args _args)
{
Args args;
Form formanimate;
FormRun formrun;
FormBuildDesign formdesign;
FormBuildAnimateControl animatecontrol;
FormBuildGroupControl groupcontrol;
Container c;
counter counter;
;
#AviFiles
c =[#AviFileCopy,#AviFileDel,#AviFileDelr,#AviFileMove,#AviSearch];
formanimate = new form();
formanimate.name("Example for Animation Controls");
formdesign = formanimate.addDesign("design");
formdesign.caption("AviFiles from MacroFiles");
formdesign.columns(3);
for(counter = 1;counter<=conlen(c);counter++)
{
groupControl = formDesign.addControl(FormControlType::Group,'group'+int2str(counter));
groupControl.widthMode(FormWidth::ColumnWidth);
groupControl.caption(strfmt("@SYS70938", conpeek(c,counter), conpeek(c,counter)));
animateControl = groupControl.addControl(FormControlType::Animate,'animate'+int2str(counter));
animateControl.autoPlay(true);
animateControl.animateFile(conpeek(c,counter));
}
args = new Args();
args.object(formanimate);
formRun = classFactory.formRunClass(args);
formRun.init();
formRun.run();
formRun.detach();
}
Run the following job and check it out.
static void Animate(Args _args)
{
Args args;
Form formanimate;
FormRun formrun;
FormBuildDesign formdesign;
FormBuildAnimateControl animatecontrol;
FormBuildGroupControl groupcontrol;
Container c;
counter counter;
;
#AviFiles
c =[#AviFileCopy,#AviFileDel,#AviFileDelr,#AviFileMove,#AviSearch];
formanimate = new form();
formanimate.name("Example for Animation Controls");
formdesign = formanimate.addDesign("design");
formdesign.caption("AviFiles from MacroFiles");
formdesign.columns(3);
for(counter = 1;counter<=conlen(c);counter++)
{
groupControl = formDesign.addControl(FormControlType::Group,'group'+int2str(counter));
groupControl.widthMode(FormWidth::ColumnWidth);
groupControl.caption(strfmt("@SYS70938", conpeek(c,counter), conpeek(c,counter)));
animateControl = groupControl.addControl(FormControlType::Animate,'animate'+int2str(counter));
animateControl.autoPlay(true);
animateControl.animateFile(conpeek(c,counter));
}
args = new Args();
args.object(formanimate);
formRun = classFactory.formRunClass(args);
formRun.init();
formRun.run();
formRun.detach();
}
Code Access security
The new Dynamics Ax 4.0 release proivdes more tighter security access over API's System tables, and System level classes. I am really delighted with the leap jump in the
security portion which is imperative in todays scenario......
I have listed out the new security classes that have been added to Ax
SqlStatementExecutePermission
SqlDataDictionaryPermission
SkipAOSValidationPermission
RunAsPermission
InteropPermission
ExecutePermission
CodeAccessPermission
FileIOPermission
For Example if you are using Sysdictclass.callobject method with the new security structure it would be something like this
ExecutePermisssion::Assert();
SysDictClass.callobject(.........);
and also remember to call the revertassert option, when ever you are access to the secured system class is complete
The Class codeAccessSecurity is an abstract type and you will have to extend it too. SysDatabaseLogPermission class is a good example which would explain you about
exending and using the codeAccessSecurity permisssion class (you can expect a post on this soon).
The Best Practice compiler is so designed to give you a Best practice warning. whenever you feel that you don't need to use the security classes , just write //BP Deviation
Documented above the line to avoid BP warning
//BP Deviation Documented
SysDictClass.callobject(.........);
security portion which is imperative in todays scenario......
I have listed out the new security classes that have been added to Ax
SqlStatementExecutePermission
SqlDataDictionaryPermission
SkipAOSValidationPermission
RunAsPermission
InteropPermission
ExecutePermission
CodeAccessPermission
FileIOPermission
For Example if you are using Sysdictclass.callobject method with the new security structure it would be something like this
ExecutePermisssion::Assert();
SysDictClass.callobject(.........);
and also remember to call the revertassert option, when ever you are access to the secured system class is complete
The Class codeAccessSecurity is an abstract type and you will have to extend it too. SysDatabaseLogPermission class is a good example which would explain you about
exending and using the codeAccessSecurity permisssion class (you can expect a post on this soon).
The Best Practice compiler is so designed to give you a Best practice warning. whenever you feel that you don't need to use the security classes , just write //BP Deviation
Documented above the line to avoid BP warning
//BP Deviation Documented
SysDictClass.callobject(.........);
Wednesday, May 21, 2008
Thursday, April 24, 2008
Dynamics AX Architecture
ÜAxapta is a highly customizable global ERP system
üMicrosoft Dynamics™ AX 4.0 is an adaptable, global business management solution for midsize to large businesses and global enterprises that works like and with familiar Microsoft® software and helps organizations gain competitive advantage. Through the use of Web services and other enhancements, Microsoft Dynamics AX 4.0 delivers a complete enterprise resource planning (ERP) package to automate and streamline processes across a company’s financials, customer relationships, business services, human resources and the supply chain.
ÜAxapta meets the needs of Enterprise Level Business
ü Multi Languages, -Currencies, -Location > 30 countries
ü 1 Business Logic,1 Source Code , 1 Database,1 Toolbox
ü IDE - Integrated development Environment
ü E-Commerce
ü Web Integration/ Web Portals
ü Sales/Procurement/Manufacturing/Distribution Planning
ü IT Professional Service and Network Integration
üVisibility and business insight across locations and countries for global companies
üReal-time visibility across locations and countries with role-based information and processes via the Web
üTwo or more companies can use the same system while maintaining separate financial records
üEnterprise portal with Microsoft Windows Share point service integration
üReporting services with Microsoft SQL Server 2005
üWeb services and .NET interoperability with Microsoft Visual Studio 2005
üBusiness document exchange and integration framework with Microsoft BizTalk Server 2006
Solution functionality:
Financial Management
Supply Chain Management
CRM
Human Resourcesand Payroll
Industry Enabling:
Supply Chain Execution
Demand Planning
Fund Accounting
Quality Management Vertical Solutions:
High Tech, Aerospace,
Metals, IEM, Oil & Gas, Chemicals, CPG, Food & Bev, Industrial, Hospitality, Apparel, Food & Bev, Auto Dealer, Specialty Store, Healthcare, Works, Fin and Admin, Utilities, Transport, NFP, Construction, Arch & Engineer, IT Services, Legal Services, Advertising
Metals, IEM, Oil & Gas, Chemicals, CPG, Food & Bev, Industrial, Hospitality, Apparel, Food & Bev, Auto Dealer, Specialty Store, Healthcare, Works, Fin and Admin, Utilities, Transport, NFP, Construction, Arch & Engineer, IT Services, Legal Services, Advertising
Microsoft partners delivers solutions tailored to all of the below mentioned industries
Subscribe to:
Posts (Atom)
