PowerShell Script to Merge NAV Versionlist

070914_0851_PowershellT1.pngI’ve been trying to get this out for a while now.. finally I was able to :-).

If you have been to one of the Directions (US or EMEA) or the last session of the Dutch Dynamics Community, you might have visited one of the session about the great new addition in NAV2015 (in fact, already in NAV2013 R2 CU9): the new PowerShell commandlets to merge Microsoft Dynamics NAV objects .. or its official name: RapidStart Upgrade – Code. If you have, you might have figured that “dealing with Versionlists” is something you’ll have to do yourself, as it’s really dependend on how you handle your versionlists – which might differ from partner to partner, product to product, case to case.. .

In Microsoft’s presentation, a PowerShell script was shown in PowerPoint .. and the moment I saw that script, I knew that was the solution on how we do versionlists in my company. So I took that script, changed it a little bit (I didn’t like working with the mergeinfo, as you don’t always have this object, neither it is convenient to test…) .. and now I have a prefectly working script that I have used many times in my company, and – for us – works like a charm!

Here it is:

function Merge-NAVVersionList
{
  param (
  [String]$OriginalVersionList,
  [String]$ModifiedVersionList,
  [String]$TargetVersionList,
  [String[]]$Versionprefix
)
  $allVersions = @() + $OriginalVersionList.Split(',')
  $allversions += $ModifiedVersionList.Split(',')
  $allversions += $TargetVersionList.Split(',')
  $mergedversions = @()
  foreach ($prefix in $Versionprefix)
  {
    #add the "highest" version that starts with the prefix
    $mergedversions += $allVersions | where { $_.StartsWith($prefix) } | Sort | select -last 1
    # remove all prefixed versions
    $allversions = $allVersions.Where({ !$_.StartsWith($prefix) })
  }
  # return a ,-delimited string consiting of the "hightest" prefixed versions and any other non-prefixed versions
  $mergedversions += $allVersions
  $mergedVersions -join ','
}

It’s a simple concept. Let’s suppose I’m the script. This is how I would handle your versionlist:

  • Put all the versiontags into an array, so I can sort it, filter it, .. .
  • Give me all the prefixes of which you want the highest tag of
  • For each prefix you give me, I’ll
    • filter the array on that prefix
    • Sort it
    • Get the highest number
    • Put that in a separate variable
    • Remove everything from that prefix in the original aray
  • In the end, I add everything that’s left in my array
  • There you go, you have your merged VersionList

This is a script that even cleans up your VersionList as you can re-sort it, having all your productversions in the right order for all objects. I really love it!

Here is an example on how to use it:

$MyVersionprefix = 'NAVW1', 'NAVBE', 'I'
$OrigVersionlist = 'NAVW17.10.00.37563,NAVBE7.10.00.37563'
$ModVersionList = 'NAVW17.10.00.37563,NAVBE7.10.00.37563,I7.4,M22344,M65877'
$TgtVersionList = 'NAVW18.00,NAVBE8.00'
Merge-NAVVersionList `
	-OriginalVersionList $OrigVersionlist `
	-ModifiedVersionList $ModVersionList `
	-TargetVersionList $TgtVersionList `
	-Versionprefix $MyVersionprefix

So, just provide the original, modified and target versionlist, and add the prefixes you want in your resulting versionlist. The result of the code above would be: ‘NAVW18.00,NAVBE8.00,I7.4,M22344,M65877’

Just for your reference, an extract from my main merge-script, where I use this very same function:


Thanks to Microsoft for getting me into the right direction! This script has saved me loads of time!

4.83 avg. rating (96% score) - 6 votes

Permanent link to this article: http://www.waldo.be/2014/10/28/powershell-script-to-merge-nav-versionlist/

18 comments

7 pings

Skip to comment form

    • Derk Bernhardt on October 30, 2014 at 12:25 pm
    • Reply

    Thanks for this script! This is a great addtional to the new NAV merge process. I made a small change to the script: I added “.TrimStart()” during the version list split to remove spaces in front of version tags.

      • waldo on November 3, 2014 at 8:18 am
        Author

      Makes a lot of sense! Thanks for sharing!

    • Angel on November 19, 2014 at 7:32 am
    • Reply

    I Used your script as below, but i got the error.

    Command:

    Merge-NAVApplicationObject -OriginalPath ‘C:\_Navision\Merging\Merge Test\Original\TAB14.txt’ -ModifiedPath ‘C:\_Navision\Merging\Merge Test\Modified\TAB14.txt’ -TargetPath ‘C:\_Navision\Merging\Merge Test\Target\TAB14.txt’ -ResultPath ‘C:\_Navision\Merging\Merge Test\Result\’ -force $MergeResult | Where-Object MergeResult -eq ‘Merged’ | foreach { Set-NAVApplicationObjectProperty -Target $_.Result -VersionListProperty (Merge-NAVVersionList -OriginalVersionList $_.Original.VersionList -ModifiedVersionList $_.Modified.VersionList -TargetVersionList $_.Target.VersionList -Versionprefix ‘TEST’)}

    Error :

    Merge-NAVApplicationObject : A positional parameter cannot be found that accepts argument ‘$null’.
    At line:2 char:1
    + Merge-NAVApplicationObject -OriginalPath ‘C:\_Navision\Merging\Merge Test\Origin …
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : InvalidArgument: (:) [Merge-NAVApplicationObject], ParameterBindingException
    + FullyQualifiedErrorId : PositionalParameterNotFound,Microsoft.Dynamics.Nav.Model.Tools.Cmdlets.MergeNavApplicationObject

      • waldo on December 15, 2014 at 4:13 pm
        Author

      Could it be you’re using an old version of PowerShell?

      I have had a similar issue on a server 2008 (older version of PowerShell – not sure which version though). Here is how I solved the script:

      function Merge-NAVVersionList
      {
      param (
      [String]$OriginalVersionList,
      [String]$ModifiedVersionList,
      [String]$TargetVersionList,
      [String[]]$Versionprefix
      )

      [Array]$allVersions = $null
      $allversions += $OriginalVersionList.Split(‘,’)
      $allversions += $ModifiedVersionList.Split(‘,’)
      $allversions += $TargetVersionList.Split(‘,’)

      $mergedversions = @()
      foreach ($prefix in $Versionprefix)
      {
      #add the “highest” version that starts with the prefix
      $mergedversions += $allVersions | where { $_.StartsWith($prefix) } | Sort | select -last 1

      # remove all prefixed versions
      $allversions = $allVersions | Where-Object { !$_.StartsWith($prefix) }
      }

      # return a ,-delimited string consiting of the “hightest” prefixed versions and any other non-prefixed versions
      $mergedversions += $allVersions | select -uniq
      $mergedVersions -join ‘,’
      }

  1. You should also be aware of another critical issue with the merge cmdlets:
    https://grumpynav.wordpress.com/2015/01/26/caution-the-merge-cmdlets-might-merge-incorrectly/

      • waldo on February 3, 2015 at 8:47 am
        Author

      Thanks, man, to add this. It’s indeed something to take into account. Luckily we don’t use curly brackets 😉 (at least I assume!)

    • Himanshu Yadav on February 4, 2015 at 8:06 am
    • Reply

    Hi,

    I am using this script but when I run It in window PowerShell 2015 nothing happens. Do I need to change something, I want to merge the version list of 2013 object with 2015.

    Please suggest me what can I do.???

      • waldo on February 4, 2015 at 10:37 am
        Author

      What do you mean “nothing happens”? You should at least get an error message?

      I assume you’re familiar with PowerShell?

  2. Nice, but how to determine which VersionPrefixes are used?

    To get a complete list of all version list prefixes one could use the following SQL-script.
    I think it must be quite simple to convert this one to a powershell script, but that’s for someone else to do.
    If anyone does have a powershell equivalent for it, please share it.

    What it does is first create a one column table with all available values in [Version List]
    This (cte)table is used to strip the numbers from the Version list, leaving the VersionPrefixes and those are concatenated to a single text, to be used as $MyVersionprefix

    USE [nav database];

    DECLARE @VersionTagList VARCHAR(MAX)

    WITH cte( DataItem, Data)
    AS ( SELECT Cast( LEFT( [Version List], Charindex( ‘,’, [Version List] + ‘,’ ) – 1 ) AS VARCHAR(100)) AS DataItem
    ,Cast( Isnull( Stuff( [Version List], 1, Charindex( ‘,’, [Version List] + ‘,’ ), ” ), ” ) AS VARCHAR(100)) AS Data
    FROM
    [dbo].[Object]
    UNION ALL
    SELECT Cast( LEFT( Data, Charindex( ‘,’, Data + ‘,’ ) – 1 ) AS VARCHAR(100))
    ,Cast( Stuff( Data, 1, Charindex( ‘,’, Data + ‘,’ ), ” ) AS VARCHAR(100))
    FROM
    cte
    WHERE Data > ” )
    SELECT DISTINCT
    LEFT( DataItem, Patindex( ‘%[0-9]%’, DataItem + ‘1’ ) – 1 ) VersionTag
    INTO #T1
    FROM
    cte

    SELECT @VersionTagList = COALESCE(@VersionTagList+’, ‘, ”) + ””
    + VersionTag + ””
    FROM
    #T1
    WHERE VersionTag ”

    SELECT @VersionTagList
    print @VersionTagList

    DROP TABLE #T1

      • waldo on February 19, 2015 at 3:17 pm
        Author

      thanks, Remco 🙂

    • Kristof on January 13, 2017 at 9:20 am
    • Reply

    Hi there!

    Have you ever experienced an empty Version list (or more precise empty object Properties) while playing around with this after the Merge-NAVApplicationObject? I do have a Table within Modified and Target but not in Original. And both text files are identical and have Objects-Properties set. When i run the merge it tells me: all unchanged, and moves targetfile to result. this is done fine. but when i open the Txt file my Object Properties are gone.

    I can use your code above to rebuild the version list also on unchanged obejcts (while missing date and time). But looks a bit strange to me, even maybe an error in the Navion MergeObject?As it would take the none existing original to somehow set the version list.

    Thanks for your help upfront 🙂

      • waldo on January 13, 2017 at 11:07 am
        Author

      I haven’t noticed anything like this before.
      but tell me – how come you have it in your mod and target? can you tell me some more what is your orig, mod and target version?

    • Dominik on August 14, 2017 at 12:53 pm
    • Reply

    Hi,

    what am i doing wrong, when i get every version tag two or more times in the result?

      • waldo on April 25, 2019 at 10:34 pm
        Author

      Probably your versionprefix is wrong.

    • Al on October 9, 2017 at 3:00 pm
    • Reply

    Have you been able to get this to work on a per-object basis? Or do you have to run the merge command individually for each object?

      • waldo on April 25, 2019 at 10:32 pm
        Author

      Well, if you split the objects, you can create a loop. Look at this script as an example: https://github.com/waldo1001/Cloud.Ready.Software.PowerShell/blob/master/PSModules/CRS.NavContainerHelperExtension/NAVObjectMgt/Release-NCHNAVApplicationObjects.ps1

    • wei on April 25, 2019 at 8:43 pm
    • Reply

    hi I am new to use powershell. I testeed this function works well, but how to convert the whole company objects version list? this need loop.
    thank you

  1. […] Continue reading » […]

  2. […] 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 […]

  3. […] 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 […]

  4. […] while ago, I blogged about merging VersionLists with PowerShell. It shows a solution on how to handle (merge) version lists with […]

  5. […] while ago, I blogged about merging VersionLists with PowerShell. It shows a solution on how to handle (merge) version lists with […]

  6. […] while ago, I blogged about merging VersionLists with PowerShell. It shows a solution on how to handle (merge) version lists with […]

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.

%d bloggers like this: