PowerShell: Installing a Program from Its Zip Archive

# installProgramFromExeZipArchive.ps1

# User inputs
$computernames=@(
	'SERVER001',
	'SERVER002'
)
$fileURL="https://dl.dell.com/FOLDER08543783M/1/DellEMC-iDRACTools-Web-WINX64-10.3.0.0-4945.exe"
$expectedExecutable='racadm.exe'
$expectedInstallPath='C:\Program Files\Dell\SysMgt\iDRACTools\racadm'
$stageFolder='C:\Temp\'

function installProgramFromExeZipArchive{
	param(
		$computernames=$env:computername,
		$fileURL="https://dl.dell.com/FOLDER07549599M/1/DellEMC-iDRACTools-Web-WINX64-10.2.0.0-4583_A00.exe",
		$expectedExecutable='racadm.exe',
		$expectedInstallPath='C:\program files\Dell\SysMgt\iDRACTools\racadm',
		$stageFolder='C:\Temp\'
	)
	$results=[hashtable]@{}
	foreach($computerName in $computernames){
		$alreadyInstalled=invoke-command -computername $computername -scriptblock{param($expectedExecutable);try{get-command $expectedExecutable -EA Ignore}catch{$false}} -Args $expectedExecutable
		if($alreadyInstalled){
			write-host "$computername has already installed $expectedExecutable"
			$results+=[hashtable]@{$computername=$true}
		}else{
			# Autogen variables
			$fileName=[regex]::match($fileURL,'[^/\\&\?]+\.\w{3,4}(?=([\?&].*$|$))').value
			$translatedVolume=[regex]::match($stageFolder,'^(\w)\:').captures.groups[1].value+'$'
			$translatedFoldername=[regex]::match($stageFolder,'\:(.*)$').captures.groups[1].value
			$remoteSmbPath=join-path $('\\'+$computerName+"\$translatedVolume") $translatedFoldername
			try{
				# Download the file directly onto target server's staging folder
				Import-Module BitsTransfer
				if(!(test-path $remoteSmbPath)){$null=mkdir $remoteSmbPath}
				# Start-BitsTransfer -Source $fileURL -Destination $output
				[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
				Start-BitsTransfer -Source $fileURL -Destination $remoteSmbPath
				$psSession=new-pssession $computerName
				if($psSession.State -eq 'Opened'){
					$result=invoke-command -Session $psSession -ScriptBlock{
						param($stageFolder,$filename,$expectedExecutable,$expectedInstallPath)
						# write-host "$env:computername : $stageFolder,$filename,$expectedExecutable,$expectedInstallPath"
						# pause					
						$commandAvailable=try{get-command $expectedExecutable -EA Ignore}catch{$false}
						$toInstall=if(!$commandAvailable){
							if(!($env:path -like "*$expectedInstallPath*")){$env:path+=";$expectedInstallPath"}						
							$null=RefreshEnv
							$commandNowAvailable=try{get-command $expectedExecutable -EA Ignore}catch{$false}
							if($commandNowAvailable){$false}else{$true}
						}else{
							write-host "Command $expectedExecutable is available on $env:computername"
							$true
						}
						if ($toInstall){
							$exeExists=try{ls $expectedInstallPath -EA Ignore|?{$_.Name -like $expectedExecutable}}catch{$false}
							if($exeExists){
								$env:path+=";$expectedInstallPath"
								$null=RefreshEnv
								$commandNowAvailable=try{get-command $expectedExecutable -EA Ignore}catch{$false}
								if($commandNowAvailable){return $true}else{return $false}
							}else{
								$expectedFileLocation=join-path $stageFolder $filename
								$zipFilename=$([System.IO.Path]::GetFileNameWithoutExtension($expectedFileLocation))+'.zip'
								$newZipFile=join-path $stageFolder $zipFilename
								#[System.IO.Path]::GetExtension($expectedFileLocation)
								Rename-Item -Path $expectedFileLocation -NewName $newZipFile -EA Ignore
								# $null=Expand-Archive -Path $newZipFile -DestinationPath $stageFolder
								# alternative method: backward compatible to older systems
								Add-Type -AssemblyName System.IO.Compression.FileSystem
								$null=[System.IO.Compression.ZipFile]::ExtractToDirectory($newZipFile, $stageFolder)
								$msiFile=(ls $stageFolder|?{$_.FullName -match '\.msi$'}|sort -property LastWriteTime|select -first 1).FullName
								Start-Process $msiFile -ArgumentList "/quiet" -wait
								# this command doesn't work: msiexec /i $msiFile /quiet /qn /norestart
								$environmentalPathExists=$env:path -like "*$expectedInstallPath*"
								if(!$environmentalPathExists){
									$env:path+=";C:\Program Files\Dell\SysMgt\iDRACTools\racadm"
									$null=RefreshEnv
								}
								$commandNowAvailable=try{get-command $expectedExecutable -EA Ignore}catch{$false}
								if($commandNowAvailable){return $true}else{return $false}
							}
						}					
					} -Args $stageFolder,$fileName,$expectedExecutable,$expectedInstallPath
					Remove-PSSession $psSession
					write-host "$computername result: $result"
					$results+=[hashtable]@{$computername=$result}
				}else{
					write-warning "Unable to connect to $computername via WinRM"
					$results+=[hashtable]@{$computername=$null}
				}
			}catch{
				write-warning $_
				$results+=[hashtable]@{$computername=$null}
			}
		}
	}
	return $results
}
installProgramFromExeZipArchive

Leave a Reply

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