0
votes

I have an inquiry in the process of printing the printer.

Below are three of my program descriptions.

[My Application info]

  1. Hook the APIs related to printing, such as StartDoc, StartPage, ExtTextOut, EndPage, and EndDoc.

  2. After checking the entire string obtained from ExtTextOut in EndDoc API during printing, when a specific string is detected, the printer is deleted and the approval page is viewed.

  3. After receiving approval, I would like to reprint the existing printer. (JOB_CONTROL_RESUME will not be used in my program. You must print again after deleting unconditionally.)

  4. Don't show the dialog again when reprinting. With all the property information of the print that was started at the beginning in the DocumentProperties API, the same print is restarted with that information.

[Current Re-Print Logic] This is my current status. If you delete Print and proceed with printing again (this is the logic to run StartDoc, StartPage, Endpage, EndDoc that was previously in progress after creating a new printer DC), in a specific document (textbox of Excel, etc.), normal output is not possible. I checked MSDN and it was confirmed that there is no API to output a specific print name in Windows, so I wrote the code as above.

[PowerShell Command] Also, for printing, I tried the following command using PowerShell to print several files (ppt, xls, doc ...etc) including txt files. PowerShell > Start-Process -FilePath "C:\Users\DeveloperO\Desktop\1234.docx" -Verb print The above command worked, but the result is not what I want because a new process has been started.

Starting a new process and starting a print doesn't work for me.

[Please Answer]

Question 0) Is there a command to print an open process without starting the process using powershell? (Currently, I know that only txt files can be printed.)

Question 1) I've been working in C++ language, is there an API to programmatically request a printer using C++?

Question 2) I've also tried the ScheduleJob API. But this keeps giving 3002 Error. (Cannot find spool file.)

The code for this is below, can you give me some advice?

int main()
{
    BOOL bResult = FALSE;
    HANDLE hPrinter = NULL;
    DWORD dNeedNum = 0;
    CHAR szFullPath[MAX_PATH] = { 0, };
    DWORD size = 4096;
    ADDJOB_INFO_1 * JobInfo = { 0, };

    W2M(g_wszFullPath, szFullPath);

    bResult = OpenPrinter("Printer Name", &hPrinter, NULL);
    if (bResult == FALSE)
    {
        printf("Error = %d", GetLastError());
    }

    JobInfo = (ADDJOB_INFO_1)LocalAlloc((LMEM_FIXED / LMEM_ZEROINIT), size);
    bResult = AddJob(hPrinter, 1, (BYTE)JobInfo, size, &dNeedNum);

    if (bResult == FALSE)
    {
        printf("Error = %d", GetLastError());
    }

    ZeroMemory(JobInfo->Path, sizeof(JobInfo->Path));
    StringCbCopy(JobInfo->Path, sizeof(szFullPath), szFullPath);
    bResult = ScheduleJob(hPrinter, JobInfo->JobId);
    if (bResult == FALSE)
    {
        printf("Error = %d", GetLastError()); // <- Error Point 3002 Error
    }
    LocalFree(JobInfo);
    ClosePrinter(hPrinter);
}
1
There are more in msdn. - Louis Go
I've read all the documentation on MSDN. What I want is to print an existing file or document. But all the questions and answers are how to use WritePrinter to write a string to a new printer and print the file. Both of the above are talking about the same thing and that's not the answer I'm looking for - DevOST
This request is pretty clear an straight forward. It's worth being in your title and question by edit. Not just in a comment. - Louis Go
Are you talking about editing the question? - DevOST

1 Answers

0
votes

This isn't an answer to your specific questions 1,2 and 3, but in your comment, you mention 'What I want is to print and existing file or document'.

In this case, the Win32 APIs will only print GDI or XPS documents*, which means if you have a word document you want to print, you'll need to either convert it to XPS first, or use Word interop to print it, where the Word application will convert it to XPS or GDI and print it.

Unfortunately, any simple Win32 APIs for printing XPS files have been deprecated and are noted to be removed in later versions of windows.

Therefore, the remaining root to printing an XPS document is using the Print Document API, which is unfortunately non-trivial to explain.

https://docs.microsoft.com/en-us/windows/win32/printdocs/printdocs-printing

The premise at a high level would be to:

  1. Open your document to print as an xps package using CreatePackageFromStream(...)
  2. Create a package target for your print job using CreateDocumentPackageTargetForPrintJob(...).
  3. Get a package target and package writer for printing your document using GetPackageTarget(...) and GetXpsOMPackageWriter(...).
  4. Enumerate the documents and pages in the xps package and print them to your package writer.

The steps above don't really do justice to the complexity of these APIs I'm afraid.

If you need to pass in settings, you'll need to:

  1. Get the default devmode for the printer you're targeting.
  2. Convert the devmode to a print ticket for that printer.
  3. Update the settings in the print ticket.
  4. Use the print ticket in the relevant package writer APIs.

As an alternative, if you can use a separate printing process, you could use the C# APIs which are a lot more simple, and take a path to a file and print it with a single call.

https://docs.microsoft.com/en-us/dotnet/api/system.printing.printqueue.addjob?redirectedfrom=MSDN&view=net-5.0#overloads

* Unless your using passthrough APIs, with a specific printer driver.