Audyt dodatków Office zainstalowanych na lokalnym lub zdalnym komputerze.

📦 Office 365 POWERSHELL ChrisTitusTech

Audyt dodatków Office zainstalowanych na lokalnym lub zdalnym komputerze.

Pobierz .ps1

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

📄 Get-OfficeAddins-Modern.ps1 🕒 2026-04-13 📦 Źródło: christitustech
Get-OfficeAddins-Modern.ps1
#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
}