; Universal Printer Installer for Network Printers ; Installs HP/Xerox network printers from ShopDB via TCP/IP [Setup] AppId={{7B9C3E41-5F2A-4D8B-9E1C-8A6D4F3E2B1A}} AppName=WJDT GE Aerospace Printer Installer AppVersion=1.0 AppPublisher=WJDT AppPublisherURL=http://tsgwp00524.logon.ds.ge.com AppSupportURL=http://tsgwp00524.logon.ds.ge.com AppUpdatesURL=http://tsgwp00524.logon.ds.ge.com CreateAppDir=no ChangesAssociations=no PrivilegesRequired=admin ; Force 64-bit installation mode on 64-bit compatible systems ArchitecturesInstallIn64BitMode=x64compatible OutputDir=C:\Users\570005354\Downloads\Output OutputBaseFilename=PrinterInstaller SolidCompression=yes WizardStyle=modern SetupIconFile=gea-logo.ico WizardImageFile=patrick.bmp WizardSmallImageFile=patrick-sm.bmp CreateUninstallRegKey=no DisableWelcomePage=no [Languages] Name: "english"; MessagesFile: "compiler:Default.isl" [Messages] WelcomeLabel2=This utility will install network printers.%n%nFeatures:%n- Query HP/Xerox printers from ShopDB%n- Install via TCP/IP using FQDN or IP address%n- Automatic driver installation (HP Universal PCL6, Xerox Global Print Driver)%n%nClick Next to continue. [Files] ; HP Universal Print Driver x64 Source: "drivers\hp_x64\*"; DestDir: "{tmp}\hp_drivers_x64"; Flags: ignoreversion recursesubdirs; Check: Is64BitInstallMode ; HP Universal Print Driver x32 Source: "drivers\hp_x32\*"; DestDir: "{tmp}\hp_drivers_x32"; Flags: ignoreversion recursesubdirs; Check: not Is64BitInstallMode ; Xerox Universal Print Driver x64 Source: "drivers\xerox_x64\*"; DestDir: "{tmp}\xerox_drivers_x64"; Flags: ignoreversion recursesubdirs; Check: Is64BitInstallMode ; Xerox Universal Print Driver x32 Source: "drivers\xerox_x32\*"; DestDir: "{tmp}\xerox_drivers_x32"; Flags: ignoreversion recursesubdirs; Check: not Is64BitInstallMode [Code] var PrinterSelectionPage: TInputOptionWizardPage; PrinterDataArray: array of record PrinterName: String; FQDN: String; IPAddress: String; Vendor: String; Model: String; IsInstalled: Boolean; end; // Query database for printers via web API function QueryPrinters(): Boolean; var ResultCode: Integer; TempScriptPath, TempOutputPath: String; PSScript: String; Output: AnsiString; Lines: TStringList; I: Integer; Fields: TStringList; begin Result := False; // Build PowerShell script to query database API PSScript := 'try {' + #13#10 + ' $url = "https://tsgwp00525.rd.ds.ge.com/shopdb/api_printers.asp"' + #13#10 + ' # Allow TLS 1.2 for HTTPS connections' + #13#10 + ' [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12' + #13#10 + ' $response = Invoke-WebRequest -Uri $url -Method GET -UseBasicParsing -UseDefaultCredentials -ErrorAction Stop' + #13#10 + ' $printers = $response.Content | ConvertFrom-Json' + #13#10 + ' foreach ($printer in $printers) {' + #13#10 + ' if (($printer.isactive -eq 1 -or $printer.isactive -eq $true) -and ($printer.vendor -eq "HP" -or $printer.vendor -eq "Xerox" -or $printer.vendor -eq "HID")) {' + #13#10 + ' $name = $printer.printerwindowsname' + #13#10 + ' $vendor = $printer.vendor' + #13#10 + ' $model = $printer.modelnumber' + #13#10 + ' # Use FQDN or IP if available, otherwise default to USB for card printers' + #13#10 + ' if ($printer.fqdn -and $printer.fqdn -ne "" -and $printer.fqdn -ne "USB") {' + #13#10 + ' $address = $printer.fqdn' + #13#10 + ' } elseif ($printer.ipaddress -and $printer.ipaddress -ne "") {' + #13#10 + ' $address = $printer.ipaddress' + #13#10 + ' } else {' + #13#10 + ' $address = "USB"' + #13#10 + ' }' + #13#10 + ' if ($address -and $address -ne "") {' + #13#10 + ' Write-Output "$name|$address|$vendor|$model"' + #13#10 + ' }' + #13#10 + ' }' + #13#10 + ' }' + #13#10 + '} catch {' + #13#10 + ' Write-Error "Failed to query printers: $_"' + #13#10 + ' exit 1' + #13#10 + '}'; TempScriptPath := ExpandConstant('{tmp}\query_printers.ps1'); TempOutputPath := ExpandConstant('{tmp}\printers_output.txt'); SaveStringToFile(TempScriptPath, PSScript, False); if not Exec('powershell.exe', '-NoProfile -ExecutionPolicy Bypass -Command "& ''' + TempScriptPath + ''' | Out-File -FilePath ''' + TempOutputPath + ''' -Encoding ASCII"', '', SW_HIDE, ewWaitUntilTerminated, ResultCode) then begin DeleteFile(TempScriptPath); Exit; end; DeleteFile(TempScriptPath); if not FileExists(TempOutputPath) then Exit; if not LoadStringFromFile(TempOutputPath, Output) then begin DeleteFile(TempOutputPath); Exit; end; DeleteFile(TempOutputPath); Lines := TStringList.Create; try Lines.Text := Output; // Count valid lines I := 0; while I < Lines.Count do begin if (Trim(Lines[I]) = '') or (Pos('|', Lines[I]) = 0) then Lines.Delete(I) else I := I + 1; end; if Lines.Count = 0 then Exit; SetArrayLength(PrinterDataArray, Lines.Count); for I := 0 to Lines.Count - 1 do begin Fields := TStringList.Create; try Fields.Delimiter := '|'; Fields.StrictDelimiter := True; Fields.DelimitedText := Trim(Lines[I]); if Fields.Count >= 4 then begin PrinterDataArray[I].PrinterName := Trim(Fields[0]); PrinterDataArray[I].FQDN := Trim(Fields[1]); PrinterDataArray[I].IPAddress := Trim(Fields[1]); PrinterDataArray[I].Vendor := Trim(Fields[2]); PrinterDataArray[I].Model := Trim(Fields[3]); Result := True; end; finally Fields.Free; end; end; finally Lines.Free; end; end; // Check which printers are already installed function CheckInstalledPrinters(): Boolean; var ResultCode: Integer; TempScriptPath, TempOutputPath: String; PSScript: String; Output: AnsiString; Lines: TStringList; I, J: Integer; begin Result := False; // Build PowerShell script to get installed printers PSScript := 'try {' + #13#10 + ' Get-Printer | Select-Object -ExpandProperty Name | ForEach-Object { Write-Output $_ }' + #13#10 + '} catch { exit 1 }'; TempScriptPath := ExpandConstant('{tmp}\check_installed.ps1'); TempOutputPath := ExpandConstant('{tmp}\installed_output.txt'); SaveStringToFile(TempScriptPath, PSScript, False); if not Exec('powershell.exe', '-NoProfile -ExecutionPolicy Bypass -Command "& ''' + TempScriptPath + ''' | Out-File -FilePath ''' + TempOutputPath + ''' -Encoding ASCII"', '', SW_HIDE, ewWaitUntilTerminated, ResultCode) then begin DeleteFile(TempScriptPath); Exit; end; DeleteFile(TempScriptPath); if not FileExists(TempOutputPath) then Exit; if not LoadStringFromFile(TempOutputPath, Output) then begin DeleteFile(TempOutputPath); Exit; end; DeleteFile(TempOutputPath); Lines := TStringList.Create; try Lines.Text := Output; // Check each printer in database against installed printers for I := 0 to GetArrayLength(PrinterDataArray) - 1 do begin PrinterDataArray[I].IsInstalled := False; for J := 0 to Lines.Count - 1 do begin if Trim(Lines[J]) = PrinterDataArray[I].PrinterName then begin PrinterDataArray[I].IsInstalled := True; Break; end; end; end; Result := True; finally Lines.Free; end; end; // Initialize wizard pages procedure InitializeWizard(); var I: Integer; DisplayText: String; AutoSelectPrinter: String; FoundMatch: Boolean; begin // Query printers from database if not QueryPrinters() then begin MsgBox('Failed to query printers from ShopDB database.' + #13#10#13#10 + 'Please ensure:' + #13#10 + '- You have network connectivity' + #13#10 + '- The ShopDB server (tsgwp00525.rd.ds.ge.com) is accessible' + #13#10 + '- You are connected to the GE network' + #13#10 + '- The API endpoint is running', mbError, MB_OK); WizardForm.Close; Exit; end; if GetArrayLength(PrinterDataArray) = 0 then begin MsgBox('No printers found in the database.' + #13#10#13#10 + 'This installer supports:' + #13#10 + '- HP and Xerox network printers (TCP/IP)' + #13#10 + '- HID card printers (USB)', mbInformation, MB_OK); WizardForm.Close; Exit; end; // Check which printers are already installed CheckInstalledPrinters(); // Check for command-line parameter to auto-select printer(s) // Usage: PrinterInstaller.exe /PRINTER="PrinterName" // Or multiple: /PRINTER="Printer1,Printer2,Printer3" AutoSelectPrinter := ExpandConstant('{param:PRINTER|}'); FoundMatch := False; // Create printer selection page PrinterSelectionPage := CreateInputOptionPage(wpWelcome, 'Manage Network Printers', 'Select printers to install or uncheck to remove', 'Checked printers will be installed. Unchecked printers that are currently installed will be removed. ' + 'Already-installed printers are pre-checked.', False, False); // Add printers to selection page for I := 0 to GetArrayLength(PrinterDataArray) - 1 do begin if PrinterDataArray[I].PrinterName <> '' then begin if PrinterDataArray[I].IsInstalled then DisplayText := '[INSTALLED] ' else DisplayText := ''; DisplayText := DisplayText + PrinterDataArray[I].PrinterName + ' - ' + PrinterDataArray[I].Vendor + ' ' + PrinterDataArray[I].Model + ' (' + PrinterDataArray[I].FQDN + ')'; PrinterSelectionPage.Add(DisplayText); // Check if this printer should be auto-selected via command line if AutoSelectPrinter <> '' then begin // First try exact match against each comma-separated printer name if Pos(',', AutoSelectPrinter) > 0 then begin // Multiple printers separated by comma - check for exact matches if Pos(',' + PrinterDataArray[I].PrinterName + ',', ',' + AutoSelectPrinter + ',') > 0 then begin PrinterSelectionPage.Values[I] := True; FoundMatch := True; end else if PrinterDataArray[I].IsInstalled then PrinterSelectionPage.Values[I] := True else PrinterSelectionPage.Values[I] := False; end else begin // Single printer - use partial match (original behavior) if Pos(AutoSelectPrinter, PrinterDataArray[I].PrinterName) > 0 then begin PrinterSelectionPage.Values[I] := True; FoundMatch := True; end else if PrinterDataArray[I].IsInstalled then PrinterSelectionPage.Values[I] := True else PrinterSelectionPage.Values[I] := False; end; end // No auto-select parameter - pre-check if already installed else if PrinterDataArray[I].IsInstalled then begin PrinterSelectionPage.Values[I] := True; end else begin PrinterSelectionPage.Values[I] := False; end; end; end; // If command-line parameter was provided but no match found, show warning if (AutoSelectPrinter <> '') and (not FoundMatch) then begin MsgBox('Printer "' + AutoSelectPrinter + '" not found in the database.' + #13#10#13#10 + 'Please select a printer from the list manually.', mbInformation, MB_OK); end; end; // Validate selection before continuing function NextButtonClick(CurPageID: Integer): Boolean; var I: Integer; HasChange: Boolean; begin Result := True; if CurPageID = PrinterSelectionPage.ID then begin HasChange := False; // Check if any printer state has changed for I := 0 to GetArrayLength(PrinterDataArray) - 1 do begin // If checkbox state differs from installation state, we have a change if PrinterSelectionPage.Values[I] <> PrinterDataArray[I].IsInstalled then begin HasChange := True; Break; end; end; if not HasChange then begin MsgBox('No changes detected. Select printers to install or uncheck installed printers to remove them.', mbInformation, MB_OK); Result := False; end; end; end; // Install printers during installation phase (after files are extracted) procedure CurStepChanged(CurStep: TSetupStep); var I: Integer; PSScript: String; TempScriptPath: String; ResultCode: Integer; TotalCount: Integer; IsX64: Boolean; HPDriverPath, XeroxDriverPath: String; begin // Run after files are extracted but before finishing if CurStep = ssPostInstall then begin // Check if there are any changes to process (installs or removals) TotalCount := 0; for I := 0 to GetArrayLength(PrinterDataArray) - 1 do begin // Count changes: either installing (not installed but checked) or removing (installed but unchecked) if (not PrinterDataArray[I].IsInstalled and PrinterSelectionPage.Values[I]) or (PrinterDataArray[I].IsInstalled and not PrinterSelectionPage.Values[I]) then TotalCount := TotalCount + 1; end; if TotalCount = 0 then Exit; // Determine architecture and driver paths IsX64 := Is64BitInstallMode; if IsX64 then begin HPDriverPath := ExpandConstant('{tmp}\hp_drivers_x64'); XeroxDriverPath := ExpandConstant('{tmp}\xerox_drivers_x64\UNIV_5.1055.3.0_PCL6_x64_Driver.inf\x3UNIVX.inf'); end else begin HPDriverPath := ExpandConstant('{tmp}\hp_drivers_x32'); XeroxDriverPath := ExpandConstant('{tmp}\xerox_drivers_x32'); end; // Build PowerShell installation script PSScript := '$ErrorActionPreference = "Continue"' + #13#10 + '# Installer architecture mode (matches file copy behavior)' + #13#10; if IsX64 then PSScript := PSScript + '$Is64BitInstallMode = $true' + #13#10 else PSScript := PSScript + '$Is64BitInstallMode = $false' + #13#10; PSScript := PSScript + 'Write-Host ""' + #13#10 + 'Write-Host "========================================" -ForegroundColor Cyan' + #13#10 + 'Write-Host " WJDT Printer Installer" -ForegroundColor Cyan' + #13#10 + 'Write-Host "========================================" -ForegroundColor Cyan' + #13#10 + 'Write-Host ""' + #13#10 + '' + #13#10 + '# Function to install printer driver' + #13#10 + 'function Install-PrinterDriver {' + #13#10 + ' param(' + #13#10 + ' [string]$Vendor,' + #13#10 + ' [string]$DriverPath' + #13#10 + ' )' + #13#10 + '' + #13#10 + ' try {' + #13#10 + ' if ($Vendor -eq "HP") {' + #13#10 + ' $driverName = "HP Universal Printing PCL 6"' + #13#10 + ' # Use different INF file for x32 vs x64' + #13#10 + ' if ($DriverPath -like "*x64*") {' + #13#10 + ' $infFile = Join-Path $DriverPath "hpcu345u.inf"' + #13#10 + ' } else {' + #13#10 + ' $infFile = Join-Path $DriverPath "hpcu345c.inf"' + #13#10 + ' }' + #13#10 + ' } elseif ($Vendor -eq "Xerox") {' + #13#10 + ' $driverName = "Xerox Global Print Driver PCL6"' + #13#10 + ' # Check if DriverPath is already an INF file (x64) or directory (x32)' + #13#10 + ' if ($DriverPath -like "*.inf") {' + #13#10 + ' $infFile = $DriverPath' + #13#10 + ' } else {' + #13#10 + ' $infFile = Join-Path $DriverPath "x3UNIVX.inf"' + #13#10 + ' }' + #13#10 + ' } else {' + #13#10 + ' return $false' + #13#10 + ' }' + #13#10 + '' + #13#10 + ' # Check if driver already installed' + #13#10 + ' $existingDriver = Get-PrinterDriver -Name $driverName -ErrorAction SilentlyContinue' + #13#10 + ' if ($existingDriver) {' + #13#10 + ' Write-Host " $driverName already installed" -ForegroundColor Gray' + #13#10 + ' return $true' + #13#10 + ' }' + #13#10 + '' + #13#10 + ' Write-Host " Installing $driverName driver..." -ForegroundColor Yellow' + #13#10 + '' + #13#10 + ' # Locate pnputil.exe - check all possible locations' + #13#10 + ' $pnputil = $null' + #13#10 + ' $pnputilLocations = @(' + #13#10 + ' (Join-Path $env:SystemRoot "System32\pnputil.exe"),' + #13#10 + ' (Join-Path $env:SystemRoot "SysNative\pnputil.exe"),' + #13#10 + ' (Join-Path $env:SystemRoot "Syswow64\pnputil.exe"),' + #13#10 + ' "C:\Windows\System32\pnputil.exe",' + #13#10 + ' "C:\Windows\SysNative\pnputil.exe",' + #13#10 + ' "C:\Windows\Syswow64\pnputil.exe"' + #13#10 + ' )' + #13#10 + '' + #13#10 + ' foreach ($location in $pnputilLocations) {' + #13#10 + ' if (Test-Path $location) {' + #13#10 + ' $pnputil = $location' + #13#10 + ' Write-Host " Found pnputil at: $pnputil" -ForegroundColor Gray' + #13#10 + ' break' + #13#10 + ' }' + #13#10 + ' }' + #13#10 + '' + #13#10 + ' # Try PATH as last resort' + #13#10 + ' if (-not $pnputil) {' + #13#10 + ' $pnputil = (Get-Command pnputil.exe -ErrorAction SilentlyContinue).Path' + #13#10 + ' if ($pnputil) {' + #13#10 + ' Write-Host " Found pnputil in PATH: $pnputil" -ForegroundColor Gray' + #13#10 + ' }' + #13#10 + ' }' + #13#10 + '' + #13#10 + ' # If still not found, try without full path' + #13#10 + ' if (-not $pnputil) {' + #13#10 + ' $pnputil = "pnputil.exe"' + #13#10 + ' Write-Host " Using pnputil.exe from system PATH (no full path)" -ForegroundColor Gray' + #13#10 + ' }' + #13#10 + '' + #13#10 + ' # Use pnputil to add driver package' + #13#10 + ' try {' + #13#10 + ' # Debug: Verify file exists' + #13#10 + ' Write-Host " INF file path: $infFile" -ForegroundColor Gray' + #13#10 + ' if (Test-Path $infFile) {' + #13#10 + ' Write-Host " INF file exists: YES" -ForegroundColor Green' + #13#10 + ' } else {' + #13#10 + ' Write-Host " INF file exists: NO - FILE NOT FOUND!" -ForegroundColor Red' + #13#10 + ' Write-Host " ERROR: Cannot proceed without INF file" -ForegroundColor Red' + #13#10 + ' return $false' + #13#10 + ' }' + #13#10 + ' Write-Host " Running: & $pnputil /add-driver $infFile /install" -ForegroundColor Gray' + #13#10 + ' $pnpResult = & $pnputil /add-driver "$infFile" /install 2>&1' + #13#10 + ' $pnpExitCode = $LASTEXITCODE' + #13#10 + ' Write-Host " pnputil exit code: $pnpExitCode" -ForegroundColor Gray' + #13#10 + ' if ($pnpResult) {' + #13#10 + ' Write-Host " pnputil output: $pnpResult" -ForegroundColor Gray' + #13#10 + ' }' + #13#10 + '' + #13#10 + ' # Exit code 0 = success, 259 = driver already installed' + #13#10 + ' if ($pnpExitCode -ne 0 -and $pnpExitCode -ne 259) {' + #13#10 + ' Write-Host " Warning: pnputil returned code $pnpExitCode" -ForegroundColor Yellow' + #13#10 + ' }' + #13#10 + ' } catch {' + #13#10 + ' Write-Host " Warning: pnputil execution failed: $_" -ForegroundColor Yellow' + #13#10 + ' Write-Host " Attempting to continue with Add-PrinterDriver..." -ForegroundColor Yellow' + #13#10 + ' }' + #13#10 + '' + #13#10 + ' Start-Sleep -Seconds 5' + #13#10 + '' + #13#10 + ' # Try to add printer driver using PowerShell cmdlet' + #13#10 + ' try {' + #13#10 + ' Add-PrinterDriver -Name $driverName -ErrorAction Stop' + #13#10 + ' Write-Host " $driverName installed successfully" -ForegroundColor Green' + #13#10 + ' return $true' + #13#10 + ' } catch {' + #13#10 + ' # If Add-PrinterDriver fails, try legacy rundll32 method' + #13#10 + ' Write-Host " Add-PrinterDriver failed, trying legacy method..." -ForegroundColor Yellow' + #13#10 + ' try {' + #13#10 + ' $null = rundll32 printui.dll,PrintUIEntry /ia /m "$driverName" /f "$infFile"' + #13#10 + ' Start-Sleep -Seconds 3' + #13#10 + ' # Verify driver was installed' + #13#10 + ' $verifyDriver = Get-PrinterDriver -Name $driverName -ErrorAction SilentlyContinue' + #13#10 + ' if ($verifyDriver) {' + #13#10 + ' Write-Host " $driverName installed via legacy method" -ForegroundColor Green' + #13#10 + ' return $true' + #13#10 + ' } else {' + #13#10 + ' Write-Host " Warning: Driver installation could not be verified" -ForegroundColor Yellow' + #13#10 + ' return $true # Continue anyway' + #13#10 + ' }' + #13#10 + ' } catch {' + #13#10 + ' Write-Host " Warning: Legacy installation also failed" -ForegroundColor Yellow' + #13#10 + ' return $true # Continue anyway, printer creation might still work' + #13#10 + ' }' + #13#10 + ' }' + #13#10 + ' } catch {' + #13#10 + ' Write-Host " Error installing driver: $_" -ForegroundColor Red' + #13#10 + ' return $false' + #13#10 + ' }' + #13#10 + '}' + #13#10 + '' + #13#10 + '# Function to remove printer and its port' + #13#10 + 'function Remove-NetworkPrinter {' + #13#10 + ' param(' + #13#10 + ' [string]$PrinterName,' + #13#10 + ' [string]$PortAddress' + #13#10 + ' )' + #13#10 + '' + #13#10 + ' try {' + #13#10 + ' Write-Host ""' + #13#10 + ' Write-Host "Removing: $PrinterName" -ForegroundColor Magenta' + #13#10 + '' + #13#10 + ' # Check if printer exists' + #13#10 + ' $existingPrinter = Get-Printer -Name $PrinterName -ErrorAction SilentlyContinue' + #13#10 + ' if (-not $existingPrinter) {' + #13#10 + ' Write-Host " SKIPPED: Printer not found" -ForegroundColor Yellow' + #13#10 + ' return $true' + #13#10 + ' }' + #13#10 + '' + #13#10 + ' # Remove printer' + #13#10 + ' Write-Host " Removing printer..." -ForegroundColor Yellow' + #13#10 + ' Remove-Printer -Name $PrinterName -ErrorAction Stop' + #13#10 + ' Write-Host " Printer removed" -ForegroundColor Green' + #13#10 + '' + #13#10 + ' # Remove port if exists and not used by other printers' + #13#10 + ' $portName = "IP_$PortAddress"' + #13#10 + ' $existingPort = Get-PrinterPort -Name $portName -ErrorAction SilentlyContinue' + #13#10 + ' if ($existingPort) {' + #13#10 + ' $printersUsingPort = Get-Printer | Where-Object { $_.PortName -eq $portName }' + #13#10 + ' if ($printersUsingPort.Count -eq 0) {' + #13#10 + ' Write-Host " Removing unused port..." -ForegroundColor Yellow' + #13#10 + ' Remove-PrinterPort -Name $portName -ErrorAction Stop' + #13#10 + ' Write-Host " Port removed: $portName" -ForegroundColor Green' + #13#10 + ' } else {' + #13#10 + ' Write-Host " Port still in use by other printers" -ForegroundColor Gray' + #13#10 + ' }' + #13#10 + ' }' + #13#10 + '' + #13#10 + ' Write-Host " SUCCESS: $PrinterName removed" -ForegroundColor Green' + #13#10 + ' return $true' + #13#10 + ' } catch {' + #13#10 + ' Write-Host " ERROR: $_" -ForegroundColor Red' + #13#10 + ' return $false' + #13#10 + ' }' + #13#10 + '}' + #13#10 + '' + #13#10 + '# Function to install individual printer' + #13#10 + 'function Install-NetworkPrinter {' + #13#10 + ' param(' + #13#10 + ' [string]$PrinterName,' + #13#10 + ' [string]$PortAddress,' + #13#10 + ' [string]$Vendor,' + #13#10 + ' [string]$Model' + #13#10 + ' )' + #13#10 + '' + #13#10 + ' try {' + #13#10 + ' Write-Host ""' + #13#10 + ' Write-Host "Installing: $PrinterName" -ForegroundColor Cyan' + #13#10 + ' Write-Host " Address: $PortAddress" -ForegroundColor Gray' + #13#10 + ' Write-Host " Model: $Vendor $Model" -ForegroundColor Gray' + #13#10 + '' + #13#10 + ' # Determine driver name' + #13#10 + ' if ($Vendor -eq "HP") {' + #13#10 + ' $driverName = "HP Universal Printing PCL 6"' + #13#10 + ' } elseif ($Vendor -eq "Xerox") {' + #13#10 + ' $driverName = "Xerox Global Print Driver PCL6"' + #13#10 + ' } elseif ($Vendor -eq "HID") {' + #13#10 + ' $driverName = "DTC4500e Card Printer"' + #13#10 + ' } else {' + #13#10 + ' Write-Host " Unknown vendor: $Vendor" -ForegroundColor Red' + #13#10 + ' return $false' + #13#10 + ' }' + #13#10 + '' + #13#10 + ' # For USB card printers, driver installation is enough' + #13#10 + ' # User plugs in USB device and Windows auto-configures it' + #13#10 + ' if ($PortAddress -eq "USB") {' + #13#10 + ' Write-Host " USB card printer - driver installed" -ForegroundColor Green' + #13#10 + ' Write-Host " Connect printer via USB and Windows will detect it" -ForegroundColor Gray' + #13#10 + ' Write-Host " SUCCESS: $driverName ready for USB device" -ForegroundColor Green' + #13#10 + ' return $true' + #13#10 + ' }' + #13#10 + '' + #13#10 + ' # For network printers, check if printer already exists' + #13#10 + ' $existingPrinter = Get-Printer -Name $PrinterName -ErrorAction SilentlyContinue' + #13#10 + ' if ($existingPrinter) {' + #13#10 + ' Write-Host " SKIPPED: Printer already exists" -ForegroundColor Yellow' + #13#10 + ' return $true' + #13#10 + ' }' + #13#10 + '' + #13#10 + ' # Create port name for network printers' + #13#10 + ' $portName = "IP_$PortAddress"' + #13#10 + '' + #13#10 + ' # Check if port exists' + #13#10 + ' $existingPort = Get-PrinterPort -Name $portName -ErrorAction SilentlyContinue' + #13#10 + ' if (-not $existingPort) {' + #13#10 + ' Write-Host " Creating printer port..." -ForegroundColor Yellow' + #13#10 + ' Add-PrinterPort -Name $portName -PrinterHostAddress $PortAddress -ErrorAction Stop' + #13#10 + ' Write-Host " Port created: $portName" -ForegroundColor Green' + #13#10 + ' } else {' + #13#10 + ' Write-Host " Using existing port: $portName" -ForegroundColor Gray' + #13#10 + ' }' + #13#10 + '' + #13#10 + ' # Add printer' + #13#10 + ' Write-Host " Adding printer..." -ForegroundColor Yellow' + #13#10 + ' Add-Printer -Name $PrinterName -DriverName $driverName -PortName $portName -ErrorAction Stop' + #13#10 + ' Write-Host " SUCCESS: $PrinterName installed" -ForegroundColor Green' + #13#10 + ' return $true' + #13#10 + ' } catch {' + #13#10 + ' Write-Host " ERROR: $_" -ForegroundColor Red' + #13#10 + ' return $false' + #13#10 + ' }' + #13#10 + '}' + #13#10 + '' + #13#10 + 'Write-Host "Step 1: Installing printer drivers..." -ForegroundColor Cyan' + #13#10 + 'Write-Host ""' + #13#10 + '' + #13#10; // Install HP driver if needed PSScript := PSScript + 'if (Install-PrinterDriver -Vendor "HP" -DriverPath "' + HPDriverPath + '") {' + #13#10 + ' Write-Host ""' + #13#10 + '} else {' + #13#10 + ' Write-Host "Failed to install HP driver. Continuing anyway..." -ForegroundColor Yellow' + #13#10 + ' Write-Host ""' + #13#10 + '}' + #13#10; // Install Xerox driver (both x64 and x32 now supported) PSScript := PSScript + 'if (Install-PrinterDriver -Vendor "Xerox" -DriverPath "' + XeroxDriverPath + '") {' + #13#10 + ' Write-Host ""' + #13#10 + '} else {' + #13#10 + ' Write-Host "Failed to install Xerox driver. Continuing anyway..." -ForegroundColor Yellow' + #13#10 + ' Write-Host ""' + #13#10 + '}' + #13#10 + '' + #13#10; PSScript := PSScript + 'Write-Host "Step 2: Processing printer changes..." -ForegroundColor Cyan' + #13#10 + '' + #13#10 + '$installedCount = 0' + #13#10 + '$removedCount = 0' + #13#10 + '$failCount = 0' + #13#10 + '' + #13#10; // Process each printer: install, remove, or skip for I := 0 to GetArrayLength(PrinterDataArray) - 1 do begin // If was installed but now unchecked - REMOVE if PrinterDataArray[I].IsInstalled and (not PrinterSelectionPage.Values[I]) then begin PSScript := PSScript + 'if (Remove-NetworkPrinter -PrinterName "' + PrinterDataArray[I].PrinterName + '" ' + '-PortAddress "' + PrinterDataArray[I].FQDN + '") {' + #13#10 + ' $removedCount++' + #13#10 + '} else {' + #13#10 + ' $failCount++' + #13#10 + '}' + #13#10; end // If not installed and now checked - INSTALL else if (not PrinterDataArray[I].IsInstalled) and PrinterSelectionPage.Values[I] then begin PSScript := PSScript + 'if (Install-NetworkPrinter -PrinterName "' + PrinterDataArray[I].PrinterName + '" ' + '-PortAddress "' + PrinterDataArray[I].FQDN + '" ' + '-Vendor "' + PrinterDataArray[I].Vendor + '" ' + '-Model "' + PrinterDataArray[I].Model + '") {' + #13#10 + ' $installedCount++' + #13#10 + '} else {' + #13#10 + ' $failCount++' + #13#10 + '}' + #13#10; end; // If state hasn't changed - SKIP (no code generated) end; // Add summary PSScript := PSScript + '' + #13#10 + 'Write-Host ""' + #13#10 + 'Write-Host "========================================" -ForegroundColor Cyan' + #13#10 + 'Write-Host " Operation Complete" -ForegroundColor Cyan' + #13#10 + 'Write-Host "========================================" -ForegroundColor Cyan' + #13#10 + 'Write-Host ""' + #13#10 + 'if ($installedCount -gt 0) {' + #13#10 + ' Write-Host " Printers installed: $installedCount" -ForegroundColor Green' + #13#10 + '}' + #13#10 + 'if ($removedCount -gt 0) {' + #13#10 + ' Write-Host " Printers removed: $removedCount" -ForegroundColor Magenta' + #13#10 + '}' + #13#10 + 'if ($failCount -gt 0) {' + #13#10 + ' Write-Host " Failed operations: $failCount" -ForegroundColor Red' + #13#10 + '}' + #13#10 + 'if ($installedCount -eq 0 -and $removedCount -eq 0 -and $failCount -eq 0) {' + #13#10 + ' Write-Host " No changes were made" -ForegroundColor Gray' + #13#10 + '}' + #13#10 + 'Write-Host ""' + #13#10 + 'Write-Host "Press any key to close..." -ForegroundColor Gray' + #13#10 + '$null = $Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")'; // Save and execute script TempScriptPath := ExpandConstant('{tmp}\install_printers.ps1'); SaveStringToFile(TempScriptPath, PSScript, False); Exec('powershell.exe', '-NoProfile -ExecutionPolicy Bypass -File "' + TempScriptPath + '"', '', SW_SHOW, ewWaitUntilTerminated, ResultCode); DeleteFile(TempScriptPath); end; end; // Skip directory selection function ShouldSkipPage(PageID: Integer): Boolean; begin Result := False; if PageID = wpSelectDir then Result := True; end;