Author Posts

November 15, 2013 at 1:53 am

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
$MSIProc = ($MSIName.trimend(".msi"))
write-host $MSIProc

$MSIProc = [string]$MSIProc

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"))
$install = Foreach-Object {([wmiclass]"\\$($_.trim())\root\cimv2:win32_process").Create("msiexec /i c:\$MSIName /q /n")}| Select-Object -Property ReturnValue | Format-Wide -Column 1

start-sleep -Seconds 5

$MSItest = get-process -cn $strComputer -name "$MSIProc"

while ($MSItest -ne 0)
{
start-sleep -seconds 1
write-host "waiting for MSI install to complete"
$MSItest = get-process -cn $strComputer -name "$MSIProc"

}
}
Starting Job...
Waiting for 1 Jobs to Complete sleeping 5 seconds
Waiting for 1 Jobs to Complete sleeping 5 seconds
Waiting for 1 Jobs to Complete sleeping 5 seconds
Waiting for 1 Jobs to Complete sleeping 5 seconds
Waiting for 1 Jobs to Complete sleeping 5 seconds
Security Installer
KB2708437
You cannot call a method on a null-valued expression.
+ CategoryInfo : InvalidOperation: (trim:String) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull
Cannot convert value "\\\root\cimv2:win32_process" to type "System.Management.ManagementClass". Error: "Invalid parameter "
+ CategoryInfo : NotSpecified: (:) [], RuntimeException
+ FullyQualifiedErrorId : RuntimeException
Cannot find a process with the name "KB2708437". Verify the process name and call the cmdlet again.
+ CategoryInfo : ObjectNotFound: (KB2708437:String) [Get-Process], ProcessCommandException
+ FullyQualifiedErrorId : NoProcessFoundForGivenName,Microsoft.PowerShell.Commands.GetProcessCommand
Security Installer
KB2708941
You cannot call a method on a null-valued expression.
+ CategoryInfo : InvalidOperation: (trim:String) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull
Cannot convert value "\\\root\cimv2:win32_process" to type "System.Management.ManagementClass". Error: "Invalid parameter "
+ CategoryInfo : NotSpecified: (:) [], RuntimeException
+ FullyQualifiedErrorId : RuntimeException
Cannot find a process with the name "KB2708941". Verify the process name and call the cmdlet again.
+ CategoryInfo : ObjectNotFound: (KB2708941:String) [Get-Process], ProcessCommandException
+ FullyQualifiedErrorId : NoProcessFoundForGivenName,Microsoft.PowerShell.Commands.GetProcessCommand
Security Installer
KB926857 (2)
You cannot call a method on a null-valued expression.
+ CategoryInfo : InvalidOperation: (trim:String) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull
Cannot convert value "\\\root\cimv2:win32_process" to type "System.Management.ManagementClass". Error: "Invalid parameter "
+ CategoryInfo : NotSpecified: (:) [], RuntimeException
+ FullyQualifiedErrorId : RuntimeException
Cannot find a process with the name "KB926857 (2)". Verify the process name and call the cmdlet again.
+ CategoryInfo : ObjectNotFound: (KB926857 (2):String) [Get-Process], ProcessCommandException
+ FullyQualifiedErrorId : NoProcessFoundForGivenName,Microsoft.PowerShell.Commands.GetProcessCommand
Security Installer
KB926857
You cannot call a method on a null-valued expression.
+ CategoryInfo : InvalidOperation: (trim:String) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull
Cannot convert value "\\\root\cimv2:win32_process" to type "System.Management.ManagementClass". Error: "Invalid parameter "
+ CategoryInfo : NotSpecified: (:) [], RuntimeException
+ FullyQualifiedErrorId : RuntimeException
Cannot find a process with the name "KB926857". Verify the process name and call the cmdlet again.
+ CategoryInfo : ObjectNotFound: (KB926857:String) [Get-Process], ProcessCommandException
+ FullyQualifiedErrorId : NoProcessFoundForGivenName,Microsoft.PowerShell.Commands.GetProcessCommand
Total time for JOBs: 0.43 Minutes
I need help with this section of my script. I am trying to run multiple .msi against a list of machines, but I keep receiving these errors above. Could someone please help me with this issue. Also, I dont know which WMICLASS line I should use? I am new to powershell so any help or advice would be awesome!!!

November 15, 2013 at 5:10 am

You can't start a pipeline with ForEach-Object; it's intended to be used only when something is piped into it. Since you only have a single object to worry about in this code, there's no need for any type of loop there, and the first "[wmiclass]" line should work better.

I haven't tested the rest of the code, but your while loop could be revised slightly to get rid of those error messages, something like this:

copy-item $MSIFullName \\$strComputer\c$\$MSIName -force

$result = (([WMICLASS]"\\$strComputer\ROOT\CIMV2:win32_process").Create("msiexec.exe /I c:\$MSIName /qn /passive"))

if ($result.ReturnValue -eq 0)
{
    do
    {
        Start-Sleep -Seconds 1
        $process = Get-WmiObject -Class Win32_Process -ComputerName $strComputer -Filter "ProcessID = '$($result.ProcessId)'"
    }
    while ($null -ne $process)
}

November 17, 2013 at 3:47 am

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)