Monday, September 19, 2011

Bug in the training material for AX 2012 Development II

In chapter 1, Introduction to X++, under Jobs you can find the following statement:
"... Jobs are used primarily for testing code during development and running batch processes within Microsoft Dynamics AX that affect large amounts of data".

Jobs are not in any way related to the batch capabilities of AX, and due to that fact that they are executed on the client, you'd never use a job to work with large amount of data.

I think the author somehow confuses the RunBase(Batch) framework with the Jobs node in the AOT.

You can find the same error in the course material for AX 2009.

Tuesday, September 13, 2011

Querying printer queues from X++

For a client we need to print a page of an X++ report and then some attached files, like PDF or Word documents.

We need all the connected documents to be printed in one batch and we must not print the next X++ page before the attached documents are printed.

So we need to figure out if the shell and the printer are finished printing the attached documents before sending the next document from AX.

Luckily we can use the .NET library System.Printing to query the queue  and in particular we can call the NumberOfJobs to figure out if the attached documents have been printed.

Here's a few bits of code for querying the printer queues:
    System.Printing.PrintServer           printServer = new System.Printing.LocalPrintServer();
    System.Printing.PrintQueueCollection  printQueueCollection = printServer.GetPrintQueues();
    System.Printing.PrintQueue            printQueue;
    System.Collections.IEnumerator        enumerator;
    // Print the local server name
    print printServer.get_Name();
    // Enumerate and print names of all the queues on the server
    enumerator = printQueueCollection.GetEnumerator();
    while (enumerator.MoveNext())
        printQueue = enumerator.get_Current();
        print printQueue.get_FullName();
    // Get information for a particular print queue
    printQueue = new System.Printing.PrintQueue(printServer, "HP Color LaserJet 5550 PS");
    print printQueue.get_Description();
    print printQueue.get_NumberOfJobs();
    print ClrInterop::getAnyTypeForObject(printQueue.get_IsBusy());
    print ClrInterop::getAnyTypeForObject(printQueue.get_IsPrinting());


In AX 2012 I would probably have placed the supporting code in a Visual Studio project rather than calling these CLR objects from X++.

Thursday, September 8, 2011

Changing AOS service name

Sometimes in a development environment you may have an AOS serving a specific purpose or project and maybe the role of the AOS changes over time.

When the role changes it would be nice that the service name was changed, to correctly indicate what it serves. Here is the command line for changing the display name of the service:

sc config AOS50$01 DisplayName= "Dynamics AX Object Server 5.0$01_MyNewPurpose"

This of course doesn't change things like the name of the folder holding the binaries (which you probably shouldn't change if you want to be able to uninstall the service). To change everything you'd need to install a AOS service and possibly uninstall the old service.

Changing the service name is just a quick way to indicate the changed purpose of the service.

Monday, September 5, 2011

Fun observation about BOF dialogs

After reading the Client User Experience Guidelines for dialog boxes, I noticed that the automatically generated dialogs from the Business Operation Framework (BOF) doesn't quite meet the guidelines.

According to the guidelines you need to display a "Main instruction":

But if you take a look at the dialog generated by BOF, theres is no "Main instruction" section, and I haven't really figured out how I can add it myself:

The Dialog form which is the base for all RunBase dialogs has a StaticText control for this main instruction, but the SysOperationTemplateForm, which is the base for BOF dialogs, dosn't have a control for displaying the main instruction.

Not a big deal, but still a bit fun...