first commit

This commit is contained in:
Stefan Hacker
2026-04-03 09:38:48 +02:00
commit 37ad745546
47450 changed files with 3120798 additions and 0 deletions
+84
View File
@@ -0,0 +1,84 @@
#Requires -RunAsAdministrator
<#
.SYNOPSIS
Importiert das SSL-Zertifikat einer Starface-Anlage in den Windows-Zertifikatspeicher.
.DESCRIPTION
Verbindet sich per SSL/TLS zur angegebenen Starface-Anlage, extrahiert das
Zertifikat und importiert es als vertrauenswürdig. Danach kann das Outlook
Add-in die Starface REST-API über HTTPS erreichen.
.EXAMPLE
.\import-cert.ps1 -StarfaceHost 192.168.1.100
.EXAMPLE
.\import-cert.ps1 -StarfaceHost pbx.firma.local -Port 8443
#>
param(
[Parameter(Mandatory = $true)]
[string]$StarfaceHost,
[int]$Port = 443
)
$ErrorActionPreference = "Stop"
Write-Host ""
Write-Host "============================================================" -ForegroundColor Cyan
Write-Host " Starface-Zertifikat importieren" -ForegroundColor Cyan
Write-Host "============================================================" -ForegroundColor Cyan
Write-Host ""
Write-Host " Verbinde mit ${StarfaceHost}:${Port} ..." -ForegroundColor Green
try {
$tcpClient = New-Object System.Net.Sockets.TcpClient
$tcpClient.Connect($StarfaceHost, $Port)
$sslStream = New-Object System.Net.Security.SslStream(
$tcpClient.GetStream(),
$false,
{ $true } # Alle Zertifikate akzeptieren für den Abruf
)
$sslStream.AuthenticateAsClient($StarfaceHost)
$remoteCert = $sslStream.RemoteCertificate
$x509Cert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2($remoteCert)
$sslStream.Close()
$tcpClient.Close()
Write-Host " Zertifikat erhalten:" -ForegroundColor Green
Write-Host " Subject: $($x509Cert.Subject)" -ForegroundColor White
Write-Host " Aussteller: $($x509Cert.Issuer)" -ForegroundColor White
Write-Host " Gültig bis: $($x509Cert.NotAfter)" -ForegroundColor White
Write-Host " Thumbprint: $($x509Cert.Thumbprint)" -ForegroundColor White
Write-Host ""
# Prüfen ob bereits vorhanden
$rootStore = New-Object System.Security.Cryptography.X509Certificates.X509Store(
[System.Security.Cryptography.X509Certificates.StoreName]::Root,
[System.Security.Cryptography.X509Certificates.StoreLocation]::LocalMachine
)
$rootStore.Open([System.Security.Cryptography.X509Certificates.OpenFlags]::ReadOnly)
$existing = $rootStore.Certificates | Where-Object { $_.Thumbprint -eq $x509Cert.Thumbprint }
$rootStore.Close()
if ($existing) {
Write-Host " Zertifikat ist bereits als vertrauenswürdig gespeichert." -ForegroundColor Yellow
} else {
$rootStore.Open([System.Security.Cryptography.X509Certificates.OpenFlags]::ReadWrite)
$rootStore.Add($x509Cert)
$rootStore.Close()
Write-Host " Zertifikat erfolgreich als vertrauenswürdig importiert!" -ForegroundColor Green
}
} catch {
Write-Host " Fehler: $_" -ForegroundColor Red
Write-Host ""
Write-Host " Mögliche Ursachen:" -ForegroundColor Yellow
Write-Host " - Starface nicht erreichbar (IP/Hostname prüfen)" -ForegroundColor Yellow
Write-Host " - Falscher Port (Standard: 443)" -ForegroundColor Yellow
Write-Host " - Firewall blockiert die Verbindung" -ForegroundColor Yellow
exit 1
}
Write-Host ""
Read-Host "Eingabetaste zum Beenden"
+146
View File
@@ -0,0 +1,146 @@
/**
* Minimaler lokaler HTTPS-Server für das Starface Outlook Sync Add-in.
* Liefert nur statische Dateien aus dem webroot-Verzeichnis aus.
* Wird als Windows-Dienst oder Scheduled Task ausgeführt.
*/
const https = require("https");
const http = require("http");
const fs = require("fs");
const path = require("path");
const url = require("url");
// Konfiguration aus config.json laden
const configPath = path.join(__dirname, "config.json");
if (!fs.existsSync(configPath)) {
console.error("config.json nicht gefunden:", configPath);
process.exit(1);
}
const config = JSON.parse(fs.readFileSync(configPath, "utf-8"));
const PORT = config.port || 444;
const WEBROOT = path.join(__dirname, "webroot");
const CERT_DIR = path.join(__dirname, "certs");
// MIME-Types
const MIME_TYPES = {
".html": "text/html; charset=utf-8",
".js": "application/javascript; charset=utf-8",
".css": "text/css; charset=utf-8",
".json": "application/json; charset=utf-8",
".png": "image/png",
".jpg": "image/jpeg",
".svg": "image/svg+xml",
".ico": "image/x-icon",
".xml": "application/xml; charset=utf-8",
};
function getMimeType(filePath) {
const ext = path.extname(filePath).toLowerCase();
return MIME_TYPES[ext] || "application/octet-stream";
}
function handleRequest(req, res) {
// CORS-Header für Office Add-in
res.setHeader("Access-Control-Allow-Origin", "*");
res.setHeader("Access-Control-Allow-Methods", "GET, OPTIONS");
res.setHeader("Access-Control-Allow-Headers", "Content-Type");
if (req.method === "OPTIONS") {
res.writeHead(204);
res.end();
return;
}
if (req.method !== "GET") {
res.writeHead(405, { "Content-Type": "text/plain" });
res.end("Method Not Allowed");
return;
}
// URL parsen und Pfad bereinigen
const parsedUrl = url.parse(req.url);
let filePath = decodeURIComponent(parsedUrl.pathname || "/");
// Directory index
if (filePath === "/" || filePath === "") {
filePath = "/taskpane.html";
}
// Pfad-Traversal verhindern
const safePath = path.normalize(filePath).replace(/^(\.\.[\/\\])+/, "");
const fullPath = path.join(WEBROOT, safePath);
// Sicherstellen, dass der Pfad innerhalb des webroot liegt
if (!fullPath.startsWith(WEBROOT)) {
res.writeHead(403, { "Content-Type": "text/plain" });
res.end("Forbidden");
return;
}
// Datei ausliefern
fs.stat(fullPath, (err, stats) => {
if (err || !stats.isFile()) {
res.writeHead(404, { "Content-Type": "text/plain" });
res.end("Not Found: " + safePath);
return;
}
const mimeType = getMimeType(fullPath);
res.writeHead(200, {
"Content-Type": mimeType,
"Cache-Control": "no-cache",
});
const stream = fs.createReadStream(fullPath);
stream.pipe(res);
stream.on("error", () => {
res.writeHead(500, { "Content-Type": "text/plain" });
res.end("Internal Server Error");
});
});
}
// Zertifikate laden und HTTPS-Server starten
const certFile = path.join(CERT_DIR, "localhost.crt");
const keyFile = path.join(CERT_DIR, "localhost.key");
if (!fs.existsSync(certFile) || !fs.existsSync(keyFile)) {
console.error("Zertifikate nicht gefunden in:", CERT_DIR);
console.error("Bitte zuerst setup.ps1 ausführen.");
process.exit(1);
}
const serverOptions = {
cert: fs.readFileSync(certFile),
key: fs.readFileSync(keyFile),
};
const server = https.createServer(serverOptions, handleRequest);
server.listen(PORT, "127.0.0.1", () => {
console.log(`Starface Outlook Sync - Lokaler Server`);
console.log(`Läuft auf: https://localhost:${PORT}`);
console.log(`Webroot: ${WEBROOT}`);
console.log(`PID: ${process.pid}`);
});
server.on("error", (err) => {
if (err.code === "EADDRINUSE") {
console.error(`Port ${PORT} ist bereits belegt.`);
console.error("Bitte anderen Port in config.json wählen.");
} else {
console.error("Server-Fehler:", err.message);
}
process.exit(1);
});
// Graceful Shutdown
process.on("SIGINT", () => {
console.log("Server wird beendet...");
server.close(() => process.exit(0));
});
process.on("SIGTERM", () => {
console.log("Server wird beendet...");
server.close(() => process.exit(0));
});
+482
View File
@@ -0,0 +1,482 @@
#Requires -RunAsAdministrator
<#
.SYNOPSIS
Setup-Script für Starface Outlook Sync Add-in.
.DESCRIPTION
- Fragt Starface-Host (für Zertifikat) und lokalen Port ab
- Extrahiert das SSL-Zertifikat der Starface und importiert es als vertrauenswürdig
- Erstellt eine lokale CA und ein localhost-Zertifikat
- Installiert den lokalen HTTPS-Webserver als Windows-Dienst
- Registriert das Outlook Add-in
Login-Daten werden NICHT benötigt - diese werden später im Add-in selbst
in den Sync-Profilen konfiguriert.
#>
param(
[string]$InstallDir = "$env:ProgramFiles\StarfaceOutlookSync"
)
$ErrorActionPreference = "Stop"
$scriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
# ============================================================
# Hilfsfunktionen
# ============================================================
function Write-Header($text) {
Write-Host ""
Write-Host "============================================================" -ForegroundColor Cyan
Write-Host " $text" -ForegroundColor Cyan
Write-Host "============================================================" -ForegroundColor Cyan
Write-Host ""
}
function Write-Step($text) {
Write-Host "$text" -ForegroundColor Green
}
function Write-Warn($text) {
Write-Host "$text" -ForegroundColor Yellow
}
function Write-Err($text) {
Write-Host "$text" -ForegroundColor Red
}
function Test-NodeJs {
try {
$version = & node --version 2>$null
if ($version) {
Write-Step "Node.js gefunden: $version"
return $true
}
} catch {}
return $false
}
function Test-PortAvailable($port) {
$listener = Get-NetTCPConnection -LocalPort $port -ErrorAction SilentlyContinue
return ($null -eq $listener)
}
function Import-StarfaceCert($host_, $port_) {
Write-Step "Verbinde mit ${host_}:${port_} ..."
$tcpClient = New-Object System.Net.Sockets.TcpClient
$tcpClient.Connect($host_, $port_)
$sslStream = New-Object System.Net.Security.SslStream(
$tcpClient.GetStream(),
$false,
{ $true } # Alle Zertifikate akzeptieren für den Abruf
)
$sslStream.AuthenticateAsClient($host_)
$remoteCert = $sslStream.RemoteCertificate
$x509Cert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2($remoteCert)
$sslStream.Close()
$tcpClient.Close()
Write-Step "Zertifikat erhalten: $($x509Cert.Subject)"
Write-Step "Aussteller: $($x509Cert.Issuer)"
Write-Step "Gültig bis: $($x509Cert.NotAfter)"
# In den Trusted Root Store importieren
$store = New-Object System.Security.Cryptography.X509Certificates.X509Store(
[System.Security.Cryptography.X509Certificates.StoreName]::Root,
[System.Security.Cryptography.X509Certificates.StoreLocation]::LocalMachine
)
$store.Open([System.Security.Cryptography.X509Certificates.OpenFlags]::ReadWrite)
$store.Add($x509Cert)
$store.Close()
Write-Step "Starface-Zertifikat als vertrauenswürdig importiert."
return $x509Cert
}
# ============================================================
# Voraussetzungen prüfen
# ============================================================
Write-Header "Starface Outlook Sync - Setup"
# Node.js prüfen
if (-not (Test-NodeJs)) {
Write-Err "Node.js ist nicht installiert."
Write-Host " Bitte installieren Sie Node.js von https://nodejs.org/" -ForegroundColor Yellow
Write-Host " (LTS-Version empfohlen)" -ForegroundColor Yellow
Read-Host "Eingabetaste zum Beenden"
exit 1
}
# ============================================================
# Benutzereingaben
# ============================================================
Write-Header "Starface-Verbindung (nur für Zertifikat-Import)"
Write-Host " Login-Daten werden hier nicht benötigt." -ForegroundColor Gray
Write-Host " Diese konfigurieren Sie später im Add-in in den Sync-Profilen." -ForegroundColor Gray
Write-Host ""
$starfaceHost = Read-Host "Starface Host/IP-Adresse (z.B. 192.168.1.100 oder pbx.firma.local)"
if ([string]::IsNullOrWhiteSpace($starfaceHost)) {
Write-Err "Kein Host angegeben."
exit 1
}
$starfacePortInput = Read-Host "Starface HTTPS-Port [443]"
$starfacePort = if ([string]::IsNullOrWhiteSpace($starfacePortInput)) { 443 } else { [int]$starfacePortInput }
Write-Host ""
Write-Header "Lokaler Webserver"
$localPortInput = Read-Host "Lokaler HTTPS-Port für das Add-in [444]"
$localPort = if ([string]::IsNullOrWhiteSpace($localPortInput)) { 444 } else { [int]$localPortInput }
if (-not (Test-PortAvailable $localPort)) {
Write-Warn "Port $localPort ist bereits belegt!"
$localPortInput = Read-Host "Bitte einen anderen Port wählen"
$localPort = [int]$localPortInput
if (-not (Test-PortAvailable $localPort)) {
Write-Err "Port $localPort ist ebenfalls belegt. Abbruch."
exit 1
}
}
Write-Step "Verwende Port: $localPort"
# ============================================================
# Schritt 1: Starface SSL-Zertifikat extrahieren und importieren
# ============================================================
Write-Header "Schritt 1: Starface-Zertifikat importieren"
try {
Import-StarfaceCert $starfaceHost $starfacePort
} catch {
Write-Err "Fehler beim Abrufen des Starface-Zertifikats: $_"
Write-Warn "Die Verbindung zur Starface API könnte fehlschlagen."
Write-Warn "Sie können das Zertifikat später nachholen mit:"
Write-Host " .\import-cert.ps1 -Host $starfaceHost -Port $starfacePort" -ForegroundColor White
Write-Host ""
Write-Host " Möchten Sie trotzdem fortfahren? (j/n)" -ForegroundColor Yellow
$continue = Read-Host
if ($continue -ne "j") { exit 1 }
}
# ============================================================
# Schritt 2: Lokale CA und localhost-Zertifikat erstellen
# ============================================================
Write-Header "Schritt 2: Lokale Zertifikate erstellen"
$certDir = Join-Path $InstallDir "certs"
New-Item -ItemType Directory -Path $certDir -Force | Out-Null
# Lokale CA erstellen
Write-Step "Erstelle lokale CA ..."
$caParams = @{
Subject = "CN=Starface Outlook Sync Local CA"
KeyLength = 2048
KeyAlgorithm = "RSA"
HashAlgorithm = "SHA256"
KeyExportPolicy = "Exportable"
NotAfter = (Get-Date).AddYears(10)
CertStoreLocation = "Cert:\LocalMachine\My"
KeyUsage = "CertSign", "CRLSign"
TextExtension = @("2.5.29.19={text}CA=true&pathlength=1")
}
$caCert = New-SelfSignedCertificate @caParams
Write-Step "Lokale CA erstellt: $($caCert.Thumbprint)"
# CA in Trusted Root Store importieren
$rootStore = New-Object System.Security.Cryptography.X509Certificates.X509Store(
[System.Security.Cryptography.X509Certificates.StoreName]::Root,
[System.Security.Cryptography.X509Certificates.StoreLocation]::LocalMachine
)
$rootStore.Open([System.Security.Cryptography.X509Certificates.OpenFlags]::ReadWrite)
$rootStore.Add($caCert)
$rootStore.Close()
Write-Step "Lokale CA als vertrauenswürdig importiert."
# Localhost-Zertifikat erstellen, signiert von der lokalen CA
Write-Step "Erstelle localhost-Zertifikat ..."
$localhostParams = @{
Subject = "CN=localhost"
KeyLength = 2048
KeyAlgorithm = "RSA"
HashAlgorithm = "SHA256"
KeyExportPolicy = "Exportable"
NotAfter = (Get-Date).AddYears(5)
CertStoreLocation = "Cert:\LocalMachine\My"
Signer = $caCert
DnsName = "localhost", "127.0.0.1"
TextExtension = @("2.5.29.37={text}1.3.6.1.5.5.7.3.1") # Server Authentication
}
$localhostCert = New-SelfSignedCertificate @localhostParams
Write-Step "Localhost-Zertifikat erstellt: $($localhostCert.Thumbprint)"
# Zertifikat und Key als PEM exportieren (für Node.js)
Write-Step "Exportiere Zertifikate für den Webserver ..."
# Zertifikat als PEM
$certPem = "-----BEGIN CERTIFICATE-----`n"
$certPem += [Convert]::ToBase64String($localhostCert.RawData, [Base64FormattingOptions]::InsertLineBreaks)
$certPem += "`n-----END CERTIFICATE-----"
Set-Content -Path (Join-Path $certDir "localhost.crt") -Value $certPem -Encoding ASCII
# Private Key als PEM
$keyBytes = $localhostCert.PrivateKey.ExportPkcs8PrivateKey()
$keyPem = "-----BEGIN PRIVATE KEY-----`n"
$keyPem += [Convert]::ToBase64String($keyBytes, [Base64FormattingOptions]::InsertLineBreaks)
$keyPem += "`n-----END PRIVATE KEY-----"
Set-Content -Path (Join-Path $certDir "localhost.key") -Value $keyPem -Encoding ASCII
# CA-Zertifikat exportieren (für Deinstallation)
$caCertPem = "-----BEGIN CERTIFICATE-----`n"
$caCertPem += [Convert]::ToBase64String($caCert.RawData, [Base64FormattingOptions]::InsertLineBreaks)
$caCertPem += "`n-----END CERTIFICATE-----"
Set-Content -Path (Join-Path $certDir "local-ca.crt") -Value $caCertPem -Encoding ASCII
# Thumbprints speichern (für Deinstallation)
$certInfo = @{
caThumbprint = $caCert.Thumbprint
localhostThumbprint = $localhostCert.Thumbprint
}
$certInfo | ConvertTo-Json | Set-Content (Join-Path $InstallDir "cert-info.json") -Encoding UTF8
Write-Step "Zertifikate exportiert nach: $certDir"
# ============================================================
# Schritt 3: Add-in Dateien installieren
# ============================================================
Write-Header "Schritt 3: Add-in Dateien installieren"
$webrootDir = Join-Path $InstallDir "webroot"
New-Item -ItemType Directory -Path $webrootDir -Force | Out-Null
# Prüfen ob dist-Ordner existiert (bereits gebaut)
$distDir = Join-Path $scriptDir "..\dist"
if (-not (Test-Path $distDir)) {
Write-Step "Baue Add-in (npm run build) ..."
Push-Location (Join-Path $scriptDir "..")
& npm run build 2>&1 | Out-Null
Pop-Location
}
if (-not (Test-Path $distDir)) {
Write-Err "Build fehlgeschlagen. dist-Ordner nicht gefunden."
exit 1
}
# Dateien kopieren
Copy-Item -Path "$distDir\*" -Destination $webrootDir -Recurse -Force
Write-Step "Add-in Dateien kopiert nach: $webrootDir"
# manifest.xml mit korrektem Port anpassen
$manifestPath = Join-Path $webrootDir "manifest.xml"
if (Test-Path $manifestPath) {
$manifestContent = Get-Content $manifestPath -Raw -Encoding UTF8
$manifestContent = $manifestContent -replace "https://localhost:3000", "https://localhost:$localPort"
Set-Content -Path $manifestPath -Value $manifestContent -Encoding UTF8
Write-Step "manifest.xml angepasst (Port: $localPort)"
}
# Auch eine Kopie der manifest.xml ins Installationsverzeichnis
Copy-Item -Path $manifestPath -Destination (Join-Path $InstallDir "manifest.xml") -Force
# ============================================================
# Schritt 4: Server-Konfiguration und Installation
# ============================================================
Write-Header "Schritt 4: Lokalen Webserver einrichten"
# Server-Dateien kopieren
Copy-Item -Path (Join-Path $scriptDir "local-server.js") -Destination $InstallDir -Force
# import-cert.ps1 ins Installationsverzeichnis kopieren (für spätere Nutzung)
$importCertSrc = Join-Path $scriptDir "import-cert.ps1"
if (Test-Path $importCertSrc) {
Copy-Item -Path $importCertSrc -Destination $InstallDir -Force
}
# uninstall.ps1 ins Installationsverzeichnis kopieren
$uninstallSrc = Join-Path $scriptDir "uninstall.ps1"
if (Test-Path $uninstallSrc) {
Copy-Item -Path $uninstallSrc -Destination $InstallDir -Force
}
# config.json erstellen
$serverConfig = @{
port = $localPort
}
$serverConfig | ConvertTo-Json | Set-Content (Join-Path $InstallDir "config.json") -Encoding UTF8
Write-Step "Server-Konfiguration erstellt."
# Windows Scheduled Task erstellen (startet beim Systemstart)
$taskName = "StarfaceOutlookSyncServer"
# Bestehenden Task entfernen falls vorhanden
Unregister-ScheduledTask -TaskName $taskName -Confirm:$false -ErrorAction SilentlyContinue
$nodeExe = (Get-Command node).Source
$serverScript = Join-Path $InstallDir "local-server.js"
$action = New-ScheduledTaskAction -Execute $nodeExe -Argument "`"$serverScript`"" -WorkingDirectory $InstallDir
$trigger = New-ScheduledTaskTrigger -AtStartup
$principal = New-ScheduledTaskPrincipal -UserId "SYSTEM" -LogonType ServiceAccount -RunLevel Highest
$settings = New-ScheduledTaskSettingsSet -AllowStartIfOnBatteries -DontStopIfGoingOnBatteries -StartWhenAvailable -ExecutionTimeLimit ([TimeSpan]::Zero)
Register-ScheduledTask -TaskName $taskName -Action $action -Trigger $trigger -Principal $principal -Settings $settings -Description "Lokaler HTTPS-Server für Starface Outlook Sync Add-in" | Out-Null
# Task sofort starten
Start-ScheduledTask -TaskName $taskName
Start-Sleep -Seconds 2
# Prüfen ob der Server läuft
try {
[System.Net.ServicePointManager]::ServerCertificateValidationCallback = { $true }
$response = Invoke-WebRequest -Uri "https://localhost:$localPort/taskpane.html" -UseBasicParsing -TimeoutSec 5
if ($response.StatusCode -eq 200) {
Write-Step "Lokaler Webserver läuft auf https://localhost:$localPort"
}
} catch {
Write-Warn "Server-Test fehlgeschlagen. Server startet möglicherweise verzögert."
}
# ============================================================
# Schritt 5: Outlook Add-in registrieren
# ============================================================
Write-Header "Schritt 5: Outlook Add-in registrieren"
# Manifest-Katalog-Ordner einrichten
$catalogDir = Join-Path $InstallDir "manifest-catalog"
New-Item -ItemType Directory -Path $catalogDir -Force | Out-Null
Copy-Item -Path (Join-Path $InstallDir "manifest.xml") -Destination $catalogDir -Force
# Terminal Server erkennen
$isTerminalServer = $false
$rdRole = Get-WindowsFeature -Name "RDS-RD-Server" -ErrorAction SilentlyContinue
if ($rdRole -and $rdRole.Installed) {
$isTerminalServer = $true
} elseif ((Get-ItemProperty "HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server" -Name "TSAppCompat" -ErrorAction SilentlyContinue).TSAppCompat -eq 1) {
$isTerminalServer = $true
}
if ($isTerminalServer) {
Write-Step "Terminal Server erkannt - registriere Add-in für alle Benutzer (HKLM)."
}
# Outlook Classic: Shared Folder Catalog per Registry konfigurieren
# Terminal Server: HKLM (gilt für alle User), sonst HKCU
$outlookVersions = @("16.0", "15.0")
$registeredClassic = $false
foreach ($ver in $outlookVersions) {
# Prüfen ob diese Outlook-Version installiert ist
$outlookPath = "HKLM:\Software\Microsoft\Office\$ver\Outlook"
if (-not (Test-Path $outlookPath)) {
$outlookPath = "HKLM:\Software\WOW6432Node\Microsoft\Office\$ver\Outlook"
}
if (Test-Path $outlookPath) {
Write-Step "Outlook $ver (Classic) gefunden."
$catalogId = [guid]::NewGuid().ToString("B")
# Bei Terminal Server: in HKLM registrieren (gilt für alle User)
if ($isTerminalServer) {
$outlookRegPath = "HKLM:\Software\Microsoft\Office\$ver\WEF\TrustedCatalogs"
$catalogRegPath = Join-Path $outlookRegPath $catalogId
New-Item -Path $catalogRegPath -Force | Out-Null
New-ItemProperty -Path $catalogRegPath -Name "Url" -Value $catalogDir -PropertyType String -Force | Out-Null
New-ItemProperty -Path $catalogRegPath -Name "Flags" -Value 1 -PropertyType DWord -Force | Out-Null
Write-Step "Add-in Katalog für alle Benutzer registriert (HKLM)."
}
# Immer auch in HKCU für den aktuellen User (Fallback / Einzelplatz)
$outlookRegPathUser = "HKCU:\Software\Microsoft\Office\$ver\WEF\TrustedCatalogs"
$catalogRegPathUser = Join-Path $outlookRegPathUser $catalogId
New-Item -Path $catalogRegPathUser -Force | Out-Null
New-ItemProperty -Path $catalogRegPathUser -Name "Url" -Value $catalogDir -PropertyType String -Force | Out-Null
New-ItemProperty -Path $catalogRegPathUser -Name "Flags" -Value 1 -PropertyType DWord -Force | Out-Null
Write-Step "Add-in Katalog für Outlook Classic registriert."
$registeredClassic = $true
}
}
if (-not $registeredClassic) {
Write-Warn "Outlook Classic nicht in der Registry gefunden."
}
# Prüfen ob New Outlook installiert ist
$newOutlook = Get-AppxPackage -Name "Microsoft.OutlookForWindows" -ErrorAction SilentlyContinue
if ($newOutlook) {
Write-Step "Neues Outlook gefunden: Version $($newOutlook.Version)"
Write-Warn "Für das neue Outlook muss das Add-in manuell hinzugefügt werden:"
Write-Host " 1. Neues Outlook öffnen" -ForegroundColor White
Write-Host " 2. Einstellungen (Zahnrad) → Add-Ins verwalten" -ForegroundColor White
Write-Host " 3. 'Benutzerdefinierte Add-Ins' → 'Aus Datei hinzufügen'" -ForegroundColor White
Write-Host " 4. Datei wählen: $catalogDir\manifest.xml" -ForegroundColor White
} else {
Write-Step "Neues Outlook nicht installiert (nur Classic erkannt)."
}
# ============================================================
# Schritt 6: Installationsinfo speichern
# ============================================================
$installInfo = @{
installDir = $InstallDir
localPort = $localPort
taskName = $taskName
installedAt = (Get-Date).ToString("o")
catalogDir = $catalogDir
manifestUrl = "https://localhost:$localPort"
caThumbprint = $caCert.Thumbprint
localhostThumbprint = $localhostCert.Thumbprint
}
$installInfo | ConvertTo-Json | Set-Content (Join-Path $InstallDir "install-info.json") -Encoding UTF8
# ============================================================
# Zusammenfassung
# ============================================================
Write-Header "Installation abgeschlossen!"
Write-Host " Installationsverzeichnis: $InstallDir" -ForegroundColor White
Write-Host " Lokaler Server: https://localhost:$localPort" -ForegroundColor White
Write-Host " Manifest: $catalogDir\manifest.xml" -ForegroundColor White
Write-Host ""
if ($registeredClassic) {
Write-Host " Outlook Classic: Add-in wurde automatisch registriert." -ForegroundColor Green
Write-Host " → Outlook neu starten, dann 'Kontakt-Sync' im Ribbon suchen." -ForegroundColor Green
}
if ($newOutlook) {
Write-Host ""
Write-Host " Neues Outlook: Bitte Add-in manuell hinzufügen (siehe oben)." -ForegroundColor Yellow
}
Write-Host ""
Write-Host " Nächster Schritt: Im Add-in ein Sync-Profil mit den" -ForegroundColor White
Write-Host " Starface-Zugangsdaten einrichten." -ForegroundColor White
Write-Host ""
Write-Host " Weitere Starface-Anlagen einbinden? Zertifikat importieren mit:" -ForegroundColor Gray
Write-Host " .\import-cert.ps1 -StarfaceHost <host> [-Port <port>]" -ForegroundColor Gray
Write-Host ""
Write-Host " Deinstallation: uninstall.ps1 als Administrator ausführen" -ForegroundColor Gray
Write-Host ""
# Firewall-Regel für den lokalen Port (nur localhost, rein vorsichtshalber)
New-NetFirewallRule -DisplayName "Starface Outlook Sync" -Direction Inbound -LocalPort $localPort -Protocol TCP -Action Allow -Profile Private -ErrorAction SilentlyContinue | Out-Null
Read-Host "Eingabetaste zum Beenden"
+171
View File
@@ -0,0 +1,171 @@
#Requires -RunAsAdministrator
<#
.SYNOPSIS
Deinstalliert das Starface Outlook Sync Add-in.
.DESCRIPTION
Entfernt Server, Zertifikate, Scheduled Task, Registry-Einträge und Dateien.
#>
param(
[string]$InstallDir = "$env:ProgramFiles\StarfaceOutlookSync"
)
$ErrorActionPreference = "Stop"
function Write-Header($text) {
Write-Host ""
Write-Host "============================================================" -ForegroundColor Cyan
Write-Host " $text" -ForegroundColor Cyan
Write-Host "============================================================" -ForegroundColor Cyan
Write-Host ""
}
function Write-Step($text) {
Write-Host "$text" -ForegroundColor Green
}
function Write-Warn($text) {
Write-Host "$text" -ForegroundColor Yellow
}
Write-Header "Starface Outlook Sync - Deinstallation"
# Sicherheitsabfrage
Write-Host " Dies entfernt das Starface Outlook Sync Add-in vollständig." -ForegroundColor Yellow
Write-Host " Installationsverzeichnis: $InstallDir" -ForegroundColor Yellow
$confirm = Read-Host " Fortfahren? (j/n)"
if ($confirm -ne "j") {
Write-Host " Abgebrochen." -ForegroundColor Gray
exit 0
}
# ============================================================
# Schritt 1: Scheduled Task stoppen und entfernen
# ============================================================
Write-Header "Schritt 1: Server stoppen"
$taskName = "StarfaceOutlookSyncServer"
$task = Get-ScheduledTask -TaskName $taskName -ErrorAction SilentlyContinue
if ($task) {
if ($task.State -eq "Running") {
Stop-ScheduledTask -TaskName $taskName
Write-Step "Server gestoppt."
}
Unregister-ScheduledTask -TaskName $taskName -Confirm:$false
Write-Step "Scheduled Task entfernt."
} else {
Write-Warn "Scheduled Task '$taskName' nicht gefunden."
}
# ============================================================
# Schritt 2: Zertifikate entfernen
# ============================================================
Write-Header "Schritt 2: Zertifikate entfernen"
$certInfoPath = Join-Path $InstallDir "cert-info.json"
if (Test-Path $certInfoPath) {
$certInfo = Get-Content $certInfoPath -Raw | ConvertFrom-Json
# Localhost-Zertifikat aus dem persönlichen Store entfernen
if ($certInfo.localhostThumbprint) {
$cert = Get-ChildItem "Cert:\LocalMachine\My" | Where-Object { $_.Thumbprint -eq $certInfo.localhostThumbprint }
if ($cert) {
Remove-Item $cert.PSPath -Force
Write-Step "Localhost-Zertifikat entfernt."
}
}
# Lokale CA aus dem Root Store entfernen
if ($certInfo.caThumbprint) {
$caCert = Get-ChildItem "Cert:\LocalMachine\Root" | Where-Object { $_.Thumbprint -eq $certInfo.caThumbprint }
if ($caCert) {
Remove-Item $caCert.PSPath -Force
Write-Step "Lokale CA entfernt."
}
# Auch aus dem persönlichen Store
$caCertMy = Get-ChildItem "Cert:\LocalMachine\My" | Where-Object { $_.Thumbprint -eq $certInfo.caThumbprint }
if ($caCertMy) {
Remove-Item $caCertMy.PSPath -Force
}
}
} else {
Write-Warn "cert-info.json nicht gefunden. Zertifikate müssen ggf. manuell entfernt werden."
}
# ============================================================
# Schritt 3: Outlook Add-in Registrierung entfernen
# ============================================================
Write-Header "Schritt 3: Outlook-Registrierung entfernen"
$outlookVersions = @("16.0", "15.0")
foreach ($ver in $outlookVersions) {
# HKCU (Einzelplatz / aktueller User)
$catalogBasePath = "HKCU:\Software\Microsoft\Office\$ver\WEF\TrustedCatalogs"
if (Test-Path $catalogBasePath) {
$catalogs = Get-ChildItem $catalogBasePath -ErrorAction SilentlyContinue
foreach ($catalog in $catalogs) {
$url = Get-ItemProperty -Path $catalog.PSPath -Name "Url" -ErrorAction SilentlyContinue
if ($url -and $url.Url -like "*StarfaceOutlookSync*") {
Remove-Item $catalog.PSPath -Recurse -Force
Write-Step "Outlook $ver Katalog-Registrierung entfernt (HKCU)."
}
}
}
# HKLM (Terminal Server / alle User)
$catalogBasePathLM = "HKLM:\Software\Microsoft\Office\$ver\WEF\TrustedCatalogs"
if (Test-Path $catalogBasePathLM) {
$catalogs = Get-ChildItem $catalogBasePathLM -ErrorAction SilentlyContinue
foreach ($catalog in $catalogs) {
$url = Get-ItemProperty -Path $catalog.PSPath -Name "Url" -ErrorAction SilentlyContinue
if ($url -and $url.Url -like "*StarfaceOutlookSync*") {
Remove-Item $catalog.PSPath -Recurse -Force
Write-Step "Outlook $ver Katalog-Registrierung entfernt (HKLM)."
}
}
}
}
# ============================================================
# Schritt 4: Firewall-Regel entfernen
# ============================================================
Write-Header "Schritt 4: Firewall-Regel entfernen"
Remove-NetFirewallRule -DisplayName "Starface Outlook Sync" -ErrorAction SilentlyContinue
Write-Step "Firewall-Regel entfernt."
# ============================================================
# Schritt 5: Dateien entfernen
# ============================================================
Write-Header "Schritt 5: Dateien entfernen"
if (Test-Path $InstallDir) {
Remove-Item -Path $InstallDir -Recurse -Force
Write-Step "Installationsverzeichnis entfernt: $InstallDir"
} else {
Write-Warn "Verzeichnis nicht gefunden: $InstallDir"
}
# ============================================================
# Zusammenfassung
# ============================================================
Write-Header "Deinstallation abgeschlossen"
Write-Host " Das Starface Outlook Sync Add-in wurde entfernt." -ForegroundColor Green
Write-Host ""
Write-Host " Hinweis: Falls das Add-in im neuen Outlook manuell" -ForegroundColor Gray
Write-Host " hinzugefügt wurde, muss es dort auch manuell entfernt werden:" -ForegroundColor Gray
Write-Host " Einstellungen → Add-Ins verwalten → Add-In entfernen" -ForegroundColor Gray
Write-Host ""
Write-Host " Das Starface-Zertifikat wurde NICHT entfernt," -ForegroundColor Yellow
Write-Host " da es ggf. von anderen Anwendungen benötigt wird." -ForegroundColor Yellow
Write-Host ""
Read-Host "Eingabetaste zum Beenden"