# installProgramFromExeZipArchive.ps1
# Automated installation of the racadm program
$computerlist=@'
HyperV01
HyperV02
'@
$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\'
$computernames=@($computerlist -split "`n")|%{$_.Trim()}
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]@{}
function addEnvironmentalPath($pathToAdd){
$registryEnvironment='Registry::HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Environment'
$pathToAdd=if($pathToAdd -match '\\$'){$pathToAdd -replace '.$'}else{$pathToAdd}
try{
$originalPaths=(Get-ItemProperty -Path $registryEnvironment -Name PATH).path
$pathsArray=$originalPaths -split ';'|?{$_.trim() -ne ''}|%{if($_ -match '\\$'){$_ -replace '.$'}else{$_}}|Sort-Object -Unique
if($pathToAdd -in $pathsArray){
write-host "$pathToAdd is already included in the environmental paths: '$originalPaths'"
return $true
}else{
$newPathsArray=$pathsArray+$pathToAdd
$newPaths=$newPathsArray -join ';'
Set-ItemProperty -Path $registryEnvironment -Name PATH -Value $newPaths
$newRegistryEnvironment=(Get-ItemProperty -Path $registryEnvironment -Name PATH).Path
write-host "Environmental paths have been changed:`r`nFrom: $originalPaths`r`nTo: $newPaths"
$env:Path = [System.Environment]::GetEnvironmentVariable("Path","Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path","User")
return $true
}
}catch{
write-warning $_
return $false
}
}
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,$addEnvironmentalPath)
# 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){
[scriptblock]::create($addEnvironmentalPath).invoke($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,${function:addEnvironmentalPath}
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 $computernames
Categories: