Welcome to MSDN Blogs Sign in | Join | Help

TS/RDC/RDP Failure in 2003/XP clients

If you are getting this error message when attempting to establish a Remote Desktop Connection (formerly known as a Terminal Services Client session) you may need to install the new 6.0 version of the client.

 

The remote computer requires network level authentication, which your computer does not support

 

http://support.microsoft.com/default.aspx/kb/925876

Posted by DavidFerguson | 0 Comments
Filed under:

Creating a report in X++ code and running

Here is a small job that demonstrates the main parts of build a report dynamically in X++ and launching it.

 

static void MakeReportJob(Args _args)

{

    #AOT

    str reportName = 'aaMakeReport';

    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();

}

 

Posted by DavidFerguson | 0 Comments
Filed under:

X++ Server Threads

You can create threads in X++ to perform tasks in the background.  Here is a vey simple class that demonstrates the basics.

 

class ThreadDemo

{

    static server void main()

    {

        Thread t;

        ;

        new ExecutePermission().assert();

        //BP Deviation Documented

        t = new Thread();

        t.run(classnum(ThreadDemo), staticmethodstr(ThreadDemo, run));

    }

   

    static server void run(Thread t)

    {

        AsciiIo ai;

        // Change this to some path that your server will have access to

        str fileName = '\\t\\HelloWorld.txt';

        ;

        sleep(5000);

        new FileIOPermission(fileName, 'w').assert();

        //BP Deviation Documented

        ai = new AsciiIo(fileName, 'w');

        ai.write('Hello World!');

    }

}

 

I use the directory d:\t for temporary files.  You will have to either create the directory or change the example to point to some other directory.  In either case make sure that SYSTEM has read/write permission to the directory.

 

Create and run a simple job like this:

 

static void ThreadDemoJob(Args _args)

{

    ;

    ThreadDemo::main();

    print 'Ok';

    pause;

}

 

When you run the job it will return immediately.  Monitor the output directory and notice that the output file is created five seconds later.

 

One interesting quality of server side threads is that they have their own session block and that session block doesn’t have a client.  This means that any attempt to instantiate a client side only class will fail.  This can create some interesting bugs since almost no code does good error handling for when classes are not new-able.
Posted by DavidFerguson | 3 Comments
Filed under:

Visual Studio Macro for Live Search

Here is a Visual Studio macro that takes the highlighted text and starts a search of the msdn/msdn2 sites.  It often works better than the built-in help system.  I usually assign it to hot key Alt+F1.

 

'--------------------------------------------------------------------------

'You will need to add a reference to 'System.Web' for HttpUtility.UrlEncode

'--------------------------------------------------------------------------

Public Sub SearchLiveForSelectedText()

    Dim s As String = ActiveWindowSelection().Trim()

    If s.Length > 0 Then

        'If there is a space, then put quotes around the phrase.

        Dim i As Integer

        i = s.IndexOf(" ")

        If i <> -1 Then

            s = """" & s & """"

        End If

 

        'Adding 'header library' to the search string helps focus

        'the search on non-.NET stuff

        Dim ext As String = LCase(Path.GetExtension(ActiveDocument().Name))

        If ext = ".cpp" Or ext = ".inl" Or ext = ".hpp" Or ext = ".cxx" Then

            s = s + " header library "

        End If

 

        DTE.ItemOperations.Navigate("http://www.live.com/?searchonly=true&q=" & _

            Web.HttpUtility.UrlEncode(s) & " (site:msdn2.microsoft.com OR site:msdn.Microsoft.com)")

    End If

End Sub

Posted by DavidFerguson | 1 Comments
Filed under:

Enable Debug on Server

When single stepping through X++ code on the client you can bump into code that can only execute on the server.  In a default deployment you will not be able to single step through the code.  To enable this feature you must turn it on in the ‘Microsoft Dynamics AX Server Configuration Utility’ tool.

 

If necessary, use the Manage button to Create Configuraton.  On the first tab, Application Object Server, make sure that the [x] Enable breakpoints to debug X++ code running on this server check box is checked.

 

You can also do by a direct registry hack, like so:

 

REGEDIT4

 

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Dynamics Server\4.0\01\ Original (installed configuration)]

"xppdebug"="1"

 

Posted by DavidFerguson | 0 Comments
Filed under:

Command Line To Import Data

In Axapta 4.0 you can use the -startupcmd=autorun_ command line option to batch import data is two steps.

 

1. Create an xml file (demoData.xml for example) that looks like this:

<?xml version="1.0" encoding="utf-8" ?>

<AxaptaAutoRun exitWhenDone="true" version="4.0" logFile="axautodata.log">

       <CompanyAccounts >

              <Company name="Demo Company" id="DMO" overwrite="true" />

       </CompanyAccounts>

       <DataImport companyId="DMO" file="demoData.dat" />

</AxaptaAutoRun>

 

2. Then launch the client with command line like this:

ax32.exe -startupcmd=autorun_demoData.xml

 

Notice the prefix autorun is added to the xml file name.  Since exitWhenDone is set to “true”, the client will exit after importing the data.

 

You can see a list of all the tags that are handled by the -startupcmd=autorun_ command by looking in the X++ classDeclaration of SysAutoRun.

 

I work on version 4.0, so I don’t know if it also works in 3.0.

Posted by DavidFerguson | 1 Comments
Filed under:

Live Meeting Error “An error has occured while creating an error report”

I was having the following bug with live meeting.  Immediately after starting live meeting a small dialog box would pop up with this error message.  The dialog was behind the main Live Meeting window.  In a few seconds Live Meeting would disappear.  The problem was caused by the Data Execution Prevention (DEP) feature for Windows.  Data Execution Protection helps protect against damage from viruses or other threats. Some programs may not run correctly when it is turned on.  In particular programs that used and older version of the ATL windowing library will fail.  The solution is to disable DEP for the Live Meeting.

 

  1. Navigate to Control Panel/System/Advanced (tab)/Performance (section)/Settings (button)/Data Execution Prevention (tab)/Add (button) 
  2. Navigate to the exe.  On my system it was here C:\Program Files\Microsoft Office\Live Meeting 7\Console\7.5.2302.14\PWConsole.exe 
  3. Click Open.  Click Ok.  Click Ok.

You can test the fix by going to http://go.microsoft.com/fwlink/?linkid=52354.

 

I had a similar problem with the Microsoft Document Imaging application.
Posted by DavidFerguson | 7 Comments
Filed under:

Args and the Axapta Construction Pattern

When looking through Axapta code you will see a lot of references to the type Args.  This type is used as a general method for sharing construction parameters.  It works well because in the Axapta usage pattern because

 

  1. the typical number of parameters is small
  2. the types of parameters used is very similar
  3. construction of the main objects often entails constructing multiple collaborating objects that need access to the same shared constructor arguments.

In traditional OO code each object will have one or more constructors.  These constructors would have different numbers of arguments and types, as required.  For example, a class representing a form might have a default constructor that would simply show all the items in the table.  It could also have a constructor that accepted a string that was used to highlight the row with a matching primary key, newSelect(str key).  Or one that filtered all the values to match the provided range, newMinMax(str smin, str smax).  Side note: in Axapta there is no overloading, we accomplish the same thing with multiple static constructor methods.  They are typically named newXyz, newAbc, etc.  Sometimes the create prefix is used, for example createXyz, createAbc.

 

This works well in the simple case, however if a class needs to construct many collaborating objects each requiring the same specialized constructors, the process becomes unwieldy.  In addition, the construction is often handled indirectly.  That is, there is some logic used to determine which constructor to use and the results of these decisions must pass through multiple layers.  Also, as it turns out in Axapta the variety of startup parameters is remarkable similar for report, forms, action classes and other objects.  The solution chosen by Axapta is to have a single constructor that takes an Args parameter.  This single parameter packages up the most commonly used parameters.

 

This transforms the traditional OO multiple constructors (like this)

 

final class FormRun extends ObjectRun

{

    static MyForm newSelect(str key)

        { ...new up a form with row selected ...}

 

    static MyForm newRange(str smin, str smax)

        { ...new up a form with only range visible ...}

}

 

Into the he Axapta Args constructor pattern, which would look like this:

 

final class FormRun extends ObjectRun

{

    public void new(Args _args)

    {

        if (something in _args)

            { ...new up a form with row selected ...}

        if (something else in _args)

        { ...new up a form with only range visible ...}

 

    }

}

 

The work is simply moved for a multiple static constructors to multiple if-else blocks.  Note that most forms and reports do the work in the init() method instead of an overloaded new.  The effect is the same.  When you consider that many forms/reports have at least one helper class (often with the same name) and the sub‑elements (sections, queries, controls) that may also need to modify their behavior based on the startup parameters you can see that passing a single Args around is much easier.  You don’t even have to pass the Args around if the object inherits from ObjectRun (which all forms and reports do), since ObjectRun holds the initial constructor Args.  The pattern would break down if the number and type of parameters were vastly different.

 

Classes and jobs also use the Args pattern.  Classes that are the target of an Action menu item will have a static main method that accepts a single Args parameter.  By default jobs will also receive a single Args parameter.

 

Generic Args Properties:

Property

Type

Description

caller

object

A reference to the object that created the Args.

dataset

tableId

The table that lookupField and record refer too.  However, this is often left null since the proper dataset is implied.

designName

str

Which of the designs within a report should be used, null implies the default design.

lookupField

fieldId

When showing a form, the field to filter on.

lookupValue

str

When showing a form, the value to filter with.

menuItemName

str

The name of the menu item that caused the object to be created.

menuItemType

menuItemType

The type of the menu item that caused the object to be created.

name

str

For reports and forms this is the name of menu item that invoked the form/report

parentWnd

int

I have only seen this used internally in the kernel to insure dialogs child windows are properly nested.

parm

str

A generic string property.

parmEnum

int

One of the values from the base enum specified by parmEnumType.  Works together with the parmEnumType to select different behaviors.

parmEnumType

int

The id of the base enum.  Typically you would use the enumnum(some-type) function.

parmObject

object

A generic object property.

record

common

A blank record for dataset.  You can create a blank record with the DictTable. makeRecord() method.  Often the lookupField is filled in with the lookupValue.

 

An interesting example on using Args to launch a form/report is in the \Classes\ClassFactory\drillDown method.

 

public void drillDown(OutputField _outputField, MenuItemType _menuItemType, str _menuItemName)

{

    Args            args            = new Args();

    MenuFunction    menuFunction    = new MenuFunction(_menuItemName, _menuItemType);

    DictTable       dt              = new DictTable(_outputField.tableHandle());

    Common          record          = dt.makeRecord();

    sysReportRun    sysReportRun;

    FormRun         formRun;

    ;

    args.caller(null);

    record.(_outputField.fieldHandle()) = _outputField.formatValue();

    args.record(record);

    args.name(menuFunction.object());

    args.lookupField(_outputField.fieldHandle());

    args.lookupValue(_outputField.formatValue());

    ...SNIP...

}   

 

An example of a form taking different actions based on the enumeration parameter can be seen in the PriceDiscGroup form:

 

void  init()

{

    InventTableModule  inventTableModule;

    ;

    super();

    if (element.args().parmEnumType())

    {

        module = element.args().parmEnum();

    }

    ...SNIP...

}

 

An example of a class preparing some enumeration args for a form to consume can be found in the ProdJournalCreateBOM class:

 

client static void main(Args args)

{

    ...SNIP...

    if (journalId)

    {

        argsTable = new Args();

        argsTable.name(formstr(ProdJournalTable));

        argsTable.parmEnumType(enumnum(ProdJournalType));

        argsTable.parmEnum(ProdJournalType::Picklist);

       

    ...SNIP...

}   

Posted by DavidFerguson | 0 Comments
Filed under:

Using dimof() on a Dynamic Array

I stumbled across some older X++ code that was using the little know dynamic array.  It took a while to find out how to retreive the size of the dynamic array.  Here is a little example of using a dynamic array in Axapta:

 

int foo[];

int r;

;

foo[10] = 1;

r = dimof(foo);  // r will be 16 here

foo[100] = 3;

r = dimof(foo);  // r will be 112 here

 

As you can see there is no special syntax required to access individual elements, simply start stuffing values in.  Like all Axapta arrays it is limited to a single dimension and basic types (that is no objects).  The array grows in 16 element chunks.  You can find the current dimensions of the array using the dimof().  Note that this is the actually allocated length of the array and not the highest element actually used so far.  If you need this information you will have to store it separately.  A higher level abstraction that removes many of these limitations can be found in the Array class.

Posted by DavidFerguson | 0 Comments
Filed under:

Know where the fall line is

Microsoft is full of interesting people.  Some of the guys in my group go snowboarding once a week and they are kind enough to take me along and show me the ropes.  We usually go to the Stevens Pass one day a week after work.  If you leave a little early, around four, you can easily get 3 or 4 hours of boarding.

 

I am from Florida and have never seen snow before. . . well there was one trip to Yosemite national park, but you get the idea.  In Florida we have two seasons, brutally turkey basting hot summer and not quite burning up summer.  So you can image what a change it has been to experience the seasons here in Redmond.  I have really enjoyed it especially the mountains, Wow.

 

Back to snowboarding.  If you haven’t tried it. . . stop what you are doing right now.  I mean it stop it.  Get in your car, drive up to the mountain and get a snowboarding leason.  You will never regret it.  Nobody lays on their death bed and wishes they had fixed one more bug.  But if you miss the chance to experiences God’s mountains on a snowboard, you will always regret it.  Please note I highly recommend lessons to reduce the initial learning pain.

 

As you can imagine I am still very much a learner.  Even though I spend a lot of time laying in snow trying to figure out how I went from zooming down the mountain (ok. . .ok maybe not zooming) to laying on my butt in the snow, I probably enjoy my time on the mountain more than anyone else.

 

One of the hardest things for me to learn is “know where the fall line is”.  You can think of the fall line as the direction a marble would go (if marbles would roll down the side of a snow covered mountain).  The direction you can go and which edge of the board you can use is determined by the fall line.  I am constantly seeing a false fall line in the direction I want to travel.  It is a form of wishful thinking.  I convince myself that the fall line is in a direction compatible with where I want to go and turn accordingly.  Of course the brutal laws of gravity show no mercy and I will catch an edge and face plant.  So the deal is. . . no matter how much you may want the fall line to be going in a different direction, you have to accept reality and know where the real fall line is.

 

So how does this apply to programming…..

 

Know how much you can actual do and don’t over commit.  When your manager or teammate ask how many features you can complete or how many bugs you can resolve, know your fall line, and don’t over commit.  No matter how much you may wish the schedule was headed in a different direction, it is not.  And even though the happy answer may relive a little stress for the moment it will end up in a face plant very quickly.

 

Know where the fall line is.

Posted by DavidFerguson | 2 Comments
Filed under:

What are Menu item references on report control?

Menu item references are used to add alternative drill down links in a report.  When you right click on the output field in the report the list of menu items will be presented in a popup menu.  The easiest way to add menu items to a report is to drag-n-drop them from the menu item node in the AOT.  You can also manually create menu item references by entering the information in the property editor.  When clicked on, the corresponding report (output) or form (display) will be invoked with an Args parameter constructed from the drill down field (see Classes/ClassFactory/drilldown for details on ths).

Posted by DavidFerguson | 0 Comments
Filed under:

Making things "click"

I answer questions in discussion groups from time to time.  Yesterday, I answered a question and got a very nice thank you.  It really brightened my day, and reminded me of what I like best about software, it is so cool when things “click”.  You look and think and look and think and look and think and then ...... someone helps you and it all "clicks" in to place.  I really like helping things “click” for other people and I really like it when others help me see things more clearly.

Axapta DLLs (What to Blog)

So, I was wondering what to blog about....  There are many things that I would like to discuss but at the end of the day I would rather go home and play with the kids or go to the mountains and hit the snow.

So.....I thought I would try recording some of the tid-bits that come during work.  I keep a text file of little things that seem usefull for my work.  As I add items there I will also post them here.  Some of the items are for MS employess only and are posted on my internal blog, so if you are inside the MS firewall you can see more items here http://blogs/davfer.

There was a recent was recent question about what DLL's Axapta 4.0 needs.  Of course you can fire up 'tasklist /m' and get a list but it tends to be fully of system DLLs. Here is a registry script from Egil Ivar that should register Axapta specific DLL’s.  This should be a pretty good list of non‑system DLLs that you need to run Axapta. 

regsvr32.exe Gear32pd.dll /s

regsvr32.exe anameter.dll /s

regsvr32.exe aspupload.dll /s

regsvr32.exe axafiles.dll /s

regsvr32.exe axcfg300.dll /s

regsvr32.exe Axhotlib.dll /s

regsvr32.exe Vxcsv32.dll /s

regsvr32.exe VCWIN32.DLL /s

regsvr32.exe VCSCED32.DLL /s

regsvr32.exe VCPRCT32.DLL /s

regsvr32.exe VCPANE32.DLL /s

regsvr32.exe Vcgantt.ocx /s

regsvr32.exe vc6-re200l.dll /s

regsvr32.exe TLBINF32.DLL /s

regsvr32.exe TDSOLClockControl.ocx /s

regsvr32.exe TDSOLCalendarControl.ocx /s

regsvr32.exe smmdrop2.ocx /s

regsvr32.exe smmaxol.dll /s

regsvr32.exe smmWrap.ocx /s

regsvr32.exe smmphone.ocx /s

             msvcr71.dll

             msvcp71.dll

             MFC71.dll

regsvr32.exe IGLZW32S.DLL /s

regsvr32.exe GridEX20.ocx /s

regsvr32.exe GEAR32PD.DLL /s

regsvr32.exe DSMailer.dll /s

regsvr32.exe dbghelp.dll /s

regsvr32.exe ctyear.ocx /s

regsvr32.exe CFX2032.DLL /s

regsvr32.exe Bcfont32.dll /s

Posted by DavidFerguson | 2 Comments
Filed under:

A Fresh Beginning

I am a new employee at Microsoft.  It has been very exciting joining this team.  I was quite suprised to see how helpful and friendly the entire culture is here, after all the rumors that I had heard.  I am a developer in the Microsoft Business Solutions division.  I am working on the kernel of the Axapta business software product.  I am also new to blogging.

We will see how it all goes!

Cheers...David

Posted by DavidFerguson | 3 Comments
Filed under:
 
Page view tracker