Thanks Dave for that.. I was wondering if you could assist with my script. I can get the .msu portion to install no problem, but when I place a .msi in the patch folder. It will not install. I am also trying to document the processID in a the out-gridview. The block comes up, but there is no ID in there to view. If you can assist that would be awesome. The code is below. I included the whole script for everyone else to use if they cut out the the MSI section it works fine. thanks for the help in advance.
####################################################################################
Mass installer
####################################################################################
####################################################################################
Scriptblock
####################################################################################
$ScriptBlock = {
param([String]$strComputer, [string]$targetfolder, [array]$FileList )
####################################################################################
Install Functions
####################################################################################
function InstallMSU {
param([String]$strComputer, $objFile, $sysArch, $antiarch)
write-host ""
write-host "MSU install"
write-host ""
$msuName = $objFile.name
$msuExt = $objFile.extension
$msuFullName = $objFile.FullName
$msuFolder = ($msuName.trimend(".msu"))
$msuCab = $msuFolder + ".cab"
if (($msuName -Notmatch $sysArch) -and ($msuName -match $antiarch))
{
return
}
if ($msuName -match "ia64")
{
return
}
$regex = [regex]"KB......."
$KB = ($regex.match($msuName)).value
if ($kb -eq $null)
{
$regex = [regex]"kb......."
$KB = ($regex.match($msuName)).value
}
$ret = Get-WmiObject -cn $strComputer -query 'select * from win32_quickfixengineering' | where {$_.hotfixid -eq "$KB"} | foreach {$_.hotfixid}
if ($ret -eq $null)
{
write-host "$KB not found on $strComputer" -ForegroundColor Red
copy-item $msuFullName \\$strComputer\c$\$msuName -force
$install = (([WMICLASS]"\\$strComputer\ROOT\CIMV2:win32_process").Create("cmd /c md c:\$msuFolder"))
start-sleep -seconds 1
$install = (([WMICLASS]"\\$strComputer\ROOT\CIMV2:win32_process").Create("cmd /c expand -F:* c:\$msuName C:\$msuFolder"))
$wait = test-path \\$strComputer\c$\$msuFolder\*.cab
while ($wait -eq $false)
{
start-sleep -seconds 1
$wait = test-path \\$strComputer\c$\$msuFolder\*.cab
}
$wsuscabtest = test-path \\$strComputer\c$\$msuFolder\wsusscan.cab
if ($wsuscabtest -eq $true)
{
remove-item \\$strComputer\c$\$msuFolder\wsusscan.cab
}
$cabs = get-childitem \\$strComputer\c$\$msuFolder -filter "*.cab"
foreach ($cab in $cabs)
{
$cabName = $cab.name
$install = (([WMICLASS]"\\$strComputer\ROOT\CIMV2:win32_process").Create("cmd /c DISM.exe /Online /Add-Package /PackagePath:C:\$msuFolder\$msuCab"))
}
start-sleep -Seconds 5
$dismtest = get-process -cn $strComputer -name "dismhost"
while ($dismtest -ne $null)
{
start-sleep -seconds 1
#write-host "waiting for install to complete"
$dismtest = get-process -cn $strComputer -name "dismhost"
}
remove-item \\$strComputer\c$\$msuName -force
remove-item \\$strComputer\c$\$msuFolder -recurse -force
}
else
{
write-host "$KB found on $strComputer" -ForegroundColor Green
}
}
function InstallExe {
param([String]$strComputer, $objFile, $sysArch)
}
function InstallMSI {
param([String]$strComputer, $objFile, $sysArch, $antiarch)
write-host ""
write-host "Security Installer"
write-host ""
$MSIName = [string]$objFile.name
$MSIExt = $objFile.extension
$MSIFullName = $objFile.FullName
$Process = ($MSIName.trimend(".msi"))
write-host $Process
$Process = [string]$Process
if (($MSIName -Notmatch $sysArch) -and ($MSIName -match $antiarch))
{
return
}
if ($MSIName -match "ia64")
{
return
}
copy-item $MSIFullName \\$strComputer\c$\$MSIName -force
$Install = (([WMICLASS]"\\$strComputer\ROOT\CIMV2:win32_process").Create(" msiexec.exe /I c:\$MSIName /qn /passive"))
start-sleep -Seconds 5
if ($Install.ReturnValue -eq 0)
{
do
{
start-sleep -seconds 1
write-host "Checking endstate Process ID "
$process = Get-WmiObject -Class Win32_Process -ComputerName $strComputer -Filter "ProcessID = '$($Install.ProcessId)'"
}
while ($null -ne $process)
}
}
function InstallJava {
param([String]$strComputer, $objFile, $sysArch, $antiarch)
write-host ""
write-host "Security Installer"
write-host ""
$JavaName = [string]$objFile.name
$JavaExt = $objFile.extension
$JavaFullName = $objFile.FullName
$JavaProc = ($JavaName.trimend(".exe"))
write-host $JavaProc
$JavaProc = [string]$JavaProc
if (($JavaName -Notmatch $sysArch) -and ($JavaName -match $antiarch))
{
return
}
if ($JavaName -match "ia64")
{
return
}
copy-item $JavaFullName \\$strComputer\c$\$JavaName -force
$install = (([WMICLASS]"\\$strComputer\ROOT\CIMV2:win32_process").Create("cmd /c c:\$JavaName /s"))
start-sleep -Seconds 5
$javatest = get-process -cn $strComputer -name "$JavaProc"
while ($javatest -ne $null)
{
start-sleep -seconds 1
write-host "waiting for java install to complete"
$javatest = get-process -cn $strComputer -name "$JavaProc"
}
<#
$javatest = get-process -cn target1 -name “trustedinstaller.exe” -ea silentlycontinue
while ($javatest -ne $null)
{
start-sleep -seconds 1
#write-host "waiting for install to complete"
$javatest = get-process -cn target1 -name "trustedinstaller.exe" -ea silentlycontinue
}
#>
}
####################################################################################
Start doing stuff!
####################################################################################
$reply = Get-WmiObject -Class Win32_PingStatus -Filter “Address=‘$strComputer’”
if ($reply.statuscode -eq 0)
{
$pingIPaddress = $reply.IPV4Address.ipaddresstostring
$PingResponse = "Success"
$sysArch = (Get-WmiObject -Class Win32_OperatingSystem -ComputerName $strComputer -ea 0).OSArchitecture
if ($sysArch -eq "64-bit")
{
$sysArch = "x64"
$antiarch = "x86"
}
if ($sysarch -eq "32-bit")
{
$sysArch = "x86"
$antiarch = "x64"
}
#######################################################################################
Disable the on-access file scanner
#######################################################################################
if ($sysArch -eq "x86")
{
$Onaccess = (([WMICLASS]"\\$strComputer\ROOT\CIMV2:win32_process").Create('"c:\Program Files\McAfee\VirusScan Enterprise\shstat.exe" -disable'))
}
else
{
$Onaccess = (([WMICLASS]"\\$strComputer\ROOT\CIMV2:win32_process").Create('"c:\Program Files (x86)\McAfee\VirusScan Enterprise\shstat.exe" -disable'))
}
#######################################################################################
Loop through install files and run the correct install function
#######################################################################################
Foreach ($objFile in $FileList)
{
$FileExtension = $objFile.Extension
$Filename = $objFile.name
if ($FileExtension -match ".msu")
{
InstallMSU $strComputer $objFile $sysArch $antiarch
}
elseif (($FileExtension -match ".exe") -and ($Filename -match "jre"))
{
InstallJava $strComputer $objFile $sysArch $antiarch
}
elseif ($FileExtension -match ".msi")
{
InstallMSI $strComputer $objFile $sysArch $antiarch
}
}
#######################################################################################
Re-enable Onaccess scanning
#######################################################################################
if ($sysArch -eq "x86")
{
$Onaccess = (([WMICLASS]"\\$strComputer\ROOT\CIMV2:win32_process").Create('"c:\Program Files\McAfee\VirusScan Enterprise\shstat.exe" -enable'))
}
else
{
$Onaccess = (([WMICLASS]"\\$strComputer\ROOT\CIMV2:win32_process").Create('"c:\Program Files (x86)\McAfee\VirusScan Enterprise\shstat.exe" -enable'))
}
}
Else #means we had a bad ping
{
#Report the reason for the bad ping based on WMI ping error code
if ($reply.statuscode -eq $null) #null status code means no DNS entry was found. Delete that shit from ADUC (unless it's the three-star's laptop...)
{
$PingResponse = "No DNS Entry"
$pingIPaddress = $null
}
#Report the reason for the bad ping based on WMI ping error code
If ($reply.statuscode -eq "11010")
{
#Ping timeouts still return the IP address from DNS
$pingIPaddress = $reply.IPV4Address.ipaddresstostring
$PingResponse = "Request Timed Out"
}
#Report the reason for the bad ping based on WMI ping error code
If ($reply.statuscode -eq "11003")
{
$pingIPaddress = $reply.IPV4Address.ipaddresstostring
$PingResponse = "Unable to reach host"
}
}
####################################################################################
End of scriptblock
####################################################################################
$ResultProps = @{
ComputerName = $strComputer
PingResponse = $PingResponse
ProcessID = $Process
}
$return = New-Object PSObject -Property $ResultProps
return $return
}
####################################################################################
Pull Target Folder and Target List
Init variables
####################################################################################
#$targetList = read-host “Enter path\filename of target list”
#$targetFolder = read-host “Enter path of patch folder”
$targetList = get-content C:\targets\computers.txt
$targetFolder = “C:\targets\patch”
$BreakCounter = 0
$results = @()
$MaxConcurrentJobs = 50
$counter = 1
$starttimer = Get-Date
$FileList = Get-ChildItem -path $targetFolder -include @(“.exe",".msu”,“*.msi”) -recurse
####################################################################################
Multi thread start
####################################################################################
foreach ($machineName in $targetList)
{
Write-host "$counter `t $machineName Starting Job..."
$counter ++
start-job -name ("InstallJob-" + $machineName) -scriptblock $scriptblock -ArgumentList $machineName, $targetFolder, $FileList | out-null
while (((get-job | where-object { $_.Name -like "InstallJob*" -and $_.State -eq "Running" }) | measure).Count -gt $MaxConcurrentJobs)
{
"{0} Concurrent jobs running, sleeping 5 seconds" -f $MaxConcurrentJobs
Start-Sleep -seconds 5
}
get-job | where { $_.Name -like "InstallJob*" -and $_.state -eq "Completed" } | % { $results += Receive-Job $_ ; Remove-Job $_ }
}
while (((get-job | where-object { $_.Name -like "InstallJob*" -and $_.state -eq "Running" }) | measure).count -gt 0)
{
get-job | where { $_.Name -like "InstallJob*" -and $_.state -eq "Completed" } | % { $results += Receive-Job $_ ; Remove-Job $_ }
$jobcount = ((get-job | where-object { $_.Name -like "InstallJob*" -and $_.state -eq "Running" }) | measure).count
Write-Host "Waiting for $jobcount Jobs to Complete sleeping 5 seconds"
Start-Sleep -seconds 5
$BreakCounter++
if ($BreakCounter -gt 50) {
Write-Host "Exiting loop $jobCount Jobs did not complete"
get-job | where-object { $_.Name -like "InstallJob*" -and $_.state -eq "Running" } | select Name
break
}
}
get-job | where { $.Name -like “InstallJob*” -and $.state -eq “Completed” } | % { $results += Receive-Job $_ ; Remove-Job $_ }
####################################################################################
END OF MULTITHREAD
####################################################################################
####################################################################################
Send results to grid view
Print total runtime
####################################################################################
$results | select ComputerName, PingResponse, ProcessID | Sort-Object PingResponse | out-gridview
#Pulls end time and prints total time for actions
$stoptimer = Get-Date
“Total time for JOBs: {0} Minutes” -f [math]::round(($stoptimer - $starttimer).TotalMinutes , 2)