Feb 08 2022 12:42 PM - edited Apr 25 2022 01:05 AM
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"
]
}
Feb 09 2022 05:01 AM
Feb 09 2022 05:17 AM - edited Feb 09 2022 05:17 AM
Thank you, still work in progress but I think I have most things covered now 😉