CreateProcess and WaitForSingleObject fails on the second of two PDF files - delphi

All
I use CreateProcess and WaitForSingleObject in Delphi 2007 to open files and wait for them to be closed.
I have found that when I open two PDF files in a row, the second WaitForSingleObject returns immediately. I have also found that this happens for jpg and tif files but not txt files. Also the second PDF takes 10 seconds longer to open than if opened by itself!
It also happens on both Vista and XP, and on a range of computers.
Am I using CreateProcess incorrectly or is it something else?
Any help would be appreciated.
Regards
Bob

What happens depends on the application that is registered to open PDF or JPG files. If you open the documents in an SDI application, then every CreateProcess() call returns a process handle for an application, which you can wait for - this will return when the application editing the document closes.
If however an application is limited to a single instance, then every further call will return as soon as the new instance has passed the data to the first instance (which will usually open the document in a new frame), and then has exited. I think that is what happens in your case, probably you are using Acrobat Reader to open the PDF files?

Related

How to find out if a program accepts as parameters just a file or a list of files?

I would like to write some code in Delphi for opening some files (e.g. mp3, png) with the associated program in Windows.
With AssocQueryString, I can find the program for a given extension.
With this program, I can start the given file, when only one file was selected.
The problem is when I try to start the program with a list of files.
Example 1 - mp3 is associated with AIMP3 and this call works fine
D:\Tools\AIMP3\AIMP3.exe "F:\TestFiles\mp3\file1.mp3" "F:\TestFiles\mp3\file2.mp3"
Example 2 - png is associated with IrfanView and this call fail
D:\Tools\IrfanView\i_view32.exe "F:\TestFiles\png\file1.png" "F:\TestFiles\png\file2.png"
IrfanView does not accept calling it with a list of files, but only with one file.
My question is, how do I find out if a program accepts as parameters just a single file or a list of files?
I have tried to check the Registry but found nothing. In shell->open->command I can find "%1" for both programs.
I have tried to use the IDropTarget interface, but this does not work with IrfanView, either (drop multiple files on i_view32.exe doesn't work in Windows Explorer, either).
On the other hand, Windows Explorer (if using Open from the context menu for many png files) opens a new instance of IrfanView for each file. If I had this information, I could also start IrfanView for each file.

Opening a file in a memory stream with the correct program

My application saves files to a database field. It will take file types of .pdf, .doc, .xls, and .html (for example) save them to the table, so I can later extract the value and open it as a file.
Currently, I am saving a file (type pdf in this example) to a Varbinary field in a SQL table I created. I am then reading that file back into a memory stream using the following code:
TBlobField(FieldByName('FileData')).SaveToStream(FileData);
I can save this to desktop as a pdf just fine. However I would like to open it directly from the memory stream with the appropriate application (in this example adobe acrobat). I could write this to file first and then open it with shellexecute but i would rather open it directly. How would I go about accomplishing this? Any help would be greatly appreciated, I've looked all over and can only find examples using shellexecute to open Filepaths. ShellExecuteEx claims the lpFile can be set to an object but i haven't had any luck getting it to work.
You cannot do that. Memory is private to a process. When the Acrobat process executes, it cannot read your memory. You will have to save to a file and ask Acrobat to open that, or host a PDF viewer component in your process.

How to ensure that a file is correctly written to file system?

I hava an application that reads a file from a ZIP archive and saves it to file on file system. After writing it to file system I start start immediately to read this file with a SAX2 reader. On bigger files (300+ MB) it sometimes occures, that SAX2 stops parsing because of an unclosed tag. But when I check the file (or even try to read it again later) it works, so the file it self it OK.
FZipKit.ExtractToStream(LFileName, LStream);
LStream.SaveToFile(OutputFilename);
SAX2.processUrl(OutputFilename);
My assumption is, that the file was not yet fully written to file system when I started the parsing process.
Is there a way to ensure, that the file was written or the steam has been flushed to file system?
thx
I'm going to first of all assume that the XML parser operates correctly. If it is incapable of reading files, well the solution is obvious.
Which leads us to look at how the file is created. When you call SaveToFile, the file is opened, written, closed and buffers are flushed. In a plain vanilla system, your XML parser will see the entire content of the file. The only conclusion is that something is interfering. The most like suspect is your virus scanner. Many scanners, even the most respected ones, cannot properly handle a file being closed and then immediately re-opened.
The bottom line is that your code is fine and the problem almost certainly lies with your local environment.

Using PDFSharp to print: how can I suppress Adobe window?

I have a simple C# utility that invokes PDFSharp to send a PDF file to a printer. However, it seems to behave inconsistently on a Windows 7 machine. Here's the code
PdfFilePrinter.AdobeReaderPath = "C:\\Program Files\\Adobe\\Reader 10.0\\Reader\\AcroRd32.exe";
PdfFilePrinter printer = new PdfFilePrinter(fileToPrint, printerName);
try
{
printer.Print();
When testing I launch the utility from the command line several times in a row processing a bunch of PDF files one file at a time. During some of these runs, a small Adobe window pops up. I don't have a link to what it looks like but it's a window with standard Adobe Reader X menus, a "Open a recent file" list on bottom left and "Acrobat.com services" on bottom right. Unless I manually close this window, printer.Print(); will never complete, which is a problem since I need to batch process hundreds of files at a time.
When this happens seems to be random. Sometimes it happens when the 1st test file is being processed and sometimes it's the 5th or the 7th.
How can I either ensure that this window does not appear or suppress it automatically if it does?
Any chance your printer supports PDF natively? If so, you could just send it directly to the printer either via LPR/RAW 9100 or through a Windows print queue: How to send raw data to a printer

Need help opening printer spool shadow file (.SHD) that is locked

I'm interested in some information inside a shadow file (.shd) located inside the windows print spooling directory "C:\Windows\System32\spool\PRINTERS". Every time a print job is started, a spool file (.spl) and a shadow file (.shd) are created in that directory. So far I have been successful in detecting when a print job has started, and have been able to pause that print job. If you don't pause the job, the files eventually make their way to the printer and then are deleted by windows.
My problem is. I cannot open the .SHD files because they are locked in such a way that you can not read them while they are open by the sprint spooler. I've even tried going to the file in windows explorer and simply copying the file to another file, and that didn't work either. The .SPL spool files I can open though. I simply wait, and fairly quickly the spooler release that file. For the shadow file though, it permanently holds on to this file. Unfortunately, its the one I need.
The line of code I'm using specifically to open the file is as follows:
m_spoolJobStream = new FileStream(spoolFilePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
The IOException I get is:
The process cannot access the file 'C:\Windows\system32\spool\PRINTERS\FP00083.SHD' because it is being used by another process.
So yes, it is being used by another process. Its being used by the window's print spooler service. But I don't think there is anything I can do about that. All I want to do is read the file. I don't want to make any changes to it. Is there anything I can do here or am I just screwed?
Check the option: "Keep printed documents" (if you have HP printer) and then see your spool file folder, both shadow and spool files would be there.
Well, I did not find a way around this problem. I suspect there is no solution for this and it is by design. However I did find another way to get the information I wanted (at least it seems so thus far).
I'm using the FindNextPrinterChangeNotification() routine out of the winspool.drv library. This guy returns a pointer to a PRINTER_NOTIFY_INFO structure, which in turn contains an array of PRINTER_NOTIFY_INFO_DATA structures. Within that array, there is an element with its "Field" member marked as "JOB_NOTIFY_FIELD_DEVMODE". This element contains a fairly large structure of type DEVMODE. The structure is explained by M$ here http://msdn.microsoft.com/en-us/library/dd183565%28v=vs.85%29.aspx . This structure looks like it contains what I'm looking for and apparently is wrapped up in the .SHD file anyways according to this page http://www.undocprint.org/formats/winspool/shd. I'd like to know what else is in that .SHD file, but I still can't open it because its locked while the job is paused, and I suspect that it stays locked until the job is complete. Oh well, I think my new solution is more elegant anyways.
Just make sure you pause the job in the spool on BOTH your box and the server, then you should be able to copy/open/move the shd file just like you can the spl file. Worked for me, anyway...
This works for me:
- Hang your printer (e.g. jam the paper)
- Print and observe .SHD and .SPL being created
- Stop Print Spooler
- Open the file
The problem might be the FileShare.ReadWrite parameter. You're asking to read and write on the file and maybe that's why you get an error. You should try asking for read-only permission.

Resources