Install Visual C++ Redistributable applications with PowerShell in MDT

Creating the perfect reference image is a time consuming task and there’s always something to tune. Over the years I’ve used various scripts and wrappers created by community members to improve the reference image creation process, in addition to a bunch of scripts that I’ve made myself. With Windows 10, more and more organizations are looking to deploy the new version and for that you’ll need a reference image. Reference images can be thick, thin or “optimal”, but in my experience there are always some sort of application baseline that you end up including in the image. Visual C++ Redistributable files are a perfect example of such baseline applications.

From time to time, Microsoft releases a new Visual C++ version that we want to include in the reference image. There are many great community scripts out there to both download and install these for and during the reference image creation process, using either MDT or ConfigMgr. But I wanted to create a script that would be dynamic in terms that you’d not have to amend the script every time a new Visual C++ redistributable was released (to be frank, it doesn’t happen very often). I also like to make things what I call future proof, meaning that you should not have to amend the solution in place, rather add new content.

With this set in mind, I’ve (finally) written a PowerShell script that is able to enumerate a Source folder for containing the desired Visual C++ executables that should be included in the reference image. Below you’ll find the code, save it as Install-VisualCRedist.ps1 or jump over to my GitHub repository and download the script from there in MDT\Reference Image.


    Dynamically install Microsoft Visual C++ Redistributables by architecture 

    This script will install Microsoft Visual C++ Redistributables by specified architecture. 
    It requires a supported folder layout e.g. like the following: 

    Place the script in the same folder where you create the 'Source' folder. The 'Source' folder is hard-coded 
    into the script and cannot be named something else. If the source folder does not exist, the script will fail. 
    There's a requirement of either x86 or x64 in the sub-folder names, or the script will fail as well. 
    Desired executables for each version and architecture should be placed in the supported sub-folders. 

.PARAMETER Architecture 
    Select desired architecture to install Visual C++ applications on. You can specify both x86 and x64 as a string array. 

.PARAMETER ShowProgress 
    Show a progressbar displaying the current operation. 

    Install Visual C++ Redistributables for both x86 and x64 architectures, in addition to show the current progress: 
    .\Install-VisualCRedist.ps1 -Architecture x86, x64 -ShowProgress 

    Script name: Install-VisualCRedist.ps1 
    Author:      Nickolaj Andersen 
    Contact:     @NickolajA 
    DateCreated: 2016-02-29 
    [parameter(Mandatory=$true, HelpMessage="Select desired architecture to install Visual C++ applications on. You can specify both x86 and x64 as a string array.")]
    [string[]]$Architecture = "x86, x64",
    [parameter(Mandatory=$false, HelpMessage="Show a progressbar displaying the current operation.")]
    [switch]$ShowProgress = $true
Process {
    # Functions
    function Install-ApplicationExectuable {
        if ($Script:PSBoundParameters["ShowProgress"]) {
            $ProgressCount = 0
        # Determine application executable list
        $ApplicationExecutableFolders = Get-ChildItem -LiteralPath $CurrentWorkingDirectory -Filter "*$($ApplicationArchitecture)*" | Select-Object -ExpandProperty FullName
        # Validate that the Source directory is not empty
        if ($ApplicationExecutableFolders -ne $null) {
            $ApplicationExecutableFolderCount = ($ApplicationExecutableFolders | Measure-Object).Count
            foreach ($ApplicationExecutableFolder in $ApplicationExecutableFolders) {
                $CurrentApplicationPath = Get-ChildItem -LiteralPath $ApplicationExecutableFolder | Select-Object -ExpandProperty FullName
                # Validate executable count
                if (($CurrentApplicationPath | Measure-Object).Count -eq 1) {
                    # Validate that executable file exists
                    if (($CurrentApplicationPath -ne $null) -and ([System.IO.Path]::GetExtension((Split-Path -Path $CurrentApplicationPath -Leaf)) -like ".exe")) {
                        $CurrentFileDescription = (Get-Item -LiteralPath $CurrentApplicationPath | Select-Object -Property VersionInfo).VersionInfo.FileDescription
                        if ($Script:PSBoundParameters["ShowProgress"]) {
                            Write-Progress -Activity "Installing Microsoft Visual C++ Redistributables ($($ApplicationArchitecture))" -Id 1 -Status "$($ProgressCount) / $($ApplicationExecutableFolderCount)" -CurrentOperation "Installing: $($CurrentFileDescription)" -PercentComplete (($ProgressCount / $ApplicationExecutableFolderCount) * 100)
                        Write-Verbose -Message "Installing: $($CurrentFileDescription)"
                        # Install the current executable
                        $ReturnValue = Start-Process -FilePath $CurrentApplicationPath -ArgumentList "/q /norestart" -Wait -PassThru
                        if (($ReturnValue.ExitCode -eq 0) -or ($ReturnValue.ExitCode -eq 3010)) {
                            Write-Verbose -Message "Successfully installed: $($CurrentFileDescription)"
                        else {
                            Write-Verbose -Message "Failed to install: $($CurrentFileDescription)"
                    else {
                        Write-Warning -Message "Unsupported file extension found in folder: $($ApplicationExecutableFolder)"
                else {
                    Write-Warning -Message "Skipping folder due to unsupported number of files in: $($ApplicationExecutableFolder)"
            if ($Script:PSBoundParameters["ShowProgress"]) {
                Write-Progress -Activity "Installing Microsoft Visual C++ Redistributables ($($ApplicationArchitecture))" -Id 1 -Completed -Status "Completed"

    # Install Microsoft Visual C++ Redistributables
    foreach ($Arch in $Architecture) {
        Install-ApplicationExectuable -ApplicationArchitecture $Arch -CurrentWorkingDirectory (Join-Path -Path (Split-Path -Path $MyInvocation.MyCommand.Definition -Parent) -ChildPath "\Source")

Using the script in MDT

I’m gonna show you an example of how we can leverage this script, with the desired Visual C++ redistributables already downloaded, as an Application in MDT 2013. In this example we’ll be including Visual C++ redistributables for both x86 and x64. You’ll need

1. Either save the script from above, or download it from my GitHub repository and place it in e.g. C:\SourceFiles\Apps\Install – Visual C++ Redistributables, or wherever you store source files for importing an application in MDT. Create a folder called Source in the same folder where you placed the PowerShell script, like shown below:

2. As you may already have read in the description of the script itself, you need to create a certain folder structure in the Source folder for the script to function properly. This structure is a no brainer, simply create a structure like show below for each Visual C++ redistributable and place it on the corresponding folder:

It’s important that you at least include the correct architecture in each folder name, like in the screenshot above, since it’s a requirement for the script.

3. Open the Deployment WorkBench, right click on Applications and select New Application.
4. Select Application with source files and click Next.
5. In the Application Name field, enter a suitable name e.g. Install – Visual C++ Redistributables and click Next.
6. Browse to the location where you’ve saved the script file and create the required folder structure, in my example that would be C:\SourceFiles\Apps\Install – Visual C++ Redistributables and click Next.
7. Click Next on the Destination page.
8. As the Quiet install command, enter the following:

powershell.exe -ExecutionPolicy ByPass -Command "& .\Install-VisualCRedist.ps1 -Architecture 'x64','x86' -ShowProgress -Verbose"

Note the double and single quotations in the above command line. Click Next.
9. On the Summary page, click Next.
10. Click Finish.

You can now add the application in your task sequence, e.g. like shown below:


By implementing this script in your reference image creation process, you’ll simplify how Visual C++ redistributables are installed and in the long run give you a more dynamic approach. Just to give you an overview of how the script looks in action, I’ve recorded a short video of it running in my lab environment:

Let me know if you have any questions by leaving a comment below.


  1. kitaab

    Thank you , this is great,

    Could you share other scripts/tasks/suggestions that you adhere to when you prepare the reference image.

    1. NickolajNickolaj (Post author)

      Hi kitaab,

      I’ll be posting my Remove Built-in Apps script in the near future. Are there any other steps that you were thinking about?


  2. Marc Westerink

    Seriously Nickolaj,

    This is great stuff, it really takes the pain away of installing all the redistributables.

    Unfortunately, a few runtimes (I believe the 2005 ones) gave error messages. I removed the ‘/norestart’ argument in the argumentlist part of your script. After that it ran flawlessly…

    I also noticed that when I downloaded the .ps1 file from GitHub, I got something else than the script itself. So I copied the script from this post to fix it.

    Nevertheless, awesome stuff and keep up the good work.

    1. NickolajNickolaj (Post author)

      Hi Marc,

      I’m glad that you like it. It’s really something that speeds up the process. Good point regarding the 2005 redist, I guess they don’t support that “modern” parameter.

      Have you copied the script from this URL:


      1. Marc Westerink

        Hi Nickolaj,

        I tried to download the script from the link mentioned in the post itself. It is possible that the issue is more PEBKAC related 😉

        I also noticed different behaviour in the script when trying to build and capture a Windows 7 reference image. I followed your blog to the letter. The script asked for pipeline inputs after running the x64 installs. I didn’t get this behaviour at Windows 10.

        I didn’t install any WMF package prior to run this script.

        Is there a PowerShell version requirement for this script?

        Kind regards,


        1. NickolajNickolaj (Post author)

          Hi Marc,

          There seems to have been a slight “bug” in the script where the Write-Progress cmdlet used for completing the current progress required the -Status parameter on PowerShell 2.0. I’ve now updated the script and tested it on a Windows 7 SP1 system with PowerShell 2.0, where it worked fine. Let me know if you still run into any issues.


  3. Pingback: Install Visual C++ Redistributable applications with PowerShell in MDT | System Center ConfigMgr | Skatterbrainz Blog

Leave a Comment

Your email address will not be published. Required fields are marked *