views:

1645

answers:

4

I have a program that send a document to a pdf printer driver and that driver prints to a particular directory. After the print I want to attach the pdf to an e-mail (MailMessage) and send it off.

Right now, I send the document to the printer (wich spawns a new process) and then call a FileSystemWatcher.WaitForChanged(WaitForChangedResult.Created) but when the object is created, it's still not done "printing" and the pdf printer still has a lock on it, throwing an error when I try to attach that file to an e-mail.

  • I've considered a plain Thread.Sleep(2000) or whatever, but that's far less than ideal.
  • I considered putting the attachment code in a try/catch block and looping on failure, but again, that's just bad news.

I can't really think of an elegant solution.

+1  A: 

Well, as long as the watcher is watching the file and letting you know whenever it's changed, you can just ignore the change notifications that occur while the files is still locked (still being written) and wait for the ultimate change notification which would signal the last write event, after which the file should be accessible (at which point you could finally disable the watch).

Other than that I'm not sure what you can do, because the watcher has no "file closed" event AFAIK.

Assaf Lavie
+3  A: 

WaitForChanges is waiting for the created event as you have it coded. As the document is being created, you get notified: this does not mean that the file is fully written and the lock removed.

Sadly, I don't know of a good solution other than polling the file periodically. If there was a "all locks removed" event, you could use that, but there isn't.

I just checked our PDF dump to directory code, and we only use WaitForChanges to detect the start of a new file. We then use an try {} catch {} where the catch (failing to get rights over the file) resubmits the attempt into the queue we maintain: each attempt "backs off" for longer, so the first try is 1 second after we detected the file, the second is 2 seconds later, then 4, 8, etc. This reduces the number retries on large files while still being fairly responsive to shorter files.

Godeke
precisely what I was thinking with my second bullet. That's what I'll probably end up doing (though, with a static timeout because all files are going to be the same size). It still feels like an itch that needs to be scratched though.
SnOrfus
A: 

AFAIK there is no way to check for file locks without error handling.

Does the pdf printer start with a new process maybe? Then you should be able to monitor that process and when it has exited your file will be unlocked.

Jesper Palm
A: 

If you're using Adobe's Acrobat for this, you can generate the PDF with Acrodist.exe (off the top of my head, you want the /N switch), and then wait for the spawned process to exit

Rowland Shaw