Hi Rick,
Related to the orphan EXE conversation, I sent some logs over to Martina at Eqeus to see if she had any thoughts. In reviewing the wwXFRX9.PrintReport
method, she noted that there were 2 calls to the XFRX Finalize()
method. There should only be a single call to Finalize()
when the XFRX process is complete. I'd recommend removing the call at line 1262 and moving the nulling of the object into the FINALLY
block of the TRY..CATCH
. I don't know if this will address the occasional issue I'm seeing but it smells right to me. 😃
Richard,
I didn't actually create this provider - I think it was Keith Hacket who wrote this and I took it in verbatim.
Make it work and send me your changes and I'll put it in. At this point I don't have a good way to test it.
To me it looks all the cleanup code should be in the finally block:
FINALLY
this.oPDF.Finalize()
this.oPDF = .null.
ENDTRY
The ISNULL()
check is there just in case the PDF object was never created.
Can you try this function and make sure this works? I made another change to remove the unnecessary EVAL()
at that the top of that code.
Later: Agh - no the eval has to stay so if XFRX is not present it doesn't break. Fixed in the code below
FUNCTION PrintReport(lcReport, lcOutputFile, lcExtraReportClauses, llAppend)
LOCAL loEval, ltStart, lnHandle, lcSetPrinterStr, lnRetVal, lcOutputDir
lcExtraReportClauses=IIF(EMPTY(lcExtraReportClauses),'',lcExtraReportClauses)
this.oPDF = EVALUATE( [XFRX("XFRX#LISTENER")] )
this.lSuccessful = .t.
TRY
IF VARTYPE(this.oPDF) # 'O'
this.cErrorMsg = [Unable to create report generator instance]
this.lSuccessful = .f.
ELSE
this.oPDF.cLogfile = this.cLogFile
m.lcExtraReportClauses = IIF(EMPTY(lcExtraReportClauses),'',lcExtraReportClauses)
IF TYPE('m.lcOutputFile') = 'C' AND !EMPTY(m.lcOutputFile);
AND NOT m.lcOutputFile == this.cOutputName
this.cOutputName = m.lcOutputFile
this.nParamsRetVal = .f.
ENDIF
IF VARTYPE(this.nParamsRetVal) # 'N'
this.SetParams(m.llAppend)
ENDIF
IF !this.lResetPageNo
m.lcExtraReportClauses = m.lcExtraReportClauses + ' noreset'
ENDIF
this.lResetPageNo = .f.
IF this.nParamsRetVal = 0
*this.oPDF.setEmbeddingType(this.nEmbeddingType)
IF UPPER(JUSTEXT(m.lcReport))=[LBX]
LABEL FORM (m.lcReport) OBJECT this.oPDF &lcExtraReportClauses
ELSE
REPORT FORM (m.lcReport) OBJECT this.oPDF NOPAGEEJECT &lcExtraReportClauses
ENDIF
SET PRINTER TO default
ELSE
this.cErrorMsg = [Unable to set report parameters, error code ] + TRANSFORM(this.nParamsRetVal)
this.lSuccessful = .f.
ENDIF
ENDIF
CATCH TO oError
this.lSuccessful = .f.
this.cErrorMsg = oError.Message
FINALLY
this.oPDF.Finalize()
this.oPDF = .null.
ENDTRY
RETURN this.lSuccessful
ENDFUNC
* wwXFRX :: PrintReport
+++ Rick ---
Will do.
If for some reason the object creation is not successful, putting the finalize()
in the FINALLY
will blow up. This is why I suggested putting it after everything else has succeeded and just using the FINALLY for cleanup. IAC I'll send you my suggested changes aster I finish testing.
If creation doesn't work, nothing will work and the code will blow up anyway because the instance is bad. The code should immediately check for a failed this.oPdf
and then bail.
FUNCTION PrintReport(lcReport, lcOutputFile, lcExtraReportClauses, llAppend)
LOCAL loEval, ltStart, lnHandle, lcSetPrinterStr, lnRetVal, lcOutputDir
lcExtraReportClauses=IIF(EMPTY(lcExtraReportClauses),'',lcExtraReportClauses)
this.oPDF = EVALUATE( [XFRX("XFRX#LISTENER")] )
IF VARTYPE(this.oPDF) # 'O'
this.cErrorMsg = [Unable to create XFRX report generator instance.]
this.lSuccessful = .f.
RETURN .F.
ENDIF
this.lSuccessful = .t.
TRY
this.oPDF.cLogfile = this.cLogFile
m.lcExtraReportClauses = IIF(EMPTY(lcExtraReportClauses),'',lcExtraReportClauses)
IF TYPE('m.lcOutputFile') = 'C' AND !EMPTY(m.lcOutputFile);
AND NOT m.lcOutputFile == this.cOutputName
this.cOutputName = m.lcOutputFile
this.nParamsRetVal = .f.
ENDIF
IF VARTYPE(this.nParamsRetVal) # 'N'
this.SetParams(m.llAppend)
ENDIF
IF !this.lResetPageNo
m.lcExtraReportClauses = m.lcExtraReportClauses + ' noreset'
ENDIF
this.lResetPageNo = .f.
IF this.nParamsRetVal = 0
*this.oPDF.setEmbeddingType(this.nEmbeddingType)
IF UPPER(JUSTEXT(m.lcReport))=[LBX]
LABEL FORM (m.lcReport) OBJECT this.oPDF &lcExtraReportClauses
ELSE
REPORT FORM (m.lcReport) OBJECT this.oPDF NOPAGEEJECT &lcExtraReportClauses
ENDIF
SET PRINTER TO default
ELSE
this.cErrorMsg = [Unable to set report parameters, error code ] + TRANSFORM(this.nParamsRetVal)
this.lSuccessful = .f.
ENDIF
CATCH TO oError
this.lSuccessful = .f.
this.cErrorMsg = oError.Message
FINALLY
this.oPDF.Finalize()
this.oPDF = .null.
ENDTRY
RETURN this.lSuccessful
ENDFUNC
OK, here you go. I've left my comments in and you should do what you wish with them or convert my tabs to spaces as you see fit. 😃 There are a couple of other bits I've added such as saving and restoring the workarea and handling for LBX vx FRX.
FUNCTION PrintReport(lcReport, lcOutputFile, lcExtraReportClauses, llAppend)
LOCAL loEval, ltStart, lnHandle, lcSetPrinterStr, lnRetVal, lcOutputDir, lnOldArea as Integer
lnOldArea = SELECT() && save current work area
lcExtraReportClauses=IIF(EMPTY(lcExtraReportClauses),'',lcExtraReportClauses)
*!* - rk - 2024-4-29 - just call this without the bother of creating a var
this.oPDF = EVALUATE([XFRX("XFRX#LISTENER")])
this.lSuccessful = .t.
*!* - rk - 2024-4-29 - move the vartype test outside of the try..catch block and just bail if it's not there per rs.
IF VARTYPE(this.oPDF) # 'O'
this.cErrorMsg = [Unable to create report generator instance]
RETURN .f.
ENDIF
TRY
this.oPDF.cLogfile = this.cLogFile
m.lcExtraReportClauses = IIF(EMPTY(lcExtraReportClauses),'',lcExtraReportClauses)
IF TYPE('m.lcOutputFile') = 'C' AND !EMPTY(m.lcOutputFile);
AND NOT m.lcOutputFile == this.cOutputName
this.cOutputName = m.lcOutputFile
this.nParamsRetVal = .f.
ENDIF
IF TYPE('this.nParamsRetVal') # 'N'
this.SetParams(m.llAppend)
ENDIF
*!* - rk - 2021-4-1 - put back extension check
IF !this.lResetPageNo AND UPPER(JUSTEXT(m.lcReport))=[FRX]
m.lcExtraReportClauses = m.lcExtraReportClauses + ' noreset'
ENDIF
this.lResetPageNo = .f.
IF this.nParamsRetVal = 0
*this.oPDF.setEmbeddingType(this.nEmbeddingType)
IF UPPER(JUSTEXT(m.lcReport))=[LBX]
LABEL FORM (m.lcReport) OBJECT this.oPDF &lcExtraReportClauses
ELSE
REPORT FORM (m.lcReport) OBJECT this.oPDF NOPAGEEJECT &lcExtraReportClauses
ENDIF
SELECT (lnOldArea) && restore previous work area
SET PRINTER TO default
ELSE
this.cErrorMsg = [Unable to set report parameters, error code ] + TRANSFORM(this.nParamsRetVal)
this.lSuccessful = .f.
ENDIF
this.oPDF.Finalize()
*!* - rk - 2024-4-26 - finalize should only be called once. also if the object creation failed this would throw a var not found error
*!* - rk - 2024-4-26 - also if the object creation failed this would throw a var not found error.
*!* - rk - 2024-4-26 - also move the oPDF nulling to the FINALLY block
*!* this.oPDF.Finalize()
CATCH TO oError
this.lSuccessful = .f.
this.cErrorMsg = oError.Message
FINALLY
this.oPdf = null
ENDTRY
RETURN this.lSuccessful
ENDFUNC
* wwXFRX :: PrintReport