1️⃣. PS – Apex One Agent Deploy Script

„Install-TrendMicro.ps1“ – Das Skript um den Apex One Security Agent von Trend Micro zu deployen!

In diesem Beitrag stelle ich dir ein Powershell-Skript vor, das für die automatische Installation und Überwachung eines Trend Micro OfficeScan-Updates in einer Windows-Domänenumgebung entwickelt wurde. Das Skript führt verschiedene Aufgaben aus – von der Logrotation über das Auslesen von Versionsinformationen bis hin zur Startsteuerung relevanter Dienste. Es richtet sich an fortgeschrittene Administratoren, die Prozesse automatisieren und gleichzeitig eine lückenlose Dokumentation sicherstellen möchten.


🔍 Überblick über das Skript

Es handelt sich im Grunde nur um zwei Funktionen, eine dient zum loggen und die andere Funktion „Install-TM“ beinhaltet den Kernteil. Im Kernteil werden zusätzlich die Trend Micro Dienste lokal auf dem Client geprüft und ggf. gestartet. Den Teil mit den Diensten könnte man noch in eine eigene Funktion überführen.

✅ Write-Log
✅ Install-TM #TM Dienste werden zusätzlich geprüft

PowerShell
param (
    # Das Logverzeichnis – standardmäßig C:\Temp\log
    [string]$LogFilePath = "C:\Temp\log",
    # $Server ist verpflichtend (z.B. "Exampleserver.domain.de")
    [Parameter(Mandatory = $true)]
    [string]$Server,
    # Der Share wird aus dem Servernamen gebildet
	#[string]$ServerShare = '\$Server\ofcscan',
    [string]$ServerShare = ('\\{0}\ofcscan' -f $Server),
    [string]$FileName = 'OFCSCAN.INI'
)

# Erstelle den ServerFilePath
$ServerFilePath = Join-Path $ServerShare "ofcscan.ini"

# Erstelle das Logverzeichnis, falls es nicht existiert
if (-not (Test-Path $LogFilePath)) {
    New-Item -Path $LogFilePath -ItemType Directory -Force | Out-Null
}

# Definiere den Pfad der Logdatei und das Archiv (als ZIP) im gleichen Verzeichnis
$LogFile = Join-Path $LogFilePath "log.txt"

Das Skript beginnt mit der Definition von Parametern, die folgende Informationen beinhalten:

  1. LogFilePath: Das Verzeichnis, in dem Logdateien gespeichert werden (Standard: C:\Temp\log).
  2. Server: Der Name des Servers (z. B. Exampleserver.domain.de), von dem die Konfigurationsdatei geladen wird – dieser Parameter ist verpflichtend.
  3. ServerShare: Der Pfad zum freigegebenen Ordner auf dem Server, in dem sich die zentrale Konfigurationsdatei (OFCSCAN.INI) befindet.
  4. FileName: Der Name der Konfigurationsdatei, standardmäßig OFCSCAN.INI.

Anschließend wird ein Pfad zur Server-Konfigurationsdatei erstellt und das Logverzeichnis erzeugt, falls es noch nicht existiert. Alle wichtigen Aktionen werden in einer Logdatei dokumentiert – inklusive einer automatischen Logrotation, wenn die Logdatei 5 MB überschreitet.


🚀 Teil 1: Logdatei und Logrotation

PowerShell
# Das Archiv erhält einen Zeitstempel im Dateinamen; standardmäßig wird hier eine ZIP erstellt
$DefaultArchiveZipFilePattern = "log_archive_{0:yyyyMMdd_HHmmss}.zip"
$ArchiveZipFile = Join-Path $LogFilePath ([string]::Format($DefaultArchiveZipFilePattern, (Get-Date)))

function Write-Log {
    param (
        [string]$Message,
        [string]$LogFile
    )
    $timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
    "$timestamp - $Message" | Out-File -FilePath $LogFile -Append
}

Die Funktion Write-Log fügt jedem Logeintrag einen Zeitstempel hinzu. Ist die Logdatei zu groß, wird sie temporär umbenannt, komprimiert und archiviert – so bleibt der Logordner übersichtlich und alte Daten werden gesichert.


🚀 Teil 2: Lokale und Server-Konfiguration auslesen

PowerShell
function Install-TM {
    param (
        [string]$LogFile,
        [string]$LogFilePath,
        [string]$ArchiveZipFile,
        [string]$ServerFilePath,
        [string]$FileName
    )
    # Log-Rotation prüfen und durchführen
    if (Test-Path $LogFile) {
        $logSize = (Get-Item $LogFile).Length
        if ($logSize -gt 5MB) {
            $tempArchive = "$LogFile.tmp"
            Rename-Item -Path $LogFile -NewName $tempArchive -Force
            try {
                Compress-Archive -Path $tempArchive -DestinationPath $ArchiveZipFile -Force
                Remove-Item $tempArchive -Force
                Write-Log -Message "Archivierte Logdatei komprimiert zu: $ArchiveZipFile" -LogFile $LogFile
            }
            catch {
                Write-Log -Message "Fehler beim Komprimieren der archivierten Logdatei: $_" -LogFile $LogFile
            }
        }
    }
    Write-Log -Message "TM Skript läuft" -LogFile $LogFile

    # Lokale Pfade definieren (z.B. OfficeScan Client und Security Agent)
    $localPaths = @(
        Join-Path $env:"ProgramFiles(x86)" "Trend Micro\OfficeScan Client",
        Join-Path $env:"ProgramFiles(x86)" "Trend Micro\Security Agent"
    )

    # Lokale INI-Datei einlesen
    $lokalFile = $null
    foreach ($path in $localPaths) {
        $iniPath = Join-Path -Path $path -ChildPath $FileName
        if (Test-Path $iniPath) {
            try {
                $lokalFile = Get-Content -Path $iniPath -ErrorAction Stop
                if ($lokalFile) { break }
            }
            catch {
                Write-Log -Message "Fehler beim Lesen der lokalen INI-Datei in $iniPath: $_" -LogFile $LogFile
            }
        }
    }
    if (-not $lokalFile) {
        Write-Log -Message "Lokale INI-Datei nicht gefunden." -LogFile $LogFile
        return
    }

    # Lokale Version auslesen
    try {
        $localVersionString = ($lokalFile | Select-String -Pattern "PccNT_Version").Line.Split("=")[1].Trim()
        $localVersionParts = $localVersionString.Split(".")
        $localVersion = @{
            Version    = [int]$localVersionParts[0]
            SubVersion = [int]$localVersionParts[1]
            BuildNum   = [int]( ($lokalFile | Select-String -Pattern "PccNT_BuildNum").Line.Split("=")[1].Trim() )
        }
    }
    catch {
        Write-Log -Message "Fehler beim Auslesen der lokalen Version: $_" -LogFile $LogFile
        return
    }

    # Server INI-Datei einlesen
    if (-not (Test-Path $ServerFilePath)) {
        Write-Log -Message "Server INI-Datei nicht gefunden: $ServerFilePath" -LogFile $LogFile
        return
    }
    try {
        $serverFile = Get-Content -Path $ServerFilePath -ErrorAction Stop
    }
    catch {
        Write-Log -Message "Fehler beim Lesen der Server INI-Datei: $_" -LogFile $LogFile
        return
    }

    # Server Version auslesen
    try {
        $serverVersionString = ($serverFile | Select-String -Pattern "PccNT_Version").Line.Split("=")[1].Trim()
        $serverVersionParts = $serverVersionString.Split(".")
        $serverVersion = @{
            Version    = [int]$serverVersionParts[0]
            SubVersion = [int]$serverVersionParts[1]
            BuildNum   = [int]( ($serverFile | Select-String -Pattern "PccNT_BuildNum").Line.Split("=")[1].Trim() )
        }
    }
    catch {
        Write-Log -Message "Fehler beim Auslesen der Server Version: $_" -LogFile $LogFile
        return
    }

    # Installationsentscheidung treffen
    $clientPath = Join-Path $env:"ProgramFiles(x86)" "Trend Micro\OfficeScan Client"
    $startInstall = $false
    if (-not (Test-Path $clientPath)) {
        Write-Log -Message "OfficeScan Client nicht gefunden. Installation wird gestartet." -LogFile $LogFile
        $startInstall = $true
    }
    else {
        if ($localVersion.Version -lt $serverVersion.Version) {
            $startInstall = $true
        }
        elseif ($localVersion.Version -eq $serverVersion.Version -and $localVersion.SubVersion -lt $serverVersion.SubVersion) {
            $startInstall = $true
        }
        elseif ($localVersion.Version -eq $serverVersion.Version -and $localVersion.SubVersion -eq $serverVersion.SubVersion -and $localVersion.BuildNum -lt $serverVersion.BuildNum) {
            $startInstall = $true
        }
    }

Im nächsten Schritt sucht das Skript in zwei vordefinierten Verzeichnissen nach der lokalen OFCSCAN.INI Datei. Wird die Datei gefunden, wird der darin enthaltene Versionsstring (sowohl PccNT_Version als auch PccNT_BuildNum) ausgelesen und in eine Hashtable überführt. Anschließend erfolgt das Auslesen der entsprechenden Werte aus der zentralen Konfigurationsdatei, die über einen UNC-Pfad erreichbar ist.

Durch den Vergleich der Versionsnummern wird ermittelt, ob eine Aktualisierung erforderlich ist:

  1. Ist die lokale Hauptversion kleiner als die Server-Version, wird ein Update initiiert.
  2. Ist die Hauptversion gleich, aber die Nebenversion kleiner, erfolgt ebenfalls ein Update.
  3. Bei gleichen Haupt- und Nebenversionen wird zusätzlich die Buildnummer verglichen.

🚀 Teil 3: Update-Entscheidung und Dienststeuerung

PowerShell
 if ($startInstall) {
        Write-Log -Message "Starte Installation von Trend Micro. Lokale Version: $($localVersion.Version).$($localVersion.SubVersion).$($localVersion.BuildNum) - Server Version: $($serverVersion.Version).$($serverVersion.SubVersion).$($serverVersion.BuildNum)" -LogFile $LogFile
        try {
            Start-Process -FilePath "\\$Server\ofcscan\Autopcc.exe"
        }
        catch {
            Write-Log -Message "Fehler beim Starten der Installation: $_" -LogFile $LogFile
        }
    }
    else {
        Write-Log -Message "Keine Installation notwendig. Lokale Version ist aktuell." -LogFile $LogFile
    }

    # Dienste überprüfen und starten
    $services = @(
        'ntrtscan',
        'tmccsf',
        'tmlisten',
        'TmPfw',
        'TmWSCSvc'
    )

    foreach ($service in $services) {
        try {
            $svc = Get-Service -Name $service -ErrorAction Stop
            if ($svc.Status -ne 'Running') {
                Write-Log -Message "Starte Dienst: $($svc.DisplayName)" -LogFile $LogFile
                Start-Service -Name $service
            }
            else {
                Write-Log -Message "Dienst läuft bereits: $($svc.DisplayName)" -LogFile $LogFile
            }
        }
        catch {
            Write-Log -Message "Fehler beim Verarbeiten des Dienstes $service: $_" -LogFile $LogFile
        }
    }
}

Wenn festgestellt wird, dass die lokale Version veraltet ist, startet das Skript das Update, indem es die Anwendung Autopcc.exe vom zentralen Server ausführt. Zusätzlich prüft das Skript eine Liste von wichtigen Trend Micro-Diensten (wie ntrtscan, tmccsf und weitere) – sollten diese nicht laufen, werden sie automatisch gestartet.


📌 Das Ergebnis

PowerShell
param (
    # Das Logverzeichnis – standardmäßig C:\Temp\log
    [string]$LogFilePath = "C:\Temp\log",
    
    # $Server ist verpflichtend (z.B. "Exampleserver.domain.de")
    [Parameter(Mandatory = $true)]
    [string]$Server,
    
    # Der Share wird aus dem Servernamen gebildet
    [string]$ServerShare = ('\\{0}\ofcscan' -f $Server),
    
    # Name der INI-Datei
    [string]$FileName = 'OFCSCAN.INI'
)

# Erstelle den ServerFilePath
$ServerFilePath = Join-Path -Path $ServerShare -ChildPath "ofcscan.ini"

# Erstelle das Logverzeichnis, falls es nicht existiert
if (-not (Test-Path -Path $LogFilePath)) {
    New-Item -Path $LogFilePath -ItemType Directory -Force | Out-Null
}

# Definiere den Pfad der Logdatei und das Archiv (als ZIP) im gleichen Verzeichnis
$LogFile = Join-Path -Path $LogFilePath -ChildPath "log.txt"
# Das Archiv erhält einen Zeitstempel im Dateinamen; standardmäßig wird hier eine ZIP erstellt
$DefaultArchiveZipFilePattern = "log_archive_{0:yyyyMMdd_HHmmss}.zip"
$ArchiveZipFile = Join-Path -Path $LogFilePath -ChildPath ([string]::Format($DefaultArchiveZipFilePattern, (Get-Date)))

function Write-Log {
    param (
        [string]$Message,
        [string]$LogFile
    )
    $timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
    "$timestamp - $Message" | Out-File -FilePath $LogFile -Append
}

function Install-TM {
    param (
        [string]$LogFile,
        [string]$LogFilePath,
        [string]$ArchiveZipFile,
        [string]$ServerFilePath,
        [string]$FileName
    )
    # Log-Rotation prüfen und durchführen
    if (Test-Path -Path $LogFile) {
        $logSize = (Get-Item -Path $LogFile).Length
        if ($logSize -gt 5MB) {
            $tempArchive = "$LogFile.tmp"
            Rename-Item -Path $LogFile -NewName $tempArchive -Force
            try {
                Compress-Archive -Path $tempArchive -DestinationPath $ArchiveZipFile -Force
                Remove-Item -Path $tempArchive -Force
                Write-Log -Message "Archivierte Logdatei komprimiert zu: $ArchiveZipFile" -LogFile $LogFile
            }
            catch {
                Write-Log -Message "Fehler beim Komprimieren der archivierten Logdatei: $($_.Exception.Message)" -LogFile $LogFile
            }
        }
    }
    
    Write-Log -Message "TM Skript läuft" -LogFile $LogFile

    # Lokale Pfade definieren (z.B. OfficeScan Client und Security Agent)
    $localPaths = @(
        (Join-Path -Path ${env:ProgramFiles(x86)} -ChildPath "Trend Micro\OfficeScan Client"),
        (Join-Path -Path ${env:ProgramFiles(x86)} -ChildPath "Trend Micro\Security Agent")
    )

    # Lokale INI-Datei einlesen
    $lokalFile = $null
    foreach ($path in $localPaths) {
        $iniPath = Join-Path -Path $path -ChildPath $FileName
        if (Test-Path -Path $iniPath) {
            try {
                $lokalFile = Get-Content -Path $iniPath -ErrorAction Stop
                if ($lokalFile) { break }
            }
            catch {
                Write-Log -Message "Fehler beim Lesen der lokalen INI-Datei in $iniPath : $($_.Exception.Message)" -LogFile $LogFile
            }
        }
    }
    
    if (-not $lokalFile) {
        Write-Log -Message "Lokale INI-Datei nicht gefunden." -LogFile $LogFile
        return
    }

    # Lokale Version auslesen
    try {
        $localVersionString = ($lokalFile | Select-String -Pattern "PccNT_Version").Line.Split("=")[1].Trim()
        $localVersionParts = $localVersionString.Split(".")
        $localVersion = @{
            Version    = [int]$localVersionParts[0]
            SubVersion = [int]$localVersionParts[1]
            BuildNum   = [int](($lokalFile | Select-String -Pattern "PccNT_BuildNum").Line.Split("=")[1].Trim())
        }
    }
    catch {
        Write-Log -Message "Fehler beim Auslesen der lokalen Version: $($_.Exception.Message)" -LogFile $LogFile
        return
    }

    # Server INI-Datei einlesen
    if (-not (Test-Path -Path $ServerFilePath)) {
        Write-Log -Message "Server INI-Datei nicht gefunden: $ServerFilePath" -LogFile $LogFile
        return
    }
    
    try {
        $serverFile = Get-Content -Path $ServerFilePath -ErrorAction Stop
    }
    catch {
        Write-Log -Message "Fehler beim Lesen der Server INI-Datei: $($_.Exception.Message)" -LogFile $LogFile
        return
    }

    # Server Version auslesen
    try {
        $serverVersionString = ($serverFile | Select-String -Pattern "PccNT_Version").Line.Split("=")[1].Trim()
        $serverVersionParts = $serverVersionString.Split(".")
        $serverVersion = @{
            Version    = [int]$serverVersionParts[0]
            SubVersion = [int]$serverVersionParts[1]
            BuildNum   = [int](($serverFile | Select-String -Pattern "PccNT_BuildNum").Line.Split("=")[1].Trim())
        }
    }
    catch {
        Write-Log -Message "Fehler beim Auslesen der Server Version: $($_.Exception.Message)" -LogFile $LogFile
        return
    }

    # Installationsentscheidung treffen
    $clientPath = Join-Path -Path ${env:ProgramFiles(x86)} -ChildPath "Trend Micro\OfficeScan Client"
    $startInstall = $false
    
    if (-not (Test-Path -Path $clientPath)) {
        Write-Log -Message "OfficeScan Client nicht gefunden. Installation wird gestartet." -LogFile $LogFile
        $startInstall = $true
    }
    else {
        if ($localVersion.Version -lt $serverVersion.Version) {
            $startInstall = $true
        }
        elseif ($localVersion.Version -eq $serverVersion.Version -and $localVersion.SubVersion -lt $serverVersion.SubVersion) {
            $startInstall = $true
        }
        elseif ($localVersion.Version -eq $serverVersion.Version -and $localVersion.SubVersion -eq $serverVersion.SubVersion -and $localVersion.BuildNum -lt $serverVersion.BuildNum) {
            $startInstall = $true
        }
    }

    if ($startInstall) {
        Write-Log -Message "Starte Installation von Trend Micro. Lokale Version: $($localVersion.Version).$($localVersion.SubVersion).$($localVersion.BuildNum) - Server Version: $($serverVersion.Version).$($serverVersion.SubVersion).$($serverVersion.BuildNum)" -LogFile $LogFile
        try {
            Start-Process -FilePath "\\$Server\ofcscan\Autopcc.exe"
        }
        catch {
            Write-Log -Message "Fehler beim Starten der Installation: $($_.Exception.Message)" -LogFile $LogFile
        }
    }
    else {
        Write-Log -Message "Keine Installation notwendig. Lokale Version ist aktuell." -LogFile $LogFile
    }

    # Dienste überprüfen und starten
    $services = @(
        'ntrtscan',
        'tmccsf',
        'tmlisten',
        'TmPfw',
        'TmWSCSvc'
    )
    
    foreach ($service in $services) {
        try {
            $svc = Get-Service -Name $service -ErrorAction Stop
            if ($svc.Status -ne 'Running') {
                Write-Log -Message "Starte Dienst: $($svc.DisplayName)" -LogFile $LogFile
                Start-Service -Name $service
            }
            else {
                Write-Log -Message "Dienst läuft bereits: $($svc.DisplayName)" -LogFile $LogFile
            }
        }
        catch {
            Write-Log -Message "Fehler beim Verarbeiten des Dienstes $service : $($_.Exception.Message)" -LogFile $LogFile
        }
    }
}

Install-TM -LogFile $LogFile -LogFilePath $LogFilePath -ArchiveZipFile $ArchiveZipFile -ServerFilePath $ServerFilePath -FileName $FileName

Dieses Skript bietet eine umfassende Lösung zur Automatisierung von OfficeScanAgent-Updates in einer Windows-Domänenumgebung. Durch die Kombination von Logrotation, Versionsvergleich und automatisierter Dienststeuerung können Administratoren sicherstellen, dass ihre Systeme stets auf dem neuesten Stand und optimal geschützt sind.

Wenn man das Ganze noch etwas aufhübscht, die comment-based Hilfe hinzufügt und das logging erweitert, erhält man ein gutes Skript und leicht verständliches Skript.

PowerShell
<#
.SYNOPSIS
 Installiert oder aktualisiert den Trend Micro OfficeScan Client.

.DESCRIPTION
 Dieses Skript vergleicht die lokal installierte Version des Trend Micro OfficeScan Clients
 mit der Version auf dem angegebenen Server. Wenn die lokale Version älter ist oder der Client
 nicht installiert ist, wird automatisch eine Installation oder ein Update durchgeführt.
 Zusätzlich werden relevante Trend Micro Dienste überprüft und bei Bedarf gestartet.

.PARAMETER LogFilePath
 Pfad zum Logverzeichnis. Wenn nicht angegeben, wird standardmäßig "C:\Temp\log" verwendet.

.PARAMETER Server
 Name des Servers, auf dem die Trend Micro OfficeScan-Installationsdateien liegen.
 Dieser Parameter ist obligatorisch.

.PARAMETER ServerShare
 Netzwerkpfad zum OfficeScan-Share auf dem Server. Wird automatisch aus dem Servernamen generiert.
 Standardwert: \\[Server]\ofcscan

.PARAMETER FileName
 Name der INI-Datei, die für den Versionsvergleich verwendet wird.
 Standardwert: OFCSCAN.INI

.EXAMPLE
 .\Install-TrendMicro.ps1 -Server "Exampleserver.domain.de"
 Führt das Skript mit dem angegebenen Server und Standardwerten für die anderen Parameter aus.

.EXAMPLE
 .\Install-TrendMicro.ps1 -Server "Exampleserver.domain.de" -LogFilePath "D:\Logs\TrendMicro"
 Führt das Skript mit angepasstem Logverzeichnis aus.

.NOTES
 Dateiname:      Install-TrendMicro.ps1
 Autor:          Ismahil Ahmed
 Erstelldatum:   04.04.2023
 Version:        1.1 
 Änderungsprotokoll:
 1.0 - Ursprüngliche Version
 1.1 - Skriptverbesserungen und Comment-Help hinzugefügt
#>

[CmdletBinding()]
param (
    # Das Logverzeichnis – standardmäßig C:\Temp\log
    [string]$LogFilePath = "C:\Temp\log", 
    
    # $Server ist verpflichtend (z.B. "Exampleserver.domain.de")
    [Parameter(Mandatory = $true)]
    [string]$Server, 
    
    # Der Share wird aus dem Servernamen gebildet
    [string]$ServerShare = ('\\{0}\ofcscan' -f $Server), 
    
    # Name der INI-Datei
    [string]$FileName = 'OFCSCAN.INI'
)

# Erstelle den ServerFilePath
$ServerFilePath = Join-Path -Path $ServerShare -ChildPath $FileName

# Erstelle das Logverzeichnis, falls es nicht existiert
if (-not (Test-Path -Path $LogFilePath)) {
    New-Item -Path $LogFilePath -ItemType Directory -Force | Out-Null
}

# Definiere den Pfad der Logdatei und das Archiv (als ZIP) im gleichen Verzeichnis
$LogFile = Join-Path -Path $LogFilePath -ChildPath "log.txt"
# Das Archiv erhält einen Zeitstempel im Dateinamen; standardmäßig wird hier eine ZIP erstellt
$DefaultArchiveZipFilePattern = "log_archive_{0:yyyyMMdd_HHmmss}.zip"
$ArchiveZipFile = Join-Path -Path $LogFilePath -ChildPath ([string]::Format($DefaultArchiveZipFilePattern, (Get-Date)))

function Write-Log {
    <#
    .SYNOPSIS
    Schreibt Nachrichten mit Zeitstempel in eine Logdatei. 
    
    .PARAMETER Message
    Die zu protokollierende Nachricht. 
    
    .PARAMETER LogFile
    Pfad zur Logdatei.
    #>
    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true)]
        [string]$Message, 
        
        [Parameter(Mandatory = $true)]
        [string]$LogFile
    ) 
    
    $timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
    "$timestamp - $Message" | Out-File -FilePath $LogFile -Append
}

function Install-TM {
    <#
    .SYNOPSIS
    Hauptfunktion zur Installation und Aktualisierung von Trend Micro OfficeScan. 
    
    .DESCRIPTION
    Prüft die lokale Version gegen die Server-Version und installiert oder aktualisiert den Client bei Bedarf.
    Startet außerdem relevante Dienste. 
    
    .PARAMETER LogFile
    Pfad zur Logdatei. 
    
    .PARAMETER LogFilePath
    Pfad zum Logverzeichnis. 
    
    .PARAMETER ArchiveZipFile
    Pfad zur archivierten Logdatei (ZIP). 
    
    .PARAMETER ServerFilePath
    Vollständiger Pfad zur INI-Datei auf dem Server. 
    
    .PARAMETER FileName
    Name der INI-Datei.
    #>
    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true)]
        [string]$LogFile, 
        
        [Parameter(Mandatory = $true)]
        [string]$LogFilePath, 
        
        [Parameter(Mandatory = $true)]
        [string]$ArchiveZipFile, 
        
        [Parameter(Mandatory = $true)]
        [string]$ServerFilePath, 
        
        [Parameter(Mandatory = $true)]
        [string]$FileName
    ) 
    
    # Log-Rotation prüfen und durchführen
    if (Test-Path -Path $LogFile) {
        $logSize = (Get-Item -Path $LogFile).Length
        if ($logSize -gt 5MB) {
            $tempArchive = "$LogFile.tmp"
            Rename-Item -Path $LogFile -NewName $tempArchive -Force
            try {
                Compress-Archive -Path $tempArchive -DestinationPath $ArchiveZipFile -Force
                Remove-Item -Path $tempArchive -Force
                Write-Log -Message "Archivierte Logdatei komprimiert zu: $ArchiveZipFile" -LogFile $LogFile
            }
            catch {
                Write-Log -Message "Fehler beim Komprimieren der archivierten Logdatei: $($_.Exception.Message)" -LogFile $LogFile
            }
        }
    } 
    
    Write-Log -Message "TM Skript läuft" -LogFile $LogFile

    # Hilfsfunktion zur Installation
    function Start-Installation {
        Write-Log -Message "Starte Installation/Update von Trend Micro." -LogFile $LogFile
        try {
            $installPath = "\\$Server\ofcscan\Autopcc.exe"
            Write-Log -Message "Starte Installer von: $installPath" -LogFile $LogFile 
            
            $process = Start-Process -FilePath $installPath -PassThru -Wait -ErrorAction Stop 
            
            if ($process.ExitCode -eq 0) {
                Write-Log -Message "Installation/Update erfolgreich abgeschlossen." -LogFile $LogFile
            }
            else {
                Write-Log -Message "Installation/Update mit Exit-Code $($process.ExitCode) beendet." -LogFile $LogFile
            }
        }
        catch {
            Write-Log -Message "Fehler beim Starten der Installation: $($_.Exception.Message)" -LogFile $LogFile
        }
    } 
    
    # Hilfsfunktion zum Starten der Dienste
    function Start-TrendMicroServices {
        $services = @(
            'ntrtscan',
            'tmccsf',
            'tmlisten',
            'TmPfw',
            'TmWSCSvc'
        ) 
        
        Write-Log -Message "Überprüfe Trend Micro Dienste..." -LogFile $LogFile 
        
        foreach ($service in $services) {
            try {
                $svc = Get-Service -Name $service -ErrorAction Stop
                if ($svc.Status -ne 'Running') {
                    Write-Log -Message "Starte Dienst: $($svc.DisplayName)" -LogFile $LogFile
                    Start-Service -Name $service -ErrorAction Stop 
                    
                    # Warte kurz und prüfe, ob der Dienst gestartet wurde
                    Start-Sleep -Seconds 2
                    $svc = Get-Service -Name $service
                    if ($svc.Status -eq 'Running') {
                        Write-Log -Message "Dienst $($svc.DisplayName) erfolgreich gestartet." -LogFile $LogFile
                    }
                    else {
                        Write-Log -Message "Dienst $($svc.DisplayName) konnte nicht gestartet werden." -LogFile $LogFile
                    }
                }
                else {
                    Write-Log -Message "Dienst läuft bereits: $($svc.DisplayName)" -LogFile $LogFile
                }
            }
            catch {
                Write-Log -Message "Fehler beim Verarbeiten des Dienstes $service : $($_.Exception.Message)" -LogFile $LogFile
            }
        } 
        
        Write-Log -Message "Dienste-Überprüfung abgeschlossen." -LogFile $LogFile
    }

    # Lokale Pfade definieren (z.B. OfficeScan Client und Security Agent)
    $path1 = Join-Path -Path ${env:ProgramFiles(x86)} -ChildPath "Trend Micro\OfficeScan Client"
    $path2 = Join-Path -Path ${env:ProgramFiles(x86)} -ChildPath "Trend Micro\Security Agent"
    $localPaths = @($path1, $path2)

    # Lokale INI-Datei einlesen
    $lokalFile = $null
    foreach ($path in $localPaths) {
        $iniPath = Join-Path -Path $path -ChildPath $FileName
        if (Test-Path -Path $iniPath) {
            try {
                $lokalFile = Get-Content -Path $iniPath -ErrorAction Stop
                if ($lokalFile) { 
                    Write-Log -Message "Lokale INI-Datei gefunden in: $iniPath" -LogFile $LogFile
                    break 
                }
            }
            catch {
                Write-Log -Message "Fehler beim Lesen der lokalen INI-Datei in $iniPath : $($_.Exception.Message)" -LogFile $LogFile
            }
        }
    } 
    
    if (-not $lokalFile) {
        Write-Log -Message "Lokale INI-Datei nicht gefunden. Installation wird gestartet." -LogFile $LogFile
        Start-Installation
        return
    }

    # Lokale Version auslesen
    try {
        $localVersionString = ($lokalFile | Select-String -Pattern "PccNT_Version").Line.Split("=")[1].Trim()
        $localVersionParts = $localVersionString.Split(".")
        $localVersion = @{
            Version    = [int]$localVersionParts[0]
            SubVersion = [int]$localVersionParts[1]
            BuildNum   = [int](($lokalFile | Select-String -Pattern "PccNT_BuildNum").Line.Split("=")[1].Trim())
        } 
        
        Write-Log -Message "Lokale Version: $($localVersion.Version).$($localVersion.SubVersion) Build $($localVersion.BuildNum)" -LogFile $LogFile
    }
    catch {
        Write-Log -Message "Fehler beim Auslesen der lokalen Version: $($_.Exception.Message)" -LogFile $LogFile
        return
    }

    # Server INI-Datei einlesen
    if (-not (Test-Path -Path $ServerFilePath)) {
        Write-Log -Message "Server INI-Datei nicht gefunden: $ServerFilePath" -LogFile $LogFile
        return
    } 
    
    try {
        $serverFile = Get-Content -Path $ServerFilePath -ErrorAction Stop
    }
    catch {
        Write-Log -Message "Fehler beim Lesen der Server INI-Datei: $($_.Exception.Message)" -LogFile $LogFile
        return
    }

    # Server Version auslesen
    try {
        $serverVersionString = ($serverFile | Select-String -Pattern "PccNT_Version").Line.Split("=")[1].Trim()
        $serverVersionParts = $serverVersionString.Split(".")
        $serverVersion = @{
            Version    = [int]$serverVersionParts[0]
            SubVersion = [int]$serverVersionParts[1]
            BuildNum   = [int](($serverFile | Select-String -Pattern "PccNT_BuildNum").Line.Split("=")[1].Trim())
        } 
        
        Write-Log -Message "Server Version: $($serverVersion.Version).$($serverVersion.SubVersion) Build $($serverVersion.BuildNum)" -LogFile $LogFile
    }
    catch {
        Write-Log -Message "Fehler beim Auslesen der Server Version: $($_.Exception.Message)" -LogFile $LogFile
        return
    }

    # Installationsentscheidung treffen
    $clientPath = Join-Path -Path ${env:ProgramFiles(x86)} -ChildPath "Trend Micro\OfficeScan Client"
    $startInstall = $false 
    
    if (-not (Test-Path -Path $clientPath)) {
        Write-Log -Message "OfficeScan Client nicht gefunden. Installation wird gestartet." -LogFile $LogFile
        $startInstall = $true
    }
    else {
        if ($localVersion.Version -lt $serverVersion.Version) {
            $startInstall = $true
            Write-Log -Message "Hauptversion ist veraltet. Update erforderlich." -LogFile $LogFile
        }
        elseif ($localVersion.Version -eq $serverVersion.Version -and $localVersion.SubVersion -lt $serverVersion.SubVersion) {
            $startInstall = $true
            Write-Log -Message "Unterversion ist veraltet. Update erforderlich." -LogFile $LogFile
        }
        elseif ($localVersion.Version -eq $serverVersion.Version -and 
            $localVersion.SubVersion -eq $serverVersion.SubVersion -and 
            $localVersion.BuildNum -lt $serverVersion.BuildNum) {
            $startInstall = $true
            Write-Log -Message "Build-Nummer ist veraltet. Update erforderlich." -LogFile $LogFile
        }
    }

    # Installation oder Update starten
    if ($startInstall) {
        Start-Installation
    }
    else {
        Write-Log -Message "Keine Installation notwendig. Lokale Version ist aktuell." -LogFile $LogFile
    }

    # Dienste überprüfen und starten
    Start-TrendMicroServices 
}

# Hauptskript ausführen
try {
    Write-Log -Message "=== Skript gestartet ===" -LogFile $LogFile
    Install-TM -LogFile $LogFile -LogFilePath $LogFilePath -ArchiveZipFile $ArchiveZipFile -ServerFilePath $ServerFilePath -FileName $FileName
    Write-Log -Message "=== Skript erfolgreich beendet ===" -LogFile $LogFile
}
catch {
    Write-Log -Message "=== Skript mit Fehler beendet: $($_.Exception.Message) ===" -LogFile $LogFile
}

Hast du Fragen oder Anregungen zu diesem Ansatz? Teile deine Erfahrungen und Tipps gern in den Kommentaren mit!

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert