{"record":{"id":"43c1a39983cc7370","repo":"dotnet/wpf","slug":"printsystemexception-printsystemjobinfo-refresh","errorCode":null,"errorMessage":"PrintSystemException.PrintSystemJobInfo.Refresh","messagePattern":"PrintSystemException\\.PrintSystemJobInfo\\.Refresh","errorType":"exception","errorClass":"PrintJobException","httpStatus":null,"severity":"error","filePath":"src/Microsoft.DotNet.Wpf/src/System.Printing/CPP/src/PrintSystemJobInfo.cpp","lineNumber":1105,"sourceCode":"    void\n    )\n{\n    VerifyAccess();\n\n    try\n    {\n        PopulateJobProperties(refreshPropertiesFilter);\n    }\n    catch (InternalPrintSystemException^ internalException)\n    {\n        if (IsErrorInvalidParameter(internalException->HResult))\n        {\n            get_InternalPropertiesCollection(\"Status\")->GetProperty(\"Status\")->IsInternallyInitialized = true;\n            this->JobStatusSecondary = static_cast<Int32>(PrintJobStatus::Deleted);\n        }\n        else\n        {\n            throw CreatePrintJobException(internalException->HResult,\n                                          \"PrintSystemException.PrintSystemJobInfo.Refresh\");\n        }\n    }\n}\n\n__declspec(noinline)\nbool\nPrintSystemJobInfo::\nIsErrorInvalidParameter(\n    int hResult\n    )\n{\n    return PrinterHResult::HResultCode(hResult) == ERROR_INVALID_PARAMETER;\n}\n\n\nPrintProperty^\nPrintSystemJobInfo::","sourceCodeStart":1087,"sourceCodeEnd":1123,"githubUrl":"https://github.com/dotnet/wpf/blob/81131a70a4c573cd62748a5c36908fc4d662daa9/src/Microsoft.DotNet.Wpf/src/System.Printing/CPP/src/PrintSystemJobInfo.cpp#L1087-L1123","documentation":"PrintSystemJobInfo.Refresh threw CreatePrintJobException with this message when the native refresh of the print job's properties failed against the spooler. In the source path, Refresh succeeds only while the underlying spool job still exists; when the job handle/lookup fails (typically because the job no longer exists), the native code falls into the else branch and throws this exception carrying the inner COM exception's HResult. It indicates the cached PrintSystemJobInfo no longer maps to a live spooler job.","triggerScenarios":"Calling PrintSystemJobInfo.Refresh() after the job has been deleted from the queue, finished printing and been purged by the spooler, or when the underlying HResult from the spooler (PRNJOB lookup) indicates the job is gone; also when the print queue connection is broken mid-refresh.","commonSituations":"Monitoring a print queue in a loop and the job completes/is cancelled between property reads; user cancels the job from the printer UI while your app holds a PrintSystemJobInfo; remote print server goes offline; a race between job deletion notification and the next Refresh call.","solutions":["Catch PrintSystemException (or the derived print exception) around Refresh and treat it as 'job no longer exists': re-enumerate via PrintQueue.GetPrintJobInfoCollection instead of refreshing the stale object.","Check JobStatus for PrintJobStatus.Deleted/Completed/Error before calling Refresh and skip the refresh for terminal states.","Wrap long-running queue monitoring in a try/catch that re-creates the PrintQueue connection (PrintServer.GetPrintQueue) when refresh fails repeatedly.","If the spooler was temporarily unavailable, retry Refresh after a short delay and verify queue connectivity (PrintQueue.IsOffline / queue status)."],"exampleFix":"// before\njob.Refresh();\nConsole.WriteLine(job.JobStatus);\n// after\ntry\n{\n    if ((job.JobStatus & PrintJobStatus.Deleted) == 0 &&\n        (job.JobStatus & PrintJobStatus.Completed) == 0)\n    {\n        job.Refresh();\n    }\n}\ncatch (PrintSystemException ex)\n{\n    // job vanished from the spooler; re-enumerate\n    var jobs = printQueue.GetPrintJobInfoCollection();\n}","handlingStrategy":"try-catch","validationCode":"// before refresh\nif ((job.JobStatus & PrintJobStatus.Deleted) != 0 ||\n    (job.JobStatus & PrintJobStatus.Completed) != 0 ||\n    (job.JobStatus & PrintJobStatus.Error) != 0)\n    return; // skip refresh for terminal states","typeGuard":null,"tryCatchPattern":"try { job.Refresh(); }\ncatch (PrintSystemException ex)\n{\n    // job no longer exists on the spooler; re-enumerate\n    jobs = printQueue.GetPrintJobInfoCollection();\n    job = jobs.FirstOrDefault(j => j.Name == expectedName);\n}","preventionTips":["Check JobStatus for Deleted/Completed/Error before each Refresh in polling loops.","Re-enumerate queue jobs instead of refreshing long-lived PrintSystemJobInfo references.","Refresh at most on job-status change events, not on tight timers, to shrink the delete race window.","Verify print-server connectivity (queue online, not offline) before batch refreshes."],"tags":["wpf","printing","print-spooler","native"],"backgroundTag":"resource-not-found","analyzedSha":"81131a70a4c573cd62748a5c36908fc4d662daa9","analyzedAt":"2026-09-14T10:12:48.479Z","contentChangedAt":"2026-09-14T10:12:48.479Z","schemaVersion":2},"datasetVersion":"2026-09-22T01:17:13.364Z"}