Help with some C++ printer code...
Posted: Sun May 02, 2004 9:34 pm
I apologize for posting all of this but I am trying to understand exactly how it works and use the same method in PB..
I'm trying to batch print PDF files, something that this code will do if compiled but I'm failing to understand how it works..
It looks like it opens Acrobat Reader and uses a print "verb". I thought that was just something you could do to print text file on the command line (issue "print myfile.txt" - but if I do that on the command line here it printes the contents of the PDF, not the rendered PDF file. This code does seem to work, so if anyone can give me a hand porting it to PB and understanding how that ShellExecute is working I'd really really appreciate it!!!
I'm trying to batch print PDF files, something that this code will do if compiled but I'm failing to understand how it works..
It looks like it opens Acrobat Reader and uses a print "verb". I thought that was just something you could do to print text file on the command line (issue "print myfile.txt" - but if I do that on the command line here it printes the contents of the PDF, not the rendered PDF file. This code does seem to work, so if anyone can give me a hand porting it to PB and understanding how that ShellExecute is working I'd really really appreciate it!!!
Code: Select all
#include <stdio.h>
#include <windows.h>
#include <winspool.h>
#define TIMEOUT 60
int multiplier=1;
HANDLE hProcessAdobe=0;
HWND hWndAdobe=0;
BOOL isRunning = FALSE;
BOOL wasRunning = TRUE;
char szAdobe[MAX_PATH];
// Callback for isAdobeRunning
BOOL CALLBACK EnumCallBack(HWND hwnd, LPARAM lParam)
{
char s[MAX_PATH];
// If window title contains match string
GetWindowText (hwnd, s, MAX_PATH);
if (strstr(s, (char *)lParam)) {
// Set the hWnd
hWndAdobe=hwnd;
// Set our flag
isRunning = TRUE;
return FALSE;
}
else
{
isRunning = FALSE;
return TRUE;
}
}
// Determine if Acrobat or Reader is running
BOOL isAdobeRunning()
{
// Search all windows for title starting with szWnd
EnumWindows (EnumCallBack, (LPARAM)szAdobe);
return(isRunning);
}
void usage(char *p)
{
printf("usage:\t%s [-p printer] [drive:][path]<filename>\n", p);
printf("Specifies drive, directory, and/or file(s) to print.\n");
printf("Prints to default printer unless [printer] specified.\n");
}
int pdfprint(char* fname, char* szAdobe, char* szPrinter)
{
DWORD size=1024;
SHELLEXECUTEINFO ei;
DWORD lpExitCode;
FILE *f;
int i;
int printed=0;
long lSize;
// Find the file's length
f = fopen(fname, "r");
if(f == NULL)
return 0;
fseek(f,0,SEEK_END);
lSize=ftell(f);
fclose(f);
// Extend the timeout for each MB of filesize
multiplier = (int)(lSize / 1000000)+1;
// Set up the ShellExecute parameters
ZeroMemory( &ei, sizeof(ei) );
ei.cbSize = sizeof(ei);
ei.fMask = SEE_MASK_FLAG_DDEWAIT | SEE_MASK_NOCLOSEPROCESS;
ei.nShow = SW_HIDE;
// Open Acrobat/Reader if it's not running
if(!isRunning)
{
wasRunning=FALSE;
ei.lpVerb = "open";
ei.lpFile = fname;
ei.lpParameters = NULL;
ShellExecuteEx(&ei);
hProcessAdobe = ei.hProcess;
for(i=0;i<TIMEOUT;i++)
{
Sleep(1000);
if(isAdobeRunning())
break;
}
}
// If Printer was specified on command line
if(strlen(szPrinter)>0)
{
// Set verb and printer name
ei.lpVerb = "printto";
ei.lpParameters = szPrinter;
}
else
// Otherwise, use default printer
ei.lpVerb = "print";
printf("Printing: '%s'\n", fname);
// Start the print job
ei.lpFile = fname;
ShellExecuteEx (&ei);
// Wait for print job to complete
for(i=0;i<(TIMEOUT*multiplier);i++)
{
GetExitCodeProcess(ei.hProcess, &lpExitCode);
if(lpExitCode!=STILL_ACTIVE)
{
printed = 1;
break;
}
Sleep(1000);
}
// If timeout
if(printed==0)
printf("Timeout\n");
return printed;
}
int main(int argc, char* argv[])
{
char szPrinter[MAX_PATH];
char szFile[MAX_PATH];
char szPath[MAX_PATH];
char *p;
int i;
int s=1;
int nPrinted=0;
HANDLE hPrinter=0;
WIN32_FIND_DATA find_data;
HANDLE hFind;
char *pattern;
if (argc < 2)
{
usage(argv[0]);
return 0;
}
*szPrinter='\0';
// Check for printer
if( (stricmp(argv[1], "-p")==0) || (stricmp(argv[1],"/p")==0) )
{
s=3;
strcpy(szPrinter, argv[2]);
// Make sure printer name is valid
if(OpenPrinter(szPrinter, &hPrinter, NULL)==0)
{
// If not valid, return
printf("Printer not found: '%s'\n", szPrinter);
return 0;
}
ClosePrinter(hPrinter);
// Wrap printer name in double quotes to pass as arg
// in case there are spaces in the name
sprintf(szPrinter, "\"%s\"", argv[2]);
printf("Printer: %s\n", szPrinter);
}
for(i=s;i<argc;i++)
{
// Expand any wildcards
pattern = argv[i];
hFind = FindFirstFile(pattern, &find_data);
if (hFind != INVALID_HANDLE_VALUE)
{
do {
// Construct full path to file
strcpy(szPath, argv[i]);
p = strrchr(szPath, '\\');
if(p == NULL)
*szPath = '\0';
else
*(p+1) = '\0';
strcat(szPath, find_data.cFileName);
// Get the path to the executable
ZeroMemory (szFile, MAX_PATH);
// Make sure Adobe Acrobat/Reader is installed
FindExecutable(szPath, NULL, szFile);
if (!szFile[0])
{
printf("'%s' not found or Adobe Acrobat or Reader not installed.\n", szPath);
continue;
}
// Make sure it's a PDF file
p = strrchr(szPath,'.');
if(p==NULL)
{
printf("Not a PDF file: '%s'\n", szPath);
continue;
}
if( (stricmp(p,".pdf")!=0) && (stricmp(p,".fdf")!=0) && (stricmp(p,".xfdf")!=0) )
{
printf("Not a PDF file: '%s'\n", szPath);
continue;
}
// Determine whether system uses Reader or Acrobat for PDF
if (strstr(szFile, "AcroRd32"))
strcpy (szAdobe, "Adobe Reader");
else
strcpy (szAdobe, "Adobe Acrobat");
// Set flags if Acrobat/Reader already running
isAdobeRunning();
// Tell Acrobat/Reader to print the file
nPrinted += pdfprint(szPath, szAdobe, szPrinter);
} while (FindNextFile(hFind, &find_data));
}
FindClose(hFind);
}
// If Acrobat/Reader wasn't running when we started, terminate it
if(!wasRunning)
{
if(hProcessAdobe)
{
// Politely ask Acrobat/Reader to quit
for(i=0;i<10;i++)
{
if(isAdobeRunning())
SendMessage (hWndAdobe, WM_CLOSE, 0, 0);
else
break;
Sleep(1000);
}
// If it's still running, time to get rude
if(isAdobeRunning())
TerminateProcess(hProcessAdobe, 0);
}
}
printf("%d File(s) Printed\n", nPrinted);
return(nPrinted);
}