0

Having issues deleting a printer port as a WMI object

This

param(
[Parameter(Mandatory=$true)]
[string] $printerName
)

$printer=gwmi win32_Printer -filter "name='$printerName'"
$printer.Delete()
Write-Host $printer.portname


$port=gwmi win32_tcpipprinterport -filter "name='$($printer.portname)'" -EnableAllPrivileges
Write-host $port

$port.Delete() 

Fails with the following:

Exception calling "Delete" with "0" argument(s): "Generic failure "
At line:14 char:1
+ $port.Delete()
+ ~~~~~~~~~~~~~~
+ CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : DotNetMethodException

However when a sleep is added for 10 seconds between $printer.Delete and $port=gwmi... it works!

Any suggestions on what it could be and how to fix it other than a sleep?

Charlie Hardy
  • 175
  • 1
  • 3
  • 14
  • Remote actions take time, especially when using wmi. If it works with a sleep, leave it in. – Maximilian Burszley Feb 16 '18 at 16:35
  • @TheIncorrigible1 this is being run on the print server itself so it's not really remote. – Charlie Hardy Feb 16 '18 at 16:39
  • My statement about wmi still holds. I missed that it wasn't remote, but it does treat it like a remote connection (with wmi being the client and the underlying system being the server). It probably doesn't need 10 seconds depending on the speed of your server, but I would give it 1-2 seconds after each `.Delete()` action. – Maximilian Burszley Feb 16 '18 at 16:41
  • @TheIncorrigible1 we tried all the way up to 9 seconds and we only got consistent results at 10 seconds – Charlie Hardy Feb 16 '18 at 16:45
  • @TheIncorrigible1 is there someway we can effectively force a refresh or something? – Charlie Hardy Feb 16 '18 at 16:47
  • 1
    You can probably throw a loop into there to check that the printer exists until it doesn't, then move onto the next task. I'll write an answer with this suggestion – Maximilian Burszley Feb 16 '18 at 16:48
  • Share the code that makes the call remotely. I've had issues where Start-Sleep solved a problem because asynchronous operations were being cleaned up before they completed because my PSSession closed. – veefu Feb 17 '18 at 15:18
  • @veefu this code isn't being called remotely, at the moment I'm testing the script directly by running it from PowerShell ISE directly on the Print server and still getting the issue – Charlie Hardy Feb 19 '18 at 09:46
  • I take it the [PrintManagement](https://learn.microsoft.com/en-us/powershell/module/printmanagement/?view=win10-ps) module isn't available? – veefu Feb 19 '18 at 10:10
  • @veefu used the print management module and that was equally as dodgy and didn't work – Charlie Hardy Feb 21 '18 at 10:50

2 Answers2

0

Instead of having a hard-coded amount of time in there, you can utilize a loop to check for the printer until it stops existing:

Param(
    [Parameter(Mandatory = $True, Position = 0, ValueFromPipeline = $True)]
    [String]
    $PrinterName
)
$local:ErrorActionPreference = [System.Management.Automation.ActionPreference]::SilentlyContinue

$Printer = Get-WmiObject -Class Win32_Printer -Filter "Name='$PrinterName'"
$Port = Get-WmiObject -Class Win32_TcpIpPrinterPort -Filter "Name='$($Printer.PortName)'" -EnableAllPrivileges

Write-Host $Printer.PortName
Write-Host $Port

If (-not $Printer) { Return }
$Printer.Delete()
Do
{
    Start-Sleep -Seconds 2
} While (Get-WmiObject -Class Win32_Printer -Filter "Name='$PrinterName'")

If (-not $Port) { Return }
$Port.Delete()
Do
{
    Start-Sleep -Seconds 2
} While (Get-WmiObject -Class Win32_TcpIpPrinterPort -Filter "Name='$($Printer.PortName)'" -EnableAllPrivileges)
Maximilian Burszley
  • 18,243
  • 4
  • 34
  • 63
  • Unfortunately didn't work, it just seemed to get stuck in the end loop for deleting the port – Charlie Hardy Feb 16 '18 at 17:16
  • I cannot help further as I don't have a print server to test with available. Just ensure your wmi calls are being populated with data (variables are not null or empty). @CharlieHardy – Maximilian Burszley Feb 16 '18 at 18:34
0

This is how I ended up fixing it:

param(
    [Parameter(Mandatory=$true)]
    [string] $printerName
    )

$printer=gwmi win32_Printer -filter "name='$printerName'"
$printer.Delete()
Write-Host $printer.portname

$port=gwmi win32_tcpipprinterport -filter "name='$($printer.portname)'" -EnableAllPrivileges



if(!$port){
    throw "Printer port could not be found, this printer may have not been 
removed correctly"
}

$unableToDeletePort = $true
$counter = 10

while($unableToDeletePort -and $counter -ge 0)
{
    try{
        $port.Delete()
        $unableToDeletePort = $false
        write-host "deleted port"
       }
     catch{
        $unableToDeletePort = $true
        write-host "didn't delete port"
}
    Start-Sleep -Seconds 2
    $counter-=1

    $port=gwmi win32_tcpipprinterport -filter "name='$($printer.portname)'" -EnableAllPrivileges
}



if($unableToDeletePort){
    Restart-Service "Spooler"

    $counter=5

    while($unableToDeletePort -and $counter -ge 0)
    {
        try{
            $port.Delete()
            $unableToDeletePort = $false
            write-host "deleted port"
            }
    catch{
        $unableToDeletePort = $true
        write-host "didn't delete port"
         }
    Start-Sleep -Seconds 2
    $counter-=1

    $port=gwmi win32_tcpipprinterport -filter "name='$($printer.portname)'" -EnableAllPrivileges
    }

    if($unableToDeletePort){
        throw "Unable to delete port"
    }
}
Charlie Hardy
  • 175
  • 1
  • 3
  • 14