Mission : Auto-remediate with Powershell
So, based on the last post about the PuTTY and WinSCP issues, I thought it would be good after getting a report from the previous script that it would be nice to get a script to remediate that issue at the same time, so lets get the requirement from the get-go:
- Get a list of servers from a text file
- Copy the software from a network share to the servers in the list
- Copy the executables from the network share to the folder c:\temp
- Install putty with the "upgrade" mode for all users
- Install winscp with the "update" and "for all users" mode
- Upgrade status can be confirmed with the previous script
Pitfalls with the plan
Well there was only one issue I can across this was the fact that when PuTTY installed, it did not install as it should do, the installer ran but I got this as the error:
Well there was only one issue I can across this was the fact that when PuTTY installed, it did not install as it should do, the installer ran but I got this as the error:
Windows Installer installed the product. Product Name: PuTTY release 0.81 (64-bit). Product Version: 0.81.0.0. Product Language: 1033. Manufacturer: Simon Tatham. Installation success or error status: 1625.
This means in English language and not error codes, which can be lookup by "net helpmsg xxx"
This installation is forbidden by system policy. Contact your administrator.
Then question is why? That has a good question as well at the start of the issue, I checked all the usual places like SRP (Software restriction policys) then all the group policy locations, is this something that was being set to stop things running from the c:\temp folder?
No. it was none of this, the cause of this was UAC or user access control, this is the excellent of idea that if you are an administrator you need to ask for permission to actually be an administrator this looks like this, no problem with that, and the fix to not to turn off UAC that is insecure and stupid.
The fix for this is to use the syntax in your script that in the variables contains this parameter "-Verb RunAs" - then rather than fail the install it changed to this:
Windows Installer installed the product. Product Name: PuTTY release 0.81 (64-bit). Product Version: 0.81.0.0. Product Language: 1033. Manufacturer: Simon Tatham. Installation success or error status: 0.
The fix for this is to use the syntax in your script that in the variables contains this parameter "-Verb RunAs" - then rather than fail the install it changed to this:
Windows Installer installed the product. Product Name: PuTTY release 0.81 (64-bit). Product Version: 0.81.0.0. Product Language: 1033. Manufacturer: Simon Tatham. Installation success or error status: 0.
Mission Completion : The Script
This is the script that does the magic, and as usual customisable items are in bold, and that's all there is to it - simples!
# Path to the text file containing the list of remote computers
$computerListFilePath = "target_servers.txt"
# Read the list of remote computers from the text file
$computers = Get-Content $computerListFilePath
# Function to update Putty
function Update-Putty {
param(
[string]$ComputerName
)
# Command to upgrade Putty silently
$puttyInstallerPath = "\\$ComputerName\c$\temp\putty-64bit-0.81-installer.msi"
if ($ComputerName -ne $null -and $ComputerName -ne "") {
Invoke-Command -ComputerName $ComputerName -ScriptBlock {
param($puttyInstallerPath)
Start-Process msiexec -ArgumentList "/i", "$puttyInstallerPath", "/qn", "/norestart" -Verb RunAs -Wait
} -ArgumentList $puttyInstallerPath
} else {
Write-Host "Computer name is null or empty."
}
}
# Function to update WinSCP
function Update-WinSCP {
param(
[string]$ComputerName
)
# Command to upgrade WinSCP silently
$winscpInstallerPath = "\\$ComputerName\c$\temp\WinSCP-6.3.3-Setup.exe"
if ($ComputerName -ne $null -and $ComputerName -ne "") {
Invoke-Command -ComputerName $ComputerName -ScriptBlock {
param($winscpInstallerPath)
Start-Process $winscpInstallerPath -ArgumentList "/verysilent", "/allusers" -Wait
} -ArgumentList $winscpInstallerPath
} else {
Write-Host "Computer name is null or empty."
}
}
# Function to copy files from network share to remote server
function Copy-FilesToRemoteServer {
param(
[string]$ComputerName
)
# Check if the remote folder exists, if not, create it
$remoteFolder = "\\$ComputerName\c$\temp"
if (-not (Test-Path $remoteFolder)) {
New-Item -Path $remoteFolder -ItemType Directory -Force
}
# Copy files from network share to remote folder
Copy-Item -Path "\\bearsmb-lon\autoupdate\putty-64bit-0.81-installer.msi", "\\bearsmb-lon\autoupdateWinSCP-6.3.3-Setup.exe" -Destination $remoteFolder -Force
}
# Loop through each computer
foreach ($computer in $computers) {
# Copy files from network share to remote server
Copy-FilesToRemoteServer -ComputerName $computer
# Update Putty
Update-Putty -ComputerName $computer
# Update WinSCP
Update-WinSCP -ComputerName $computer
}