Skip to content

Instantly share code, notes, and snippets.

@OSDeploy
Created February 20, 2019 21:45
Show Gist options
  • Save OSDeploy/3ccc133b6a91dc2a602f2b5df0c5ae97 to your computer and use it in GitHub Desktop.
Save OSDeploy/3ccc133b6a91dc2a602f2b5df0c5ae97 to your computer and use it in GitHub Desktop.
OSDUpdateOffline.ps1 BETA
function Get-MSPFileInfo {
param
(
[Parameter(Mandatory = $true)][IO.FileInfo]$Path,
[Parameter(Mandatory = $true)][ValidateSet('Classification', 'Description', 'DisplayName', 'KBArticle Number', 'ManufacturerName', 'ReleaseVersion', 'TargetProductName', 'Release', 'MoreInfoURL', 'OptimizedInstallMode', 'CreationTimeUTC', 'AllowRemoval', 'OptimizeCA', 'BuildNumber', 'StdPackageName', 'PatchType', 'IsMinorUpgrade')][string]$Property
)
try {
#Creating windows installer object
$WindowsInstaller = New-Object -ComObject WindowsInstaller.Installer
#Loads the MSI database and specifies the mode to open it in by the last number on the line
$MSIDatabase = $WindowsInstaller.GetType().InvokeMember("OpenDatabase", "InvokeMethod", $Null, $WindowsInstaller, @($Path.FullName, 32))
#Specifies to query the MSIPatchMetadata table and get the value associated with the designated property
$Query = "SELECT Value FROM MsiPatchMetadata WHERE Property = '$($Property)'"
#Open up the property view
$View = $MSIDatabase.GetType().InvokeMember("OpenView", "InvokeMethod", $null, $MSIDatabase, ($Query))
$View.GetType().InvokeMember("Execute", "InvokeMethod", $null, $View, $null)
#Retrieve the associate Property
$Record = $View.GetType().InvokeMember("Fetch", "InvokeMethod", $null, $View, $null)
#Retrieve the associated value of the retrieved property
$Value = $Record.GetType().InvokeMember("StringData", "GetProperty", $null, $Record, 1)
return $Value
} catch {
Write-Output $_.Exception.Message
}
}
Write-Host "Find all Installed Microsoft Office 2016 32-Bit Updates ..." -ForegroundColor Cyan
$InstalledUpdates = foreach ($key in (Get-ChildItem -Path HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Installer\UserData\S-1-5-18\Products | Where-Object {$_.Name -match "F01FEC"})){
$subkey = $key.PSChildName
Get-ChildItem -Path HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Installer\UserData\S-1-5-18\Products\$subkey\Patches -ErrorAction SilentlyContinue |
Get-ItemProperty | Select-Object displayname,@{Name='KBNumber';Expression={$_.moreinfourl.substring($_.moreinfourl.length-11).ToUpper() -replace '[\W]'}} | Where-Object {$_.displayname -ne ""}
}
Write-Host "Find all Microsoft Office Update MSPs in $PSScriptRoot\Office 2016 32-Bit ..." -ForegroundColor Cyan
$OfficeUpdates = Get-ChildItem "$PSScriptRoot\Office 2016 32-Bit\*" -Recurse -File -Include *.msp
Write-Host "Gather Microsoft Office 2016 32-Bit MSP Information ..." -ForegroundColor Cyan
foreach ($Update in $OfficeUpdates) {
$mspReleaseVersion = Get-MSPFileInfo -Path $Update.FullName -Property 'ReleaseVersion'
$mspRelease = Get-MSPFileInfo -Path $Update.FullName -Property 'Release'
$mspDescription = Get-MSPFileInfo -Path $Update.FullName -Property 'Description'
$mspDisplayName = Get-MSPFileInfo -Path $Update.FullName -Property 'DisplayName'
$mspClassification = Get-MSPFileInfo -Path $Update.FullName -Property 'Classification'
$mspMoreInfoURL = Get-MSPFileInfo -Path $Update.FullName -Property 'MoreInfoURL'
$mspOptimizedInstallMode = Get-MSPFileInfo -Path $Update.FullName -Property 'OptimizedInstallMode'
$mspTargetProductName = Get-MSPFileInfo -Path $Update.FullName -Property 'TargetProductName'
$mspManufacturerName = Get-MSPFileInfo -Path $Update.FullName -Property 'ManufacturerName'
$mspCreationTimeUTC = Get-MSPFileInfo -Path $Update.FullName -Property 'CreationTimeUTC'
$mspAllowRemoval = Get-MSPFileInfo -Path $Update.FullName -Property 'AllowRemoval'
$mspOptimizeCA = Get-MSPFileInfo -Path $Update.FullName -Property 'OptimizeCA'
$mspBuildNumber = Get-MSPFileInfo -Path $Update.FullName -Property 'BuildNumber'
$mspKBArticleNumber = Get-MSPFileInfo -Path $Update.FullName -Property 'KBArticle Number'
$mspStdPackageName = Get-MSPFileInfo -Path $Update.FullName -Property 'StdPackageName'
$mspPatchType = Get-MSPFileInfo -Path $Update.FullName -Property 'PatchType'
$mspIsMinorUpgrade = Get-MSPFileInfo -Path $Update.FullName -Property 'IsMinorUpgrade'
$Update = $Update | Add-Member @{KBArticleNumber=$mspKBArticleNumber[1]} -PassThru
$Update = $Update | Add-Member @{ManufacturerName=$mspManufacturerName[1]} -PassThru
$Update = $Update | Add-Member @{TargetProductName=$mspTargetProductName[1]} -PassThru
$Update = $Update | Add-Member @{Classification=$mspClassification[1]} -PassThru
$Update = $Update | Add-Member @{DisplayName=$mspDisplayName[1]} -PassThru
$Update = $Update | Add-Member @{Description=$mspDescription[1]} -PassThru
$Update = $Update | Add-Member @{ReleaseVersion=$mspReleaseVersion[1]} -PassThru
$Update = $Update | Add-Member @{Release=$mspRelease[1]} -PassThru
$Update = $Update | Add-Member @{MoreInfoURL=$mspMoreInfoURL[1]} -PassThru
$Update = $Update | Add-Member @{OptimizedInstallMode=$mspOptimizedInstallMode[1]} -PassThru
#$Update = $Update | Add-Member @{CreationTimeUTC=$mspCreationTimeUTC[1]} -PassThru
$Update = $Update | Add-Member @{AllowRemoval=$mspAllowRemoval[1]} -PassThru
$Update = $Update | Add-Member @{OptimizeCA=$mspOptimizeCA[1]} -PassThru
$Update = $Update | Add-Member @{BuildNumber=$mspBuildNumber[1]} -PassThru
$Update = $Update | Add-Member @{StdPackageName=$mspStdPackageName[1]} -PassThru
$Update = $Update | Add-Member @{PatchType=$mspPatchType[1]} -PassThru
$Update = $Update | Add-Member @{IsMinorUpgrade=$mspIsMinorUpgrade[1]} -PassThru
}
#Sort
#$OfficeUpdates = $OfficeUpdates | Select-Object -Property * | Sort-Object -Property KBArticleNumber | Out-GridView -Wait
#$OfficeUpdates = $OfficeUpdates | Select-Object -Property Name, FullName, LastWriteTime, KBArticleNumber, ManufacturerName, TargetProductName, Classification, DisplayName, Description, ReleaseVersion, Release, MoreInfoURL, OptimizedInstallMode, AllowRemoval, OptimizeCA, BuildNumber, StdPackageName, PatchType, IsMinorUpgrade | Sort-Object -Property KBArticleNumber | Out-GridView -Wait
#$OfficeUpdates = $OfficeUpdates | Select-Object -Property LastWriteTime, Name, FullName, KBArticleNumber, ManufacturerName, TargetProductName, Classification, DisplayName, Description, ReleaseVersion, Release, MoreInfoURL, OptimizedInstallMode, OptimizeCA, BuildNumber, StdPackageName, PatchType, IsMinorUpgrade | Sort-Object -Property LastWriteTime | Out-GridView -Wait
$OfficeUpdates = $OfficeUpdates | Select-Object -Property LastWriteTime, Name, FullName, KBArticleNumber, ManufacturerName, TargetProductName, Classification, DisplayName, Description, ReleaseVersion, Release, MoreInfoURL, OptimizedInstallMode, OptimizeCA, BuildNumber, StdPackageName, PatchType, IsMinorUpgrade | Sort-Object -Property LastWriteTime
#Return
foreach ($Update in $OfficeUpdates) {
$DoUpdate = $true
#Write-Host "Checking KB$($Update.KBArticleNumber)" -ForegroundColor DarkGray
foreach ($InstalledUpdate in $InstalledUpdates) {
if ("KB$($Update.KBArticleNumber)" -eq "$($InstalledUpdate.KBNumber)") {
#Write-Host "Installed $($InstalledUpdate.KBNumber)" -ForegroundColor DarkGray
$DoUpdate = $false
}
}
$Name = $Update.Name
$DisplayName = $Update.DisplayName
$KBArticleNumber = $Update.KBArticleNumber
if ($DoUpdate) {
Write-Host "$DisplayName $Name ... Installing" -ForegroundColor Cyan
msiexec /p "$($Update.FullName)" /qr REBOOT=ReallySuppress MSIRESTARTMANAGERCONTROL=Disable | Out-Null
} else {
Write-Host "$DisplayName $Name ... installed" -ForegroundColor DarkGray
}
}
#Read-Host -Prompt "Press Enter to exit"
#ToDo
#Get-ItemProperty HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\* | Where-Object($_.DisplayName -Like "*Microsoft Office*") | Select-Object -Property DisplayName, DisplayVersion, Publisher | Out-GridView
#Get-ItemProperty HKLM:\Software\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\* | Where-Object {$_.DisplayName -Like "*Microsoft Office Professional*"} | Select-Object -Property * | Out-GridView
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment