How to use Acrobat Reader DC to print pdf files and keep them in right order

  adobe, c++, pdf, winapi

I’m tring to using win32 api: CreateProcess and ShellExecuteExW to print pdf files via Acrobat Reader DC, but I cannot get an expected result.

I want all the pdf files to be printted in order and in a short time.

Scenario 1
    Use ShellExecuteExW to print pdf file via Acrobat Reader DC.
    Acrobat Reader DC is not alive before printing.
Condition:
    WaitForSingleObject after ShellExecuteExW, timeout is INFINITE.
Result:
    The pdf was printed, and… Infinity wait time
the program was blocked
Scenario 1

Scenario 2
    Use ShellExecuteExW to print pdf file via Acrobat Reader DC.
    Acrobat Reader DC is not alive before printing.
Condition:
    WaitForSingleObject after ShellExecuteExW, timeout is 10s.
Result:
    The first one wait to timeout (10s)
    The following others printed fast
Scenario 2

Scenario 3
    Use ShellExecuteExW to print pdf file via Acrobat Reader DC.
    Acrobat Reader DC is alive before printing.
Condition:
    WaitForSingleObject after ShellExecuteExW, timeout is 10s.
Result:
    Printed fast (when timeout is INFINITE the result is same)
Scenario 3

Scenario 4
    check if Acrobat Reader DC is alive before printing. If not, then use CreateProcessW to startup it.
    Use ShellExecuteExW to print pdf file via Acrobat Reader DC.
    Acrobat Reader DC is not alive before printing.
Condition:
    WaitForSingleObject after CreateProcessW, timeout is INFINITE.
    WaitForSingleObject after ShellExecuteExW, timeout is INFINITE.
Result:
    Infinity wait time

Scenario 5
    check if Acrobat Reader DC is alive before printing. If not, then use CreateProcessW to startup it.
    Use ShellExecuteExW to print pdf file via Acrobat Reader DC.
    Acrobat Reader DC is not alive before printing.
Condition:
    WaitForSingleObject after CreateProcessW, timeout is 10s.
    WaitForSingleObject after ShellExecuteExW, timeout is INFINITE.
Result:
    The first one wait to timeout (10s)
    the following others printed fast
Scenario 5

Scenario 6
    check if Acrobat Reader DC is alive before printing. If not, then use CreateProcessW to startup it.
    Use ShellExecuteExW to print pdf file via Acrobat Reader DC.
    Acrobat Reader DC is alive before printing.
Condition:
    WaitForSingleObject after CreateProcessW, timeout is 10s.
    WaitForSingleObject after ShellExecuteExW, timeout is INFINITE.
Result:
    Printed fast
Scenario 6
All above:
    The printing order is in a mess, e.g.
order of printting

It looks like that I shouldn’t use WaitForSingle object to detect if Acrobat Reader DC has already been startupde or the printting task has fired and already done. Is there any other approach for these?
I also notice that the pid of Acrobat Reader DC is not single, could this "strange" test result relate to the Acrobat Reader DC’s self sand box?
pids of Acrobat Reader DC in task manager

my cpp is:

//// DemoCpp.cpp : This file contains the 'main' function. Program execution begins and ends there.
////
//
//#include <iostream>
//
//int main()
//{
//    std::cout << "Hello World!n";
//}
//
//// Run program: Ctrl + F5 or Debug > Start Without Debugging menu
//// Debug program: F5 or Debug > Start Debugging menu
//
//// Tips for Getting Started: 
////   1. Use the Solution Explorer window to add/manage files
////   2. Use the Team Explorer window to connect to source control
////   3. Use the Output window to see build output and other messages
////   4. Use the Error List window to view errors
////   5. Go to Project > Add New Item to create new code files, or Project > Add Existing Item to add existing code files to the project
////   6. In the future, to open this project again, go to File > Open > Project and select the .sln file
#include <iostream>
#include <shlobj.h>
#include <shlwapi.h>
#include <objbase.h>
#include <tlhelp32.h>
#include <ctime>
using namespace std;

int main();
std::wstring s2ws(const std::string& s);
string GetNow();
int StartUpPDF(DWORD dwMilliseconds);
int PrintPDF(LPCWSTR pdfPath, DWORD dwMilliseconds);
int IsPDFAlive();

int main()
{
    string pdfToPrint[] = {
        "C:temptestdatatest (1).pdf",
        "C:temptestdatatest (2).pdf",
        "C:temptestdatatest (3).pdf",
        "C:temptestdatatest (4).pdf",
        "C:temptestdatatest (5).pdf",
        "C:temptestdatatest (6).pdf",
        "C:temptestdatatest (7).pdf",
        "C:temptestdatatest (8).pdf",
        "C:temptestdatatest (9).pdf",
        "C:temptestdatatest (10).pdf",
        "C:temptestdatatest (11).pdf"
    };
    for (int i = 0; i < (sizeof(pdfToPrint) / sizeof(pdfToPrint[0])); i++)
    {
        cout << GetNow() << " " << "Printing attachment " << i << endl;
        /*Codes for checking if Acrobat Reader DC is alive => */
        cout << GetNow() << " " << "Checking if Acrobat Reader DC is alive " << endl;
        if (IsPDFAlive() < 0)
        {
            cout << GetNow() << " " << "Acrobat Reader DC is not alive, tring to startup it now..." << endl;
            StartUpPDF(10 * 1000);
            //StartUpPDF(INFINITE);
            cout << GetNow() << " " << "Check it again, pid of Acrobat Reader DC is: " << IsPDFAlive() << endl;
        }
        /*Codes for checking if Acrobat Reader DC is alive <= */
        cout << GetNow() << " " << pdfToPrint[i] << endl;
        PrintPDF(s2ws(pdfToPrint[i]).c_str(), INFINITE);
        //PrintPDF(s2ws(pdfToPrint[i]).c_str(), 10 * 1000);
    }
    //char buff[256];
    //FindExecutableA("C:temptestdatatest (1).pdf", NULL, buff);
    //cout << buff;
    std::cin.get();
}
int IsPDFAlive()
{
    LPCWSTR lpName = L"AcroRd32.exe";
    DWORD dwPid = -1;
    HANDLE hProcess = NULL;
    HANDLE hProcessSnap;
    PROCESSENTRY32 pe32;
    // Take a snapshot of all processes in the system.
    hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    if (hProcessSnap == INVALID_HANDLE_VALUE)
    {
        //printf("Error: CreateToolhelp32Snapshot (of processes)rn");
        return NULL;
    }
    // Set the size of the structure before using it.
    pe32.dwSize = sizeof(PROCESSENTRY32);
    // Retrieve information about the first process,
     // and exit if unsuccessful
    if (!Process32First(hProcessSnap, &pe32))
    {
        //printf("Error: Process32Firstrn"); // show cause of failure
        CloseHandle(hProcessSnap);          // clean the snapshot object
        return -1;
    }
    // Now walk the snapshot of processes, and
     // display information about each process in turn
    int namelen = 200;
    char name[201] = { 0 };
    do
    {
        if (!wcscmp(pe32.szExeFile, lpName)) {
            dwPid = pe32.th32ProcessID;
            //hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPid);
            cout << GetNow() << " " << "find " << "AcroRd32.exe" << " pid is " << dwPid << "n";
            break;
        }

    } while (Process32Next(hProcessSnap, &pe32));

    CloseHandle(hProcessSnap);
    //CloseHandle(hProcess);
    return dwPid;
}
int PrintPDF(LPCWSTR pdfPath, DWORD dwMilliseconds)
{
    SHELLEXECUTEINFO ShExecInfo;
    bool success;

    ShExecInfo.cbSize = sizeof(SHELLEXECUTEINFO);
    ShExecInfo.fMask = SEE_MASK_FLAG_NO_UI | SEE_MASK_NOCLOSEPROCESS;;
    ShExecInfo.hwnd = NULL;
    ShExecInfo.lpVerb = L"printto";
    ShExecInfo.lpFile = pdfPath;
    ShExecInfo.lpParameters = L"PDFCreator";
    ShExecInfo.lpDirectory = NULL;
    ShExecInfo.nShow = SW_MAXIMIZE;
    ShExecInfo.hInstApp = NULL;

    cout << GetNow() << " Calling ShellExecuteExW " << endl;
    if (ShellExecuteExW(&ShExecInfo) == 0)
    {
        if (GetLastError() != ERROR_CANCELLED) // Operation canceled by the user
        {
            cout << endl << "GetLastError " << GetLastError() << endl;
        }
    }
    if (ShExecInfo.hProcess != NULL)
    {
        //std::cout << ShExecInfo.hProcess;
        //HANDLE h = OpenProcess(PROCESS_TERMINATE, false, GetProcessId(ShExecInfo.hProcess));
        //TerminateProcess(h, 1);
        //CloseHandle(h);
        //ShExecInfo.hProcess = NULL;
        cout << GetNow() << " ShellExecuteSuccess " << endl;
        // Wait until child process exits.
        /*for (int i = 0; i < 60; i++) 
        {
            if (!WaitForSingleObject(ShExecInfo.hProcess, 1000))
                break;
        }*/
        WaitForSingleObject(ShExecInfo.hProcess, dwMilliseconds);
        cout << GetNow() << " WaitForSingleObject Done " << endl << endl;
        CloseHandle(ShExecInfo.hProcess);
    }
    return 0;
}

int StartUpPDF(DWORD dwMilliseconds)
{
    STARTUPINFO si;
    PROCESS_INFORMATION pi;
    wchar_t cmdLine[1024] = L"C:Program Files (x86)AdobeAcrobat Reader DCReaderAcroRd32.exe";
    ZeroMemory(&si, sizeof(si));
    si.cb = sizeof(si);
    ZeroMemory(&pi, sizeof(pi));
    // Start the child process. 
    if (!CreateProcess(
        NULL,           // No module name (use command line)
        cmdLine,        // Command line
        NULL,           // Process handle not inheritable
        NULL,           // Thread handle not inheritable
        FALSE,          // Set handle inheritance to FALSE
        40,              // No creation flags
        NULL,           // Use parent's environment block
        NULL,           // Use parent's starting directory 
        &si,            // Pointer to STARTUPINFO structure
        &pi)            // Pointer to PROCESS_INFORMATION structure
        )
    {
        printf("CreateProcess failed (%d).n", GetLastError());
        return 0;
    }

    // Wait until child process exits.
    WaitForSingleObject(pi.hProcess, dwMilliseconds);
    cout << GetNow() << " " << "Startup Success" << endl;
    // Close process and thread handles. 
    CloseHandle(pi.hProcess); 
    CloseHandle(pi.hThread);
    return 0;
}

std::wstring s2ws(const std::string& s)
{
    int len;
    int slength = (int)s.length() + 1;
    len = MultiByteToWideChar(CP_ACP, 0, s.c_str(), slength, 0, 0);
    wchar_t* buf = new wchar_t[len];
    MultiByteToWideChar(CP_ACP, 0, s.c_str(), slength, buf, len);
    std::wstring r(buf);
    delete[] buf;
    return r;
}

string GetNow()
{
    time_t now = time(NULL);
    //char *str = asctime(localtime(&now));
    tm now_tm = {};
    char str[26] = {};
    localtime_s(&now_tm, &now);
    asctime_s(str, 26, &now_tm);
    str[24] = ' ';
    return str;
}

and version info about my Acrobat Reader DC:
version info about my Acrobat Reader DC

Source: Windows Questions C++

LEAVE A COMMENT