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 theMerge-NAVApplicationObject cmdlet. However, Microsoft provided us some examples by means of aHow 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 andExpected Result), being the fact that the NAVNL should not end up in theResult 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
functionNew-NavVersionList($MergeInfo,[string[]]$ProductCode= ("NAVW1","NAVNL","CUSTOM"))
{
$allVersions= @() +$MergeInfo.modified.versionlist-split‘,’
$allVersions+=$mergeInfo.target.versionlist-split‘,’
$mergedVersions= @()
foreach
($codein$ProductCode)
{
# keep
the “highest” version tag for $code
$mergedVersions+=$allVersions|where {$_-like“$code*”
} |sort|select-last1
# 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
functionNew-NavVersionList($MergeInfo,[string[]]$ProductCode= ("NAVW1","NAVNL","CUSTOM"))
{
$allVersions= @() +$MergeInfo.modified.versionlist-split‘,’
$allVersions+=$mergeInfo.target.versionlist-split‘,’
$mergedVersions= @()
foreach
($codein$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-ge2))
{
# keep
the “highest” version tag for $code
$mergedVersions+=$allVersions|where {$_-like“$code*”
} |sort|select-last1
}
# 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!