Thursday, May 28, 2015

Open and close PDF reader from code

Here is an example of how you can open Adobe PDF Reader (or another PDF reader) with a particular PDF document, and close the reader again.
static void pager_FindWindow(Args _args)
    Filename    pdfFileName = 'MyDocumentFile.pdf';
    FilePath    pdfFilePath = @'C:\XYZ\'; 
    str         adobeExe;
    System.Diagnostics.Process              process;
    System.Diagnostics.ProcessStartInfo     processStartInfo;

    // Let Windows figure out the standard program and location for the PDF reader
    adobeExe = WinAPI::findExecutable(pdfFilePath + pdfFileName); 
    // Start the reader process
    new InteropPermission(InteropKind::ClrInterop).assert();

    process = new System.Diagnostics.Process();

    processStartInfo = new System.Diagnostics.ProcessStartInfo();
    processStartInfo.set_Arguments(pdfFilePath + pdfFileName);



    // Wait 5 secs. before closing the window
    sleep (5000);
    // Close the window

Wednesday, May 27, 2015

A table you might want to add to Test Data Transfer Tools exclusion lists

Users might appreciate it if you add this table to the table exclusions for the Test Data Transfer Tool:

// Personalization

Monday, May 11, 2015

Increment dates by months in X++

A question was asked in the forums, about how to increment dates by months like:

nextMth and dateMthFwd was suggested, so I just wanted to list some options.

Consider these examples.

nextMth will be off by days after hitting uneven months:
static void TestNextMth(Args _args)
    date d = nextMth(31\12\2015);
    print d;
    d = nextMth(d);
    print d;
    d = nextMth(d);
    print d;
    d = nextMth(d);
    print d;

  • 31/1/2016
  • 29/2/2016
  • 29/3/2016
  • 29/4/2016

dateMthFwd works ok:
static void TestDateMthFwd(Args _args)
    date d = mkDate(31, 12, 2015); 
    print dateMthFwd(d, 1);     
    print dateMthFwd(d, 2);
    print dateMthFwd(d, 3);
    print dateMthFwd(d, 4);    
  • 31/1/2016
  • 29/2/2016
  • 31/3/2016
  • 30/4/2016

And System.DateTime.AddMonths works ok:
static void TestAddMonths(Args _args)
    System.DateTime dateTime = new System.DateTime(2015, 12, 31);
    print dateTime.AddMonths(1);
    print dateTime.AddMonths(2);    
    print dateTime.AddMonths(3);
    print dateTime.AddMonths(4);    
  • 31/1/2016
  • 29/2/2016
  • 31/3/2016
  • 30/4/2016

Tuesday, May 5, 2015

Fix synchronization issue with fields in the AOT but not on SQL Server

Recently I was called in to help on an issue after installation of a third party module, where fields were in the AOT but wasn't synchronized to SQL Server. The fields also looked as they should in the SQLDictionary table.

New attempts to synchronize the database didn't create the fields on SQL. AX must have been under the impression that the fields were synchronized.

If I tried to delete any of the fields, I'd get an error from AX about it not being able to drop the fields on SQL Server, so I was kind of stuck.

Here is what I did to fix the situation:

  1. I looked up the SQL field names in SQLDictionary and created the fields manually on SQL Server. I was not too concerned with datatypes and other properties, as these fields were just created to be able to drop them from AX again.
  2. In the AOT I changed the SaveContents property of each field to No. This will make AX drop the fields from SQL Server.
  3. I synchronized.
  4. I changed SaveContents properties back to Yes. This will make AX create the fields again on SQL Server through the right synchronization process.
  5. I synchronized.
In the old days, this was something you could fix with SQL administration from the System administration menu, but the features to fix such issues have been broken  since version 4.0 of AX.

I never did figure out how the third party vendor brought themselves into this situation though. That would have been interesting enough to know.