Classes/printer.ps1

class Printer {
    <#
    .SYNOPSIS
        Represents a printer object, providing methods to manage printer drivers, ports, and printers.
 
    .DESCRIPTION
        The Printer class allows for the management of printer configurations, including checking for existing drivers, ports, and printers. It provides methods to add and remove printer drivers, ports, and printers.
 
    .PROPERTIES
        - Name: The name of the printer.
        - Driver: The name of the driver associated with the printer.
        - PortName: The name of the port associated with the printer.
        - PrinterHostAddress: The host address of the printer for port configuration.
 
    .METHODS
        - DriverExists
            Checks if the printer driver already exists.
 
        .EXAMPLE
            $printer = [Printer]::new('OfficePrinter', 'HP LaserJet', 'OfficePort', '192.168.1.10')
            $exists = $printer.DriverExists()
            Write-Host "Driver exists: $exists"
 
        - PortExists
            Checks if the specified printer port already exists.
 
        .EXAMPLE
            $printer = [Printer]::new('OfficePrinter', 'HP LaserJet', 'OfficePort', '192.168.1.10')
            $exists = $printer.PortExists()
            Write-Host "Port exists: $exists"
 
        - PrinterExists
            Checks if the printer already exists.
 
        .EXAMPLE
            $printer = [Printer]::new('OfficePrinter', 'HP LaserJet', 'OfficePort', '192.168.1.10')
            $exists = $printer.PrinterExists()
            Write-Host "Printer exists: $exists"
 
        - AddDriver
            Adds a printer driver if it does not already exist.
 
        .EXAMPLE
            $printer = [Printer]::new('OfficePrinter', 'HP LaserJet', 'OfficePort', '192.168.1.10')
            $printer.AddDriver()
 
        - AddPort
            Adds a printer port if it does not already exist.
 
        .EXAMPLE
            $printer = [Printer]::new('OfficePrinter', 'HP LaserJet', 'OfficePort', '192.168.1.10')
            $printer.AddPort()
 
        - AddPrinter
            Adds the printer if it does not already exist.
 
        .EXAMPLE
            $printer = [Printer]::new('OfficePrinter', 'HP LaserJet', 'OfficePort', '192.168.1.10')
            $printer.AddPrinter()
 
        - RemovePrinter
            Removes the printer if it exists.
 
        .EXAMPLE
            $printer = [Printer]::new('OfficePrinter', 'HP LaserJet', 'OfficePort', '192.168.1.10')
            $printer.RemovePrinter()
 
        - RemovePort
            Removes the printer port if it exists.
 
        .EXAMPLE
            $printer = [Printer]::new('OfficePrinter', 'HP LaserJet', 'OfficePort', '192.168.1.10')
            $printer.RemovePort()
 
        - RemoveDriver
            Removes the printer driver if it exists.
 
        .EXAMPLE
            $printer = [Printer]::new('OfficePrinter', 'HP LaserJet', 'OfficePort', '192.168.1.10')
            $printer.RemoveDriver()
 
        - InstallPrinter
            Installs the printer, including the driver and port, if they do not already exist.
 
        .EXAMPLE
            $printer = [Printer]::new('OfficePrinter', 'HP LaserJet', 'OfficePort', '192.168.1.10')
            $printer.InstallPrinter()
 
        - RemoveAll
            Removes the printer, port, and driver.
 
        .EXAMPLE
            $printer = [Printer]::new('OfficePrinter', 'HP LaserJet', 'OfficePort', '192.168.1.10')
            $printer.RemoveAll()
 
        - FindUnassignedTCPIPPorts
            Find all TCP/IP ports that are unassigned i.e not in use
 
        .EXAMPLE
        # Create a Printer object
        $printer = [Printer]::new('null', 'null', 'null', 'null')
 
        # Find unassigned TCP/IP ports
        #$unassignedPorts = $printer.FindUnassignedTCPIPPorts()
 
        - RemoveUnassignedTCPIPPorts
            Remove any unassigned TCP/IP ports i.e delete any TCP/IP ports not in use
 
        .EXAMPLE
            # Create a Printer object
            $printer = [Printer]::new('null', 'null', 'null', 'null')
 
            # Remove unassigned TCP/IP ports
            $printer.RemoveUnassignedTCPIPPorts()
 
        .NOTES
        Author : owen.heaume
        Version: 1.0 - Initial release
                    1.1 - Add methods: FindUnassignedTCPIPPorts and RemoveUnassignedTCPIPPorts
    #>


    [string]$Name
    [string]$Driver
    [string]$PortName
    [string]$PrinterHostAddress

    # Constructor to initialise the printer object
    Printer([string]$name, [string]$driver, [string]$portName, [string]$printerHostAddress) {
        $this.Name = $name
        $this.Driver = $driver
        $this.PortName = $portName
        $this.PrinterHostAddress = $printerHostAddress
    }

    # Check if a printer driver already exists
    [bool] DriverExists() {
        return Get-PrinterDriver -Name $this.Driver -ErrorAction SilentlyContinue
    }

    # Check if a port already exists
    [bool] PortExists() {
        return Get-PrinterPort -Name $this.PortName -ErrorAction SilentlyContinue
    }

    # Check if a printer already exists
    [bool] PrinterExists() {
        return Get-Printer -Name $this.Name -ErrorAction SilentlyContinue
    }

    # Add a printer driver if it doesn't exist
    [void] AddDriver() {
        if (-not $this.DriverExists()) {
            try {
                Write-Host "Adding driver: $($this.Driver) for printer: $($this.Name)"
                Add-PrinterDriver -Name $this.Driver -ErrorAction Stop
            } catch {
                Write-Error "Failed to add driver $($this.Driver) for printer $($this.Name): $_"
                throw 'Driver installation failed.'
            }
        } else {
            Write-Host "Driver $($this.Driver) already exists."
        }
    }

    # Add a port if it doesn't exist
    [void] AddPort() {
        if (-not $this.PortExists()) {
            try {
                Write-Host "Adding port: $($this.PortName) for printer: $($this.Name)"
                # Add the printer port using PrinterHostAddress
                Add-PrinterPort -Name $this.PortName -PrinterHostAddress $this.PrinterHostAddress -ErrorAction Stop
            } catch {
                Write-Error "Failed to add port $($this.PortName) for printer $($this.Name): $_"
                throw 'Port installation failed.'
            }
        } else {
            Write-Host "Port $($this.PortName) already exists."
        }
    }

    # Add the printer if it doesn't exist
    [void] AddPrinter() {
        if (-not $this.PrinterExists()) {
            try {
                Write-Host "Adding printer: $($this.Name) using driver: $($this.Driver) on port: $($this.PortName)"
                Add-Printer -Name $this.Name -DriverName $this.Driver -PortName $this.PortName -ErrorAction Stop
            } catch {
                Write-Error "Failed to add printer $($this.Name): $_"
                throw "Printer installation failed. $_"
            }
        } else {
            Write-Host "Printer $($this.Name) already exists."
        }
    }

    # Remove the printer
    [void] RemovePrinter() {
        if ($this.PrinterExists()) {
            try {
                Write-Host "Removing printer: $($this.Name)"
                Remove-Printer -Name $this.Name -ErrorAction Stop
            } catch {
                Write-Error "Failed to remove printer $($this.Name): $_"
                throw 'Printer removal failed.'
            }
        } else {
            Write-Host "Printer $($this.Name) does not exist."
        }
    }

    # Remove the port
    [void] RemovePort() {
        if ($this.PortExists()) {
            try {
                Write-Host "Removing port: $($this.PortName)"
                Remove-PrinterPort -Name $this.PortName -ErrorAction Stop
            } catch {
                Write-Error "Failed to remove port $($this.PortName): $_"
                throw 'Port removal failed.'
            }
        } else {
            Write-Host "Port $($this.PortName) does not exist."
        }
    }

    # Remove the driver
    [void] RemoveDriver() {
        if ($this.DriverExists()) {
            try {
                Write-Host "Removing driver: $($this.Driver)"
                Remove-PrinterDriver -Name $this.Driver -ErrorAction Stop
            } catch {
                Write-Error "Failed to remove driver $($this.Driver): $_"
                throw 'Driver removal failed.'
            }
        } else {
            Write-Host "Driver $($this.Driver) does not exist."
        }
    }

    # Install all: driver, port, and printer
    [void] InstallPrinter() {
        try {
            $this.AddDriver()
            $this.AddPort()
            $this.AddPrinter()
        } catch {
            Write-Error "Failed to install the printer $($this.Name): $_"
            throw 'Printer installation process failed.'
        }
    }

    # Remove all: printer, port, and driver
    [void] RemoveAll() {
        try {
            $this.RemovePrinter()
            $this.RemovePort()
            $this.RemoveDriver()
        } catch {
            Write-Error "Failed to remove the printer $($this.Name): $_"
            throw 'Printer removal process failed.'
        }
    }

    # Method to find unassigned TCP/IP ports with minimal output
    [System.Object[]] FindUnassignedTCPIPPorts() {
        try {
            # Get all TCP/IP printer ports
            $tcpPorts = Get-PrinterPort | Where-Object { $_.PortMonitor -eq 'TCPMON.dll' }

            # Get ports that are currently assigned to printers
            $assignedPorts = Get-Printer | Select-Object -ExpandProperty PortName

            # Find ports that are not assigned to any printer
            $unassignedPorts = $tcpPorts | Where-Object { $assignedPorts -notcontains $_.Name }

            # Count unassigned ports using a loop
            [int]$count = 0
            $unassignedPorts | ForEach-Object { $count++ }

            # Output the count of unassigned ports
            if ($count -gt 0) {
                Write-Host "Found $count unassigned port(s):" -ForegroundColor DarkYellow
                foreach ($port in $unassignedPorts) {
                    Write-Host "Unassigned Port: $($port.Name)" -ForegroundColor Yellow
                }
            } else {
                Write-Host 'No unassigned TCP/IP ports found.' -ForegroundColor DarkGray
            }

            return $unassignedPorts  # Return the found unassigned ports

        } catch {
            Write-Error "An error occurred while finding unassigned TCP/IP ports: $_" -ea stop
            return @()
        }
    }


    # Method to remove unassigned TCP/IP ports
    [void] RemoveUnassignedTCPIPPorts() {
        try {
            $unassignedPorts = $this.FindUnassignedTCPIPPorts()

            if ($unassignedPorts) {
                foreach ($port in $unassignedPorts) {
                    try {
                        Write-Host "Removing port: $($port.Name)..." -ForegroundColor DarkGray -NoNewline
                        Remove-PrinterPort -Name $port.Name -ErrorAction Stop
                        Write-Host 'Removed' -ForegroundColor DarkGreen
                    } catch {
                        Write-Error "An error occurred while removing the port: $_"
                    }
                }
            } else {
                Write-Host 'No unassigned ports to remove.' -ForegroundColor DarkGray
            }
        } catch {
            Write-Error "An error occurred while removing unassigned TCP/IP ports: $_"
            throw 'Port removal process failed.'
        }
    }
}