How-To: Install your apps, modules and settings the easy way

MVP

Whenever I reinstall my Windows laptop (Or a new management VM), I have a lot of apps, modules, RSAT Tools, Sysinternals tools  and settings that need to be installed or configured. So... Let's automate that :) Below are my installation scripts which you can use to install everything, or just the programs or perhaps just the PowerShell modules. Options are there to do so and you can add/remove things in the JSON file easily and let it run again. Just put the three files in one location, run install.cmd as Administrator and lean back...

Shortcuts for newly installed software will be removed from your desktop, hate those ;) , and programs that start automatically after installing will be closed. Be aware of the fact that your machine might restart during installation, save your work and you can re-run the script to continue installing the rest (It will check and skip things that are already installed)

Install.cmd 

 

 

@echo off
TITLE Installing Apps, Features and PowerShell Modules...
echo Your computer might restart, please save your work before continuing!
echo After restart, you can restart this script to finish installation
pause
powershell -executionpolicy bypass -noprofile -file "%~dp0install_apps.ps1" -All
echo Logging is available in %Temp%\Install.log
echo Press any to update installed apps or CTRL-C to exit and then reboot your system manually
pause
winget upgrade --all --silent --force
echo. 
echo Done updating, press any key to quit and reboot your system manually
pause

 

 

 

Install_Apps.ps1

 

 

<#
.SYNOPSIS

Installs Programs, Modules, Features and settings using Winget and PowerShell

.DESCRIPTION

Installs/Configures all options from the .json file

.PARAMETER All
Install all Programs, Modules, Features and Settings

.PARAMETER Apps
Install all Software

.PARAMETER Features
Install all Windows Features

.PARAMETER MicrosftVCRuntime
Install all Microsoft VC++ Runtimes

.PARAMETER PowerShellCommands
Execute all PowerShell commands like Update-Help

.PARAMETER PowerShellModules
Install all PowerShell Modules

.PARAMETER PowerShellModulesUpdate
Update all installed PowerShell Modules to the latest version

.PARAMETER PowerShellProfile
Update the PowerShell Profile

.PARAMETER RSATTools
Install the Windows Remote System Administration Tools

.PARAMETER $SCCMTools
Install the System Center Configuration Manager tools like CMTrace

.PARAMETER SysInternalsSuite
Install the Windows Remote System Administration Tools

.PARAMETER IntuneWinAppUtil
Install the IntuneWinAppUtil in c:\windows\system32

.INPUTS

Defaults to -All if no other Parameters are specified

.OUTPUTS

Screen output and TransAction log which is available in %Temp%\Install.log

.EXAMPLE

PS> Install_Apps.ps1 -Apps
Installs all Applications

.EXAMPLE

PS> Install_Apps.ps1 -SCCMTools -PowerShellModule
Installs the System Center Configuration Manager Tools and installs all PowerShell Modules

.LINK

None

#>

#Parameters
[CmdletBinding(DefaultParameterSetName = "All")]
param (
    [Parameter(Mandatory = $False, HelpMessage = "Install all Software, Modules, Features and Settings", ParameterSetName = "All")][Switch]$All,
    [Parameter(Mandatory = $false, HelpMessage = "Install all Software", ParameterSetName = "Optional")][Switch]$Apps,
    [Parameter(Mandatory = $false, HelpMessage = "Install all Windows Features", ParameterSetName = "Optional")][Switch]$Features,
    [Parameter(Mandatory = $false, HelpMessage = "Install all Microsoft VC++ Runtimes", ParameterSetName = "Optional")][Switch]$MicrosftVCRuntime,
    [Parameter(Mandatory = $false, HelpMessage = "Execute all PowerShell commands like Update-Help", ParameterSetName = "Optional")][Switch]$PowerShellCommands,
    [Parameter(Mandatory = $false, HelpMessage = "Install all PowerShell Modules", ParameterSetName = "Optional")][Switch]$PowerShellModules,
    [Parameter(Mandatory = $false, HelpMessage = "Update all installed PowerShell Modules to the latest version", ParameterSetName = "Optional")][Switch]$PowerShellModulesUpdate,
    [Parameter(Mandatory = $false, HelpMessage = "Update the PowerShell Profile", ParameterSetName = "Optional")][Switch]$PowerShellProfile,
    [Parameter(Mandatory = $false, HelpMessage = "Install the Windows Remote System Administration Tools", ParameterSetName = "Optional")][Switch]$RSATTools,
    [Parameter(Mandatory = $false, HelpMessage = "Install the System Center Configuration Manager tools like CMTrace", ParameterSetName = "Optional")][Switch]$SCCMTools,
    [Parameter(Mandatory = $false, HelpMessage = "Install all SysInternals Suite tools and add them to the system path", ParameterSetName = "Optional")][Switch]$SysInternalsSuite,
    [Parameter(Mandatory = $false, HelpMessage = "Install the IntuneWinAppUtil to c:\windows\system32", ParameterSetName = "Optional")][Switch]$IntuneWinAppUtil
)
if ($PSCmdlet.ParameterSetName -eq 'All') {
    Write-Host No parameter was specified and using all options -ForegroundColor Green
    $All = $True
}

#Requires -RunAsAdministrator
#Start Transcript logging in Temp folder
Start-Transcript $ENV:TEMP\install.log

#Set-Executionpolicy and no prompting
Set-ExecutionPolicy Bypass -Force:$True -Confirm:$false -ErrorAction SilentlyContinue
Set-Variable -Name 'ConfirmPreference' -Value 'None' -Scope Global

#Change invoke-webrequest progress bar to hidden for faster downloads
$ProgressPreference = 'SilentlyContinue'

#Import list of apps, features and modules that can be installed using json file
$json = Get-Content "$($PSScriptRoot)\Install_apps.json" | ConvertFrom-Json

#Check if Winget is installed, if not install it by installing VCLibs (Prerequisite) followed by Winget itself
if ($Apps -or $MicrosftVCRuntime -or $All) {
    if (!(Get-AppxPackage -Name Microsoft.Winget.Source)) {
        Write-Host Winget was not found and installing now -ForegroundColor Yellow
        Invoke-Webrequest -uri https://aka.ms/Microsoft.VCLibs.x64.14.00.Desktop.appx -Outfile $ENV:TEMP\Microsoft.VCLibs.x64.14.00.Desktop.appx
        Invoke-Webrequest -uri https://aka.ms/getwinget -Outfile $ENV:TEMP\winget.msixbundle    
        Add-AppxPackage $ENV:TEMP\Microsoft.VCLibs.x64.14.00.Desktop.appx -ErrorAction SilentlyContinue
        Add-AppxPackage -Path $ENV:TEMP\winget.msixbundle -ErrorAction SilentlyContinue
    }
}

if ($MicrosftVCRuntime -or $All) {
    #Install Microsoft Visual C++ Runtimes using WinGet
    Write-Host Installing Microsoft Visual C++ Runtime versions but skipping install if already present -ForegroundColor Green
    $CurrentVC = Get-WmiObject -Class Win32_Product -Filter "Name LIKE '%Visual C++%'" -ErrorAction SilentlyContinue | Select-Object Name
    Foreach ($App in $json.MicrosftVCRuntime) {
        Write-Host Checking if $App is already installed...
        if (!($CurrentVC | Select-String $App.split('+')[2].SubString(0, 4) | Select-String $App.split('-')[1])) {
            Write-Host $App was not found and installing now -ForegroundColor Yellow
            winget.exe install $App --silent --force --source winget --accept-package-agreements --accept-source-agreements
        }
    }
}

if ($Apps -or $All) {
    #Install applications using WinGet
    Write-Host Installing Applications but skipping install if already present -ForegroundColor Green
    Foreach ($App in $json.Apps) {
        Write-Host Checking if $App is already installed...
        winget.exe list --id $App --accept-source-agreements | Out-Null
        if ($LASTEXITCODE -eq '-1978335212') {
            Write-Host $App.Split('.')[1] was not found and installing now -ForegroundColor Yellow
            winget.exe install $App --silent --force --source winget --accept-package-agreements --accept-source-agreements
            Foreach ($Application in $json.ProcessesToKill) {
                get-process $Application -ErrorAction SilentlyContinue | Stop-Process -Force:$True -Confirm:$false
            }
        } 
    }
    #Clean-up downloaded Winget Packages
    Remove-Item $ENV:TEMP\Winget -Recurse -Force:$True -ErrorAction:SilentlyContinue

    #Cleanup shortcuts from installed applications
    Foreach ($File in $json.filestoclean) {
        Write-Host Cleaning $File from personal ad public Windows Desktop -ForegroundColor Green
        $UserDesktop = ([Environment]::GetFolderPath("Desktop"))
        Get-ChildItem C:\users\public\Desktop\$File -ErrorAction SilentlyContinue | Where-Object LastWriteDate -LE ((Get-Date).AddHours( - 1)) | Remove-Item -Force:$True
        Get-ChildItem $UserDesktop\$File -ErrorAction SilentlyContinue | Where-Object LastWriteDate -LE ((Get-Date).AddHours( - 1)) | Remove-Item -Force:$True
        Get-ChildItem C:\users\public\Desktop\$File -Hidden -ErrorAction SilentlyContinue | Where-Object LastWriteDate -LE ((Get-Date).AddHours( - 1)) | Remove-Item -Force:$True
        Get-ChildItem $UserDesktop\$File -Hidden -ErrorAction SilentlyContinue | Where-Object LastWriteDate -LE ((Get-Date).AddHours( - 1)) | Remove-Item -Force:$True
    }
}

if ($SCCMTools -or $All) {
    #Download and install System Center 2012 R2 Configuration Manager Toolkit for CMTRACE tool
    Write-Host Checking if System Center 2012 R2 Configuration Manager Toolkit is already installed -ForegroundColor Green
    if (!(Test-Path 'C:\Program Files (x86)\ConfigMgr 2012 Toolkit R2')) {
        Write-Host SCCM 2012 R2 Toolkit was not found and installing now -ForegroundColor Yellow
        Invoke-Webrequest -uri https://download.microsoft.com/download/5/0/8/508918E1-3627-4383-B7D8-AA07B3490D21/ConfigMgrTools.msi -UseBasicParsing -Outfile $ENV:TEMP\ConfigMgrTools.msi
        msiexec.exe /i $ENV:TEMP\ConfigMgrTools.msi /qn    
    }
}

if ($SysInternalsSuite -or $All) {
    #Download and extract SysInternals Suite and add to system path
    Write-Host Checking if SysInternals Suite is present -ForegroundColor Green
    if (!(Test-Path 'C:\Program Files (x86)\SysInterals Suite')) {
        Write-Host SysInternalsSuite was not found and installing now -ForegroundColor Yellow
        Invoke-Webrequest -uri https://download.sysinternals.com/files/SysinternalsSuite.zip -Outfile $ENV:TEMP\SysInternalsSuite.zip
        Expand-Archive -LiteralPath $ENV:TEMP\SysInternalsSuite.zip -DestinationPath 'C:\Program Files (x86)\SysInterals Suite'
        $OldPath = (Get-ItemProperty -Path 'Registry::HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Environment' -Name PATH).Path
        $NewPath = $OldPath + ';C:\Program Files (x86)\SysInterals Suite\'
        Set-ItemProperty -Path 'Registry::HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Environment' -Name PATH -Value $NewPath
    }
}

if ($IntuneWinAppUtil -or $All) {
    #Download IntuneWinAppUtil to c:\windows\system32
    Write-Host Checking if IntuneWinAppUtil Suite is present -ForegroundColor Green
    if (!(Test-Path 'c:\windows\system32\IntuneWinAppUtil.exe')) {
        Write-Host IntuneWinAppUtil was not found and installing now -ForegroundColor Yellow
        Invoke-Webrequest -uri https://github.com/microsoft/Microsoft-Win32-Content-Prep-Tool/raw/master/IntuneWinAppUtil.exe -Outfile c:\windows\system32\intunewinapputil.exe
    }
}

if ($Features -or $All) {
    #Install Features
    Write-Host Installing Features but skipping install if already present -ForegroundColor Green
    Foreach ($Feature in $json.Features) {
        Write-Host Checking if $Feature is already installed...
        if ((Get-WindowsOptionalFeature -Online -FeatureName:$Feature).State -ne 'Enabled') {
            Write-Host $Feature was not found and installing now -ForegroundColor Yellow
            Enable-WindowsOptionalFeature -Online -FeatureName:$Feature -NoRestart:$True -ErrorAction SilentlyContinue | Out-Null
        }
    }
}

if ($PowerShellModules -or $All) {
    #Install PowerShell Modules
    Write-Host Installing Modules but skipping install if already present -ForegroundColor Green
    [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12

    Set-PSRepository PSGallery -InstallationPolicy Trusted

    Foreach ($Module in $json.PowerShellModules) {
        Write-Host Checking if the $Module is already installed...
        if (!(Get-Module $Module -ListAvailable)) {
            Write-Host $Module PowerShell Module was not found and installing now -ForegroundColor Yellow
            Install-Module -Name $Module -Scope AllUsers -Force:$True -AllowClobber:$True
        }
    }
}

if ($RSATTools -or $All) {
    #Install selected RSAT Tools
    Write-Host Installing RSAT components but skipping install if already present -ForegroundColor Green
    Foreach ($Tool in $json.RSATTools) {
        Write-Host Checking if $Tool.Split('~')[0] is already installed...
        if ((Get-WindowsCapability -Online -Name:$Tool).State -ne 'Installed') {
            Write-Host $Tool.Split('~')[0] was not found and installing now -ForegroundColor Yellow
            DISM.exe /Online /add-capability /CapabilityName:$Tool /NoRestart /Quiet | Out-Null
        }
    }
}

if ($PowerShellProfile -or $All) {
    #Add settings to PowerShell Profile (Creating Profile if not exist)
    Write-Host Adding settings to PowerShell Profile but skipping setting if already present -ForegroundColor Green
    Foreach ($Setting in $json.PowerShellProfile) {
        Write-Host Checking if $Setting is already added...
        if (!(Test-Path $profile)) {
            New-Item -Path $profile -ItemType:File -Force:$True | out-null 
        }
        if (!(Get-Content $profile | Select-String -Pattern $Setting -SimpleMatch)) {
            Write-Host $Setting was not found and adding now -ForegroundColor Yellow
            Add-Content $profile "`n$($Setting)"
        }
    }
}

if ($PowerShellModulesUpdate -or $All) {
    #Update PowerShell Modules if needed
    Write-Host Checking for older versions of PowerShell Modules and removing those if present -ForegroundColor Green
    Set-PSRepository PSGallery -InstallationPolicy Trusted

    Foreach ($Module in Get-InstalledModule | Select-Object Name) {
        Write-Host Checking for older versions of the $Module.Name PowerShell Module
        $AllVersions = Get-InstalledModule -Name $Module.Name -AllVersions -ErrorAction:SilentlyContinue
        $AllVersions = $AllVersions | Sort-Object PublishedDate -Descending 
        $MostRecentVersion = $AllVersions[0].Version
        if ($AllVersions.Count -gt 1 ) {
            Foreach ($Version in $AllVersions) {
                if ($Version.Version -ne $MostRecentVersion) {
                    Write-Host "Uninstalling previous version" $Version.Version "of Module" $Module.Name -ForegroundColor Yellow
                    Uninstall-Module -Name $Module.Name -RequiredVersion $Version.Version -Force:$True
                }
            }
        }
    }
}

if ($PowerShellCommands -or $All) {
    #Run PowerShell commandline options
    Write-Host Running Commandline options and this could take a while -ForegroundColor Green
    Foreach ($Command in $json.PowerShellCommands) {
        Write-Host Running $Command -ForegroundColor Yellow
        Powershell.exe -Executionpolicy Bypass -Command $Command
    }
}

#Stop Transcript logging
Stop-Transcript

 

 

 

Install_Apps.json

 

 

{
   "Apps": [
      "Microsoft.SQLServerManagementStudio",
      "7zip.7zip",
      "Adobe.Acrobat.Reader.64-bit",
      "AnyConnect",
      "BraveSoftware.BraveBrowser",
      "Canonical.Ubuntu",
      "Cisco.CiscoWebexMeetings",
      "Citrix.Workspace",
      "Famatech.AdvancedIPScanner",
      "Fortinet.FortiClientVPN",
      "Git.Git",
      "GitHub.GitHubDesktop",
      "Google.Chrome",
      "Graphviz.Graphviz",
      "Insecure.Nmap",
      "JAMSoftware.TreeSize.Free",
      "Microsoft.AzureCLI",
      "Microsoft.AzureStorageExplorer",
      "Microsoft.DeploymentToolkit",
      "Microsoft.dotnetRuntime.3-x64",
      "Microsoft.dotnetRuntime.3-x86",
      "Microsoft.dotnetRuntime.5-x64",
      "Microsoft.dotnetRuntime.5-x86",
      "Microsoft.EdgeWebView2Runtime",
      "Microsoft.PowerBI",
      "Microsoft.Powershell",
      "Microsoft.PowerToys",
      "Microsoft.RemoteDesktopClient",
      "Microsoft.VisualStudioCode",
      "Microsoft.WindowsAdminCenter",
      "Microsoft.WindowsADK",
      "Microsoft.WindowsTerminal",
      "Microsoft.XMLNotepad",
      "Mozilla.FireFox",
      "Notepad++.Notepad++",
      "Obsidian.Obsidian",
      "Ookla.Speedtest",
      "OpenVPNTechnologies.OpenVPNConnect",
      "Oracle.JavaRuntimeEnvironment",
      "PuTTY.PuTTY",
      "Python.Python.3",
      "Rufus.Rufus",
      "Teamviewer.Teamviewer",
      "Telerik.Fiddler",
      "VideoLAN.VLC",
      "WinSCP.WinSCP",
      "WiresharkFoundation.Wireshark",
      "Zoom.Zoom"
   ],
   "Features": [
      "Containers-DisposableClientVM",
      "Microsoft-Windows-Subsystem-Linux",
      "TelnetClient",
      "TFTP"
   ],
   "FilesToClean": [
      "*.lnk",
      "desktop.ini"
   ],
   "MicrosftVCRuntime": [
      "Microsoft.VC++2008Redist-x86",
      "Microsoft.VC++2008Redist-x64",
      "Microsoft.VC++2010Redist-x64",
      "Microsoft.VC++2010Redist-x86",
      "Microsoft.VC++2012Redist-x64",
      "Microsoft.VC++2012Redist-x86",
      "Microsoft.VC++2013Redist-x64",
      "Microsoft.VC++2013Redist-x86"
   ],
   "ProcessesToKill": [
      "advanced_ip_scanner",
      "OpenVPNConnect",
      "PowerToys.Settings",
      "PtSrv",
      "PtSrv"
   ],
   "PowerShellCommands": [
      "Update-Help -Confirm:$False -Force:$True -ErrorAction:SilentlyContinue"
   ],
   "PowerShellModules": [
      "AIPService",
      "AzureAD",
      "AzureRM",
      "AZViz",
      "AzureADPreview",
      "ExchangeOnlineManagement",
      "IntuneBackupAndRestore",
      "IntuneDocumentation",
      "IntuneWin32App",
      "Microsoft.Graph.Intune",
      "M365Documentation",
      "MSGraphFunctions",
      "Microsoft.Online.SharePoint.PowerShell",
      "Microsoft.PowerApps.Administration.Powershell",
      "Microsoft.PowerShell.Crescendo",
      "Microsoft.PowerShell.SecretManagement",
      "Microsoft.PowerShell.SecretStore",
      "MicrosoftTeams",
      "MSAL.PS",
      "MSCommerce",
      "MSOnline",
      "Oh-My-Posh",
      "ORCA",
      "PNP.PowerShell",
      "ps2exe",
      "PnP.PowerShell",
      "PSword",
      "PSWriteWord",
      "Posh-Git",
      "Powershell-yaml",
      "PSReadLine",
      "PSParseHTML",
      "PSWindowsUpdate",
      "SQLServer",
      "VMware.PowerCLI",
      "WindowsAutoPilotIntune"
   ],
   "PowerShellProfile": [
      "Import-Module Oh-My-Posh",
      "Import-Module Posh-Git",
      "Set-PSReadlineKeyHandler -Key Tab -Function Complete",
      "Set-PSReadLineOption -PredictionSource History",
      "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12"
   ],
   "RSATTools": [
      "Rsat.ActiveDirectory.DS-LDS.Tools~~~~0.0.1.0",
      "Rsat.BitLocker.Recovery.Tools~~~~0.0.1.0",
      "Rsat.CertificateServices.Tools~~~~0.0.1.0",
      "Rsat.DHCP.Tools~~~~0.0.1.0",
      "Rsat.Dns.Tools~~~~0.0.1.0",
      "Rsat.FailoverCluster.Management.Tools~~~~0.0.1.0",
      "Rsat.FileServices.Tools~~~~0.0.1.0",
      "Rsat.GroupPolicy.Management.Tools~~~~0.0.1.0",
      "Rsat.IPAM.Client.Tools~~~~0.0.1.0",
      "Rsat.LLDP.Tools~~~~0.0.1.0",
      "Rsat.NetworkController.Tools~~~~0.0.1.0",
      "Rsat.NetworkLoadBalancing.Tools~~~~0.0.1.0",
      "Rsat.RemoteAccess.Management.Tools~~~~0.0.1.0",
      "Rsat.RemoteDesktop.Services.Tools~~~~0.0.1.0",
      "Rsat.ServerManager.Tools~~~~0.0.1.0",
      "Rsat.Shielded.VM.Tools~~~~0.0.1.0",
      "Rsat.StorageMigrationService.Management.Tools~~~~0.0.1.0",
      "Rsat.StorageReplica.Tools~~~~0.0.1.0",
      "Rsat.SystemInsights.Management.Tools~~~~0.0.1.0",
      "Rsat.VolumeActivation.Tools~~~~0.0.1.0",
      "Rsat.WSUS.Tools~~~~0.0.1.0"
   ]
}

 

 

 

2 Replies
Pretty nice, not gonna lie. :'D

Thank you, still work in progress but I think I have most things covered now ;)