在printspooler API中使用SetJob函数

时间:2017-04-25 00:45:57

标签: c++ printing print-spooler-api

我使用的是getJobs函数,我发现它可以在我的打印机(而不是打印设备)中获取当前的打印作业。到目前为止,我可以告诉我的虚拟打印机队列中有多少打印作业,而且我有来自JOB_INFO_ strucs的信息,但是我试图使用SetJob()从打印队列中删除作业(存储后)我想要的信息)。有了这个,我得到一个错误:

0xC0000005: Access violation reading location 0x00002012.

我的问题是,我究竟做错了什么?我已经尝试将0作为级别并为pJob设置为NULL,然后我没有收到错误但是打印作业仍然在队列中。我似乎无法找到任何有扩展的例子。

BOOL getJobs(LPTSTR printerName) {

HANDLE hPrinter; //Printer handle variable
DWORD dwNeeded, dwReturned, i; //Mem needed, jobs found, variable for loop
JOB_INFO_1 *pJobInfo; // pointer to structure

//Find printer handle
if (!OpenPrinter(printerName, &hPrinter, NULL)) {
    return FALSE;
}
//Get amount of memory needed
if (!EnumJobs(hPrinter, 0, 0xFFFFFFFF, 1, NULL, 0, &dwNeeded, &dwReturned)) {
    if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
        ClosePrinter(hPrinter);
        return FALSE;
    }
}
//Allocate the memory, if you cant end function
if ((pJobInfo = (JOB_INFO_1 *)malloc(dwNeeded)) == NULL) {
    ClosePrinter(hPrinter);
    return FALSE;
}
//Get job info struc
if (!EnumJobs(hPrinter, 0, 0xFFFFFFFF, 1, (LPBYTE)pJobInfo, dwNeeded, &dwNeeded, &dwReturned)) {
    ClosePrinter(hPrinter);
    free(pJobInfo);
    return FALSE;
}

//If there are printjobs, get document name and data type. put into docinfo1 struc and return true
if (dwReturned > 0){
    docinfo1.pDocName = pJobInfo[1].pDocument;
    docinfo1.pDatatype = pJobInfo[1].pDatatype;

    SetJob(hPrinter, pJobInfo[1].JobId, 2, (LPBYTE)pJobInfo, JOB_CONTROL_DELETE);

    ClosePrinter(hPrinter);
    free(pJobInfo);
    return TRUE;
}
//No print jobs, Free memory and finish up :>
ClosePrinter(hPrinter);
free(pJobInfo);
return FALSE;
}

非常感谢帮助。

编辑:这个问题最终成了一个简单的错误,我告诉SetJob错误的结构类型。

1 个答案:

答案 0 :(得分:3)

除了在您实际传递JOB_INFO_2结构时指定JOB_INFO_1结构(正如评论中指出的那样),您还尝试使用 pJobInfo[]的第二个元素,甚至可能不存在:

 SetJob(hPrinter, pJobInfo[1].JobId, 2, (LPBYTE)pJobInfo, JOB_CONTROL_DELETE);

将其更改为:

 SetJob(hPrinter, pJobInfo[0].JobId, 1, (LPBYTE)pJobInfo, JOB_CONTROL_DELETE);

或者更好的是,这样做是因为删除打印作业所需的只是作业ID:

 SetJob(hPrinter, pJobInfo[0].JobId, 0, NULL, JOB_CONTROL_DELETE);