Installer packages for GE manufacturing tools: - BlueSSOFix: Blue SSO authentication fix - HIDCardPrinter: HID card printer setup - HPOfflineInstaller: HP printer offline installer - MappedDrive: Network drive mapping - PrinterInstaller: General printer installer - ShopfloorConnect: Shopfloor connectivity tool - XeroxOfflineInstaller: Xerox printer offline installer 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
798 lines
33 KiB
Plaintext
798 lines
33 KiB
Plaintext
; 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;
|