Pipeline Betriebssysteme als Variable pro Paket

Hallo Zusammen,

ist es möglich Pakete mit Variablen in die Produkautomation einzurbingen, in der ich der Pipeline die Auswahl der Betriebssysteme über das Softwarepaket mitgeben kann, anstatt das Global via Pipeline vorzugeben?

Vielen Dank

Moin Roland,

das ist im Standard so nicht möglich.

Ich könnte mir aber ein CustomSkript vorstellen, welches die OS Zugehörigkeit nach dem Import anpasst.

Hi,

ok schade. Dann versuchen wir das mal anderst zu lösen.

Falls es da aber zukünftig was gibt wäre super.

Danke

Hallo Roland,

mit diesem Skript lässt sich das Ganze via Variable steuern:

<#
.SYNOPSIS
  Setzt OS-Freigaben (dbo.ItemOSDataMapping) für angegebene Empirum-Pakete.
.DESCRIPTION
  - OS per TextID (z.B. Win11) oder Name (z.B. Windows 11) aus dbo.OSData auflösen
  - Für jede angegebene PackageId wird das Mapping in dbo.ItemOSDataMapping angelegt (falls nicht vorhanden)
  - Beendet sich ohne Fehler, wenn kein -OS angegeben wurde
  - Unterstützt kommagetrennete OS-Eingabe (z.B. "Win2019,Win2022")
.NOTES
  Version: 3.3 (17.11.2025) - neo42 GmbH
#>
[CmdletBinding(SupportsShouldProcess = $true)]
param(
    [string[]]$OS,
    [Parameter(Mandatory = $true)]
    [string[]]$PackageId,
    [string]$DBServer = "VI01-EMP01\EMPIRUM",
    [string]$DBName = "EmpDB"
)

# Ohne OS sauber beenden
if (-not $OS -or $OS.Count -eq 0) {
    Write-Host "no os given, stopping execution"
    exit 0
}

# OS-Parameter normalisieren (kommagetrennte Strings splitten)
$normalizedOS = [System.Collections.Generic.List[string]]::new()
foreach ($osEntry in $OS) {
    if ($osEntry -match ',') {
        $splitEntries = $osEntry -split ',' | ForEach-Object { $_.Trim() } | Where-Object { -not [string]::IsNullOrWhiteSpace($_) }
        foreach ($entry in $splitEntries) {
            $normalizedOS.Add($entry)
        }
    }
    else {
        $normalizedOS.Add($osEntry.Trim())
    }
}

if ($normalizedOS.Count -eq 0) {
    Write-Host "no os given, stopping execution"
    exit 0
}

# Modul laden
try {
    Import-Module SqlServer -ErrorAction Stop
}
catch {
    Write-Host "SqlServer-Modul nicht gefunden. Bitte 'Install-Module SqlServer' installieren."
    exit 1
}

function Invoke-Query {
    [CmdletBinding()]
    param(
        [Parameter(Mandatory = $true)]
        [string]$Query
    )
    
    Invoke-Sqlcmd -ServerInstance $DBServer -Database $DBName -TrustServerCertificate -Query $Query -ErrorAction Stop
}

function ConvertTo-SqlString {
    [CmdletBinding()]
    [OutputType([string])]
    param(
        [Parameter(Mandatory = $true)]
        [string]$InputString
    )
    
    return "'" + $InputString.Replace("'", "''") + "'"
}

function Get-PackageName {
    [CmdletBinding()]
    [OutputType([string])]
    param(
        [Parameter(Mandatory = $true)]
        [string]$PackageId,
        [Parameter(Mandatory = $true)]
        [hashtable]$PackageLookup
    )
    
    $key = $PackageId.ToLower()
    if ($PackageLookup.ContainsKey($key)) {
        return "$($PackageLookup[$key]) ($PackageId)"
    }
    
    return $PackageId
}

# OSData laden
try {
    $osDataRows = Invoke-Query -Query @"
SELECT ID, TextID, Name
FROM dbo.OSData
"@
}
catch {
    Write-Host "Fehler beim Lesen von dbo.OSData: $($_.Exception.Message)"
    exit 1
}

# Software-Daten laden
try {
    $softwareRows = Invoke-Query -Query @"
SELECT SoftwareID, SoftwareName
FROM dbo.Software
"@
}
catch {
    Write-Host "Fehler beim Lesen von dbo.Software: $($_.Exception.Message)"
    exit 1
}

# Lookup-Tabellen
$osByTextId = @{}
$osByName = @{}

foreach ($row in $osDataRows) {
    if ($row.TextID) {
        $osByTextId[$row.TextID.ToLower()] = $row
    }
    if ($row.Name) {
        $osByName[$row.Name.ToLower()] = $row
    }
}

# Package-Lookup erstellen
$packageLookup = @{}
foreach ($softwareRow in $softwareRows) {
    if ($softwareRow.SoftwareID) {
        $packageLookup[$softwareRow.SoftwareID.ToString().ToLower()] = $softwareRow.SoftwareName
    }
}

# Angeforderte OS in IDs auflösen
$targetOsList = [System.Collections.Generic.List[PSCustomObject]]::new()

foreach ($osEntry in $normalizedOS) {
    $key = $osEntry.ToLower()
    $osRow = $null
    
    if ($osByTextId.ContainsKey($key)) {
        $osRow = $osByTextId[$key]
    }
    elseif ($osByName.ContainsKey($key)) {
        $osRow = $osByName[$key]
    }
    
    if ($null -ne $osRow) {
        $targetOsList.Add([PSCustomObject]@{
            Id = [int]$osRow.ID
            Name = if ($osRow.Name) { [string]$osRow.Name } else { $osEntry }
        })
    }
    else {
        Write-Host "OS nicht gefunden in OSData: '$osEntry' (übersprungen)"
    }
}

if ($targetOsList.Count -eq 0) {
    Write-Host "Keine gültigen OS-Einträge auflösbar, stopping execution"
    exit 0
}

# Freigaben setzen
foreach ($pkgId in $PackageId) {
    $pkgIdQuoted = ConvertTo-SqlString -InputString $pkgId
    $packageDisplayName = Get-PackageName -PackageId $pkgId -PackageLookup $packageLookup
    
    foreach ($osItem in $targetOsList) {
        $osId = $osItem.Id
        $osName = $osItem.Name
        
        try {
            # Existenz prüfen
            $existsQuery = @"
SELECT TOP 1 1
FROM dbo.ItemOSDataMapping
WHERE [ID] = $pkgIdQuoted AND [OSDataID] = $osId
"@
            $exists = Invoke-Query -Query $existsQuery
            
            if (-not $exists) {
                if ($PSCmdlet.ShouldProcess($packageDisplayName, "Freigabe für $osName setzen")) {
                    $insertQuery = "INSERT INTO dbo.ItemOSDataMapping ([ID], [OSDataID]) VALUES ($pkgIdQuoted, $osId)"
                    Invoke-Query -Query $insertQuery
                    Write-Host "Paket '$packageDisplayName' wurde für $osName freigegeben."
                }
            }
            else {
                Write-Host "Paket '$packageDisplayName' hat bereits eine Freigabe für $osName."
            }
        }
        catch {
            Write-Host "Fehler bei Paket '$packageDisplayName' / ${osName}: $($_.Exception.Message)"
        }
    }
}

Voraussetzungen

1. Datenbank-Berechtigung für APC-Server

Der APC-Server muss in der Empirum-Datenbank als Benutzer berechtigt sein:

  1. DBUtil öffnen
  2. BenutzerverwaltungNeuer Benutzer
  3. Computerkonto hinzufügen: DOMÄNE\SERVERNAME$
  4. Rolle EmpServices zuweisen

Der SQL Server und die DB entweder im Skript oder via Parameter mitgeben!

2. PowerShell SqlServer-Modul

Das Modul muss auf dem APC-Server installiert sein:

Install-Module SqlServer -Force -AllowClobber

3. Empirum-Version

Eine aktuelle Empirum-Version mit der entsprechenden Datenbankstruktur muss im Einsatz sein.

4. Skript-Ablage

Das Skript sollte im Generalverzeichnis abgelegt werden:
Bsp.: C:\neo42\General\OSFlags.ps1

Pipeline-Integration

Schritt 1: Variable anlegen

In der Pipeline eine neue Variable erstellen:

Schritt 2: Pipeline-Task hinzufügen

Einen neuen PowerShell-Task zur Pipeline hinzufügen:

Skriptfile: <Global.GeneralDirectory>\SetOSFlags.ps1
Parameter: -OS "<Phase.OS>" -PackageID "<Run.EmpirumPackageId>"

Schritt 3: Pipeline ausführen

Beim Starten der Pipeline kann die Variable OS mit den gewünschten Betriebssystemen befüllt werden:

Unterstützte OS-Werte

Folgende Werte können kommagetrennt übergeben werden:

TextID Betriebssystem
Win7 Windows 7
Win8x Windows 8/8.1
Win10 Windows 10
Win11 Windows 11
Win2008R2 Windows Server 2008 R2
Win2012R2 Windows Server 2012 R2
Win2016 Windows Server 2016
Win2019 Windows Server 2019
Win2022 Windows Server 2022
Win2025 Windows Server 2025

Das Ganze sollte im Log sichtbar sein:

2 „Gefällt mir“

Hi,

super vielen Dank hat klasse funktioniert.

Jetzt noch eine Frage zu den Komfortfunktionen :smiley:

Kann ich die Varibale als Pflichtvariable hinterlegen, sodass Sie ausgefüllt werden muss?
Dann könnte ich die generelle OS Freigabe entfernen?

Kann ich die OS Werte irgendwie als Dropdown hinterlegen wie im EmpirumDeploy

Danke vielmals