[Gelöst] Get-NAVCumulativeUpdateFile (Waldo/Kine/Fiddi)

16. Dezember 2015 15:45

Auf den NAV TechDays hat Waldo in seiner Session "Thinking outside the box with NAV development" eine JSON-Konvertierung von Webseitendaten nutzendes Skript (von Kamil Sacek (kine) nach einer ursprünglichen Idee von Waldo bzw. seinem Team) vorgestellt, welches den zeitraubenden Workflow für das Herunterladen von Cumulative Updates automatisiert.

Im Video sieht man das Skript im Einsatz (welches ein kleiner Teil des großen Pakets hier ist).

https://www.youtube.com/watch?v=R4xfmbjiKOw#t=42m00s (Video geht ab 42. min los, genau die Stelle ab der dieses stattfindet).

Bis zu dem Punkt, wo der Hotfixlink via ConvertFrom-Json ermittelt werden soll, funktioniert bei mir das Skript, aber danach sind etliche Teile (die entscheidenen Parameter) vom Link nicht gefüllt.
Im Seitenquelltext (Strg+U) wird dabei auf den Abschnitt zugegriffen, der mit "hflist" beginnt.
hflistpattern.png

Vorhanden sind die Daten, wie im Bildbespiel hier und im Video (bei 44:35) zu sehen.
hflist.png


GetCUupdate.png


Hat jemand dieses Skript schon erfolgreich im Einsatz?

Edit: Aktueller Skriptcode bei GitHub: Cloud.Ready.Software.NAV/Upgrade/Get-NAVCumulativeUpdateFile.ps1

Code:
#requires -Version 3 -Modules BitsTransfer
#Author: Kamil, based on ideas from waldo (who had it developed in .Net) :-)
<#
    .Synopsis
    Download the Cumulative Update File for specified NAV version and localization
    .DESCRIPTION
    Download the Cumulative Update File for specified NAV version and localization, with possibility to
    select specific cumulative update
    .EXAMPLE
    Get-NAVCumulativeUpdateFile -CountryCodes 'intl','CSY' -versions '2013 R2','2015','2016'
    .EXAMPLE
    Get-NAVCumulativeUpdateFile -CountryCodes 'CSY' -versions '2013 R2' -CUNo 23
    .OUTPUT
    Objects with info about the downloaded cumulative updates
#>
function Get-NAVCumulativeUpdateFile
{
    param (
        [Parameter(Mandatory,ValueFromPipelineByPropertyName)]
        $CountryCodes = 'W1',
        [Parameter(Mandatory,ValueFromPipelineByPropertyName)]
        $versions = '2016',
        [Parameter(ValueFromPipelineByPropertyName)]
        $CUNo = '',
        [Parameter(ValueFromPipelineByPropertyName)]
        $DownloadFolder = $env:TEMP
    )

    begin {
        $ie = New-Object -ComObject 'internetExplorer.Application'       
        $ie.Visible = $true
    }
    process
    {
        foreach ($CountryCode in $CountryCodes)
        {
            foreach ($version in $versions)
            {
                $url = ''
               
                Write-Host -Object "Processing parameters $CountryCode $version $CUNo" -ForegroundColor Cyan
       
                $feedurl = 'https://blogs.msdn.microsoft.com/nav/category/announcements/cu/feed/'
                [regex]$titlepattern = 'Cumulative Update (\d+) .*'

                Write-Host -Object 'Searching for RSS item' -ForegroundColor Green

                $feed = [xml](Invoke-WebRequest -Uri $feedurl)

                if ($CUNo -gt '')
                {
                    $blogurl = $feed.SelectNodes("/rss/channel/item[./category='NAV $version' and ./category='Cumulative Updates' and contains(./title,'$CUNo')]").link | Select-Object -First 1
                } else
                {
                    $blogurl = $feed.SelectNodes("/rss/channel/item[./category='NAV $version' and ./category='Cumulative Updates']").link | Select-Object -First 1
                }

                if (!$blogurl)
                {
                    Write-Error -Message 'Blog url not found!'
                    return
                }

                Write-Host -Object "Reading blog page $blogurl" -ForegroundColor Green
               
                $blogarticle = ''
                #$blogarticle = Invoke-WebRequest -Uri $blogurl
                $null = $ie.Navigate($blogurl)
                while ($ie.Busy -eq $true)
                {
                    $null = Start-Sleep -Seconds 1
                }
               
   
                Write-Host -Object 'Searching for KB link' -ForegroundColor Green
                               
                $titlematches = $titlepattern.Matches($ie.Document.title)
                $updateno = $titlematches.Groups[1]

                #$kblink = $blogarticle.Links | Where-Object -FilterScript {
                $kblink = $ie.Document.links | Where-Object -FilterScript {
                    Write-Verbose "Link: $($_.href) id: $($_.id)"
                    $_.innerText -match 'KB'
                }

                Write-Host -Object "Opening KB link $($kblink.href)" -ForegroundColor Green
                $null = $ie.Navigate($kblink.href)
                while ($ie.Busy -eq $true)
                {
                    $null = Start-Sleep -Seconds 1
                }

                if ($ie.LocationURL -match 'https://corp.sts.microsoft.com')
                {
                    Write-Host -Object 'Trying to login' -ForegroundColor Green
                    $loginlink = $ie.Document.IHTMLDocument3_getElementById('CustomHRD_LinkButton_LiveID')
                    Write-Host -Object 'Clicking the link to login' -ForegroundColor Green
                    $loginlink.click()
                    while ($ie.Busy -eq $true)
                    {
                        $null = Start-Sleep -Seconds 1
                    }
                }

                if ($ie.LocationURL -match 'login.live.com')
                {
                    Write-Host -Object 'Please, login. Script will continue automatically...' -ForegroundColor Magenta
                    while ($ie.LocationURL -match 'login.live.com')
                    {
                        $null = Start-Sleep -Seconds 1
                    }
                }
                while ($ie.Busy -eq $true)
                {
                    $null = Start-Sleep -Seconds 1
                }   

   
                if ($ie.LocationURL -match 'https://mbs2.microsoft.com/UserInfo/SelectProfile.aspx')
                {
                    Write-Host -Object 'Searching for identity selection radiobuttons' -ForegroundColor Green
                    $radiobuttons = $ie.Document.body.getElementsByTagName('input') | Where-Object -FilterScript {
                        $_.type -eq 'radio' -and $_.name -eq 'radioGroup'
                    }
                    Write-Host -Object 'Clicking first radio button' -ForegroundColor Green
                    $null = $radiobuttons[0].setActive()
                    $null = $radiobuttons[0].click()
                    $null = $ie.Document.IHTMLDocument3_getElementsByName('continueButton')[0].click()
                    while ($ie.Busy -eq $true)
                    {
                        $null = Start-Sleep -Seconds 1
                    }
                }

                Write-Host -Object 'Searching for download link' -ForegroundColor Green
                $downloadlink = $ie.Document.links | Where-Object -FilterScript {
                    $_.id -match 'kb_hotfix_link'
                }
                Write-Host -Object "Opening download link $($downloadlink.href)" -ForegroundColor Green
                $null = $ie.Navigate($downloadlink.href)
                while ($ie.Busy -eq $true)
                {
                    $null = Start-Sleep -Seconds 1
                }

                Write-Host -Object 'Searching for Accept button' -ForegroundColor Green

                $button = $ie.Document.IHTMLDocument3_getElementsByName('accept')

                if ($button.id)
                {
                    Write-Host -Object 'Clicking Accept button' -ForegroundColor Green
                    $null = $button.click()
                    while ($ie.Busy -eq $true)
                    {
                        $null = Start-Sleep -Seconds 1
                    }   
                }

                Write-Host -Object 'Searching for list of updates' -ForegroundColor Green

                [regex]$pattern = 'hfList = (\[.+\}\])'
                $matches = $pattern.Matches($ie.Document.body.innerText)
                if (!$matches)
                {
                    Write-Error -Message 'list of hotfixes not found!'
                    return
                }

                Write-Host -Object 'Converting Json with updates' -ForegroundColor Green
                $hotfixes = $matches.Groups[1].Value.Replace('\x','') | ConvertFrom-Json

                #URL examples:
                #http://hotfixv4.microsoft.com/Dynamics NAV 2016/latest/W1KB3106089/43402/free/488130_intl_i386_zip.exe
                #http://hotfixv4.microsoft.com/Dynamics NAV 2015/latest/CZKB3106088/43389/free/488059_CSY_i386_zip.exe

                Write-Host -Object "Searching for update for language $CountryCode" -ForegroundColor Green

                $hotfix = $hotfixes | Where-Object -FilterScript {
                    $_.filename -like "$($CountryCode)*"
                }

                if (!$hotfix) {
                    $hotfix = $hotfixes | Where-Object -FilterScript {
                        $_.langcode -like "$($CountryCode)*"
                    }
                }
                Write-Host -Object 'Creating hotfix URL' -ForegroundColor Green

                $url = "http://hotfixv4.microsoft.com/$($hotfix.product)/$($hotfix.release)/$($hotfix.filename)/$($hotfix.build)/free/$($hotfix.fixid)_$($hotfix.langcode)_i386_zip.exe"

                Write-Host -Object "Hotfix URL is $url" -ForegroundColor Green

                $filename = (Join-Path -Path $DownloadFolder -ChildPath "$($hotfix.fixid)_$($hotfix.langcode)_i386_zip.exe")
                Write-Host -Object "Downloading hotfix to $filename" -ForegroundColor Green
   
                if (-not (Test-Path $filename))
                {
                    $null = Start-BitsTransfer -Source $url -Destination $filename
                }
   
                Write-Host -Object 'Hotfix downloaded' -ForegroundColor Green
                $null = Unblock-File -Path $filename

                $result = New-Object -TypeName System.Object
                $null = $result | Add-Member -MemberType NoteProperty -Name filename -Value "$filename"
                $null = $result | Add-Member -MemberType NoteProperty -Name version -Value "$version"
                $null = $result | Add-Member -MemberType NoteProperty -Name CUNo -Value "$updateno"
                $null = $result | Add-Member -MemberType NoteProperty -Name CountryCode -Value "$CountryCode"
                $null = $result | Add-Member -MemberType NoteProperty -Name langcode -Value "$($hotfix.langcode)"
                       
                Write-Output -InputObject $result
            }
        }       
    }
    end {
        $null = $ie.Quit()
    }
}


Vor dem Lauf ggf. das BITS-Transfer Modul importieren.
Code:
Import-Module BitsTransfer
Du hast keine ausreichende Berechtigung, um die Dateianhänge dieses Beitrags anzusehen.

Re: Get-NAVCumulativeUpdateFile (Waldo/Kine)

16. Dezember 2015 16:26

Kann es sein, dass das Skript nur auf einem 32bit Windows funktioniert?

Es scheint so, als ob es dem Skript nicht gelingt auf der Seite mit der Downloadliste, diese auf zu klappen, bevor es nach dem Link sucht. (es fehlt der Klick auf "Hotfixes für alle Plattformen und Sprachen anzeigen")

Gruß Fiddi

Re: Get-NAVCumulativeUpdateFile (Waldo/Kine)

16. Dezember 2015 16:51

Die Liste sucht er sich anscheinend ohne aufzuklappen, steht ja im Quelltext. Bei mir hatte er Probleme mit der Auswahl der Partner. Da musste ich eine Zeile ersetzen:

Code:
$null = $ie.Document.IHTMLDocument3_getElementsByName('continueButton')[0].click()
durch
Code:
$null = $ie.Document.getElementById('continueButton').click()

Er läd gerade runter.

Kannst du mal debuggen Kai und schauen, was genau da schief läuft?

Re: Get-NAVCumulativeUpdateFile (Waldo/Kine)

16. Dezember 2015 17:10

Download hat sauber funktioniert. Ich bin grad ratlos was bei dir schief läuft...

Re: Get-NAVCumulativeUpdateFile (Waldo/Kine)

16. Dezember 2015 17:25

SilverX hat geschrieben: Ich bin grad ratlos was bei dir schief läuft...

Ich auch :wink: . Deine Codeänderung hat bei mir keine Wirkung. So langsam habe ich unsere Firewall im Verdacht , dass diese den Zugriff blockiert und deswegen nichts zurückkommt. Ich probiere das heute Abend noch mal von meinem privaten Anschluss.

fiddi hat geschrieben:Kann es sein, dass das Skript nur auf einem 32bit Windows funktioniert?

Ich habe es "nur" mit 64bit probiert (sowohl Win10 als auch Win7). Sollte aber davon unabhängig sein.

Re: Get-NAVCumulativeUpdateFile (Waldo/Kine)

16. Dezember 2015 18:11

Hab das ganze gerade mal manuell ausgeführt in der PS. Dann kommt was richtiges raus. Der Fehler muss eigentlich in $matches liegen. da sollte eigentlich nur die "hflist.."- Zeile drin sein.

Gruß Fiddi

Re: Get-NAVCumulativeUpdateFile (Waldo/Kine)

16. Dezember 2015 19:46

Kowa hat geschrieben:Ich probiere das heute Abend noch mal von meinem privaten Anschluss.

Da bin ich nun und bekomme hier mit meinem privaten Notebook exakt die gleichen Fehlermeldungen wie im Büro. Die Firewall war es also nicht.

Re: Get-NAVCumulativeUpdateFile (Waldo/Kine)

16. Dezember 2015 20:42

Dann fällt mir nur noch Software ein, die den Traffic ggf. Verändert, bestimmte AD-Blocker oder andere Internet Security Programme.

Re: Get-NAVCumulativeUpdateFile (Waldo/Kine)

17. Dezember 2015 00:58

fiddi hat geschrieben:Hab das ganze gerade mal manuell ausgeführt in der PS. Dann kommt was richtiges raus. Der Fehler muss eigentlich in $matches liegen. da sollte eigentlich nur die "hflist.."- Zeile drin sein.

Danke für's mitprobieren :-) .
Mit manuell aus dem Quellcode der Webseite kopierten Hotfixblock (wird der Variable $hfList zugewiesen) und einem angepassten Skriptfragment an der fraglichen Stelle klappt es bei mir auch. Das sieht dann so aus:
Code:
 $CountryCode = 'DE'         
 $hfList = "hfList = [{fixid:'487517',product:'Dynamics NAV 2015',language:'English',langcode:'ENU',platform:'x86',release:'latest',filename:'NAKB3097767',version:'NAV 8.0',build:'42951',size:'659155760',credate:'9\x2f28\x2f2015 7\x3a49\x3a29 PM',moddate:'9\x2f29\x2f2015 6\x3a15\x3a23 AM'},{fixid:'487518',product:'Dynamics NAV 2015',language:'Dutch',langcode:'NLD',platform:'x86',release:'latest',filename:'NLKB3097767',version:'NAV 8.0',build:'42951',size:'608003728',credate:'9\x2f28\x2f2015 7\x3a49\x3a32 PM',moddate:'9\x2f28\x2f2015 7\x3a49\x3a32 PM'},{fixid:'487516',product:'Dynamics NAV 2015',language:'Italian',langcode:'ITA',platform:'x86',release:'latest',filename:'ITKB3097767',version:'NAV 8.0',build:'42951',size:'612595808',credate:'9\x2f28\x2f2015 7\x3a49\x3a25 PM',moddate:'9\x2f28\x2f2015 7\x3a49\x3a25 PM'},{fixid:'487514',product:'Dynamics NAV 2015',language:'English',langcode:'ENU',platform:'x86',release:'latest',filename:'GBKB3097767',version:'NAV 8.0',build:'42951',size:'606916096',credate:'9\x2f28\x2f2015 7\x3a49\x3a17 PM',moddate:'9\x2f29\x2f2015 4\x3a18\x3a58 AM'},{fixid:'487515',product:'Dynamics NAV 2015',language:'Icelandic',langcode:'ISL',platform:'x86',release:'latest',filename:'ISKB3097767',version:'NAV 8.0',build:'42951',size:'605359816',credate:'9\x2f28\x2f2015 7\x3a49\x3a20 PM',moddate:'9\x2f28\x2f2015 7\x3a49\x3a20 PM'},{fixid:'487522',product:'Dynamics NAV 2015',language:'Swedish',langcode:'SVE',platform:'x86',release:'latest',filename:'SEKB3097767',version:'NAV 8.0',build:'42951',size:'606855512',credate:'9\x2f28\x2f2015 7\x3a49\x3a47 PM',moddate:'9\x2f28\x2f2015 7\x3a49\x3a47 PM'},{fixid:'487523',product:'Dynamics NAV 2015',language:'All \x28Global\x29',langcode:'intl',platform:'x86',release:'latest',filename:'W1KB3097767',version:'NAV 8.0',build:'42951',size:'585937888',credate:'9\x2f28\x2f2015 7\x3a49\x3a50 PM',moddate:'9\x2f28\x2f2015 7\x3a49\x3a50 PM'},{fixid:'487521',product:'Dynamics NAV 2015',language:'Russian',langcode:'RUS',platform:'x86',release:'latest',filename:'RUKB3097767',version:'NAV 8.0',build:'42951',size:'644290376',credate:'9\x2f28\x2f2015 7\x3a49\x3a43 PM',moddate:'9\x2f28\x2f2015 7\x3a49\x3a43 PM'},{fixid:'487519',product:'Dynamics NAV 2015',language:'Norwegian',langcode:'NOR',platform:'x86',release:'latest',filename:'NOKB3097767',version:'NAV 8.0',build:'42951',size:'609653744',credate:'9\x2f28\x2f2015 7\x3a49\x3a35 PM',moddate:'9\x2f28\x2f2015 7\x3a49\x3a35 PM'},{fixid:'487520',product:'Dynamics NAV 2015',language:'English',langcode:'ENU',platform:'x86',release:'latest',filename:'NZKB3097767',version:'NAV 8.0',build:'42951',size:'609275384',credate:'9\x2f28\x2f2015 7\x3a49\x3a39 PM',moddate:'9\x2f28\x2f2015 8\x3a32\x3a46 PM'},{fixid:'487507',product:'Dynamics NAV 2015',language:'German',langcode:'DEU',platform:'x86',release:'latest',filename:'CHKB3097767',version:'NAV 8.0',build:'42951',size:'655613104',credate:'9\x2f28\x2f2015 7\x3a48\x3a51 PM',moddate:'10\x2f1\x2f2015 2\x3a39\x3a46 PM'},{fixid:'487508',product:'Dynamics NAV 2015',language:'Czech',langcode:'CSY',platform:'x86',release:'latest',filename:'CZKB3097767',version:'NAV 8.0',build:'42951',size:'624144776',credate:'9\x2f28\x2f2015 7\x3a48\x3a56 PM',moddate:'9\x2f28\x2f2015 7\x3a48\x3a56 PM'},{fixid:'487506',product:'Dynamics NAV 2015',language:'Dutch',langcode:'NLD',platform:'x86',release:'latest',filename:'BEKB3097767',version:'NAV 8.0',build:'42951',size:'622646752',credate:'9\x2f28\x2f2015 7\x3a48\x3a48 PM',moddate:'9\x2f28\x2f2015 7\x3a48\x3a48 PM'},{fixid:'487504',product:'Dynamics NAV 2015',language:'German',langcode:'DEU',platform:'x86',release:'latest',filename:'ATKB3097767',version:'NAV 8.0',build:'42951',size:'610973312',credate:'9\x2f28\x2f2015 6\x3a38\x3a52 PM',moddate:'9\x2f28\x2f2015 6\x3a38\x3a52 PM'},{fixid:'487505',product:'Dynamics NAV 2015',language:'English',langcode:'ENU',platform:'x86',release:'latest',filename:'AUKB3097767',version:'NAV 8.0',build:'42951',size:'610658640',credate:'9\x2f28\x2f2015 7\x3a48\x3a44 PM',moddate:'9\x2f28\x2f2015 11\x3a09\x3a54 PM'},{fixid:'487512',product:'Dynamics NAV 2015',language:'Finnish',langcode:'FIN',platform:'x86',release:'latest',filename:'FIKB3097767',version:'NAV 8.0',build:'42951',size:'606309680',credate:'9\x2f28\x2f2015 7\x3a49\x3a11 PM',moddate:'9\x2f28\x2f2015 7\x3a49\x3a11 PM'},{fixid:'487513',product:'Dynamics NAV 2015',language:'French',langcode:'FRA',platform:'x86',release:'latest',filename:'FRKB3097767',version:'NAV 8.0',build:'42951',size:'609121416',credate:'9\x2f28\x2f2015 7\x3a49\x3a14 PM',moddate:'9\x2f28\x2f2015 7\x3a49\x3a14 PM'},{fixid:'487511',product:'Dynamics NAV 2015',language:'Spanish',langcode:'ESN',platform:'x86',release:'latest',filename:'ESKB3097767',version:'NAV 8.0',build:'42951',size:'613276696',credate:'9\x2f28\x2f2015 7\x3a49\x3a07 PM',moddate:'9\x2f28\x2f2015 7\x3a49\x3a07 PM'},{fixid:'487509',product:'Dynamics NAV 2015',language:'German',langcode:'DEU',platform:'x86',release:'latest',filename:'DEKB3097767',version:'NAV 8.0',build:'42951',size:'611123920',credate:'9\x2f28\x2f2015 7\x3a49\x3a00 PM',moddate:'9\x2f28\x2f2015 7\x3a49\x3a00 PM'},{fixid:'487510',product:'Dynamics NAV 2015',language:'Danish',langcode:'DAN',platform:'x86',release:'latest',filename:'DKKB3097767',version:'NAV 8.0',build:'42951',size:'609013152',credate:'9\x2f28\x2f2015 7\x3a49\x3a03 PM',moddate:'9\x2f28\x2f2015 7\x3a49\x3a03 PM'}]"
 
[regex]$pattern = 'hfList = (\[.+\}\])'
$matches = $pattern.Matches($hfList)
if (!$matches)
{
    Write-Error -Message 'list of hotfixes not found!'
    return
}

Write-Host -Object 'Converting Json with updates' -ForegroundColor Green
$hotfixes = $matches.Groups[1].Value.Replace('\x','') | ConvertFrom-Json
Write-Host -Object "Searching for update for language $CountryCode" -ForegroundColor Green

$hotfix = $hotfixes | Where-Object -FilterScript {
    $_.filename -like "$($CountryCode)*"
}

if (!$hotfix) {
    $hotfix = $hotfixes | Where-Object -FilterScript {
        $_.langcode -like "$($CountryCode)*"
    }
}
Write-Host -Object 'Creating hotfix URL' -ForegroundColor Green
Write-Host "Complete Link Information: $hotfix"
               
$url = "http://hotfixv4.microsoft.com/$($hotfix.product)/$($hotfix.release)/$($hotfix.filename)/$($hotfix.build)/free/$($hotfix.fixid)_$($hotfix.langcode)_i386_zip.exe"

Write-Host -Object "Hotfix URL is $url" -ForegroundColor Green

Wenn man das komplett in die PowerShell ISE kopiert und F5 drückt, kommt sofort eine vollständige URL als Ergebnis:
Hotfix URL is http://hotfixv4.microsoft.com/Dynamics NAV 2015/latest/DEKB3097767/42951/free/487509_DEU_i386_zip.exe

Re: Get-NAVCumulativeUpdateFile (Waldo/Kine)

17. Dezember 2015 01:04

Hallo,

ich hab das Skript noch mal angeschaut und ein wenig überarbeitet, und es funktioniert bei mir jetzt. Das Problem scheint das öffnen der Downloadpage zu sein, hier ist der IE nicht sofort busy, und das Skript läuft weiter und findet nichts.
Desweiteren habe ich die Anmeldung entfernt, die ist für den Download nicht nötig.

Manchmal kommt noch die "Copyright Akzeptanz"- Meldung, ob die jetzt noch richtig abgefangen wird bzw. ob das Skript danach richtig weiter läuft, konnte ich leider nicht prüfen.

Code:
    #requires -Version 3 -Modules BitsTransfer
    #Author: Kamil, based on ideas from waldo (who had it developed in .Net) :-)
    <#
        .Synopsis
        Download the Cumulative Update File for specified NAV version and localization
        .DESCRIPTION
        Download the Cumulative Update File for specified NAV version and localization, with possibility to
        select specific cumulative update
        .EXAMPLE
        Get-NAVCumulativeUpdateFile -CountryCodes 'intl','CSY' -versions '2013 R2','2015','2016'
        .EXAMPLE
        Get-NAVCumulativeUpdateFile -CountryCodes 'CSY' -versions '2013 R2' -CUNo 23
        .OUTPUT
        Objects with info about the downloaded cumulative updates
    #>
    function Get-NAVCumulativeUpdateFile
    {
        param (
            [Parameter(Mandatory,ValueFromPipelineByPropertyName)]
            $CountryCodes = 'W1',
            [Parameter(Mandatory,ValueFromPipelineByPropertyName)]
            $versions = '2016',
            [Parameter(ValueFromPipelineByPropertyName)]
            $CUNo = '',
            [Parameter(ValueFromPipelineByPropertyName)]
            $DownloadFolder = $env:TEMP
        )

        begin {
            $ie = New-Object -ComObject 'internetExplorer.Application'       
            $ie.Visible = $false
        }
        process
        {
            foreach ($CountryCode in $CountryCodes)
            {
                foreach ($version in $versions)
                {
                    $url = ''
                   
                    Write-Host -Object "Processing parameters $CountryCode $version $CUNo" -ForegroundColor Cyan
           
                    $feedurl = 'https://blogs.msdn.microsoft.com/nav/category/announcements/cu/feed/'
                    [regex]$titlepattern = 'Cumulative Update (\d+) .*'

                    Write-Host -Object 'Searching for RSS item' -ForegroundColor Green

                    $feed = [xml](Invoke-WebRequest -Uri $feedurl)

                    if ($CUNo -gt '')
                    {
                        $blogurl = $feed.SelectNodes("/rss/channel/item[./category='NAV $version' and ./category='Cumulative Updates' and contains(./title,'$CUNo')]").link | Select-Object -First 1
                    } else
                    {
                        $blogurl = $feed.SelectNodes("/rss/channel/item[./category='NAV $version' and ./category='Cumulative Updates']").link | Select-Object -First 1
                    }

                    if (!$blogurl)
                    {
                        Write-Error -Message 'Blog url not found!'
                        return
                    }

                    Write-Host -Object "Reading blog page $blogurl" -ForegroundColor Green
                   
                    $blogarticle = ''
                    #$blogarticle = Invoke-WebRequest -Uri $blogurl
                    $null = $ie.Navigate($blogurl)
                    while ($ie.Busy -eq $true)
                    {
                        $null = Start-Sleep -Seconds 1
                    }
                   
                    Write-Host -Object 'Searching for KB link' -ForegroundColor Green
                                   
                    $titlematches = $titlepattern.Matches($ie.Document.title)
                    $updateno = $titlematches.Groups[1]

                    #$kblink = $blogarticle.Links | Where-Object -FilterScript {
                    $kblink = $ie.Document.links | Where-Object -FilterScript {
                        Write-Verbose "Link: $($_.href) id: $($_.id)"
                        $_.innerText -match 'KB'
                    }
                     
                             $kbno = ($kblink.href -split ';')[2]
                   
                              Write-Host -Object "Opening KB link $($kbno)" -ForegroundColor Green
                              Write-Host -Object "https://support.microsoft.com/de-de/hotfix/kbhotfix?kbnum=$kbno&kbln=en-us&sd=mbs" -ForegroundColor Yellow
                    $null = $ie.Navigate("https://support.microsoft.com/de-de/hotfix/kbhotfix?kbnum=$kbno&kbln=en-us&sd=mbs")
                    $null = Start-Sleep -Seconds 5 ## hier ist das Problem##########
                    while ($ie.Busy -eq $true)
                    {
                        $null = Start-Sleep -Seconds 1
                    }
                    Write-Host -Object 'Searching for Accept button' -ForegroundColor Green

                    $button = $ie.Document.IHTMLDocument3_getElementsByName('accept')

                    if ($button.id)
                    {
                        Write-Host -Object 'Clicking Accept button' -ForegroundColor Green
                        $null = $button.click()
                        while ($ie.Busy -eq $true)
                        {
                            $null = Start-Sleep -Seconds 1
                        }   
                    }

                    Write-Host -Object 'Searching for list of updates' -ForegroundColor Green
                    $pattern = [regex] "hfList = (\[.*\}\])"
                    $matches = $pattern.Matches($ie.Document.body.innerText)
                    if (!$matches)
                    {
                        Write-Error -Message 'list of hotfixes not found!'
                        return
                    }
                              #Write-Host -Object "xx:$($matches.Groups[1].Value):xx"
                    Write-Host -Object 'Converting Json with updates' -ForegroundColor Green
                    $hotfixes = $matches.Groups[1].Value.Replace('\x','') | ConvertFrom-Json

                    #URL examples:
                    #http://hotfixv4.microsoft.com/Dynamics NAV 2016/latest/W1KB3106089/43402/free/488130_intl_i386_zip.exe
                    #http://hotfixv4.microsoft.com/Dynamics NAV 2015/latest/CZKB3106088/43389/free/488059_CSY_i386_zip.exe

                    Write-Host -Object "Searching for update for language $CountryCode" -ForegroundColor Green

                    $hotfix = $hotfixes | Where-Object -FilterScript {
                        $_.filename -like "$($CountryCode)*"
                    }

                    if (!$hotfix) {
                        $hotfix = $hotfixes | Where-Object -FilterScript {
                            $_.langcode -like "$($CountryCode)*"
                        }
                    }
                    Write-Host -Object 'Creating hotfix URL' -ForegroundColor Green

                    $url = "http://hotfixv4.microsoft.com/$($hotfix.product)/$($hotfix.release)/$($hotfix.filename)/$($hotfix.build)/free/$($hotfix.fixid)_$($hotfix.langcode)_i386_zip.exe"

                    Write-Host -Object "Hotfix URL is $url" -ForegroundColor Green

                    $filename = (Join-Path -Path $DownloadFolder -ChildPath "$($hotfix.fixid)_$($hotfix.langcode)_i386_zip.exe")
                    Write-Host -Object "Downloading hotfix to $filename" -ForegroundColor Green
       
                    if (-not (Test-Path $filename))
                    {
                        $null = Start-BitsTransfer -Source $url -Destination $filename
                    }
       
                    Write-Host -Object 'Hotfix downloaded' -ForegroundColor Green
                    $null = Unblock-File -Path $filename

                    $result = New-Object -TypeName System.Object
                    $null = $result | Add-Member -MemberType NoteProperty -Name filename -Value "$filename"
                    $null = $result | Add-Member -MemberType NoteProperty -Name version -Value "$version"
                    $null = $result | Add-Member -MemberType NoteProperty -Name CUNo -Value "$updateno"
                    $null = $result | Add-Member -MemberType NoteProperty -Name CountryCode -Value "$CountryCode"
                    $null = $result | Add-Member -MemberType NoteProperty -Name langcode -Value "$($hotfix.langcode)"
                           
                    Write-Output -InputObject $result
                }
            }       
        }
        end {
            $null = $ie.Quit()
        }
    }


EDIT:Da wir uns für den Download nicht anmelden müssen, muss der IE auch nicht mehr sichtbar sein.

Gruß Fiddi

Re: Get-NAVCumulativeUpdateFile (Waldo/Kine)

17. Dezember 2015 10:03

Fiddi's neueste Variante läuft bei mir nun auch korrekt durch. Anscheinend ist in Norddeutschland ein etwas anderer Code notwendig, um Daten von Webseiten abzusaugen :mrgreen: .
BITS.png

GetCUupdateSuccess.png
Du hast keine ausreichende Berechtigung, um die Dateianhänge dieses Beitrags anzusehen.

Re: [Gelöst] Get-NAVCumulativeUpdateFile (Waldo/Kine/Fiddi)

19. August 2016 15:16

Geht es nur mir so, oder funktioniert das Script bei euch auch nicht?

Re: [Gelöst] Get-NAVCumulativeUpdateFile (Waldo/Kine/Fiddi)

19. August 2016 15:19

m_schneider hat geschrieben:Geht es nur mir so, oder funktioniert das Script bei euch auch nicht?

Meinst du damit schon das hier?
Kowa hat geschrieben:Edit: Aktueller Skriptcode bei GitHub: Cloud.Ready.Software.NAV/Upgrade/Get-NAVCumulativeUpdateFile.ps1

Re: [Gelöst] Get-NAVCumulativeUpdateFile (Waldo/Kine/Fiddi)

19. August 2016 15:26

Ich meinte fiddis Variante. Die hatte nämlich bei mir mal funktioniert.

Edit:
Die Github Variante funktioniert allerdings auch nicht.
Du hast keine ausreichende Berechtigung, um die Dateianhänge dieses Beitrags anzusehen.

Re: [Gelöst] Get-NAVCumulativeUpdateFile (Waldo/Kine/Fiddi)

19. August 2016 16:30

jup, same here

Re: [Gelöst] Get-NAVCumulativeUpdateFile (Waldo/Kine/Fiddi)

20. August 2016 09:32

Hallo,

bei mir hat es nach einem Fehlversuch wieder funktioniert. Das könnte aber auch daran Liegen, das ich den Versuch einmal manuell im IE gestartet habe, und danach das Skript probiert habe.

Dabei habe ich im IE die Liezenz- Bedingung- Akzeptieren- Meldung manuell angeklickt, um weitermachen zu können. Das versucht das Skript auch zu tun. Wenn der Button jetzt aber nicht mehr "accept" heißt sondern irgendwie anders, läuft das Skript auf einen Fehler, weil es die Download- Daten auf der falschen Seite sucht.

Im Skript gibt es einen Bereich, der nach diesem Button sucht:
Code:
                        $button = $ie.Document.IHTMLDocument3_getElementsByName('accept')   <<<<<<<----- Heißt der Button noch accept?

                        if ($button.id)
                        {
                            Write-Host -Object 'Clicking Accept button' -ForegroundColor Green
                            $null = $button.click()
                            while ($ie.Busy -eq $true)
                            {
                                $null = Start-Sleep -Seconds 1
                            }   
                        }


Da bei mir die "Akzeptiren"- Abfrage nicht mehr kommt, kann ich jetzt nicht prüfen, ob der Button evtl. anders benannt wurde. Dafür benötige ich den Seitenquelltext eben dieser Seite, um herauszufinden, wie der Button jetzt heißt. Wenn also jemand den Download manuell versucht, und diese Meldung bekommt, dann bitte den Seiten-Quelltext speichern, und nach dem Namen des "Akzeptieren"- Buttons suchen, und dann das Skript anpassen.

Gruß Fiddi

Re: [Gelöst] Get-NAVCumulativeUpdateFile (Waldo/Kine/Fiddi)

20. August 2016 13:51

Soweit kommt das Skript bei mir gar nicht. Er erkennt das Fenster des Internet Explorers gar nicht.
Edit:
folgender Code sollte eigentlich den Titel ausgeben. Macht er aber nicht. Mit der Adresse "www.google.de" geht es. Komisch.
Code:
$ie = new-object -com internetexplorer.application
$ie.navigate('blogs.msdn.microsoft.com/nav/2016/08/08/cumulative-update-10-for-microsoft-dynamics-nav-2016-has-been-released/')
while ($ie.busy -eq $true)
{
    Start-Sleep -Milliseconds 600
}
$ie.document.title


Edit2:

Ich habe meinen Fehler gefunden. Man darf die Domäne der Seite in den Sicherheitseinstellungen in die "vertrauenswürdigen Sites" zuordnen.

Der Button heißt noch accept. Allerdings funktioniert es trotzdem nicht.

Re: [Gelöst] Get-NAVCumulativeUpdateFile (Waldo/Kine/Fiddi)

20. August 2016 22:03

Hallo,

habe das Skript nochmal überarbeitet.

Gruß Fiddi
Du hast keine ausreichende Berechtigung, um die Dateianhänge dieses Beitrags anzusehen.

Re: [Gelöst] Get-NAVCumulativeUpdateFile (Waldo/Kine/Fiddi)

22. August 2016 10:17

fiddi hat geschrieben:...Im Skript gibt es einen Bereich, der nach diesem Button sucht:
Code:
                        $button = $ie.Document.IHTMLDocument3_getElementsByName('accept')   <<<<<<<----- Heißt der Button noch accept?

                        if ($button.id)
                        {
                            Write-Host -Object 'Clicking Accept button' -ForegroundColor Green
                            $null = $button.click()
                            while ($ie.Busy -eq $true)
                            {
                                $null = Start-Sleep -Seconds 1
                            }   
                        }

...


Ich stelle nun mal eine kühne These auf:
Der Bereich des Skriptes hat noch nie funktioniert. Die Methode "Click" ist dem System nicht bekannt und "if ($button.id)" ist ebenfalls immer $false.

Nachdem ich nun einmal händisch auf akzeptieren geklickt habe funktioniert es auch wieder. Da ich meine Cookies letztens mal gelöscht hatte, war die Einstellung weg.

Vielen Dank für eure Hilfe...