Monday, February 27, 2012
Ax2012
I just installed and configured the VirtualBox from Oracle and the Dynamics AX 2012 demo after these instructions. It worked great, so now I have a working AX2012 test and training setup.
Friday, February 17, 2012
Get the callstack without the need of breakpoints
Normally, when you debug a issue, you use the debugger and breakpoints. That's fine, but sometimes you need to debug bugs that triggers randomly and you need to check the call stack for more information or even log the call stack to a table for later inspections. Here is how to do that. Create a new class or use your existing tool class and insert the following method:
static str getCallStack(boolean _showInfo = false)
{
xSession xSession = new xSession();
container callStack = xSession::xppCallStack();
str text;
int i;
str convert2string(anytype _value, int variation = 0)
{
switch (typeof(_value))
{
case Types::String :
return _value;
case Types::Real :
return num2str(_value, 10, 4, 1, 0);
case Types::Integer :
return int2str(_value);
case Types::Date :
if (variation == 0)
return date2str(_value, 321, 2, 3, 2, 3, 4 );
else if (variation == 1)
return date2str(_value, 321, 2, 1, 2, 1, 2 );
case Types::Enum :
return enum2str(_value);
}
}
for (i = 1; i < conLen(callStack); i+=2)
{
if(_showInfo)
info( "Path: " + convert2string(conPeek(callStack, i)) + " Line: " + convert2string(conPeek(callStack, i+1)));
text += ("Path: " + convert2string(conPeek(callStack, i)) + " Line: " + convert2string(conPeek(callStack, i+1)) + "\n");
}
return text;
}
Then in your class where you want to get the call stack:
Example
...
try
{
...
} catch (..)
{
MyToolClass:: getCallStack(true);
}
...
BTW: If the code are executed in a thread or at the AOS, you should call getCallStack with false and use the returned string instead.
static str getCallStack(boolean _showInfo = false)
{
xSession xSession = new xSession();
container callStack = xSession::xppCallStack();
str text;
int i;
str convert2string(anytype _value, int variation = 0)
{
switch (typeof(_value))
{
case Types::String :
return _value;
case Types::Real :
return num2str(_value, 10, 4, 1, 0);
case Types::Integer :
return int2str(_value);
case Types::Date :
if (variation == 0)
return date2str(_value, 321, 2, 3, 2, 3, 4 );
else if (variation == 1)
return date2str(_value, 321, 2, 1, 2, 1, 2 );
case Types::Enum :
return enum2str(_value);
}
}
for (i = 1; i < conLen(callStack); i+=2)
{
if(_showInfo)
info( "Path: " + convert2string(conPeek(callStack, i)) + " Line: " + convert2string(conPeek(callStack, i+1)));
text += ("Path: " + convert2string(conPeek(callStack, i)) + " Line: " + convert2string(conPeek(callStack, i+1)) + "\n");
}
return text;
}
Then in your class where you want to get the call stack:
Example
...
try
{
...
} catch (..)
{
MyToolClass:: getCallStack(true);
}
...
BTW: If the code are executed in a thread or at the AOS, you should call getCallStack with false and use the returned string instead.
Thursday, February 16, 2012
Application environment
Sometimes when I'm working on a new customer and I don't know the Ax environment, I run this job. Check out the xInfo class for more information:
static void environment(Args _args)
{
;
info( xInfo::buildNo() + ' - '
+ xInfo::compilationDate() + ' - '
+ xInfo::dbName() + ' - '
+ xInfo::osName() + ' - '
+ xInfo::productName() + ' - '
+ xInfo::releaseVersion());
info(xinfo::componentName());
info(xinfo::configuration());
info(xInfo::directory(DirectoryType::Bin));
}
static void environment(Args _args)
{
;
info( xInfo::buildNo() + ' - '
+ xInfo::compilationDate() + ' - '
+ xInfo::dbName() + ' - '
+ xInfo::osName() + ' - '
+ xInfo::productName() + ' - '
+ xInfo::releaseVersion());
info(xinfo::componentName());
info(xinfo::configuration());
info(xInfo::directory(DirectoryType::Bin));
}
Subscribe to:
Posts (Atom)