#Requires -RunAsAdministrator <# .SYNOPSIS Unattended Installation Veeam Backup & Replication v13 mit vorhandener Microsoft SQL Server Instanz .DESCRIPTION Installation über DVD/ISO oder Netzwerkquelle Verwendung einer vorhandenen MSSQL Instanz Datenbank: SERVER\VEEAMSQLSERVER Version: 1.2 #> ############################################################ # GLOBAL SETTINGS ############################################################ $ErrorActionPreference = "Stop" Set-StrictMode -Version Latest ############################################################ # VARIABLEN ############################################################ # Installationsquellen $DVDSource = "E:\" $NetworkSource = "\\172.68.1.1\Sources" # Arbeitsverzeichnis $WorkDir = "C:\Temp\VeeamInstall" $LogDir = "$WorkDir\Logs" # Antwortdatei $AnswerFileName = "VbrAnswerFile_install.xml" $AnswerFile = "$WorkDir\$AnswerFileName" # Lizenz $LicenseSource = "$($DVDSource)\License\veeam.lic" $LicenseTarget = "$WorkDir\veeam.lic" # Server $VeeamServerName = $env:COMPUTERNAME # SQL $SQLInstanceName = "VEEAMSQLSERVER" $SQLConnection = "$VeeamServerName\$SQLInstanceName" $DatabaseName = "VeeamBackup" $SQLAuthentication = 0 # Pfade $InstallPath = "F:\Program Files\Veeam\Backup and Replication" $CatalogPath = "H:\VBRCatalog" $IRCachePath = "F:\ProgramData\Veeam\Backup\IRCache" # Ports $GuestCatalogPort = 9393 $VeeamServicePort = 9392 $SecureConnectionPort = 9401 $RestServicePort = 9419 # Neustart $RebootRequired = 0 # Plugins $Plugins = @{ "AHV_INSTALL" = 0 "KVM_INSTALL" = 0 "PVE_INSTALL" = 0 "SCP_INSTALL" = 0 "AWS_INSTALL" = 0 "AZURE_INSTALL" = 0 "GCP_INSTALL" = 0 "KASTEN_INSTALL" = 0 } # Wird später gesetzt $VeeamSource = "" $VeeamInstaller = "" $AnswerFileSource = "" $UseLicenseFile = $false ############################################################ # FUNKTIONEN ############################################################ function Write-Log { param( [Parameter(Mandatory)] [string] $Message ) $Time = Get-Date -Format "yyyy-MM-dd HH:mm:ss" $Entry = "$Time - $Message" Write-Host $Entry if(Test-Path $LogDir) { Add-Content ` -Path "$LogDir\Install.log" ` -Value $Entry } } function Initialize-Directories { Write-Log "Erstelle Arbeitsverzeichnisse" foreach($Path in @( $WorkDir, $LogDir )) { if(!(Test-Path $Path)) { New-Item ` -Path $Path ` -ItemType Directory ` -Force | Out-Null } } } function Remove-OldInstallFiles { if(Test-Path $WorkDir) { try { Remove-Item ` -Path $WorkDir ` -Recurse ` -Force ` -ErrorAction Stop Write-Host "Alte VeeamInstall-Dateien entfernt." } catch { Write-Host "Fehler beim Löschen: $($_.Exception.Message)" exit 1 } } } function Select-VeeamSource { Write-Host "" Write-Host "Veeam Installationsquelle" Write-Host "=========================" Write-Host "1 = DVD / ISO Quelle ($DVDSource)" Write-Host "2 = Netzwerkquelle ($NetworkSource)" Write-Host "" $Choice = Read-Host "Quelle auswählen (1 oder 2)" switch($Choice) { "1" { $script:VeeamSource = $DVDSource Write-Host "" Write-Host "Lokale Quelle gewählt:" Write-Host $VeeamSource } "2" { Write-Host "" Write-Host "Netzwerkquelle wird verwendet" $Credential = Get-Credential New-PSDrive ` -Name "VEEAMSRC" ` -PSProvider FileSystem ` -Root $NetworkSource ` -Credential $Credential ` -ErrorAction Stop | Out-Null $script:VeeamSource = $NetworkSource Write-Host "" Write-Host "Netzwerkquelle verbunden:" Write-Host $VeeamSource } default { Write-Host "Ungültige Auswahl" exit 1 } } $script:VeeamInstaller = "$VeeamSource\Setup\Silent\Veeam.Silent.Install.exe" $script:AnswerFileSource = "$VeeamSource\Setup\Silent\AnswerFiles\VBR\VbrAnswerFile_install.xml" } function Test-VeeamSource { Write-Log "Prüfe Installationsquelle" if(!(Test-Path $VeeamInstaller)) { Write-Log "FEHLER: Installer nicht gefunden" exit 1 } if(!(Test-Path $AnswerFileSource)) { Write-Log "FEHLER: Antwortdatei nicht gefunden" exit 1 } Write-Log "Installationsquelle OK" } ############################################################ # LIZENZ ############################################################ function Copy-VeeamLicense { Write-Log "Prüfe Lizenzdatei" $Source = "$VeeamSource\License\veeam.lic" if(Test-Path $Source) { Copy-Item ` -Path $Source ` -Destination $LicenseTarget ` -Force ` -ErrorAction Stop $script:UseLicenseFile = $true Write-Log "Lizenzdatei kopiert: $LicenseTarget" } else { $script:UseLicenseFile = $false Write-Log "Keine Lizenzdatei gefunden" Write-Log "Installation als Community Edition" } } ############################################################ # ANTWORTDATEI ############################################################ function Prepare-AnswerFile { Write-Log "Kopiere Antwortdatei" Copy-Item ` -Path $AnswerFileSource ` -Destination $AnswerFile ` -Force ` -ErrorAction Stop if(!(Test-Path $AnswerFile)) { Write-Log "FEHLER: Antwortdatei nicht vorhanden" exit 1 } # # Blockierung durch Windows entfernen # Unblock-File ` -Path $AnswerFile ` -ErrorAction SilentlyContinue # # Attribute entfernen # attrib -R $AnswerFile attrib -S $AnswerFile attrib -H $AnswerFile # # Rechte setzen # icacls ` $AnswerFile ` /grant Administrators:F ` /grant SYSTEM:F ` | Out-Null Write-Log "Antwortdatei vorbereitet" } ############################################################ # XML ÄNDERN ############################################################ function Update-AnswerFile { Write-Log "Bearbeite Antwortdatei" try { [xml]$XML = Get-Content ` -Path $AnswerFile ` -Encoding UTF8 } catch { Write-Log "XML Fehler: $($_.Exception.Message)" exit 1 } foreach($Property in $XML.unattendedInstallationConfiguration.properties.property) { switch($Property.name) { "ACCEPT_EULA" { $Property.value = "1" } "ACCEPT_LICENSING_POLICY" { $Property.value = "1" } "ACCEPT_THIRDPARTY_LICENSES" { $Property.value = "1" } "ACCEPT_REQUIRED_SOFTWARE" { $Property.value = "1" } "VBR_LICENSE_FILE" { if($UseLicenseFile) { $Property.value = $LicenseTarget } else { $Property.value = "0" } } "VBR_SQLSERVER_INSTALL" { $Property.value = "0" } "VBR_SQLSERVER_ENGINE" { $Property.value = "0" } "VBR_SQLSERVER_SERVER" { $Property.value = $SQLConnection } "VBR_SQLSERVER_DATABASE" { $Property.value = $DatabaseName } "VBR_SQLSERVER_AUTHENTICATION" { $Property.value = "$SQLAuthentication" } "VBR_ENTRAID_DATABASE_INSTALL" { $Property.value = "0" } "INSTALLDIR" { $Property.value = $InstallPath } "VM_CATALOGPATH" { $Property.value = $CatalogPath } "VBR_IRCACHE" { $Property.value = $IRCachePath } "VBRC_SERVICE_PORT" { $Property.value = "$GuestCatalogPort" } "VBR_SERVICE_PORT" { $Property.value = "$VeeamServicePort" } "VBR_SECURE_CONNECTIONS_PORT" { $Property.value = "$SecureConnectionPort" } "VBR_RESTSERVICE_PORT" { $Property.value = "$RestServicePort" } "REBOOT_IF_REQUIRED" { $Property.value = "$RebootRequired" } default { if($Plugins.ContainsKey($Property.name)) { $Property.value = "$($Plugins[$Property.name])" } } } } # # XML speichern # try { attrib -R $AnswerFile $XML.Save($AnswerFile) Write-Log "Antwortdatei gespeichert" } catch { Write-Log ` "FEHLER beim Speichern XML: $($_.Exception.Message)" exit 1 } } ############################################################ # INSTALLATIONSPFADE ############################################################ function Test-RequiredPaths { Write-Log "Prüfe Installationspfade" foreach($Path in @( $InstallPath, $CatalogPath, $IRCachePath )) { if(!(Test-Path $Path)) { try { New-Item ` -Path $Path ` -ItemType Directory ` -Force ` -ErrorAction Stop | Out-Null Write-Log "Pfad erstellt: $Path" } catch { Write-Log ` "FEHLER Pfad $Path : $($_.Exception.Message)" exit 1 } } else { Write-Log "Pfad vorhanden: $Path" } } } ############################################################ # VEEAM INSTALLATION ############################################################ function Install-Veeam { Write-Log "Starte Veeam Installation" $Arguments = @( "/AnswerFile" "`"$AnswerFile`"" "/SkipNetworkLogonErrors" ) try { $Process = Start-Process ` -FilePath $VeeamInstaller ` -ArgumentList $Arguments ` -Wait ` -PassThru ` -ErrorAction Stop } catch { Write-Log ` "FEHLER beim Start des Installers: $($_.Exception.Message)" exit 1 } Write-Log ` "Installer ExitCode: $($Process.ExitCode)" switch($Process.ExitCode) { 0 { Write-Log "Installation erfolgreich" } 3010 { Write-Log ` "Installation erfolgreich - Neustart erforderlich" } 1603 { Write-Log ` "FEHLER 1603 - MSI Installationsfehler" exit 1603 } default { Write-Log ` "Installation fehlgeschlagen" exit $Process.ExitCode } } } ############################################################ # INSTALLATIONSERGEBNIS ############################################################ function Show-Result { Write-Host "" Write-Host "=================================" Write-Host "Veeam Installation abgeschlossen" Write-Host "=================================" Write-Host "" Write-Host "Logdatei:" Write-Host "$LogDir\Install.log" Write-Host "" } ############################################################ # MAIN ############################################################ function Main { # # Alte Daten entfernen # Remove-OldInstallFiles # # Arbeitsverzeichnis erstellen # Initialize-Directories Write-Log ` "==== Veeam Backup & Replication v13 Installation gestartet ====" # # Quelle wählen # Select-VeeamSource # # Quelle prüfen # Test-VeeamSource # # Lizenz # Copy-VeeamLicense # # Antwortdatei # Prepare-AnswerFile Update-AnswerFile # # Zielpfade # Test-RequiredPaths # # Installation # Install-Veeam Write-Log ` "==== Veeam Installation beendet ====" Show-Result } ############################################################ # START ############################################################ Main