Saturday, January 6, 2018

Allow WEMO Communication through your Firewall

The following instructions will enable your WEMO devices to communicate through your firewall without Upnp enabled.  Disabling Upnp is a best practice because otherwise any device inside your network would be able to open up any port to the outside world.  The screen shots will be from a pfSense 2.4 firewall but would apply to other firewalls as well.

There are two things your WEMO devices will require:

1. Ability to ping your gateway device (ICMP traffic)
2. Allow these Inbound and outbound TCP and UDP ports:
    - TCP 8080
    - TCP 8443
    - TCP/UDP 3475-3478
    - TCP/UDP 5223-5228
    - TCP/UDP 8445-8663

0. Preparatory work

To simplify the following steps, we are going to assign static IP addresses to our WEMO devices then create two firewall aliases.  A firewall alias is just a list of ports or IP addresses that can be referenced without typing them in over and over again.

Assign Static IPs for WEMO Devices

You'll need to log into your DHCP server, i.e. wireless router or firewall, to assign those devices static IP addresses.  Go ahead and write them down for future reference.

Firewall aliases:


  • WEMO_Devices - for this alias put in the static IP address for all of your WEMO devices.  A screen shot not provided for obvious reasons.
  • WEMO_Ports - for this alias put in the list and ranges of TCP & UDP ports which we will need to allow through the firewall




1. Ability to ping your gateway device

By default I disable pinging the gateway device, just because it is unnecessary traffic.  To enable this for the WEMO devices, create a rule allowing ICMP traffic from WEMO devices to hit the gateway IP address.


2. Enable Communication Over Specific Ports

Enable outbound communication

Allow communication on those ports from the WEMO devices to the internet.


Enable inbound communication

Allow communication on those ports from the internet only to WEMO devices.  This step shouldn't be necessary but I did it just in case.  I'm interested in feedback from my readers on this!

Security

By the time you are done doing the above, you'll wonder why you bought a WEMO device to begin with, but embrace the ease of use and probably give up (allow them in your network)- just isolate these devices so that they are unable to communicate with your other machines on the network (another firewall rule); so that, if a hacker was able to enter through one of the many ports above and compromise one of the WEMO devices, there would be nothing else accessible.  The worse thing that could happen is your lights or coffee maker turning on and off without your permission.

Friday, January 5, 2018

Create a VM network in Parallels with a Linux VM Firewall

Parallels Desktop has been a solid virtualization option for my iMac.  It enables easy sharing of folders and other advanced options I felt would be useful, i.e. seamless Windows programs.  For my latest adventure I wanted to test out some Linux firewall configurations without messing around with my physical environment.  So, I did the following to create a network where the linux firewall can serve both as a gateway and DHCP server.

Create the virtual network

  1. Open up Parallels Desktop Preferences
  2. Go to Network tab
  3. First take note of the IP address of the Shared network (for configuring your linux firewall)
  4. Then click the plus to create a new "Host-Only" network
  5. Uncheck "Connect Mac to this network"
  6. Uncheck "Enable IPv4 DHCP"
  7. Uncheck "Enable IPv6 DHCP"

FYI: The IP addresses shown will not be used because the linux firewall will respond to DHCP requests.

Configure the linux firewall

Set up two network interfaces on the VM before installing your favorite linux firewall, i.e. pfSense, Untangle, CentOS, or Sophos UTM.
  1. Open the configuration for your new VM
  2. Go to Hardware tab
  3. Configure Network 1 to have a source of "Default Adapter."  That network will have a connection regardless of whether your iMac connects via wireless or wired.
  4. Create a new network interface
  5. Select the "Host-Only #2" network we created in the prior section
    Make a note of the MAC address for this network for when you configure your firewall
  6. Now boot and install your linux firewall



Thursday, December 21, 2017

Comparing BOMs in AX

Bills of material in AX 2012 can be effective dated, and this provides the ability to keep prior versions.  Now it has been several years and the question arises- what changed between versions?  There is a built-in way to compare BOMs from the same product, or even two different -perhaps related- products.  However, this functionality is hard-coded to be for China only.


In order to limit the performance impact I enable only the necessary configuration keys.  So whenever a specific report or functionality from another country could be useful, I prefer to remove the country code on those objects to allow them to be used by all countries.  This is a minor modification that does not take long, however still requires functional testing.

In this case, these four objects need to have the CountryCode property cleared.


Friday, December 15, 2017

Outlook Setup Wizard - Dynamics 365 for Finance and Operations

In Microsoft Dynamics 365 for Finance and Operations, you may want to connect your Office365 email to receive contacts, tasks, and appointments from the ERP.  To do so, navigate to Organization Administration > Setup > Office integration > Microsoft Outlook Setup Wizard.  When it asks for the Exchange Web Services URL use the following to connect to your Office365 email account:
https://smtp.office365.com/EWS/Exchange.asmx


Once that is set up, activities assigned to you in Common > Activities can synchronize with your Outlook client!

Monday, July 3, 2017

Unable to Configure Report for PrecisionForms - Record Already Exists

Symptom:
Cannot create a record in Delivery destinations (BT_DPA_AOT_ReportDestinations). AOT object ID: 13, 2.
The record already exists.


Solution:
The unique index for the BottomLine tables is RecID.  Run the following SQL statement on your AX database.  Replace DATABASE with the name of your AX database.


IF OBJECT_ID('DATABASE.dbo.[BT_DPA_AOT_ReportDestinations]', 'U') IS NOT NULL
BEGIN
       UPDATE SystemSequences
       SET NEXTVAL = 1 + (SELECT MAX(RecID) FROM BT_DPA_AOT_ReportDestinations)
       WHERE TABID = (SELECT [TABLEID] FROM [SQLDICTIONARY] WHERE [Name] = 'BT_DPA_AOT_ReportDestinations' AND [FieldID]=0)
END
IF OBJECT_ID('DATABASE.dbo.[BT_DPA_AOT_Reports]', 'U') IS NOT NULL
BEGIN
       UPDATE SystemSequences
       SET NEXTVAL = 1 + (SELECT MAX(RecID) FROM BT_DPA_AOT_Reports)
       WHERE TABID = (SELECT [TABLEID] FROM [SQLDICTIONARY] WHERE [Name] = 'BT_DPA_AOT_Reports' AND [FieldID]=0)
END
IF OBJECT_ID('DATABASE.dbo.[BT_DPA_AOT_ReportProcesses]', 'U') IS NOT NULL
BEGIN
       UPDATE SystemSequences
       SET NEXTVAL = 1 + (SELECT MAX(RecID) FROM BT_DPA_AOT_ReportProcesses)
       WHERE TABID = (SELECT [TABLEID] FROM [SQLDICTIONARY] WHERE [Name] = 'BT_DPA_AOT_ReportProcesses' AND [FieldID]=0)
END

Friday, June 2, 2017

Export AX Ledger Transactions via SQL

This SQL serves as a starting point to include any number of financial dimensions.

SELECT GENERALJOURNALENTRY.SUBLEDGERVOUCHER as Voucher,
DIMENSIONATTRIBUTEVALUECOMBINATION.DisplayValue as [Account+Dims],
MAINACCOUNT.MainAccountID as [Account],
DIMENSIONATTRIBUTELEVELVALUE.DisplayValue as [Dept],
GENERALJOURNALACCOUNTENTRY.ACCOUNTINGCURRENCYAMOUNT as AmountMST,
GENERALJOURNALACCOUNTENTRY.TRANSACTIONCURRENCYAMOUNT as AmountCur,
GENERALJOURNALACCOUNTENTRY.TRANSACTIONCURRENCYCODE as CurrencyCode
FROM DynamicsAX2012.GENERALJOURNALENTRY
INNER JOIN DynamicsAX2012.GENERALJOURNALACCOUNTENTRY
ON GENERALJOURNALENTRY.RECID = GENERALJOURNALACCOUNTENTRY.GENERALJOURNALENTRY
INNER JOIN DynamicsAX2012.DIMENSIONATTRIBUTEVALUECOMBINATION
ON DIMENSIONATTRIBUTEVALUECOMBINATION.RECID = GENERALJOURNALACCOUNTENTRY.LEDGERDIMENSION
INNER JOIN DynamicsAX2012.DIMENSIONATTRIBUTEVALUEGROUPCOMBINATION
ON DIMENSIONATTRIBUTEVALUEGROUPCOMBINATION.DIMENSIONATTRIBUTEVALUECOMBINATION = DIMENSIONATTRIBUTEVALUECOMBINATION.RECID
INNER JOIN DynamicsAX2012.DIMENSIONATTRIBUTELEVELVALUE
ON DIMENSIONATTRIBUTELEVELVALUE.DIMENSIONATTRIBUTEVALUEGROUP = DIMENSIONATTRIBUTEVALUEGROUPCOMBINATION.DIMENSIONATTRIBUTEVALUEGROUP
and DIMENSIONATTRIBUTELEVELVALUE.DimensionAttributeValue = 5637146881 -- s/b a lookup to DimensionAttribute
INNER JOIN DynamicsAX2012.MAINACCOUNT
ON MAINACCOUNT.RECID = DIMENSIONATTRIBUTEVALUECOMBINATION.MAINACCOUNT
WHERE MAINACCOUNT.MainAccountID LIKE '6%'
 AND DIMENSIONATTRIBUTELEVELVALUE.DISPLAYVALUE = '600'

Thursday, May 18, 2017

Unable to deploy AX2012 Azure Virtual Machine

There is a AX 2012 virtual machine available on the Azure Portal.  When I tried to create one, I received the following error (with typo):

Project was created but there were problems creating deployment instance. You need to be a service administrator or co-administator for the selected Azure subscription or the location selected may not be supported for deploying Microsoft Dynamics AX 2012 R3 instances.


This happens because Azure environment does not trust Lifecycle Services.
  1. Open Lifecycle services to the project you tried to use
  2. Go to Microsoft Azure settings
  3. Download the management certificate
  4. Open the old Azure Management portal.
  5. Go to Settings > Management Certificates
  6. Upload the certificate.
  7. Go back to Lifecycle services and click the plus sign to create an environment and follow the steps.

Wednesday, May 10, 2017

Finding invalid document handling references

static void listDocuHandling_InvalidPaths(Args _args)
{
    DocuRef                 docuRef;
    DocuValue               docuValue;
    SysOperationProgress    progress;
    Common                  common;
    ;
    setPrefix("Invalid document handling file references");

    // Initialize progress indicator
    select count(RecId) from docuRef;
    progress = new SysOperationProgress(1, true);
    progress.setTotal(docuRef.RecId);
    progress.setCaption(funcname());

    while select docuRef
    join docuValue
    where docuValue.RecId == docuRef.ValueRecId
    {
        progress.setText(docuRef.Name);
        common = docuRef.refCommon();
        setPrefix((docuRef.Name) ? int642str(docuRef.RecId) + ' - ' + docuRef.Name : int642str(docuRef.RecId));

        if (!common.RecId)
        {
            error(strfmt("Referenced record %1 in %2 does not exist", docuRef.RefRecId, docuRef.refTablename()));
        }

        // Check if the file exists
        if (docuRef.docuType().FilePlace != DocuFilePlace::Database
         && !WinAPI::fileExists(docuValue.Path + docuValue.fileName()))
        {
            info(docuValue.Path + docuValue.fileName());
            if (common.RecId)
                info(common.caption(), strMin(), SysInfoAction_TableField::newBuffer(common));
        }
        progress.incCount();
    }
    progress.kill();
}

Friday, May 5, 2017

Work item could not be created. Insufficient rights for user

There are 60 workflows available within AX and it can be frustrating to try and set up specific security for each one.  The following message is no exception (pun).

Symptom
Stopped (error): X++ Exception: Work item could not be created. Insufficient rights for user cluther.
 at SysWorkflowWorkItem-create
SysWorkflowWorkItem-createWorkItems
SysWorkflow-save
SysWorkflowQueue-resume
SysWorkflowMessageQueueManager-executeTask
SysWorkflowMessageQueueManager-run

Details
Throws the error from \Classes\SysWorkflowWorkItem.create() line 155

Approach
Add the following warning messages to the SysWorkflowDocument so that AX explicitly tells you what access is required in order to run the workflow.


Tuesday, April 25, 2017

Test Data Transfer Tool - Object reference error

The Test Data Transfer Tool can be invaluable in copying data from one environment to another for testing.  Sometimes you may want to export the data against a restored copy of an environment, either due to security, or to limit any chance of performance degradation during the export.

It is important that you make a copy of both the AX data database as well as the model.  The tool exports table and field ID information from the model database.  If that model database does not exist with the right name, you will get 'object reference not set to an instance of an object' errors in the export log:

C:\Program Files (x86)\Microsoft Dynamics AX 2012 Test Data Transfer Tool (Beta)\DPLog.xml


Saturday, February 18, 2017

List AOSs Supported by SQL Server Instance

I recently found myself in the situation of needing to know what Dynamics AX Application Object Servers (AOS) are online in an environment.  The situation was a bit simplified because all of the AOS were served by the same SQL Server.  So I set out to build a SQL script which would query all of the relevant AX databases, look at the online servers and clients then summarize what it found.  After some tinkering I was able to create the following result:


Here is the query should you want to use it!

Monday, February 13, 2017

Bottomline PrecisionForms: Cannot Send Failed Email Notice

The Bottomline PrecisionForms Email service can send the helpdesk an email whenever an error is encountered.  It is important that you configure this correctly otherwise errors will be shown in the trace log.

BTEmail,No from address available for SMTP, cannot send failed email notice

Steps to correct or configure
1. Open Bottomline PrecisionForms Email
2. Click Administration > Configure email
3. Validate/fill out the "On failures send email to"



4. Click SMTP button
5. Validate/fill out the "Default sender name" to be the email form which errors are sent.


Saturday, February 4, 2017

Workflow Error: Application Cannot Be Started

Recently I was trying to set up a workflow in AX 7 / Dynamics 365 for Operations.  I was unable to open the workflow editor.


After clicking the details button I found the following:
Deployment Identity                : Microsoft.Dynamics.AX.Framework.Workflow.WorkflowEditorHost.application, Version=7.0.4307.16141, Culture=neutral, PublicKeyToken=c3bce3770c238a49, processorArchitecture=amd64
...
System.Deployment.Application.InvalidDeploymentException (Zone) - Deployment and application do not have matching security zones.

The fix in this case was to add AX as a trusted web site in the Internet Explorer Internet Options and to use Internet Explorer instead of Chrome:


I also found there are other common issues with the workflow editor.  If adding AX as a trusted site did not help, you might try looking at the following post:
https://organicax.com/2016/10/19/working-with-the-workflow-editor-download-in-ax7/

Monday, January 30, 2017

Bottomline PrecisionForms Email: File Did Not Contain an Email Header

Bottomline PrecisionForms is a powerful tool for formatting and delivering beautiful reports and forms (invoice, PO, BOL, RFQ...) from Dynamics AX.  I have been using this tool for almost ten years now.  You might encounter the following issue when setting up the Bottomline PrecisionForms Email server.

File did not contain an email header or errors were encountered.

First step is to review the spooler file which the printer was trying to process:

C:\Bottomline Technologies\PrecisionForms\spool

As shown in the screen shot, the file is a PDF file with a .tmp extention.  The way that PrecisionForms knows where to send the file is that it will add some text within the .tmp file with the email details.  These details should be passed from the Director project as part of resubmitting to a different queue.  The director project confirms it should be filled out:


The fix?
Open PrecisionForms Email and configure the email queue's default project and change the default merge configuration to "PDF with Job Ticket."

Saturday, January 28, 2017

Optimizing installing ISV solutions in AX 2012 (Compare Tool)

When integrating a comprehensive ISV solution into your AX environment there is always the possibility that there is a conflict: perhaps the ISV solution was built for a different version of AX, or you already have several other solutions installed.  This means spending significant hours comparing objects, almost to the point that you could have coded the ISV solution yourself, LOL!

How can we make this process faster?  How can we optimize it?

Right click > Compare, click compare button, expand, expand...expand, expand, click, review, scroll...repeat 100 times.

Modifications to AX Compare Tool-
The first thing I noticed is that when I hit compare, the screen is so tiny that I'm constantly resizing it.
Modify the following to support the resolution you are using:  \Forms\SysCompareForm.init()
For my 4k monitor I found that using 600 by 900 enabled me to see as much code as possible.  So I added:

html.prefColumnSize(600, 900);
Tree.prefColumnSize(300, 900); // wider by 100px

You can also modify which two layers it immediately chooses.  In the past I have changed it so that the washed "layer" was never selected.

Also you could consider running the comparison in CIL.  It sounds great, however read it carefully because the generated code may not be what you expect.

The compare tool as it comes with AX already sets focus on the Compare button, so hitting enter will cause it to start the compare.  However you could modify the form to automatically hit the compare button after a second, saving you a few milliseconds.

What other hacks/tricks have you done to speed up this process?  Let me know in the comments.