Audyt dodatków Office zainstalowanych na lokalnym lub zdalnym komputerze.
📦 Office 365 POWERSHELL ChrisTitusTechAudyt dodatków Office zainstalowanych na lokalnym lub zdalnym komputerze.
Opis
Nowoczesna wersja Get-OfficeAddins.ps1. MIGRACJA — co zostało zmienione: STARE (deprecated): Get-WmiObject -List "StdRegProv" → WMI (gwmi) usunięte w PS 7 cross-platform Get-WmiObject -Class ... → Get-WmiObject deprecated od PS 3, usunięte z PS 7+ Invoke-WmiMethod → WMI method call NOWE (2026): Get-CimInstance → CIM (DCOM/WSMan), działa PS 5.1 i PS 7+ Invoke-CimMethod → CIM method call [Microsoft.Win32.RegistryKey] → natywny .NET dla rejestru (szybszy niż WMI StdRegProv) Skanuje rejestr pod kątem dodatków COM, VSTO i Web Add-in dla: - Word, Excel, PowerPoint, Outlook, Access, Project, Visio
#Requires -Version 5.1
<#
.SYNOPSIS
Audyt dodatków Office zainstalowanych na lokalnym lub zdalnym komputerze.
.DESCRIPTION
Nowoczesna wersja Get-OfficeAddins.ps1.
MIGRACJA — co zostało zmienione:
STARE (deprecated):
Get-WmiObject -List "StdRegProv" → WMI (gwmi) usunięte w PS 7 cross-platform
Get-WmiObject -Class ... → Get-WmiObject deprecated od PS 3, usunięte z PS 7+
Invoke-WmiMethod → WMI method call
NOWE (2026):
Get-CimInstance → CIM (DCOM/WSMan), działa PS 5.1 i PS 7+
Invoke-CimMethod → CIM method call
[Microsoft.Win32.RegistryKey] → natywny .NET dla rejestru (szybszy niż WMI StdRegProv)
Skanuje rejestr pod kątem dodatków COM, VSTO i Web Add-in dla:
- Word, Excel, PowerPoint, Outlook, Access, Project, Visio
.PARAMETER ComputerName
Komputer(y) do przeskanowania. Domyślnie: localhost.
.PARAMETER ExportPath
Ścieżka do pliku CSV z wynikami. Opcjonalne.
.PARAMETER IncludeDisabled
Uwzględnij też wyłączone dodatki (LoadBehavior = 0, 2).
.EXAMPLE
.\Get-OfficeAddins-Modern.ps1
.EXAMPLE
.\Get-OfficeAddins-Modern.ps1 -ComputerName PC01,PC02 -ExportPath "C:\Raporty\addins.csv"
.EXAMPLE
.\Get-OfficeAddins-Modern.ps1 -ComputerName (Get-Content servers.txt) -IncludeDisabled
.NOTES
Wersja: 2.0.0 (2026)
PS 7+: Pełna obsługa (CimInstance przez WSMan)
PS 5.1: Obsługa lokalna i przez DCOM
#>
[CmdletBinding()]
param(
[Parameter(ValueFromPipeline, ValueFromPipelineByPropertyName)]
[string[]]$ComputerName = @($env:COMPUTERNAME),
[string]$ExportPath = "",
[switch]$IncludeDisabled
)
begin {
# Ścieżki rejestru dla dodatków Office (HKLM + HKCU)
$addinRegistryPaths = @(
"SOFTWARE\Microsoft\Office\Word\Addins",
"SOFTWARE\Microsoft\Office\Excel\Addins",
"SOFTWARE\Microsoft\Office\PowerPoint\Addins",
"SOFTWARE\Microsoft\Office\Outlook\Addins",
"SOFTWARE\Microsoft\Office\Access\Addins",
"SOFTWARE\WOW6432Node\Microsoft\Office\Word\Addins",
"SOFTWARE\WOW6432Node\Microsoft\Office\Excel\Addins",
"SOFTWARE\WOW6432Node\Microsoft\Office\PowerPoint\Addins",
"SOFTWARE\WOW6432Node\Microsoft\Office\Outlook\Addins"
)
# LoadBehavior: 0=wyłączony, 2=wyłączony+autostart, 3=włączony+autostart
$loadBehaviorMap = @{
0 = "Disabled"
2 = "Disabled (Boot)"
3 = "Enabled (Boot)"
8 = "Demand Load"
9 = "Enabled (Demand)"
16 = "First Boot"
}
$allResults = [System.Collections.Generic.List[PSCustomObject]]::new()
}
process {
foreach ($computer in $ComputerName) {
Write-Host "Skanowanie: $computer" -ForegroundColor Cyan
# ============================================================
# ODCZYT REJESTRU — .NET RegistryKey (zastępuje WMI StdRegProv)
# Dla lokalnego komputera — bezpośredni dostęp przez .NET
# Dla zdalnego — CimInstance (WSMan) lub PSSession
# ============================================================
$isLocal = ($computer -eq $env:COMPUTERNAME -or $computer -eq "localhost" -or $computer -eq ".")
if ($isLocal) {
# Lokalny dostęp — Microsoft.Win32.RegistryKey
foreach ($regPath in $addinRegistryPaths) {
$application = ($regPath -split "\\") | Select-Object -Last 2 | Select-Object -First 1
foreach ($hive in @("LocalMachine", "CurrentUser")) {
try {
$baseKey = [Microsoft.Win32.RegistryKey]::OpenBaseKey(
[Microsoft.Win32.RegistryHive]::$hive,
[Microsoft.Win32.RegistryView]::Default
)
$key = $baseKey.OpenSubKey($regPath)
if (-not $key) { continue }
foreach ($addinName in $key.GetSubKeyNames()) {
$addinKey = $key.OpenSubKey($addinName)
if (-not $addinKey) { continue }
$loadBehavior = $addinKey.GetValue("LoadBehavior") ?? 0
$loadStatus = $loadBehaviorMap[$loadBehavior] ?? "Unknown ($loadBehavior)"
# Filtruj wyłączone jeśli nie podano -IncludeDisabled
if (-not $IncludeDisabled -and $loadBehavior -in @(0, 2)) { continue }
$allResults.Add([PSCustomObject]@{
ComputerName = $computer
Application = $application
AddinName = $addinName
FriendlyName = $addinKey.GetValue("FriendlyName") ?? ""
Description = $addinKey.GetValue("Description") ?? ""
Manifest = $addinKey.GetValue("Manifest") ?? $addinKey.GetValue("InProcServer32") ?? ""
LoadBehavior = $loadBehavior
LoadStatus = $loadStatus
Hive = $hive
RegistryPath = "HKEY_$($hive.ToUpper())\$regPath\$addinName"
})
$addinKey.Close()
}
$key.Close()
$baseKey.Close()
} catch {
Write-Verbose "[$computer] Brak klucza: $hive\$regPath — $($_.Exception.Message)"
}
}
}
} else {
# Zdalny komputer — CimInstance przez WSMan
# (zastępuje: Get-WmiObject -ComputerName $computer)
Write-Verbose "[$computer] Używam CimInstance (WSMan)..."
try {
# Sprawdź połączenie CIM
$cimSession = New-CimSession -ComputerName $computer -ErrorAction Stop
foreach ($regPath in $addinRegistryPaths) {
$application = ($regPath -split "\\") | Select-Object -Last 2 | Select-Object -First 1
# Odczyt przez CIM — StdRegProv przez CimInstance
# (Get-WmiObject -List "StdRegProv" → Get-CimClass)
$hklm = [uint32]"0x80000002"
$hkcu = [uint32]"0x80000001"
foreach ($hiveVal in @($hklm, $hkcu)) {
$hiveName = if ($hiveVal -eq $hklm) { "LocalMachine" } else { "CurrentUser" }
# Enumerate subkeys przez CimInstance StdRegProv
$enumParams = @{
ClassName = "StdRegProv"
Namespace = "root\default"
MethodName = "EnumKey"
Arguments = @{ hDefKey = $hiveVal; sSubKeyName = $regPath }
CimSession = $cimSession
}
try {
$enumResult = Invoke-CimMethod @enumParams -ErrorAction Stop
if ($enumResult.ReturnValue -ne 0 -or -not $enumResult.sNames) { continue }
foreach ($addinName in $enumResult.sNames) {
$addinPath = "$regPath\$addinName"
# Pobierz wartości DWORD (LoadBehavior)
$getDword = Invoke-CimMethod -ClassName "StdRegProv" -Namespace "root\default" `
-MethodName "GetDWORDValue" `
-Arguments @{ hDefKey = $hiveVal; sSubKeyName = $addinPath; sValueName = "LoadBehavior" } `
-CimSession $cimSession -ErrorAction SilentlyContinue
$loadBehavior = $getDword.uValue ?? 0
$loadStatus = $loadBehaviorMap[$loadBehavior] ?? "Unknown ($loadBehavior)"
if (-not $IncludeDisabled -and $loadBehavior -in @(0, 2)) { continue }
# Pobierz FriendlyName (string)
$getName = Invoke-CimMethod -ClassName "StdRegProv" -Namespace "root\default" `
-MethodName "GetStringValue" `
-Arguments @{ hDefKey = $hiveVal; sSubKeyName = $addinPath; sValueName = "FriendlyName" } `
-CimSession $cimSession -ErrorAction SilentlyContinue
$allResults.Add([PSCustomObject]@{
ComputerName = $computer
Application = $application
AddinName = $addinName
FriendlyName = $getName.sValue ?? ""
LoadBehavior = $loadBehavior
LoadStatus = $loadStatus
Hive = $hiveName
RegistryPath = "HKEY_$($hiveName.ToUpper())\$addinPath"
})
}
} catch {
Write-Verbose "[$computer] Błąd CIM dla $regPath : $($_.Exception.Message)"
}
}
}
Remove-CimSession -CimSession $cimSession -ErrorAction SilentlyContinue
} catch {
Write-Warning "[$computer] Nie można nawiązać sesji CIM: $($_.Exception.Message)"
Write-Warning " Sprawdź: WinRM (Enable-PSRemoting), firewall, uprawnienia."
}
}
}
}
end {
if ($allResults.Count -eq 0) {
Write-Host "Nie znaleziono dodatków Office (spełniających kryteria)." -ForegroundColor Yellow
return
}
Write-Host "`nZnaleziono $($allResults.Count) dodatków:" -ForegroundColor Green
$allResults | Format-Table ComputerName, Application, FriendlyName, LoadStatus, AddinName -AutoSize
if ($ExportPath) {
$allResults | Export-Csv -Path $ExportPath -NoTypeInformation -Encoding UTF8 -Delimiter ";"
Write-Host "Eksport: $ExportPath" -ForegroundColor Green
}
return $allResults
}