Showing posts with label ax. Show all posts
Showing posts with label ax. Show all posts

Tuesday, July 01, 2014

AX separated instances on Windows taskbar

This one is a little trick that I find very useful.

If you have to work with multiple AX instances, you will surely get annoyed by the way windows group the icons on the taskbar.

Multiple instances of the same program are not grouped separately, thus it get very hard to switch between a window or another.


Having separated AX instances on the taskbar is much better, imho


To accomplish that you have to create an hard link to the AX32 executable on the filesystem, like that:
  1. Open command prompt (CMD.exe)
  2. Go to the AX installation folder (usally C:\Program Files (x86)\Microsoft Dynamics AX\50\Client\Bin)
  3. Create N hard link for every different instance of AX:

    mklink /h ax32_DEV.exe ax32.exe
    mklink /h ax32_PROD.exe ax32.exe



  4. Create a shortcut to the newly created file (ax32_DEV.exe) wherever you want, and edit the shortcut to open the specific AXC file pointing to the desired AX instance.


  5. Open AX from that shortcut
That should work with Windows 7, 8, Vista and XP

Have fun

Friday, October 12, 2012

Enhanced table browser

If you find it hard to find fields on the Ax Table Browser, this tool may help you.

It will simply show the visible fields on the right, and you can check/uncheck those that you want to see.

If you experience some problem after installation, clear Usage data for the form



XPO download HERE

Thursday, October 11, 2012

Create custom Alert for AX with Go to Source support

To create an Alert in AX, you can use the class EventNotification and its derivates

I got some problems using these standard classes, particularly in making the button "Go to source" work.

To avoid those problem, here is some code that may help:

 public static void CreateAlert(str message,  
               str subject,  
               UserId userId = curUserId(),  
               NoYes showPopup = NoYes::Yes,  
               NoYes sendEmail = NoYes::No,  
               Common record = null,  
               str dataSourcename = '',  
               MenuFunction menuFunction = null)  
 {  
   EventInbox inbox;  
   DictTable table;  
   EventContextInformation eci;  
   EventInboxData inboxData;  
   Args args = new Args();  
   List list;  
   EventInboxId inboxId = EventInbox::nextEventId();  
   FormRun formRun;  
   WorkflowRecordCaptionGenerator recordCaptionGenerator;  
   UserInfo userInfo;  
   inboxId = EventInbox::nextEventId();  
   inbox.initValue();  
   inbox.ShowPopup      = showPopup;  
   inbox.Subject       = subject;  
   inbox.Message       = message;  
   inbox.SendEmail      = sendEmail;  
   inbox.EmailRecipient    = SysUserInfo::find().Email;  
   inbox.UserId        = userId;  
   inbox.InboxId       = inboxId;  
   inbox.AlertCreatedDateTime = DateTimeUtil::getSystemDateTime();  
   if (record)  
   {  
     table = new DictTable(record.TableId);  
     eci = new EventContextInformation();  
     if (!menuFunction)  
     {  
       menuFunction = new MenuFunction(table.formRef(),MenuItemType::Display);  
       if (!menuFunction)  
         throw error(strFmt("@SYS104114",table.formRef()));  
     }  
     //Build the data to drill down to from the notification  
     args.menuItemName(menuFunction.name());  
     args.menuItemType(MenuItemType::Display);  
     args.name(menuFunction.object());  
     eci.parmPackedArgs(args);  
     eci.parmAlertBuffer(record);  
     eci.parmAlertFormDsName(dataSourceName);  
     //eci.parmDontUseFormRunFromMenuItem(true);  
     inboxData.InboxId = inboxId;  
     inboxData.DataType = EventInboxDataType::Context;  
     inboxData.Data = eci.pack();  
     inboxData.insert();  
     inbox.AlertTableId = table.id();  
     inbox.ParentTableId = table.id();  
     recordCaptionGenerator = WorkflowRecordCaptionGenerator::construct(record);  
     inbox.AlertedFor = recordCaptionGenerator.caption();  
     list = SysDictTable::getUniqueIndexFields(table.id());  
     if (list)  
     {  
       inbox.keyFieldList(list.pack());  
       inbox.keyFieldData(SysDictTable::mapFieldIds2Values(list,record).pack());  
     }  
     inbox.CompanyId = record.company();  
   }  
   inbox.insert();  
 }  

To use this code
 static void Job155(Args _args)  
 {  
   InventTable inventTable;  
   select firstOnly inventTable;  
   DEVUtils::CreateAlert("message", "subject", curUserId(), true, false, inventTable, "InventTable", new MenuFunction(menuitemDisplayStr(EcoResProductDetailsExtended), MenuItemType::Display));  
 }  

Sending PEC (Certified E-mail) with AX

A PEC (Certified E-mail) is not very different from a usual e-mail.

You just have to use SSL to secure the connection while sending the mail.

Usually I use the class System.Net.Mail to send mails with Ax, and this one has a useful property named EnableSsl that could work. But with a PEC, no, this isn't working.

That's because, to send a PEC you need an Implicit SSL, while System.Net.Mail only supports “Explicit SSL”.

 Reference: HERE

 And, as stated in the MSDN:

The EnableSsl property specifies whether SSL is used to access the specified SMTP mail server.
The default value for this property can also be set in a machine or application configuration file. Any changes made to the EnableSsl property override the configuration file settings.
The SmtpClient class only supports the SMTP Service Extension for Secure SMTP over Transport Layer Security as defined in RFC 3207. In this mode, the SMTP session begins on an unencrypted channel, then a STARTTLS command is issued by the client to the server to switch to secure communication using SSL. See RFC 3207 published by the Internet Engineering Task Force (IETF) for more information.
An alternate connection method is where an SSL session is established up front before any protocol commands are sent. This connection method is sometimes called SMTP/SSL, SMTP over SSL, or SMTPS and by default uses port 465. This alternate connection method using SSL is not currently supported.

So, if you want to send a mail with Implicit SSL, you have to use a deprecated class from the old 2.0 .NET Framework, that is System.Web.Mail

Using this class is not difficult, and you can find a working sample down here:


 static void SendPECMail(Args _args)  
 {  
   System.Web.Mail.MailMessage  newMail;  
   System.Collections.IDictionary fields;  
   System.Collections.IList    attachementCollection;  
   System.Web.Mail.MailAttachment attachment;  
   try  
   {  
     new InteropPermission(InteropKind::ClrInterop).assert();  
     newMail = new System.Web.Mail.MailMessage();  
     fields = newMail.get_Fields();  
     fields.Add("http://schemas.microsoft.com/cdo/configuration/smtpserver", "smtps.pec.aruba.it");  
     fields.Add("http://schemas.microsoft.com/cdo/configuration/smtpserverport", "465");  
     fields.Add("http://schemas.microsoft.com/cdo/configuration/sendusing", "2");  
     fields.Add("http://schemas.microsoft.com/cdo/configuration/smtpauthenticate", "1");  
     fields.Add("http://schemas.microsoft.com/cdo/configuration/sendusername", "lmattiuzzo@pec.it");  
     fields.Add("http://schemas.microsoft.com/cdo/configuration/sendpassword", "password");  
     fields.Add("http://schemas.microsoft.com/cdo/configuration/smtpusessl", "true");  
     newMail.set_From("lmattiuzzo@pec.it");  
     newMail.set_To("santa@klaus.com");  
     newMail.set_Subject("subject");  
     newMail.set_BodyFormat(System.Web.Mail.MailFormat::Html);  
     newMail.set_Body("body of your message");  
     newMail.set_Priority(System.Web.Mail.MailPriority::High);  
     attachementCollection = newMail.get_Attachments();  
     attachment = new System.Web.Mail.MailAttachment(@"c:\file.pdf");  
     attachementCollection.Add(attachment);  
     System.Web.Mail.SmtpMail::set_SmtpServer("smtps.pec.aruba.it:465");  
     System.Web.Mail.SmtpMail::Send(newMail);  
     CodeAccessPermission::revertAssert();  
   }  
   catch( Exception::CLRError )  
   {  
     throw error(AifUtil::DEVgetClrErrorMessage());  
   }  
 }  

Friday, May 18, 2012

AxUtil GUI

If you find that the AXUtil tool for importing models is not so pratical, here's the tool for you.


I've extended the functionality of the standard "Installed models" form inside Tools -> Models Management to let you Import, Export, Move or Delete models directly from AX. How it works: With a little of reverse engineering i found that AxUtil.exe simply uses a DLL named AXUtil.dll. This DLL is already referenced in AX, so you can use it directly from X++.

Here's a sample to export a model. The code is pretty straightforward, I just pass in the name of the DB, the path where to export the file and some other params, and then I get my model saved/imported/moved/deleted.

Here you can find the project for the tool, this will work on every client (you don't need to be on the AOS to export/import models)



 private void exportModel(SysModelManifest _SysModelManifest, filePath path)  
 {  
   Microsoft.Dynamics.AX.Framework.Tools.ModelManagement.AxUtil        axutil      = new Microsoft.Dynamics.AX.Framework.Tools.ModelManagement.AxUtil();  
   Microsoft.Dynamics.AX.Framework.Tools.ModelManagement.AxUtilContext     context     = new Microsoft.Dynamics.AX.Framework.Tools.ModelManagement.AxUtilContext();  
   Microsoft.Dynamics.AX.Framework.Tools.ModelManagement.AxUtilConfiguration  config     = new Microsoft.Dynamics.AX.Framework.Tools.ModelManagement.AxUtilConfiguration();  
   Microsoft.Dynamics.AX.Framework.Tools.ModelManagement.ModelArgument     modelArgument;  
   int     modelId = _SysModelManifest.Model;  
   int     i;  
   Object ret;  
   ClrObject o; // = new ClrObject("System.Collections.Generic.List`1[System.String]");  
   ClrObject enumerator;  
   boolean hasErrors;  
   try  
   {  
     modelArgument = new Microsoft.Dynamics.AX.Framework.Tools.ModelManagement.ModelArgument(modelId);  
     config.set_ExportFile(path + _SysModelManifest.Name);  
     config.set_ModelArgument(modelArgument);  
     config.set_Database(SysSQLSystemInfo::construct().getloginDatabase());  
     config.set_Server(SysSQLSystemInfo::construct().getLoginServer());  
     axutil.Export(context, config);  
     o = context.get_Errors();  
     enumerator = o.GetEnumerator();  
     while (enumerator.MoveNext())  
     {  
       error(enumerator.get_Current());  
     }  
     o = context.get_Warnings();  
     enumerator = o.GetEnumerator();  
     while (enumerator.MoveNext())  
     {  
       warning(enumerator.get_Current());  
     }  
     hasErrors = context.get_HasError();  
     if(!hasErrors)  
       info(strFmt("Esportato modello %1 nel file %2" , _SysModelManifest.Name, path + _SysModelManifest.Name));  
   }  
   catch ( Exception::CLRError )  
   {  
     error(AifUtil::getClrErrorMessage());  
     throw Exception::Error;  
   }  
 }