Van Vugt's dynamiXs

All around NAV dev and test

New-NavVersionList - A Useful Improvement

Finally, at Van Dijk, we started to get our NAV (Dynamics everyone here is calling it) installation upgraded to the latest version. So finally I can really get into things like PowerShell, and not in the least the merge utilities. One of first things I definitely wanted to get going with.

And surely, as many, I could profit from the various resources on the Internet. Using the scripts from the product DVD, and both Bas Graaf post on the NAV team blog and waldo’s post, I created the PowerShelll script, that allowed me to upgrade our code to NAV 2016. Coming from NAV 2009 R2, this is quite a step, but indeed the merge utilities do a pretty usable job. I really like the way conflicting code is handled. I also ran into some issues where properties are not handled right, but altogether I am really positive.

One other thing I ran into was the handling of the Version List. It’s no secret that this was not properly implemented in the Merge-NAVApplicationObject cmdlet. However, Microsoft provided us some examples by means of a How do I video and a blog post both by Bas Graaf. And also waldo gave a helping hand. I tried both and decided to use Bas Graaf’s solution, called New-NavVersionList. Simply because I got it working somewhat easier and liked it better as it contains lesser lines of code.

But … I found it had one relevant issue: it did not handle the deletion of an version list part. More specifically: between NAV 2009 R2 and NAV 2016 some standard objects, localized for NL, were reverted to w1. Therefor the Version List should, after the merge and post processing with Bas' script, not have a NAVNL part in the Version List. And as you might have guessed, this went wrong.

To get a clear view on the result of the script I setup the following cases:

  • Cases 1 to 6 concerns updated w1 objects existing in NAV 2009 R2 (pure w1, or w1 localized and/or customized)
  • Case 7 a new w1 object
  • Cases 8 and 9 updated local objects (of which one is localized)
  • Case 10 a pure custom object

Guess I covered all options with this.

W1

Local

#

Object

Object Type

Updated

New

Updated

Removed

Custom

1

COD3

W1

X

2

COD11

W1

X

X

3

COD2

W1

X

X

X

4

COD74

W1

X

X

5

COD12

W1

X

X

6

COD1

W1

X

X

X

7

COD19

W1

X

8

COD11401

Local

X

9

COD11400

Local

X

X

10

COD50000

Custom

X

Running the Merge-NAVApplicationObject cmdlet and post processing it with the original New-NavVersionList the result was as follows:

#

Object

Status

Original

Modified

Target

Result

Expected Result

1

COD3

OK

NAVW14.00

NAVW19.00

NAVW14.00

NAVW19.00

NAVW19.00

2

COD11

OK

NAVW16.00.01, NAVNL5.00

NAVW19.00, NAVNL9.00

NAVW16.00.01,NAVNL5.00

NAVW19.00,NAVNL9.00

NAVW19.00,NAVNL9.00

3

COD2

OK

NAVW16.00.01, NAVNL4.00.01

NAVW19.00, NAVNL9.00

NAVW16.00.01,NAVNL4.00.01, CUSTOM6.00

NAVW19.00,NAVNL9.00, CUSTOM6.00

NAVW19.00,NAVNL9.00, CUSTOM6.00

4

COD74

OK

NAVW14.00.01

NAVW18.00

NAVW14.00.01,CUSTOM6.22

NAVW18.00,CUSTOM6.22

NAVW18.00,CUSTOM6.22

5

COD12

NOT OK

NAVW16.00.10, NAVNL5.00

NAVW19.00

NAVW16.00.10,NAVNL5.00

NAVW19.00,NAVNL5.00

NAVW19.00

6

COD1

NOT OK

NAVW16.00.10, NAVNL5.00

NAVW19.00

NAVW16.00.10,NAVNL5.00, CUSTOM6.39

NAVW19.00,NAVNL5.00, CUSTOM6.39

NAVW19.00,CUSTOM6.39

7

COD19

OK

NAVW19.00

 

NAVW19.00

NAVW19.00

8

COD11401

OK

NAVNL6.00.01

NAVNL8.00

NAVNL6.00.01

NAVNL8.00

NAVNL8.00

9

COD11400

OK

NAVNL6.00

NAVNL8.00

NAVNL6.00,CUSTOM6.25

NAVNL8.00,CUSTOM6.25

NAVNL8.00,CUSTOM6.25

10

COD50000

OK

 

CUSTOM3.0

CUSTOM3.0

CUSTOM3.0

As you can see case 5 and 6 where not OK (have a look at the Result and Expected Result), being the fact that the NAVNL should not end up in the Result as the NL localization was removed from both COD 1 and COD12 (have also a look at the Modified and Target).

For clarity this was the merge scenario:

ORIGINAL = NAV 2009 R2
MODIFIED = NAV 2016
TARGET = CUSTOM NAV 2009 R2
RESULT = CUSTOM NAV 2016

For completeness I also executed the other, valid scenario:

ORIGINAL = NAV 2009 R2
MODIFIED = CUSTOM NAV 2009 R2
TARGET = NAV 2016
RESULT = CUSTOM NAV 2016

Resulting in:

#

Object

Status

Original

Modified

Target

Result

Expected Result

11

COD3

OK

NAVW14.00

NAVW14.00

NAVW19.00

NAVW19.00

NAVW19.00

12

COD11

OK

NAVW16.00.01, NAVNL5.00

NAVW16.00.01,NAVNL5.00

NAVW19.00, NAVNL9.00

NAVW19.00,NAVNL9.00

NAVW19.00,NAVNL9.00

13

COD2

OK

NAVW16.00.01, NAVNL4.00.01

NAVW16.00.01,NAVNL4.00.01, CUSTOM6.00

NAVW19.00, NAVNL9.00

NAVW19.00,NAVNL9.00, CUSTOM6.00

NAVW19.00,NAVNL9.00, CUSTOM6.00

14

COD74

OK

NAVW14.00.01

NAVW14.00.01,CUSTOM6.22

NAVW18.00

NAVW18.00,CUSTOM6.22

NAVW18.00,CUSTOM6.22

15

COD12

OK

NAVW16.00.10, NAVNL5.00

NAVW16.00.10,NAVNL5.00

NAVW19.00

NAVW19.00

NAVW19.00

16

COD1

NOT OK

NAVW16.00.10, NAVNL5.00

NAVW16.00.10,NAVNL5.00, CUSTOM6.39

NAVW19.00

NAVW19.00,NAVNL5.00, CUSTOM6.39

NAVW19.00,CUSTOM6.39

17

COD19

OK

 

NAVW19.00

NAVW19.00

NAVW19.00

18

COD11401

OK

NAVNL6.00.01

NAVNL6.00.01

NAVNL8.00

NAVNL8.00

NAVNL8.00

19

COD11400

OK

NAVNL6.00

NAVNL6.00,CUSTOM6.25

NAVNL8.00

NAVNL8.00,CUSTOM6.25

NAVNL8.00,CUSTOM6.25

20

COD50000

OK

CUSTOM3.0

 

CUSTOM3.0

CUSTOM3.0

Being still an amateur PowerShell user I tried to tweak the script to get the desired result, but, honestly, I totally failed, and asked Bas for help, who quite quickly answered with an improved version. Well … a changed version that yielded the same results. But his second improvement was a hit.

Original Script

function New-NavVersionList($MergeInfo, [string[]]$ProductCode = ("NAVW1","NAVNL","CUSTOM"))
{
  
$allVersions = @() + $MergeInfo.modified.versionlist -split ‘,’
   $allVersions += $mergeInfo.target.versionlist -split ‘,’

   $mergedVersions = @()

   foreach ($code in $ProductCode)
   {
      # keep the “highest” version tag for $code
      $mergedVersions += $allVersions | where { $_ -like $code*” } | sort | select -last 1

     
# remove all $code version tags
      $allVersions = $allVersions | where { $_ -notlike $code*” }
   }
   # return a ,-delimited string consisting of the “highest” versions for each $ProductCode and any other tags
   $mergedVersions += $allVersions
   $mergedVersions -join ‘,’
}

Improved Script

function New-NavVersionList($MergeInfo, [string[]]$ProductCode = ("NAVW1","NAVNL","CUSTOM"))
{
  
$allVersions = @() + $MergeInfo.modified.versionlist -split ‘,’
   $allVersions += $mergeInfo.target.versionlist -split ‘,’

   $mergedVersions = @()

   foreach ($code in $ProductCode)
   {
      # add only to merged version list if the product code was not removed
      if (($MergeInfo.original.versionlist -notlike "*$code*" -or ($allVersions -like "$code*").Count -ge 2))
      {
        # keep the “highest” version tag for $code
        $mergedVersions += $allVersions | where { $_ -like $code*” } | sort | select -last 1
      }
     
# remove all $code version tags
      $allVersions = $allVersions | where { $_ -notlike $code*” }
   }
   # return a ,-delimited string consisting of the “highest” versions for each $ProductCode and any other tags
   $mergedVersions += $allVersions
   $mergedVersions -join ‘,’
}

The main part of the script was left unchanged, only an if-clause was added that incorporates the code to select the “highest” version tag.

Facit

Now it work perfectly well in all cases I am working with. As you can see I did not test it with more than three tags in the Version List. I leave that up to you.

A big thanx to Bas Graaf! Left Hug