Powershell: Printer Loop not working

Hey Guys,
Im having a weird issue trying to deploy this powershell script to setup printers.

So, if i run this script locally it works fine no issues.
We have a remote software that lets us backdoor as SYSTEM, if i run this manually as SYSTEM it works fine.

But if i run this from bigfix or the debugger it will only do the first .21 printer, it will not do the other 2 printers.

Here is the output from logging in the script

2025-02-28 16:15:34 - Trying IP: http://172.16.123.21
2025-02-28 16:15:35 - Found model name: Lexmark MS823n
2025-02-28 16:15:35 - Determined driver name: Lexmark MS820 Series XL
2025-02-28 16:15:35 - Setting up printer: 823-SIGN21 with model: Lexmark MS823n
2025-02-28 16:15:35 - Removed existing printer: 823-SIGN21
2025-02-28 16:15:36 - Created printer port: SIGN with IP: 172.16.123.21
2025-02-28 16:15:56 - Added printer: 823-SIGN21 with driver: Lexmark MS820 Series XL
2025-02-28 16:15:56 - Trying IP: http://172.16.123.22
2025-02-28 16:15:57 - Found model name: Lexmark MX521ade
2025-02-28 16:15:57 - Determined driver name: Lexmark MX520 Series XL
2025-02-28 16:15:57 - Timeout occurred while fetching the URL: http://172.16.123.22
2025-02-28 16:15:57 - Trying IP: http://172.16.123.23
2025-02-28 16:15:58 - Found model name: Lexmark MS823n
2025-02-28 16:15:58 - Determined driver name: Lexmark MS820 Series XL
2025-02-28 16:15:58 - Timeout occurred while fetching the URL: http://172.16.123.23

Now it says its timing out, but it wouldnt be able to find the ModelName if it was timing out. Quite odd.

Any ideas, why this just doesnt work from bigfix/debugger, but manually it works just fine.

Also, I cant use “powershell” i have to use bigfix action script. Not sure why, I think our environment just doesn’t allow direct scripts to run.

action uses wow64 redirection false
delete __createfile

//    CREATEFILE
createfile until END_OF_FILE

# Define the log file path
$logFilePath = "C:\software\printLogFile.log"

# Function to log messages
function Log-Message {{
    param (
        [string]$message
    )
    $timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
    $logMessage = "$timestamp - $message"
    Write-Output $logMessage | Out-File -FilePath $logFilePath -Append
}

# Get the store number from the computer name
$storeNumber = $env:COMPUTERNAME # Get PC name
$removeTextAfterHyphen = $storeNumber.Substring(0, $storeNumber.IndexOf('-')) # Remove text after - in PC name
$SN = $removeTextAfterHyphen # Store PC name in a reusable variable

# Define the function to set up printers based on model
function Set-Printer {{
    param (
        [string]$modelName,
        [string]$ipAddress,
        [string]$printerName,
        [string]$driverName,
        [string]$portName
    )

    Log-Message "Setting up printer: $printerName with model: $modelName"

    # Remove existing printer if it exists
    $existingPrinter = Get-CimInstance -Class Win32_Printer -Filter "Name='$printerName'"
    if ($existingPrinter) {{
        Remove-Printer -Name $printerName
        Log-Message "Removed existing printer: $printerName"
    }

    # Create Printer Port
    Add-PrinterPort -Name $portName -PrinterHostAddress $ipAddress
    Log-Message "Created printer port: $portName with IP: $ipAddress"

    # Add Printer
    Add-Printer -Name $printerName -DriverName $driverName -PortName $portName
    Log-Message "Added printer: $printerName with driver: $driverName"
}

# Define the hashtable
$hashtable = @{{
    "206"=150; "211"=211; "212"=212; "214"=166; "217"=151; "218"=218
}

# Define the fourth octet values
$fourthOctets = @(21, 22, 23)

# Initialize the model name variable
$modelName = ""

# Check if the $SN value exists in the hashtable
if ($hashtable.ContainsKey($SN)) {{
    $thirdOctet = $hashtable[$SN]

    # Loop through each fourth octet value
    foreach ($fourthOctet in $fourthOctets) {{
        # Construct the URL
        $url = "http://172.16.$thirdOctet.$fourthOctet"
        
        # Print the current IP address to the console
        Log-Message "Trying IP: $url"
        
        # Fetch the content from the URL with a timeout
        try {{
            $response = Invoke-WebRequest -Uri $url -UseBasicParsing
            $content = $response.Content

            # Extract the model name using regex
            $modelName = [regex]::Match($content, '(?<=<div class="printername" role="heading">).*?(?=</div>)').Value
            if (-not $modelName) {{
                $modelName = [regex]::Match($content, '<TITLE>(.*?)</TITLE>').Groups[1].Value
            }

            Log-Message "Found model name: $modelName"

            # Determine the driver name based on the model
            $driverName = switch -Wildcard ($modelName) {{
                "*ms312*" {{ "Lexmark MS310 Series v2 XL" }
                "*ms315*" {{ "Lexmark MS310 Series v2 XL" }
                "*ms32*" {{ "Lexmark MS320 Series XL" }
                "*ms33*" {{ "Lexmark Printer Software G3 XL" }
                "*ms81*" {{ "Lexmark MS810 Series XL" }
                "*ms82*" {{ "Lexmark MS820 Series XL" }
                "*mx51*" {{ "Lexmark MX510 Series XL" }
                "*mx52*" {{ "Lexmark MX520 Series XL" }
                "*mx53*" {{ "Lexmark MX530 Series XL" }
                default {{ "Lexmark Universal v2 XL" }
            }

            Log-Message "Determined driver name: $driverName"

            # Define the printer name and driver based on the fourth octet
            switch ($fourthOctet) {{
                21 {{
                    Set-Printer -modelName $modelName -ipAddress "172.16.$thirdOctet.$fourthOctet" -printerName "$SN-SIGN21" -driverName $driverName -portName "SIGN"
                }
                22 {{
                    Set-Printer -modelName $modelName -ipAddress "172.16.$thirdOctet.$fourthOctet" -printerName "$SN-MFP22" -driverName $driverName -portName "MFP"
                }
                23 {{
                    Set-Printer -modelName $modelName -ipAddress "172.16.$thirdOctet.$fourthOctet" -printerName "$SN-DSD23" -driverName $driverName -portName "DSD"
                }
                default {{
                    Set-Printer -modelName $modelName -ipAddress "172.16.$thirdOctet.$fourthOctet" -printerName "$SN-DEFAULT" -driverName "Lexmark Universal v2 XL" -portName "DEFAULT"
                }
            }
        } catch {{
            Log-Message "Timeout occurred while fetching the URL: $url"
            switch ($fourthOctet) {{
                21 {{
                    Set-Printer -modelName $modelName -ipAddress "172.16.$thirdOctet.$fourthOctet" -printerName "$SN-SIGN21" -driverName "Lexmark Universal v2 XL" -portName "SIGN"
                }
                22 {{
                    Set-Printer -modelName $modelName -ipAddress "172.16.$thirdOctet.$fourthOctet" -printerName "$SN-MFP22" -driverName "Lexmark Universal v2 XL" -portName "MFP"
                }
                23 {{
                    Set-Printer -modelName $modelName -ipAddress "172.16.$thirdOctet.$fourthOctet" -printerName "$SN-DSD23" -driverName "Lexmark Universal v2 XL" -portName "DSD"
                }
                default {{
                    Set-Printer -modelName $modelName -ipAddress "172.16.$thirdOctet.$fourthOctet" -printerName "$SN-DEFAULT" -driverName "Lexmark Universal v2 XL" -portName "DEFAULT"
                }
            }
        }
    }
}

END_OF_FILE


delete AllLexmarkGeneralStore.ps1
move __createfile AllLexmarkGeneralStore.ps1

waithidden { pathname of file ((it as string) of value "Path" of key "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\PowerShell\1\ShellIds\Microsoft.PowerShell" of native registry) } -ExecutionPolicy ByPass -File AllLexmarkGeneralStore.ps1

First, kudos on using the code markup tags. That makes it much easier to follow what you’re trying to do, which is really helpful for me as I’m not the best at PowerShell. It helps me eliminate the most common problem, that is, missing one of the { to escape as {{. All of yours look correct.

It’s a little tricky trying to understand what’s happening there, but I do like your use of a try/catch block, that really helps ensure that we can get some details when there’s an exception.

It took me several minutes to try to figure out what you’re doing in that ‘catch’ block though… one issue I see is you’re assuming that the only error was a connection timeout from Invoke-WebRequest earlier, so you explicitly print the timeout message…and then go on to try to install the printer anyway using a default driver name

catch {{
            Log-Message "Timeout occurred while fetching the URL: $url"
            switch ($fourthOctet) {{
                .... <printer installs with default driver >

Instead I think you should try logging the full exception message

# Print the error message
    Log-Message "An error occurred: $($_.Exception.Message)"
    Log-Message "Full error details: $_"

You might find that the error came from elsewhere, maybe Set-Printer or Add-PrinterPort or Add-Printer threw an error. In fact, as you point out, it did find the model name, so whatever exception it’s throwing must have come after the Invoke-WebRequest - so the error must come from inside Set-Printer. In fact since you’re retrying with the default driver in the Catch block, I’m a bit confused why you aren’t seeing a ‘Setting up printer’ message even on the failures too.

2 Likes

As @JasonWalker said, your Try contains lots of Steps, and each of them can fail - the Full Error Message will provide where it failed

1 Like