Public/Set-specIPPrinters.ps1

Function Set-specIPPrinters {
    [cmdletBinding()]

    param (
        [Parameter()]
        [System.Object[]]$ipAssignedPrinters,

        [Parameter()]
        [System.Object[]]$printerModelTblData,

        [Parameter()]
        [System.Object[]]$ipLocalPrinters
    )

    #region 4. IP Printer processing
    if ((Get-specNumberOfItems $ipAssignedPrinters) -gt 0) {
        Write-Host 'Processing IP Printers' -ForegroundColor DarkCyan
        Write-Host '----------------------' -ForegroundColor DarkCyan
    }

    $count = 0

    foreach ($ipPrtr in $ipAssignedPrinters) {
        $count++

        # Extract the printer name and IP address
        $printerName = $ipPrtr.Printer_Name
        $printerIP = $ipPrtr.Printer_Connection
        $printerPORT = "TCPPort:$printerIP"

        Write-specAlignedStrings -String1 'Processing:' -String1Value "$($count) of $(Get-specNumberOfItems $ipAssignedPrinters)" `
            -String2 'Printer:' -String2Value $($printername) `
            -String3 'Port:' -String3Value $($printerPORT)

        # Extract the printer model and model number from the Printer_Name.
        # Assumes Printer_Name follows the format: <Manufacturer>_<Model>_<OptionalDetails>
        $model = ($ipPrtr.Printer_Name.Split('_')[0, 1]) -join ('_')
        $modelNo = ($ipPrtr.Printer_Name.Split('_')[1])

        # Get the printer model details
        $printerModelIndex = $printerModelTblData | Where-Object { $_.Printer_Type -eq $model }

        # Check if the printer exists locally (using $ipLocalPrinters)
        $printerExists = $ipLocalPrinters | Where-Object { $_.Name -eq $ipPrtr.printer_name }

        if ($printerExists) {
            # The printer already exists locally
            Write-Host 'IP Printer: ' -ForegroundColor DarkCyan -NoNewline

            # Handle IP address changes for existing printers:
            # - Verify if the printer's current port matches the designated port from Azure data.
            # - If the port doesn't match, update the printer to use the designated port.
            if ($printerExists.PortName -ne "TCPPort:$printerIP") {
                Write-Host "Updating port for printer [$printerName] from [$($printerExists.PortName)] to [TCPPort:$printerIP]" -ForegroundColor DarkYellow
                try {
                    # Instantiate the Printer object
                    $printer = New-specPrinterObject -Name $printerName -Driver $printerModelIndex.Printer_DriverName -PortName $printerPORT -PrinterHostAddress $printerIP

                    # Add the new port
                    Write-Host "Adding new PrinterPort [TCPPort:$printerIP]" -ForegroundColor DarkGray
                    $printer.AddPort()

                    # Set the printer to use the new port
                    Write-Host "Setting printer [$printerName] to new printer port [TCPPort:$printerIP]" -ForegroundColor DarkGray
                    $printerExists | Set-Printer -PortName $printerPORT

                    # Remove the old port
                    # Restart the spooler,otherwise the remove port process won't work
                    Restart-Service spooler | Out-Null
                    Write-Host "Removing old printer port [$($printerExists.PortName)]" -ForegroundColor DarkGray
                    Remove-PrinterPort -Name $printerExists.PortName
                    Write-Host 'OK' -ForegroundColor DarkGreen

                } catch {
                    Write-Warning "Failed to update printer port for '$printerName': $_"
                }
            } else {
                Write-Host "$printerName already exists." -ForegroundColor darkYellow
            }
        } else {
            # The printer doesn't exist locally - add it
            Write-Host
            Write-Host 'Status...' -ForegroundColor DarkCyan
            Write-Host "IP printer $($ipPrtr.printer_name) not found locally. Checking for a matching local driver $($printerModelIndex.Printer_DriverName) against the Azure table data..." -ForegroundColor DarkGray

            # Instantiate the Printer object using New-specPrinterObject
            $printer = New-specPrinterObject -Name $printerName -Driver $printerModelIndex.Printer_DriverName -PortName $printerPORT -PrinterHostAddress $printerIP

            try {
                # Add the printer driver
                Write-Host "Adding printer driver [$($printerModelIndex.Printer_DriverName)]" -ForegroundColor DarkCyan
                $printer.AddDriver()

                # Add the printer port
                Write-Host "Adding printer port [$($printerPORT)]" -ForegroundColor DarkCyan
                $printer.AddPort()

                # Add the printer
                Write-Host "Adding printer [$($printerName)]" -ForegroundColor DarkCyan
                $printer.AddPrinter()

                Write-Host "Printer [$printerName] installed on port [$printerPORT] using driver [$($printerModelIndex.Printer_DriverName)]" -ForegroundColor DarkGreen

            } catch {
                Write-Warning "Failed to add printer '$printerName' or its components: $_"
            }
        }

        Write-Host
    }
    #endregion 4. IP Printer processing
}