Automate downloads of Microsoft Dynamics NAV Cumulative Updates

Yesterday, I blogged about the availability of the first Cumulative Update of NAV 2017. In that post, I talked about the fact that Microsoft recently changed the place where to download them.

This also means the way of automating the download had to be changed. In fact, the PowerShell function that was part of my repository (and built by Kamil originally), didn’t work anymore. I didn’t really know how to get around this – but luckily, I have a really clever colleague (well, I do have more than one ;-)) that did find a way in .Net. And we managed to transfer the logic to PowerShell .. (literally “transfer”, not rewrite … you’ll see what I mean ;-)).

I’m not going to tell you “how” it works – you can find out in the code. I’ll just show you what we created, and how it works.


The main functionality is in C# .. and you can make it available by loading and compiling it by simply calling “Load-NAVCumulativeUpdateHelper”. In C#, you’re just that more flexible – and since we’re working in HTML, and figuring stuff out in HTML, it’s just much nicer to do so in C#. And .. the fact that this is the preferred environment of my colleague might have a reason in that as well ;-).

The PowerShell function is loading (compiling) two functions in memory and make them available to me:

static System.Collections.Generic.IEnumerable[MicrosoftDownload.NAVDownload] GetDownloadLocales(int productID)
static System.Collections.Generic.IEnumerable[MicrosoftDownload.NAVDownload] GetDownloadDetail(int productID, string language)

Let me show you some examples on how to use them.

This example, is going to show you a gridview of all download URLs in a gridview, and when you select one and press ok, it starts the download. It uses the “GetDownloadLocales” to get all the languages one-by-one:


$Locales = [MicrosoftDownload.MicrosoftDownloadParser]::GetDownloadLocales(54317)
$MyDownload = $Locales | out-gridview -PassThru | foreach {
Start-BitsTransfer -Source $_.DownloadUrl -Destination C:\_Download\

The other function “GetDownloadDetail”, you need to specify the Locale (like “en-US”), which can be used to speed up the process (no need to generate and navigate to all the URLs of all the “Locales”), like:


$MyDownload = [MicrosoftDownload.MicrosoftDownloadParser]::GetDownloadDetail(54317, 'en-US') | Select-Object *

You also see that the functions need a ProductID. Well, that’s how Download Center works .. If you have the ID, you know what to download .. and to get to that ProductID, let’s look into the next function.


This function is based on the good old function that Kamil Sacek once wrote – based on the ideas of my colleague. It is going to look at the Microsoft Dynamics NAV Team Blog to figure out the link to the Download Center – and yes – to figure out the ProductID. And obviously, going to use the Helper above to be able to start the download(s). It’s still limited to only search for the latest Cumulative Update. I’m working on a solution (probably a new function) to start the download from a specific blog article, or KB article.

The function above can simply be used in this way (and here are some more examples) which will simply start the download to the specified folder:

Get-NAVCumulativeUpdateFile -versions 2017 -CountryCode W1 -DownloadFolder C:\_Download

The function also creates a JSON with specifics about the download. Not because it’s necessary .. just because we can ;-).

Do I need the complete module to be able to do this?

No. You basically only need these two functions. So go ahead and automate! :-). The result is a much more stable way to automate these downloads, simply because Download Center doesn’t require you to run through a complicated login process ..

5.00 avg. rating (97% score) - 1 vote

Permanent link to this article:


3 pings

Skip to comment form

    • Thomas on December 9, 2016 at 4:01 am
    • Reply

    Good job!!

      • waldo on December 12, 2016 at 1:07 pm

      Thanks 🙂

    • The D on January 12, 2017 at 8:54 am
    • Reply

    Actually you could do without instancing an Internet Explorer COM object in “Get-NAVCumulativeUpdateFile”. Just download the plain HTML page and parse through it using RegEx. It is much easier to REALLY automate it and have it run in an non-interactive session (we are actually doing it using a JobQueue Codeunit)

      • waldo on May 19, 2017 at 12:54 pm

      Thanks for the suggestion! Something needs to change indeed – must get much more stable :-/

    • Kristof on January 27, 2017 at 12:52 pm
    • Reply

    Didn’t an older version allow me to download a dedicated CU Version?

    Due to the latest “mess from MS” with 2017 Cu2 or 2016CU15 or … the script will of course fail as it won’t be able to download CU2 at all … I was about to use and test this scripts which i can’t right now… [get file, unzip, unblock files, create platform hotfixfolder – all in one script]

    However, would be nice to allow the CU Version to be part [again?] of the parameters and used like the following:

    $blogurl = $feed.SelectNodes(“/rss/channel/item[./category=’NAV $version’ and ./category=’Cumulative Updates’ and ./title=’Cumulative Update $CUVersion for Microsoft Dynamics NAV $version has been released’]”).link | Select-Object -First 1

    Br and a nice Weekend,

      • waldo on January 27, 2017 at 2:00 pm

      You are right. It’s still on my list to do. but please, don’t hold yourself to create issues on GitHub 😉

  1. When I use Get-NAVCumulativeUpdateFile and set version to 2015, it get’s the wrong build (41779) I guess because it appears on before the real buildnumber. It does download the correct file though. Maybe it would be better to fetch the buildnumber from the KB article, but I guess that could also go wrong if Microsoft decides to put multiple KB numbers on the blog post? 🙂

    • Robert on February 14, 2017 at 11:09 pm
    • Reply

    Awesome job….

    • Robert on February 15, 2017 at 7:49 pm
    • Reply

    Just a small addition to eliminate an issue I found with 2013/ 2013 R2 blog page not supplying the “Build No.”

    Insert this line into the Get-NAVCumulativeUpdateFile after the line “112”-> $Build = $ie.Document.body.inner……

    if ($Build.length -gt 5) {$Build = ‘xxxxx’}

    • Rafał on March 20, 2017 at 10:00 am
    • Reply

    This would be great but right now it is not working for me:

    PS >Get-NAVCumulativeUpdateFile -versions 2017 -CountryCode W1 -DownloadFolder C:\TMP
    Processing parameters W1 2017
    Searching for RSS item
    Reading blog page
    Searching KB Url
    Microsoft Download Center link
    Found Product ID 54802
    Loading NAVCumulativeUpdateHelper
    An error occurred while enumerating through a collection: Object reference not set to an instance of an object..
    At C:\Program Files\WindowsPowerShell\Modules\Cloud.Ready.Software.NAV\\Upgrade\Get-NAVCumulativeUpdateFile.ps1:97 char:21
    + … $DownloadLinks = [MicrosoftDownload.MicrosoftDownloadPars …
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : InvalidOperation: (MicrosoftDownlo…oadLocales>d__2:d__2) [], RuntimeException
    + FullyQualifiedErrorId : BadEnumeration

      • waldo on March 20, 2017 at 10:37 am

      Works like a charm here (just tested it).

      Sure you have the last version of the function? I noticed your “version”-parameter is wrong (should be “version” not “versions”)

  2. Hi Waldo and thanks for the post.

    When I am trying your first example I am getting the following error. Could you please let me know what could be wrong?

    An error occurred while enumerating through a collection: The remote server returned an error: (404) Not Found..
    At C:\Tools\test.ps1:3 char:1
    + $MyDownload = $Locales | out-gridview -PassThru | foreach {$_.Downloa …
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : InvalidOperation: (MicrosoftDownlo…oadLocales>d__2:d__2) [], RuntimeExcep
    + FullyQualifiedErrorId : BadEnumeration

    Thanks in advance.

      • waldo on May 19, 2017 at 1:00 pm

      Sorry for the late reply – is this still the case?

      • dbabas on May 20, 2017 at 2:46 pm

      Hi, yes I just tried again and I am getting the same error.

      • waldo on May 22, 2017 at 7:55 am

      I just tried this:
      Get-NAVCumulativeUpdateFile -version 2017 -CountryCode W1 -DownloadFolder C:\_Downloads
      on a new pc, and it works.

      – did you update the modules to the latest version?
      – do you have internet connection? (the error states a 404)
      – can you access “” with that user on that machine?

      • dbabas on May 22, 2017 at 1:53 pm

      Hi waldo,

      Thanks for your reply.

      Get-NAVCumulativeUpdateFile works for me too. I’m getting the error when I’m trying to run your first example:

      $Locales = [MicrosoftDownload.MicrosoftDownloadParser]::GetDownloadLocales(54317)
      $MyDownload = $Locales | out-gridview -PassThru | foreach {
      Start-BitsTransfer -Source $_.DownloadUrl -Destination C:\_Download\

      It seems that the call to [MicrosoftDownload.MicrosoftDownloadParser]::GetDownloadLocales(54317) returns the 404 error.

      The answer to all your questions is yes.

  3. Hi Eric
    Does this still work? I probably gess not because Microsoft changed the locations.
    Regards René

      • waldo on November 12, 2019 at 10:39 am

      I’m afraid not, René 🙂

      • Kristof on June 11, 2020 at 12:55 pm

      Hi – a bit late maybe but I commit some changes to the gitrepo … for me the tool most of the time works now again 🙂
      I’m not 100% aware on how long the rss feed URL will do it’s job – but I guess we will notice 😀

      • waldo on June 11, 2020 at 12:59 pm

      Update is online, thanks, Kristof!

    • Todd Scott on August 25, 2020 at 12:01 pm
    • Reply

    Hi I just submitted a pull request for a rewrite of this function. Be interested in your feedback.

Leave a Reply

Your email address will not be published.

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