Click here to Skip to main content
13,007,176 members (62,669 online)
Click here to Skip to main content
Add your own
alternative version

Tagged as


3 bookmarked
Posted 15 Apr 2014

Download #MVA Content with PowerShell

, 15 Apr 2014
Rate this:
Please Sign up or sign in to vote.
How to download #MVA content with PowerShell

image_thumb2So I'm starting to go through some of the content on Microsoft Virtual Academy but I don't have time to do this when I'm by a good internet connection and at the same time don't have time when by the good internet connection to run though all the content I need to download it to watch in my spare time.

Enter PowerShell Smile

As with any scenario like this, you turn to code. I used to create all these types of functionality in C# apps but have recently decided that it's too easy in C# and wanted to learn PowerShell better so now these are all PowerShell scripts.

The Code

There are 2 files.


#source -
#changed slightly for MSVA script

Function Remove-InvalidFileNameChars {
    This is a PowerShell function to remove invalid characters from strings to be used as file names.

    The function takes a string parameter called Name and returns a string 
    that has been stripped of invalid file name characters, i.e. *, :, \, /.  
    The Name parameter will also receive input from the pipeline.

    Specifies the file name to strip of invalid characters.

    Parameter Name accepts System.String objects from the pipeline.

    System.String.  Outpus a string object

    Remove-InvalidFileNameChars -Name "<This/name\is*an:illegal?filename>"
    PS C:\>Thisnameisanillegalfilename

    It would be easiest to copy the function from the script file and place it in your profile. 
    However, you may also dot-source the script to load the function into PowerShell:
    i.e. PS C:\>. .\Remove-InvalidFileNameChars.ps1



    $result = [RegEx]::Replace($Name, "[{0}]" -f ([RegEx]::Escape
    ([String][System.IO.Path]::GetInvalidFileNameChars())), '')
    $result = $result.Replace("Microsoft-Virtual-Academy", "")
        $result = $result.Replace("--", "-")

    return $result.Trim("-")



Write-Output ""
Write-Output ""
Write-Output ""
Write-Output ""
Write-Output ""
Write-Output ""
Write-Output ""
Write-Output ""
Write-Output ""
Write-Output ""
Write-Output "Starting"

$certPages = $("mcsd-application-lifecycle-management",
$baseSaveLocation = "Z:\Learning\Microsoft Virtual Academy"

$pathToRemoveInvalidFileNameCharsScript = "$baseSaveLocation\Remove-InvalidFileNameChars.ps1"

#------------Don't edit below here----------------#

. "$pathToRemoveInvalidFileNameCharsScript"    
foreach($certPage in $certPages)
    Write-Output "Downloading Page: $certUrl"
    $pageHtml=invoke-webrequest -uri $certUrl
    $certPage.Replace(" ","-"))"

    if (!(Test-Path $destination)) {
        New-Item -ItemType directory -Path $destination
    $filteredLinks = $pageHtml.Links | Where-Object 
    { $_.href.ToLower().StartsWith("") } 

    foreach($link in $filteredLinks)
        Write-Output "Downloading Page: $($link.href)"
        $trainingPageHtml=invoke-webrequest -uri $link.href        
        [string]$trainingTitle = $trainingPageHtml.AllElements | Where-Object 
        { $_.tagName.ToLower().StartsWith("title") } | Select-Object -ExpandProperty innerText {$_}
        $trainingTitle = $trainingTitle.Trim()
        $(Remove-InvalidFileNameChars $trainingTitle.Replace(" ","-"))"

        if (!(Test-Path $trainingDestination)) {
            New-Item -ItemType directory -Path $trainingDestination

        $idEducationTypePattern = [regex]"parent='(?<idEducationType>[^']*)'"
        [int]$idEducationType = $idEducationTypePattern.Match
        $jsonPostDataPattern = [regex]'showNextPanelEducationTypes
        foreach($jsonPostData in $jsonPostDataPattern.Matches($trainingPageHtml.Content))

            [int]$idEducationTypeSelected = $jsonPostData.Groups
            [int]$idEducationLevelSelected = $jsonPostData.Groups["idEducationLevelSelected"].Value
            [int]$numControl = $jsonPostData.Groups["numControl"].Value
            $isApproved = $jsonPostData.Groups["isApproved"].Value
            $jsonPostUri = "
            $jsonPostBody = @{
                    idEducationTypeSelected = "$idEducationTypeSelected";
                    idEducationLevelSelected = $idEducationLevelSelected;
                    isSubscribe = $true;
                    selectedIsEnabled = "true";
                    numControl = $numControl;
                    idEducationType = "$idEducationType";
                    isApproved = "$isApproved";
                 }| ConvertTo-Json 

            $jsonInvokeResult = Invoke-RestMethod -Method Post -Uri $jsonPostUri 
            -ContentType "application/json" -Body $jsonPostBody 
            $ctIDPattern = [regex]'openEmbeddedVideo((?<Id>.+));'
            foreach($ctID in $ctIDPattern.Matches($jsonInvokeResult.d.HtmlResponseMaterials))
                $Id = $ctID.Groups["Id"].Value.TrimStart("(").Split(',')[0]
                $uriForTrainingVideo = 
                Write-Output "Downloading Page: $uriForTrainingVideo"

                $trainingVideoPageHtml=invoke-webrequest -uri $uriForTrainingVideo
                [string]$trainingVideoTitle = $trainingVideoPageHtml.AllElements | 
                Where-Object { $_.tagName.ToLower().StartsWith("title") } | 
                Select-Object -ExpandProperty innerText {$_} 
                $trainingVideoTitle = $trainingVideoTitle.Trim()
                [string]$videoMp4Link = $trainingVideoPageHtml.Links | Where-Object 
                {$_.href.EndsWith(".mp4") -and $_.outerText -eq "MP4"} | 
                Select-Object -ExpandProperty href {$_} 
                $urlFileName = $($videoMp4Link.split("/")[-1])
                $videoMp4LocalFullName = "$($trainingDestination +"\" + 
                $(Remove-InvalidFileNameChars $trainingVideoTitle.Replace(" ","-"))).mp4"

                if(!(Test-Path ($videoMp4LocalFullName))) 
                    Write-Output "Downloading Video: $trainingVideoTitle to $videoMp4LocalFullName"
                    Start-BitsTransfer "$videoMp4Link" $videoMp4LocalFullName

Write-Output "Done"


  • $baseSaveLocation - Set this to the location you want to save the videos to
  • $certPages - This is an array of certification page names that you want to download content from, i.e.: for MCSD: Application Lifecycle Management which has a url, the page name would be mcsd-application-lifecycle-management. Note that you will exclude the extension.
  • $pathToRemoveInvalidFileNameCharsScript - This can stay the same unless you have placed the first script in a different location from the base location.

Next Steps

The next steps for this script will be to try and get it to download the PowerPoint slides for each video. Currently, you need to be logged in to download slides, so this might not be ready for a while. Smile


This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


About the Author

Gordon Beeming (RSA)
Software Developer Nologo Studios
South Africa South Africa
Gordon Beeming works at Nologo Studios in the sunny city of Durban, South Africa. His current focus is on Devloper Efficiencies and R&D. When he's not hacking away at a keyboard in Visual Studio he'll generally be relaxing with his family or hitting the black top getting in some mileage. He is a Visual Studio ALM Rangers, Visual Studio ALM MVP.

You may also be interested in...


Comments and Discussions

-- There are no messages in this forum --
Permalink | Advertise | Privacy | Terms of Use | Mobile
Web02 | 2.8.170628.1 | Last Updated 16 Apr 2014
Article Copyright 2014 by Gordon Beeming (RSA)
Everything else Copyright © CodeProject, 1999-2017
Layout: fixed | fluid