Printing .pdf without user interaction

The Agent(s) posted below have been around for a while, and seem to work well if manually invoked.

But what we are looking for is a way to get this to run locally, without user interaction.

What we have in mind is to have a user mail file running on a VM, that will only take in attachments (.pdf) and spit them out to a printer. No user will interact with that VM.

Is this possible?

Here’s the process as is stands (found in previous post)

===== THIS FIRST SECTION IS IN AN AGENT (run on selected documents)=====

Option Public

Use “PrintingUtilities”

Sub Initialize

Dim session As New NotesSession

Dim db As NotesDatabase

Dim dc As NotesDocumentCollection

Dim doc As NotesDocument

Dim FieldList(1) As String 'list of fields containing attachments

FieldList(0) = “Body”

Set db = session.currentdatabase

Set dc = db.UnprocessedDocuments

If dc.Count > 0 Then

Set doc = dc.GetFirstDocument()

While Not(doc Is Nothing)

Call PrintAllAttachments(doc, FieldList())

Call session.UpdateProcessedDoc( doc)

Set doc = dc.GetNextDocument(doc)

Wend

End If

End Sub

======THE FOLLOWING IS IN A SCRIPT LIBRARY CALLED ‘PrintingUtilities’======

'PrintingUtilities:

Option Public

'PrintingUtilities:

Option Explicit

%REM

Lotus Professional Services, July 2001

This library provides printing of attachments from Notes

Tested for Notes/Domino 5.0.3 Intl with MS Office 97 and 2000

Various revisions by Ernie Mercer (see notes elsewhere)

%END REM

’ Customized error messages

Const MSG_AutomationError = "Unable to find application "

Const MSG_UnableToPrint = "Unable to print file "

Const MSG_Continue = “Click OK to Continue printing supported file types”

Const MSG_NoExtension = “No file extension”

Const MSG_UnknownExtension = “Extension not recognized”

'ShellExecute

%REM

Parameter Description


hwnd Identifies the parent window. This window receives any message boxes an application produces (for example, for error reporting).

lpszOp Points to a null-terminated string specifying the operation to perform. This string can be “open” or “print.” If this parameter is NULL, “open” is the default value.

lpszFile Points to a null-terminated string specifying the file to open.

lpszParams Points to a null-terminated string specifying parameters passed to the application when the lpszFile parameter specifies an executable file. If lpszFile points to a string specifying a document file, this parameter is NULL.

LpszDir Points to a null-terminated string specifying the default directory.

FsShowCmd Specifies whether the application window is to be shown when the application is opened.

%END REM

’ Error codes for ShellExecute

Const ERROR_FILE_NOT_FOUND = 2 ’ File not found

Const ERROR_PATH_NOT_FOUND = 3 ’ Path not found

Const SE_ERR_ACCESSDENIED = 5 ’ Access denied

Const SE_ERR_OOM = 8 ’ Not enough memory to complete the operation

Const ERROR_BAD_FORMAT = 11 ’ EXE file invalid

Const SE_ERR_SHARE = 26

Const SE_ERR_ASSOCINCOMPLETE = 27 ’ Filename association invalid or incomplete

Const SE_ERR_DDETIMEOUT = 28 ’ DDE timeout

Const SE_ERR_DDEFAIL = 29 ’ DDE failed

Const SE_ERR_DDEBUSY = 30 ’ DDE already busy

Const SE_ERR_NOASSOC = 31 ’ No application associated with this extension

Const SE_ERR_DLLNOTFOUND = 32

Declare Function ShellExecute Lib “shell32.dll” Alias “ShellExecuteA” (Byval hwnd As Long, Byval lpszOp As String, Byval lpszFile As String, Byval lpszParams As String, _

Byval LpszDir As String, Byval FsShowCmd As Long) As Long

Public Sub PrintAllAttachments (doc As NotesDocument,Fields() As String)

'modification by Ernie Mercer to pass in a list of fields to print

'attachments from (not just the Body field)

'Prints out attachments in the document

Dim rtitem As notesrichtextitem

Dim x As Integer

If doc Is Nothing Then Exit Sub

For x = 0 To Ubound(Fields)

If doc.HasItem (Fields(x)) = True Then

Set rtitem = doc.GetFirstItem( Fields(x) )

If ( rtitem.Type = RICHTEXT ) = True Then

If Not(Isempty(rtitem.EmbeddedObjects)) Then

Forall o In rtitem.EmbeddedObjects ’ loops through all attachments

If ( o.Type = EMBED_ATTACHMENT ) Then

Call PrintAttachment (o)

End If

End Forall

Sleep (2) ''modification by Ernie Mercer - 3/5/2003 - give the print operations time to complete

Call CleanOutTmpDir

End If

End If

End If

Next

End Sub

Private Sub PrintAttachment ( o As Variant)

%REM

Prints out the attachment.

If the extension is not supported or the application is not installed, messagebox to the user.

Notes:

  1. We used OLE for Excel because ShellExecute only prints the first Worksheet.

With the OLE method, we print all worksheets.

  1. We did not use OLE for Word and PowerPoint because these apps support several file extensions,

which we would have to hard-code. If needed, these methods can be used, they were tested.

IN

o, the NotesEmbeddedObject to print

OUT

nothing

%END REM

Dim fname As String

Dim Period As String

Dim FileExtension As String

Dim ret As Integer

On Error Goto errHandle

fname = GetTmpDir + o.Source

Call o.ExtractFile ( fname )

Period = Instr(1, fname, “.”)

If Period = 0 Then

FileExtension = “”

Else

FileExtension = Mid$(fname, Period, 4)

End If

Select Case Lcase$(FileExtension)

Case “”

Msgbox MSG_NoExtension, 16, MSG_UnableToPrint + fname

’ Case “.doc”

’ Call PrintMSWord (fname)

Case “.xls”

Call PrintMSExcel (fname)

’ Case “.ppt”

’ Call PrintMSPowerPoint (fname)

Case Else

PrintDefault (fname)

End Select

Exit Sub

errHandle:

Msgbox "Error " + Cstr(Err) + ": " + Error$ + Chr$(13) + MSG_Continue, 16, MSG_UnableToPrint + fname

Print("Could not print attachment: " & o.source)

Exit Sub

End Sub

Private Function GetTmpDir As String

%REM

Gets (if exists) or creates a temporary directory \temp in the Notes data directory

IN

Nothing.

OUT

Nothing.

RETURN

The temporary directory, terminated by ""

%END REM

On Error Goto TmpDirError

Dim s As New NotesSession

Dim TmpDir As String

'Directory is the Notes data Directory

TmpDir = s.GetEnvironmentString (“Directory”, True)

TmpDir = TmpDir & “\temp”

If Dir$ (TmpDir , 16)=“” Then

Mkdir TmpDir

End If

TmpDir = TmpDir & ""

GetTmpDir = TmpDir

Exit Function

TmpDirError:

On Error Goto 0

GetTmpDir = “c:\temp”

Exit Function

End Function

Private Sub PrintMSWord (fname As String)

Dim app As Variant

Dim docToPrint As Variant

Dim PrintBackground As Integer

On Error 208 Goto err208

Set app = createobject(“Word.application”)

Set docToPrint = app.documents.open(fname)

’ Turn off background printing to avoid error message cf. Microsoft Technote #Q170393

PrintBackground = app.Options.PrintBackground()

If PrintBackground = True Then app.Options.PrintBackground = False

Call docToPrint.PrintOut()

app.Options.PrintBackground = PrintBackground 'Restore PrintBackground option

Call app.Quit(0)

Set app = Nothing

Exit Sub

err208: 'Cannot create automation object

Msgbox MSG_AutomationError + “MS Word”, 16, "Error " + Cstr(Err) + ": " + Error$

Exit Sub

End Sub

Private Sub PrintMSExcel (fname As String)

Dim app As Variant

Dim docToPrint As Variant

On Error 208 Goto err208

Set app = createobject(“Excel.application”)

Set docToPrint = app.workbooks.open(fname)

’ No background printing option available for Excel, no need for special handling

Call docToPrint.PrintOut()

Call app.workbooks.close

Call app.Quit()

Set app = Nothing

Exit Sub

err208: 'Cannot create automation object

Msgbox MSG_AutomationError + “MS Excel”, 16, "Error " + Cstr(Err) + ": " + Error$

Exit Sub

End Sub

Private Sub PrintMSPowerPoint (fname As String)

Dim app As Variant

Dim docToPrint As Variant

Dim PrintBackground As Integer

Dim NewInstance As Integer

’ Because PowerPoint, unlike Word and Excel, only allows one instance cf. MS Technote #Q222783

On Error 208 Goto createObject

Set app = GetObject (, “PowerPoint.Application”)

NewInstance = False

Goto objectCreated

createObject:

NewInstance = True

On Error 208 Goto err208

Set app = createobject(“PowerPoint.application”)

objectCreated:

app.visible = True ’ app has to be visible, error message otherwise

Call app.presentations.open(fname)

’ Turn off background printing to avoid error message

Set docToPrint = app.ActivePresentation

PrintBackground = docToPrint.PrintOptions.PrintInBackground

If PrintBackground = True Then app.ActivePresentation.PrintOptions.PrintInBackground = False

Call docToPrint.PrintOut()

docToPrint.PrintOptions.PrintInBackground = PrintBackground 'Restore PrintBackground option

docToPrint.Close

If NewInstance = True Then Call app.Quit() ’ Close application only if WE launched it

Set app = Nothing

Exit Sub

err208: 'Cannot create automation object

Msgbox MSG_AutomationError + “MS PowerPoint”, 16, "Error " + Cstr(Err) + ": " + Error$

Exit Sub

End Sub

Private Sub PrintDefault (fname As String)

'Ref: Microsoft article Q170918

Dim hwnd As Long

Dim ret As Long

Dim msg As String

ret = ShellExecute(hwnd, “Print”, fname, “”, “”, 0)

If ret<32 Then ’ Error

Select Case ret

Case ERROR_FILE_NOT_FOUND

msg = “File not found”

Case ERROR_PATH_NOT_FOUND

msg = “Path not found”

Case SE_ERR_ACCESSDENIED

msg = “Access denied”

Case SE_ERR_OOM

msg = “Out of memory”

Case SE_ERR_DLLNOTFOUND

msg = “DLL not found”

Case SE_ERR_SHARE

msg = “A sharing violation occurred”

Case SE_ERR_ASSOCINCOMPLETE

msg = “Incomplete or invalid file association”

Case SE_ERR_DDETIMEOUT

msg = “DDE Time out”

Case SE_ERR_DDEFAIL

msg = “DDE transaction failed”

Case SE_ERR_DDEBUSY

msg = “DDE busy”

Case SE_ERR_NOASSOC

msg = “No association for file extension”

Case ERROR_BAD_FORMAT

msg = “Invalid EXE file or error in EXE image”

Case Else

msg = “Unknown error”

End Select

Msgbox MSG_UnableToPrint + fname + Chr$(13) + MSG_Continue, 16, msg

Print("Could not print attachment: " & fname)

Else

Print("Printing attachment : " & fname)

End If

End Sub

Sub Initialize

End Sub

Private Sub CleanOutTmpDir

'Author: Ernie Mercer

'Date: 2/3/2003

Dim fname As String

Dim directory As String

directory = GetTmpDir()

'Clean out any old files still in the directory

fname$ = Dir$(directory$, 0) 'Get the name of the first file in the directory

Do While fname$ <> “”

Kill directory$ & fname$

fname$ = Dir$() 'Get the name of the next file in the directory

Loop

End Sub

Subject: Should be possible.

I believe it should be possible, but will take some configuring. Off the top of my head I can think of the following necessary steps:

  1. Have a replica of the mail file on the VM.

  2. Set up a replication schedule to replicate with the server replica.

  3. The Notes client will always need to be logged in/running.

  4. Select “Enable scheduled local agents” on the Basics tab of the User Preferences dialog box.

  5. Set the agent to run on a schedule and that it is to run on “Local” as the server.

  6. In the agent code remove all declarations and calls to fronted/UI properties and methods (if any of these are present the scheduled agent will not run). For example, you will need to remove all calls to the messagebox or msgbx method (I’d suggest adding a process to email you the results of any errors during processing).

Also, particularly as you will be working with PDF files, I’d recommend adding the following linked function to query the printer queue to determine when a print job has finished:

http://www-10.lotus.com/ldd/nd6forum.nsf/55c38d716d632d9b8525689b005ba1c0/ba7bb421d92fedf885257186006f3f78?OpenDocument

Subject: No Luck

So far… after setting up everything as mentioned, no luck.

It only works if I make it an action item and invoke it manully. On event, or scheduled doesn’t seem to work.